新聞中心
環(huán)境:Springboot2.4.12

永定ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書(shū)銷(xiāo)售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書(shū)合作)期待與您的合作!
概述
Spring Web MVC包括WebMvc.fn,這是一種輕量級(jí)函數(shù)式編程模型,其中函數(shù)用于路由和處理請(qǐng)求,參數(shù)及返回值設(shè)計(jì)為不可變。它是基于注釋的編程模型的替代方案,但在其他方面還是運(yùn)行在同一DispatcherServlet上。
在WebMvc.fn中,HTTP請(qǐng)求由HandlerFunction處理:該函數(shù)接受ServerRequest并返回ServerResponse。請(qǐng)求和響應(yīng)對(duì)象都有不可變,提供對(duì)HTTP請(qǐng)求和響應(yīng)的JDK 8友好訪問(wèn)。HandlerFunction相當(dāng)于基于注釋的編程模型中@RequestMapping方法的主體。
傳入的請(qǐng)求通過(guò)RouterFunction路由到處理程序函數(shù):一個(gè)接受ServerRequest并返回可選HandlerFunction(即可選的
示例:
@Configuration
public class PersonHandlerConfiguration {
@Bean
public RouterFunction person() {
return route().GET("/person", accept(MediaType.APPLICATION_JSON), request -> {
return ServerResponse.status(HttpStatus.OK).body("Hello World") ;
}).build() ;
}
} 我們需要在一個(gè)@Configuration配置類(lèi)中將RouterFunction暴露為Bean對(duì)象即可。
GET方法的3個(gè)參數(shù):
第一個(gè):請(qǐng)求的接口地址。
第二個(gè):謂詞也就是限定哪些調(diào)用能夠匹配上,這個(gè)類(lèi)似注解接口@RequestMapping參數(shù)中的consumer,params等屬性一樣。
第三個(gè):HandlerFunction,這就是處理器對(duì)象了,實(shí)際的業(yè)務(wù)方法的處理對(duì)比@RequestMapping的方法體了。
HandlerFunction對(duì)象
ServerRequest和ServerResponse是不可變的接口,提供對(duì)HTTP請(qǐng)求和響應(yīng)的JDK8友好訪問(wèn),包括頭、正文、方法和狀態(tài)代碼。
- ServerRequest
ServerRequest提供對(duì)HTTP方法、URI、頭和查詢參數(shù)的訪問(wèn),而對(duì)主體的訪問(wèn)是通過(guò)主體方法提供的。如下示例:
@Bean
public RouterFunction student() {
return route().GET("/student/{id}", accept(MediaType.APPLICATION_JSON), request -> {
return ServerResponse.ok().body("name = " + request.param("name").get() + ", id = " + request.pathVariable("id")) ;
})
.POST("/student", accept(MediaType.APPLICATION_JSON), request -> {
return ServerResponse.ok().body(request.body(Student.class)) ;
})
.build() ;
} GET接口獲取查詢參數(shù)和路徑上的參數(shù)。
POST接口獲取body主體內(nèi)容。
- ServerResponse
ServerResponse提供對(duì)HTTP響應(yīng)的訪問(wèn),因?yàn)樗遣豢勺兊?,所以可以使用?gòu)建方法來(lái)創(chuàng)建它??梢允褂蒙善髟O(shè)置響應(yīng)狀態(tài)、添加響應(yīng)標(biāo)題或提供正文。
在上面的示例中已經(jīng)看到了如何使用,這里就不再給出示例了。
- Handler Classes處理器類(lèi)
將處理器類(lèi)單獨(dú)定義到一個(gè)文件中進(jìn)行相應(yīng)的處理,這就與傳統(tǒng)的@RestController注解類(lèi)似了將很多的接口方法都定義在一個(gè)Controller類(lèi)中。
示例:
@Configuration
public class PersonHandlerConfiguration {
@Resource
private PersonHandler ph ;
@Bean
public RouterFunction person() {
return route()
.GET("/person/{id}", accept(MediaType.APPLICATION_JSON), ph::queryPerson)
.POST("/person", accept(MediaType.APPLICATION_JSON), ph::save)
.build() ;
}
} 處理器類(lèi)(在該類(lèi)中可以注入DAO類(lèi)進(jìn)行相關(guān)的數(shù)據(jù)庫(kù)操作)
@Component
public class PersonHandler {
public ServerResponse save(ServerRequest request) throws Exception {
return ok().body(request.body(Person.class)) ;
}
public ServerResponse queryPerson(ServerRequest request) throws Exception {
return ok().body(new Person(Integer.valueOf(request.pathVariable("id")), "中國(guó)")) ;
}
}- Validation驗(yàn)證
可以使用Spring的驗(yàn)證工具將驗(yàn)證應(yīng)用于請(qǐng)求主體。例如,給定一個(gè)人的自定義Spring驗(yàn)證器實(shí)現(xiàn)。示例:
@Component
public class PersonHandler {
@Resource
private Validator validator ;
public ServerResponse save(ServerRequest request) throws Exception {
Person person = request.body(Person.class) ;
Errors errors = validate(person) ;
if (errors == null) {
return ok().body(person) ;
}
return ok().body(errors.toString()) ;
}
private Errors validate(Person person) {
Errors errors = new BeanPropertyBindingResult(person, "person");
validator.validate(person, errors);
if (errors.hasErrors()) {
return errors ;
}
return null ;
}
}需要引入依賴:
org.springframework.boot
spring-boot-starter-validation
關(guān)于參數(shù)驗(yàn)證《Springboot項(xiàng)目中你的參數(shù)都在如何驗(yàn)證?這個(gè)starter你知道嗎?》
RouterFunction
路由器功能用于將請(qǐng)求路由到相應(yīng)的HandlerFunction。通常,你不會(huì)自己編寫(xiě)路由器函數(shù),而是使用RouterFunctions類(lèi)上的方法來(lái)創(chuàng)建路由器函數(shù)。RouterFunctions.route()(無(wú)參數(shù))為你提供了創(chuàng)建路由器函數(shù)的流暢生成器,而RouterFunctions.route(RequestPredicate,HandlerFunction)則提供了創(chuàng)建路由器的直接方法。
通常,建議使用route() 構(gòu)建,因?yàn)樗鼮榈湫陀成鋱?chǎng)景提供了方便的捷徑,而不需要難以發(fā)現(xiàn)的靜態(tài)導(dǎo)入。例如,router function builder提供方法GET(String,HandlerFunction)為GET請(qǐng)求創(chuàng)建映射;和POST(字符串、HandlerFunction)用于POST。
除了基于HTTP方法的映射之外,route builder還提供了一種在映射到請(qǐng)求時(shí)引入額外謂詞的方法。對(duì)于每個(gè)HTTP方法,都有一個(gè)重載變量,該變量將RequestPredicate作為參數(shù),通過(guò)它可以表示額外的約束。
在上面的示例中已經(jīng)看到了在做相應(yīng)GET,POST方法時(shí)傳的第二個(gè)參數(shù)。
- 謂詞Predicate
我們可以編寫(xiě)自己的RequestPredicate,但是RequestPredicates類(lèi)提供了基于請(qǐng)求路徑、HTTP方法、內(nèi)容類(lèi)型等的常用實(shí)現(xiàn)。如下示例通過(guò)Accept來(lái)限定了能夠接收的數(shù)據(jù)類(lèi)型。
import static org.springframework.web.servlet.function.RequestPredicates.accept;
@Bean
public RouterFunction hello() {
return route().GET("/hello", accept(MediaType.APPLICATION_JSON), request -> {
return ServerResponse.status(HttpStatus.OK).body("Hello World") ;
}).build() ;
} 還可以通過(guò)and 或者 or 來(lái)添加多個(gè)謂詞
accept(...).and() || or()
- 嵌套路由
在傳統(tǒng)的Controller定義時(shí),可以在類(lèi)上加@RequestMapping("/person")注解的方式來(lái)統(tǒng)一請(qǐng)求接口的前綴。在函數(shù)式接口中我們可以通過(guò)如下的方式設(shè)定:
@Bean
public RouterFunction nestPerson() {
return route()
.path("/persons", builder -> builder
.GET("/{id}", accept(MediaType.APPLICATION_JSON), ph::queryPerson)
.POST("/save", ph::save))
.build();
} 通過(guò)path定義了路由的前綴。也可以通過(guò)如下方式:
@Bean
public RouterFunction nestPerson2() {
return route()
.path("/persons2", b1 -> b1
.nest(accept(MediaType.APPLICATION_JSON), b2 -> b2
.GET("/{id}", accept(MediaType.APPLICATION_JSON), ph::queryPerson))
.POST("/save", ph::save))
.build();
} HandlerMapping
這種函數(shù)式接口既然底層還是使用的DispatcherServlet ,那么它就會(huì)有對(duì)應(yīng)的HandlerMapping和Adapter
RouterFunctionMapping:檢測(cè)Spring配置中的一個(gè)或多個(gè)RouterFunction<?>bean,對(duì)它們進(jìn)行排序,通過(guò)RouterFunction.andOther組合它們,并將請(qǐng)求路由到生成的組合RouterFunction。
HandlerFunctionAdapter:讓DispatcherHandler調(diào)用映射到請(qǐng)求的HandlerFunction的簡(jiǎn)單適配器。
過(guò)濾器
可以使用路由函數(shù)生成器上的before、after或filter方法篩選處理程序函數(shù)。對(duì)于接口注釋的方式,我們可以通過(guò)使用@ControllerAdvice、ServletFilter或兩者來(lái)實(shí)現(xiàn)類(lèi)似的功能。過(guò)濾器將應(yīng)用于生成器生成的所有路由。這意味著嵌套路由中定義的過(guò)濾器不適用于“頂層”路由。示例:
@Bean
public RouterFunction nestPerson2() {
return route()
.path("/persons2", b1 -> b1
.nest(accept(MediaType.APPLICATION_JSON), b2 -> b2
.GET("/{id}", accept(MediaType.APPLICATION_JSON), ph::queryPerson)
.before(request -> ServerRequest.from(request).header("x-pack", "123123").build()))
.POST("/save", ph::save))
.after((request, response) -> {
System.out.println("after execution..." + response.statusCode());
return response ;
})
.filter((request, next) -> {
if (request.pathVariable("id").equals("100")) {
return ServerResponse.ok().body("參數(shù)錯(cuò)誤") ;
} else {
return next.handle(request) ;
}
})
.build();
}
public ServerResponse queryPerson(ServerRequest request) throws Exception {
System.out.println(request.headers().header("x-pack")) ;
return ok().body(new Person(Integer.valueOf(request.pathVariable("id")), "中國(guó)")) ;
} before:添加了自定義header信息,然后我們可以在queryPerson中獲取到,并且該before只能應(yīng)用于當(dāng)前這個(gè)嵌套的路由中。
after:能夠應(yīng)用所有的路由中
filter:filter方法采用HandlerFilterFunction:采用ServerRequest和HandlerFunction并返回ServerResponse的函數(shù)。handler函數(shù)參數(shù)表示鏈中的下一個(gè)元素。這通常是路由到的處理程序,但如果應(yīng)用了多個(gè)過(guò)濾器,它也可以是另一個(gè)過(guò)濾器。
Swagger
此時(shí)的Swagger沒(méi)有用了,所以你的慎用啊。
完畢?。。?/p>
文章標(biāo)題:Spring MVC函數(shù)式接口Router Function你用過(guò)嗎?
轉(zhuǎn)載來(lái)于:http://www.5511xx.com/article/dpsicdo.html


咨詢
建站咨詢
