Spring WebFlux使用函数式编程之Filtering Handler Functions

环境:Springboot2.4.12


本篇主要内容:

请先阅读:

  1. 《Spring WebFlux使用函数式编程之HandlerFunction(1)》
  2. 《Spring WebFlux使用函数式编程之RouterFunction(2)》

概述

你可以通过在路由函数构建器上使用beforeafterfilter方法来筛选处理程序函数。通过使用注释,你可以通过使用@ControllerAdviceServletFilter或两者都可以实现类似的功能。过滤器将应用于构建器构建的所有路由。这意味着在嵌套路由中定义的过滤器不适用于“顶级”路由。例如,考虑下面的例子:

RouterFunction route = route()
    .path("/person", b1 -> b1
        .nest(accept(APPLICATION_JSON), b2 -> b2
            .GET("/{id}", handler::getPerson)
            .GET("", handler::listPeople)
            .before(request -> ServerRequest.from(request) // 1
                .header("X-RequestHeader", "Value")
                .build()))
        .POST("/person", handler::createPerson))
    .after((request, response) -> logResponse(response)) // 2
    .build();
  1. 添加自定义请求头的before过滤器只应用于两个GET路由。
  2. 记录响应的after过滤器应用于所有路由,包括嵌套路由。

路由器构建器上的filter方法接受HandlerFilterFunction:一个接受ServerRequestHandlerFunction并返回ServerResponse的函数。处理程序函数参数表示链中的下一个元素。这通常是路由到的处理程序,但如果应用了多个过滤器,它也可以是另一个过滤器。

完整示例

处理程序句柄

@Component
public class PersonHandler {
  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")), "中国")) ;
  }
	
  private Errors validate(Person person) {
    Errors errors = new BeanPropertyBindingResult(person, "person");
    validator.validate(person, errors);
    if (errors.hasErrors()) {
      return errors ; 
    }
    return null ;
  }
}

路由配置

@Configuration
public class PersonHandlerConfiguration {
	
  @Resource
  private PersonHandler ph ;
	
  @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("参数错误") ;
        } else {
          return next.handle(request) ;
        }
      })
      .build();
  }
	
}

POJO

public class Person {
  private Integer id ;
  @NotEmpty(message = "姓名必须填写")
  private String name ;
}

URL处理组件

URL组件可以在Spring MVC and Spring WebFlux中都可以使用。

UriComponentsBuilder帮助从带有变量的URI模板构建URI,如下例所示:

UriComponents uriComponents = UriComponentsBuilder
  .fromUriString("https://pack.com/lovers/{lover}")  // 1
  .queryParam("q", "{q}")  // 2
  .encode()  // 3
  .build();  // 4
URI uri = uriComponents.expand("lover", "hcw").toUri();  // 5
  1. 使用URI模板的静态工厂方法
  2. 添加或替换URI组件
  3. 请求对URI模板和URI变量进行编码
  4. 建立一个UriComponents
  5. 展开变量并获得URI

以上代码运行结果:

https://pack.com/lovers/lover?q=hcw

上面的例子可以合并为一个链,并使用buildAndExpand进行缩短,如下面的例子所示:

URI uri = UriComponentsBuilder
  .fromUriString("https://pack.com/lovers/{lover}")
  .queryParam("q", "{q}")
  .encode()
  .buildAndExpand("lover", "hcw")
  .toUri();

你可以通过直接进入URI(这意味着编码)来进一步缩短它,如下面的例子所示:

URI uri = UriComponentsBuilder
  .fromUriString("https://pack.com/lovers/{lover}")
  .queryParam("q", "{q}")
  .build("lover", "hcw");

你可以使用完整的URI模板进一步缩短它,如下例所示:

URI uri = UriComponentsBuilder
  .fromUriString("https://pack.com/lovers/{lover}")
  .build("lover", "hcw");

完毕!!!

Spring容器这些扩展点你都清楚了吗?
Spring事务实现原理源码分析
Spring中的@Configuration注解你真的了解吗?
SpringBoot对Spring MVC都做了哪些事?(一)
SpringBoot对Spring MVC都做了哪些事?(二)
SpringBoot对Spring MVC都做了哪些事?(三)
SpringBoot对Spring MVC都做了哪些事?(四)

展开阅读全文

页面更新:2024-03-30

标签:函数   嵌套   路由   过滤器   变量   组件   例子   模板   完整   程序

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top