Spring 5 WebFlux中@Controller和RouterFunction之间的区别 [英] Difference between @Controller and RouterFunction in Spring 5 WebFlux
问题描述
现在有两种方法可以在Spring 5公开HTTP端点.
There are two ways to expose HTTP endpoints in spring 5 now.
-
通过设置控制器的类,例如
-
@Controller
或@RestController
@Controller
or@RestController
by making the controller's class, e.g.
@RestController
@RequestMapping("persons")
public class PersonController {
@Autowired
private PersonRepo repo;
@GetMapping("/{id}")
public Mono<Person> personById(@PathVariable String id){
retrun repo.findById(id);
}
}
- 使用RouterFunction在
@Configuration
类中进行路由:
- Route in
@Configuration
class by using RouterFunctions:
@Bean
public RouterFunction<ServerResponse> personRoute(PersonRepo repo) {
return route(GET("/persons/{id}"), req -> Mono.justOrEmpty(req.pathVariable("id"))
.flatMap(repo::getById)
.flatMap(p -> ok().syncBody(p))
.switchIfEmpty(notFound().build()));
}
使用任何人的方法是否有性能差异?从头开始编写应用程序时应该使用哪一个.
Is there any performance difference in using anyone approach? Which one should I use when writing my application from scratch.
推荐答案
-
编程范例:命令式与功能式
Programming Paradigm: Imperative vs Functional
-
MVC传统:Servlet堆栈与Netty堆栈
对于带有@Controller
或@RestController
批注的情况,我们同意基于批注的模型,在该模型中,我们将批注(不仅限于)用于映射,并因此产生了副作用(功能中不允许这样做).世界)以使我们的API能够正常工作.这样的副作用可能是@Valid
注释,该注释为请求的主体提供了内置的bean验证,或者是@RequestMapping
具有整个控制器的根路径.
In the case with the @Controller
or @RestController
annotations, we agree with the annotation-based model where we use annotations for mappings (and not only) and as a result side effects (that is not allowed in the functional world) to make our API works. Such side effects could be @Valid
annotation that provides inbuilt bean validation for requests' bodies or @RequestMapping
with the root path for the whole controller.
另一方面,借助路由器功能,我们摆脱了在API实现方面由任何副作用组成的注释,并将其直接委派给功能链:router -> handler
.这两个非常适合构建基本的反应块:一个事件序列和两个主角,这些事件的发布者和订阅者.
On the other hand, with the router functions, we get rid of annotations that consist of any side effects in terms of API implementation and delegate it directly to the functional chain: router -> handler
. Those two are perfectly suited for building the basic reactive block: a sequence of events and two protagonists, a publisher and a subscriber to those events.
当我们谈论@Controller
时,我会说我们通常会用同步Java的世界来思考:Servlets
,ServletContext
,ServletContainerInitializer
,DispatcherServlet
等.即使我们返回java.nio.*
的Servlet 3.0
规范运行,并在相同的servlet容器(例如Jetty
或Tomcat
)上运行.随后,在这里,我们将使用相应的设计模式和方法来构建Web应用程序.
When we are talking about @Controller
I would say that we usually will think in term of synchronous Java world: Servlets
, ServletContext
, ServletContainerInitializer
, DispatcherServlet
etc. Even if we will return Mono
from a controller to make our application reactive we still will play in terms of Servlet 3.0
specification that supports java.nio.*
and running on the same servlets containers such as Jetty
or Tomcat
. Subsequently, here we will use corresponding design patterns and approaches for building web apps.
RouterFunction
受到源自异步Java世界的真正反应方法的启发- Netty 及其Channel Model
.
RouterFunction
on the other hand was inspired by the true reactive approach that originates from async Java world - Netty and its Channel Model
.
随后出现了用于反应性环境的一组新的类及其API: ServerResponse ,反应性宣言.
Subsequently new set of classes and their APIs for reactive environment emerged: ServerRequest, ServerResponse, WebFilter and others. As for me, they were designed by the Spring team in accordance with the previous years of maintaining the framework and understanding new web systems requirements. The name for those requirements is Reactive Manifesto.
最近,我的团队面临着无法将 Swagger 与RouterFucntion
端点集成的问题.它可以支持@Controlers
,但是Spring团队介绍了他们的解决方案- Spring REST文档轻松连接到反应式
Recently my team faced the issue that it is impossible to integrate Swagger with RouterFucntion
endpoints. It could upvote for @Controlers
, but the Spring team introduced their solution - Spring REST Docs that could be easily connected to reactive WebTestClient. And I use here word 'connected' cause it follows true reactive meaning behind: instead of Swagger with its overloaded configurations and side-effect annotations, you easily could build you API docs in tests without touching you working code at all.
Update 2020 :尽管自那时以来,Spring Webflux已经可以随后通过OpenAPI规范与Swagger集成,但它仍然缺乏配置的简单性和透明性,以我的拙见,是成为古老MVC方法一部分的结果.
Update 2020: Despite since now Spring Webflux already could be integrated with Swagger subsequently using OpenAPI specification, it still lacks configuration simplicity and transparency that, in my humble opinion, is the consequence of to be a part of the archaic MVC approach.
可能不会听到对性能的影响,类似于"这完全基于个人喜好".我同意,个人的偏爱确实有两个选择:当您让自己在同一个领域呆了十年时,前进还是后退.我认为Spring团队提供了对@Controller
的响应式支持,以使旧项目能够以某种方式与时间要求保持一致,并且至少有迁移的机会.
如果您要从头开始创建Web应用程序,请不要犹豫,并使用引入的反应式堆栈.
Cause of no performance impact it's likely to hear something similar to 'it is absolutely based on individual preference what to use'. And I agree that it's individual preference indeed among two options: moving forward or moving backwards when you let yourself to stay in the same domain for a decade. I think that reactive support for @Controller
was done by the Spring team to make it possible for old projects somehow be in tune with requirements of time and have at least opportunity for the migration.
If you are going to create a web application from scratch then do not hesitate and use introduced reactive stack.
这篇关于Spring 5 WebFlux中@Controller和RouterFunction之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!