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 MVCstarter :

 <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 获取更多资讯

个人博客:https://felord.cn

换一种方式编写 Spring MVC 接口的更多相关文章

  1. Java方式配置Spring MVC

    概述 使用Java方式配置Spring MVC,以及回顾一下Spring MVC的各种用法. Spring MVC简述 关于Spring MVC的介绍网上有很多,这里就不再赘述了,只是要说一下,Spr ...

  2. Mock测试你的Spring MVC接口

    1. 前言 在Java开发中接触的开发者大多数不太注重对接口的测试,结果在联调对接中出现各种问题.也有的使用Postman等工具进行测试,虽然在使用上没有什么问题,如果接口增加了权限测试起来就比较恶心 ...

  3. Java创建线程的第二种方式:实现runable接口

    /*需求:简单的卖票程序多个窗口买票 创建线程的第二种方式:实现runable接口 *//*步骤1.定义类实现Runable接口2.覆盖Runable接口中的run方法    将线程要运行的代码存放在 ...

  4. Android 反射-换一种方式编程

    Android 反射-换一种方式编程 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/59109933 本文出自[赵彦军的博客] 上一 ...

  5. Spring MVC接口实例

    概述 前文记录了MVC模式和Spring MVC的初步认识,现在记录创建一个项目,配置Spring MVC,编写接口程序. 创建项目 打开IntelliJ IDEA,点击"File-> ...

  6. Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别

    转: http://blog.csdn.net/it_man/article/details/5074371 Spring事务配置的五种方式 前段时间对Spring的事务配置做了比较深入的研究,在此之 ...

  7. Spring mvc 接口枚举类型数据格式化处理

    一.背景简述 首先,我们都知道枚举实例有两个默认属性,name 和 ordinal,可通过 name()和ordinal()方法分别获得.其中 name 为枚举字面量(如 MALE,FEMALE),o ...

  8. 51、多线程创建的三种方式之实现Callable接口

    实现Callable接口创建线程 Callable接口是在jdk5版本中加入的,这个接口在java.util.concurrent包下面,与其他两种方式不同的地方在于使用Callable接口创建的线程 ...

  9. @Autowired注解和启动自动扫描的三种方式(spring bean配置自动扫描功能的三种方式)

    前言: @Autowired注解代码定义 @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, Elemen ...

随机推荐

  1. SpringCloud-Hystrix 服务降级、熔断

    Hystrix 是什么? Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时.异常等,Hystrix 能够保证在一个依赖出问题的情况下 ...

  2. 微信小程序标签常见知识点归纳整理

    1. <image src='/images/logo.png' mode='widthFix'></image> mode 属性表示图片随着指定的宽度自动拉伸以显示原图的正确 ...

  3. 三步教你如何在Github部署自己的简历

    相信铁子们有很多都是将找工作的小白(和小编一样!!嘿嘿)小编也和在座的大家一样,一个普通的不能再普通的二本学生(北华大学) <  单身!单身!单身!> 听很多人都说:像我们这个样子,害!放 ...

  4. Sublime text 3快捷键壁纸版

  5. PHP中的11个魔术方法

    1.__get.__set 这两个方法是为在类和他们的父类中没有声明的属性而设计的 __get( $property )       当调用一个未定义的属性时访问此方法__set( $property ...

  6. phpspider框架的使用

    手册:https://doc.phpspider.org/configs-members.html 参考:https://www.jianshu.com/p/01052508ea7c 不多说,代码贴上 ...

  7. Content-Type 四种常见的 POST 提交数据方式

    参考于: https://blog.csdn.net/tycoon1988/article/details/40080691(了解) 和: https://www.gy0929.com/wz/1420 ...

  8. StringBuilder、StringBuffer分析比较

    StringBuilder.StringBuffer源码分析 StringBuilder源码分析 类结构 public final class StringBuilder extends Abstra ...

  9. 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 ...

  10. iOS Block 页面传值

    为什么80%的码农都做不了架构师?>>>   直接上代码 1.定义block @interface TopTypeCollectionView : UIView @property ...