换一种方式编写 Spring MVC 接口

1. 前言
通常我们编写 Spring MVC 接口的范式是这样的:
@RestController
@RequestMapping("/v1/userinfo")
public class UserInfoController {
@GetMapping("/foo")
public String foo() {
return "felord.cn";
}
}
这种我都写吐了,今天换个口味,使用 Spring 5 新引入的函数式端点(Functional Endpoints)来耍耍。 这种方式同样支持 Spring Webflux。
请注意可使用该特性的 Spring 版本不低于 Spring 5.2
2. 依赖
为了演示,这里极简化只引入 Spring MVC 的 starter :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
3. RouterFunction
在函数式端点的写法中,传统的请求映射(@RequestMapping)被路由函数(RouterFunction)所代替。上面的写法等同于:
@Bean
public RouterFunction<ServerResponse> fooFunction() {
return RouterFunctions.route()
.GET("/v1/userinfo/foo", request -> ServerResponse.ok()
.body("felord.cn"))
.build();
}
在该示例中,我使用了 RouterFunctions.route() 创建了一个RouterFunction,然后RouterFunction 提供了从请求到响应的细节操作。
4. ServerRequest/ServerResponse
ServerRequest 是对服务器端的HTTP请求的抽象,你可以通过该抽象获取请求的细节。对应的,ServerResponse 是对服务器端响应的抽象,你也可以通过该抽象构建响应的细节。这两个概念由下面的 HandlerFunction 接口进行 请求→ 响应 处理。
5. HandlerFunction
HandlerFunction 是一个函数式接口,它提供了从请求( ServerRequest)到响应(ServerResponse)的函数映射抽象。通常你的业务逻辑由该接口进行实现。从 ServerRequest 中获取请求的细节,然后根据业务构建一个 ServerResponse 响应。
HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().body("felord.cn");
6. RequestPredicate
RequestPredicate 可以让你根据请求的一些细节,比如 请求方法、请求头、请求参数等等进行断言以决定是否路由。

这里举一个例子,假如我们希望请求接口/v1/userinfo/predicate时根据不同的参数处理不同的业务,当携带参数 plan时才能进行处理。我们可以这么写:
@Bean
public RouterFunction<ServerResponse> predicateFunction() {
return RouterFunctions.route()
.GET("/v1/userinfo/predicate",
request -> request.param("plan").isPresent(),
request -> ServerResponse.ok().body("felord.cn"))
.build();
}
然后我们测试一下:
当携带参数 plan时:
GET http://localhost:8080/v1/userinfo/predicate?plan=
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 9
Date: Thu, 14 May 2020 07:57:35 GMT
Keep-Alive: timeout=60
Connection: keep-alive
felord.cn
不携带参数plan时:
GET http://localhost:8080/v1/userinfo/predicate
HTTP/1.1 404
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 14 May 2020 08:00:15 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"timestamp": "2020-05-14T08:00:15.659+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/v1/userinfo/predicate"
}
7. 小结
函数式端点是 Spring 5 提供的一个新的接口范式风格,对于 Spring MVC 来说 Spring 5.2 才进行了支持。也是顺应函数式编程的一个未来趋势。由于篇幅原因这里仅仅对其中的关键概念进行了讲解。下一篇我们会对这种接口范式进行进一步的讲解和实际使用。敬请关注:码农小胖哥 。
关注公众号:Felordcn 获取更多资讯
换一种方式编写 Spring MVC 接口的更多相关文章
- Java方式配置Spring MVC
概述 使用Java方式配置Spring MVC,以及回顾一下Spring MVC的各种用法. Spring MVC简述 关于Spring MVC的介绍网上有很多,这里就不再赘述了,只是要说一下,Spr ...
- Mock测试你的Spring MVC接口
1. 前言 在Java开发中接触的开发者大多数不太注重对接口的测试,结果在联调对接中出现各种问题.也有的使用Postman等工具进行测试,虽然在使用上没有什么问题,如果接口增加了权限测试起来就比较恶心 ...
- Java创建线程的第二种方式:实现runable接口
/*需求:简单的卖票程序多个窗口买票 创建线程的第二种方式:实现runable接口 *//*步骤1.定义类实现Runable接口2.覆盖Runable接口中的run方法 将线程要运行的代码存放在 ...
- Android 反射-换一种方式编程
Android 反射-换一种方式编程 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/59109933 本文出自[赵彦军的博客] 上一 ...
- Spring MVC接口实例
概述 前文记录了MVC模式和Spring MVC的初步认识,现在记录创建一个项目,配置Spring MVC,编写接口程序. 创建项目 打开IntelliJ IDEA,点击"File-> ...
- Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别
转: http://blog.csdn.net/it_man/article/details/5074371 Spring事务配置的五种方式 前段时间对Spring的事务配置做了比较深入的研究,在此之 ...
- Spring mvc 接口枚举类型数据格式化处理
一.背景简述 首先,我们都知道枚举实例有两个默认属性,name 和 ordinal,可通过 name()和ordinal()方法分别获得.其中 name 为枚举字面量(如 MALE,FEMALE),o ...
- 51、多线程创建的三种方式之实现Callable接口
实现Callable接口创建线程 Callable接口是在jdk5版本中加入的,这个接口在java.util.concurrent包下面,与其他两种方式不同的地方在于使用Callable接口创建的线程 ...
- @Autowired注解和启动自动扫描的三种方式(spring bean配置自动扫描功能的三种方式)
前言: @Autowired注解代码定义 @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, Elemen ...
随机推荐
- SpringCloud-Hystrix 服务降级、熔断
Hystrix 是什么? Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时.异常等,Hystrix 能够保证在一个依赖出问题的情况下 ...
- 微信小程序标签常见知识点归纳整理
1. <image src='/images/logo.png' mode='widthFix'></image> mode 属性表示图片随着指定的宽度自动拉伸以显示原图的正确 ...
- 三步教你如何在Github部署自己的简历
相信铁子们有很多都是将找工作的小白(和小编一样!!嘿嘿)小编也和在座的大家一样,一个普通的不能再普通的二本学生(北华大学) < 单身!单身!单身!> 听很多人都说:像我们这个样子,害!放 ...
- Sublime text 3快捷键壁纸版
- PHP中的11个魔术方法
1.__get.__set 这两个方法是为在类和他们的父类中没有声明的属性而设计的 __get( $property ) 当调用一个未定义的属性时访问此方法__set( $property ...
- phpspider框架的使用
手册:https://doc.phpspider.org/configs-members.html 参考:https://www.jianshu.com/p/01052508ea7c 不多说,代码贴上 ...
- Content-Type 四种常见的 POST 提交数据方式
参考于: https://blog.csdn.net/tycoon1988/article/details/40080691(了解) 和: https://www.gy0929.com/wz/1420 ...
- StringBuilder、StringBuffer分析比较
StringBuilder.StringBuffer源码分析 StringBuilder源码分析 类结构 public final class StringBuilder extends Abstra ...
- HDU 5954 Do Not Pour Out
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #defi ...
- iOS Block 页面传值
为什么80%的码农都做不了架构师?>>> 直接上代码 1.定义block @interface TopTypeCollectionView : UIView @property ...