[TOC]
## `WebHandler`简介
`WebHandler`用于请求处理的通用`Web API`,在此基础上构建具体的编程模型,如带注释的控制器和函数端点。
`org.springframework.web.server`包构建在`HttpHandler`契约之上,提供一个通用的`Web API`,通过由多个`WebExceptionHandler`、多个`WebFilter`、和一个`WebHandler`组件组成链来处理请求。该链可以与`WebHttpHandlerBuilder`放在一起,只需指定一个自动检测组件的`Spring ApplicationContext`。或通过向构建器注册组件。
`HttpHandler`的目标很简单,就是抽象不同`HTTP`服务器的使用,而`WebHandler API`的目标是提供`Web`应用程序中常用的特性,比如:
1. 带有属性的用户会话。
2. 解决请求的`Locale`或`Principal`
3. 访问解析和缓存的表单数据
4. 对复合数据的抽象
`WebHandler`相关实现类结构如下:
![](https://img.kancloud.cn/1d/af/1dafc1d5567181b4eb42fdc143b2277a_1600x626.png)
| 类 | 作用 |
| --- | --- |
|`DispatcherHandler`|`HTTP`请求处理程序/控制器的中央调度程序。调度到已注册的处理程序以处理请求,类似`Spring Mvc`中的`DispatchServlet`|
|`FilteringWebHandler`|在调用委托的`WebHandler`之前调用一个`WebFilter`链,进行过滤处理,类似`Servlet`中的`Filter`
|`ExceptionHandlingWebHandler`|用于异常处理
|`ResourceWebHandler`|用于静态资源处理|
| `HttpWebHandlerAdapter` | `WebHandler`到`HttpHandle`转换的默认适配器 |
## `WebHttpHandlerBuilder`
这个构建器有两个目的:
1. 一种是组装一个处理链,它包含一个目标`WebHandler`,然后用一组`WebFilters`进行修饰,然后进一步用一组`WebExceptionHandler`进行修饰。
2. 第二个目的是将产生的处理链调整为`HttpHandler`:最低级别的反应式`HTTP`处理抽象,然后可以将其用于任何受支持的运行时。适配是在`HttpWebHandlerAdapter`的帮助下完成的。
处理链可以通过构建器方法手工组装,或者通过`ApplicationContext`从`Spring ApplicationContext`中检测,或者两者都可以。
~~~
WebHttpHandlerBuilder.applicationContext(...).filter(...).webHandler(...).exceptionHandler(...)
.sessionManager(...).codecConfigurer(...).localeContextResolver(...).forwardedHeaderTransformer(...);
~~~
下表列出了`WebHttpHandlerBuilder`可以在`Spring ApplicationContext`中自动检测或直接注册的组件:
| Bean name | Bean type | Count| Description|
| --- | --- |--- |--- |
| 任意 | WebExceptionHandler |0..N| 为来自WebFilter实例链和目标WebHandler的异常提供处理 |
|任意| WebFilter| 0..N| 在调用目标的`WebHandler`之前调用一个`WebFilter`链,进行过滤处理|
|webHandler|WebHandler|1|请求的处理程序|
|webSessionManager|WebSessionManager|0..1|管理WebSession实例通过ServerWebExchange公开的方法,默认DefaultWebSessionManager|
|serverCodecConfigurer|ServerCodecConfigurer|0..1|用于访问HttpMessageReader实例,解析表单数据和ServerWebExchange通过方法获取的复合数据,默认ServerCodecConfigurer.create()|
|localeContextResolver|LocaleContextResolver|0..1|LocaleContext解析器,通过ServerWebExchange上公开的方法|
|forwardedHeaderTransformer|ForwardedHeaderTransformer|0..1|从“Forwarded”和“X-Forwarded-*”头中提取值来覆盖请求URI(即ServerHttpRequest.getURI()),默认不使用|
![](https://img.kancloud.cn/ed/af/edafe3bc127e05c924fe4a5a101901a4_946x624.png)
## 简单的服务器
上面介绍了`WebHandler`相关组件,以及链路的处理顺序,接下来使用`reactor-netty`创建一个简单的服务器,处理网络请求,更直观的了解`WebHandler`相关想组件的执行流程。
1.引入依赖
~~~
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<version>5.3.16</version>
<exclusions>
<exclusion>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.16</version>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
<version>1.0.19</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.4.18</version>
</dependency>
~~~
2.`DataBuffer` 公共创建方法
~~~
static DataBuffer createDataBuffer() {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer dataBuffer = dataBufferFactory.allocateBuffer();
return dataBuffer;
}
~~~
3.创建`ServerCodecConfigurer`
~~~
static ServerCodecConfigurer codecConfigurer() {
System.out.println("进入codecConfigurer...");
return ServerCodecConfigurer.create();
}
~~~
4.创建`AcceptHeaderLocaleContextResolver`
~~~
static AcceptHeaderLocaleContextResolver localeContextResolver() {
System.out.println("进入localeContextResolver...");
return new AcceptHeaderLocaleContextResolver();
}
~~~
5.创建`ForwardedHeaderTransformer`
~~~
static ForwardedHeaderTransformer forwardedHeaderTransformer() {
System.out.println("进入forwardedHeaderTransformer...");
return new ForwardedHeaderTransformer();
}
~~~
6.创建`WebSessionManager`
~~~
static WebSessionManager webSessionManager() {
return exchange -> {
System.out.println("进入WebSessionManager...");
Mono<WebSession> memory = new InMemoryWebSessionStore().retrieveSession("user_id");
return memory;
};
}
~~~
7.创建`WebFilter`
~~~
static WebFilter webFilter() {
return (exchange, chain) -> {
System.out.println("进入filter...");
return chain.filter(exchange);
};
}
~~~
8.创建`WebHandler`
~~~
static WebHandler webHandler() {
return exchange -> {
System.out.println("进入WebHandler....");
DataBuffer dataBuffer = createDataBuffer().write("hello word".getBytes());
return exchange.getResponse().writeWith(Flux.just(dataBuffer));
};
}
~~~
9.创建`WebExceptionHandler`
~~~
static WebExceptionHandler webExceptionHandler() {
return (exchange, ex) -> {
System.out.println("进入exceptionHandler...");
return exchange.getResponse().writeWith(Flux.just(createDataBuffer().write(ex.getMessage().getBytes())));
};
}
~~~
10.创建服务`HttpServer`
~~~
public static void main(String[] args) throws Exception {
HttpHandler handler =
WebHttpHandlerBuilder.webHandler(webHandler()).filter(webFilter()).
exceptionHandler(webExceptionHandler()).sessionManager(webSessionManager())
.codecConfigurer(codecConfigurer()).localeContextResolver(localeContextResolver())
.forwardedHeaderTransformer(forwardedHeaderTransformer()).build();
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create().host("127.0.0.1").port(1234).handle(adapter).bind().block();
Thread.currentThread().join();
}
}
~~~
11.执行结果
```
➜ ~ curl -i 'http://127.0.0.1:1234'
HTTP/1.1 200 OK
transfer-encoding: chunked
hello word
```
12.日志
```
进入codecConfigurer...
进入localeContextResolver...
进入forwardedHeaderTransformer...
进入WebSessionManager...
进入filter...
进入WebHandler....
```
- 1.反应式编程概述
- 2.Reactor框架
- Flux
- Mono
- 订阅(Subscribe)
- 编程创建序列
- 线程和调度器
- 错误处理
- 3.Spring WebFlux概述
- 4.Spring WebFlux核心组件
- HttpHandler
- WebHandler
- ServerWebExchange
- 编码和解码器
- JSON
- Form Data
- Multipart Data
- 过滤器
- 异常处理器
- DispatcherHandler
- 5.Spring Boot启动WebFlux
- 6.Spring WebFlux注解控制器
- 请求映射
- 处理程序方法
- 方法参数
- 返回值
- 类型转换
- 模型(Model)
- 数据绑定(DataBinder)
- 异常管理
- @ControllerAdvice
- 7.Spring WebFlux函数端点
- HandlerFunction
- RouterFunction
- 运行服务
- 函数过滤器
- 8.Spring Boot中使用函数端点
- 9.Spring Webflux请求处理流程
- 10.Spring WebFlux配置
- 11.Spring WebFlux使用R2DBC访问MySQL
- 12.Spring WebFlux访问Redis
- 13.Spring WebFlux访问MongoDB
- 14.Spring WebFlux集成Thymeleaf
- 15.Spring WebFlux集成FreeMarker
- 16.Spring WebFlux WebClient
- 17.Spring WebFlux WebSocket
- 18.测试
- 19.RSocket