接续上一篇RestController
转成Reactive,可以看到逻辑的部分已经被抽到Handler
内了,剩下就是路径转导就是交由Router
来处理。
首先看RouterFunctions.java
,大部分s结尾的都是工具类别,像是Collections
、Arrays
,RouterFunctions
内有提供route
,传入predicate
&handlerFunction
,很直觉得理解就是符合predicate
条件则交由handlerFunction
处理,这边predicate
是RequestPredicate
,传入的参数就是ServerRequest
。
public static <T extends ServerResponse> RouterFunction<T> route(
RequestPredicate predicate, HandlerFunction<T> handlerFunction) {
return new DefaultRouterFunction<>(predicate, handlerFunction);
}
很直觉得转换後,将原本的annotation-based
的写法转换如下,包含了路径与HttpMethod
,ServerRequest
本身有提供取得路径(path()
,与method()
可以取得HttpMethod
。
RouterFunctions.route(request ->
request.path().equals("/router/greeting") && HttpMethod.GET.equals(request.method()), greetingHandler::allGreeting);
接下来有一个好用的工具类别RequestPredicates.java
里面可以看到很多方便的function
,上面的条件判断都可以被简化,像是比对HttpMethod
的method()
,比对路径的path()
,就像是整合後的@GetMapping()
一样,同样有一个GET()
整合了path
跟get
,对於header
也都有支援,contentType
、accept
,这些条件(RequestPredicate
)可以透过RequestPredicate.java
内的default function (and()
)来串接,剩余其他好用的方法,之後有遇到再来介绍。
public abstract class RequestPredicates {
...
public static RequestPredicate method(HttpMethod httpMethod) {
return new HttpMethodPredicate(httpMethod);
}
public static RequestPredicate path(String pattern) {
Assert.notNull(pattern, "'pattern' must not be null");
if (!pattern.isEmpty() && !pattern.startsWith("/")) {
pattern = "/" + pattern;
}
return pathPredicates(PathPatternParser.defaultInstance).apply(pattern);
}
public static RequestPredicate GET(String pattern) {
return method(HttpMethod.GET).and(path(pattern));
}
public static RequestPredicate contentType(MediaType... mediaTypes) {
Assert.notEmpty(mediaTypes, "'mediaTypes' must not be empty");
return new ContentTypePredicate(mediaTypes);
}
public static RequestPredicate accept(MediaType... mediaTypes) {
Assert.notEmpty(mediaTypes, "'mediaTypes' must not be empty");
return new AcceptPredicate(mediaTypes);
}
...
}
经过整理後,再将另外两个也一并改写,再透过RouterFunction.java
内的default function (and()
)来串联(是不是跟上面RequestPredicate
有异曲同工之妙)。
RouterFunctions
.route(GET("/router/greeting/{id}"), greetingHandler::getGreeting);
RouterFunctions
.route(POST("/router/greeting").and(contentType(APPLICATION_JSON)), greetingHandler::saveGreeting);
RouterFunctions
.route(GET("/router/greeting"), greetingHandler::allGreeting);
////////////////////////////////
RouterFunctions.route(GET("/router/greeting/{id}"), greetingHandler::getGreeting)
.and(
RouterFunctions.route(
POST("/router/greeting").and(contentType(APPLICATION_JSON)),
greetingHandler::saveGreeting))
.and(RouterFunctions.route(GET("/router/greeting"), greetingHandler::allGreeting));
再来可以很明显可以看出and
之後都是接route
,而且没有一个像是挂在class
层的@RequestMapping()
可以把相同的路径往上抽,所以还差最後的一步骤整合
RouterFunction.java 帮你整合好的andRoute
default RouterFunction<T> andRoute(RequestPredicate predicate, HandlerFunction<T> handlerFunction) {
return and(RouterFunctions.route(predicate, handlerFunction));
}
RouterFunctions.java nest()
,他可以把整个共同的部分统一在第一个参数(predicate
),後面就放相同类型的routerFunction
public static <T extends ServerResponse> RouterFunction<T> nest(
RequestPredicate predicate, RouterFunction<T> routerFunction) {
return new DefaultNestedRouterFunction<>(predicate, routerFunction);
}
成果如下,将相同的/router/greeting
往上抽到第一层nest
,两个get
都需要有accept,抽到第二层的nest
,最後Post
与accept
无关所以并不在第二层nest
范围内。
GreetingRouter.java
public class GreetingRouter {
@Bean
public RouterFunction<ServerResponse> routerFunction(GreetingHandler handler) {
return nest(
path("/router/greeting"),
nest(
accept(APPLICATION_JSON),
route(GET("/{id}"), handler::getGreeting)
.andRoute(method(HttpMethod.GET), handler::allGreeting))
.andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::saveGreeting));
}
}
经过这两天的学习,大致上能掌握将controller
转换成reactive的方式,相信大部分的情境应该都可以在介绍的工具类别里面找到方法处理。
<<: [Day23] 如何让 Scrum Master 的经历为履历加分
>>: Day24 [实作] 一对一视讯通话(4): 加入通话及挂断机制
今天要先来看Native Camp的流程,首先是点击注册後的页面, 有信箱和密码,还有SSO的选项,...
Python实作 Request发送 如果你的Python环境没有requests模组 pip in...
Python - Python Selenium 套件使用参考笔记 参考资料 Selenium-Py...
今天继续记录一些 Mac的功能。 四角设定 非常好用的功能,只要将滑鼠移动到画面4个角落,就可以触发...
这是什麽 分而治之,分治法! 分治法的步骤是: 将一个问题拆解成多个可以处理的小问题後 处理、击破每...