WebFlux请求处理流程(二)

目录

前言

接上篇,上篇提到在HttpServerHandle.onStateChange()中会监听请求状态变化,进而对请求进行处理,目前已分析到FilteringWebHandler.filter(),上篇中对WebFilter链表已经做了介绍,后面就是DispatcherHandler.handle(),直到这里,是WebFlux真正的业务相关处理器,包括对请求参数及响应处理等。到这里,WebFlux在使用方式上会分两种,一种是沿用SpringMVC语法,WebFlux能够实现无缝衔接,另一种就是router functions,我们后面将会以router functions为例。

DispatcherHandler - WebFlux调度器

DispatcherHandler是WebFlux的调度器,核心业务流程是通过对请求地址进行解析,执行相应的处理器方法,并进行响应处理。下面我们会从两个部分对DispatcherHandler进行解析,包括初始化和请求处理。

1. DispatcherHandler 初始化

DispatcherHandler 初始化在WebFlux启动时已执行,属于spring注册、不在启动核心流程,所以第一篇里面并未提及。初始化主要是对内部其内部属性进行赋值,包括:

1)List<HandlerMapping> handlerMappings:处理器路径映射,即请求路径与业务处理器的对应关系,通过对请求路径的解析获取对应的处理器。

2)List<HandlerAdapter> handlerAdapters:处理器适配器,对不同类型的业务处理器进行相应的前置准备,如请求封装等。

3)List<HandlerResultHandler> resultHandlers:结果处理器,对业务处理器返回的数据结果进行处理。

初始化代码如下:

package org.springframework.web.reactive;
import ...

public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, ApplicationContextAware {
   

  	@Nullable
	private List<HandlerMapping> handlerMappings;
	@Nullable
	private List<HandlerAdapter> handlerAdapters;
	@Nullable
	private List<HandlerResultHandler> resultHandlers;

	/**
	 * 空构造,Spring注册时调用的即是空构造
	 */
	public DispatcherHandler() {
   }
	
  	/**
  	 * 带参构造,直接调用初始化方法
  	 */
	public DispatcherHandler(ApplicationContext applicationContext) {
   
		initStrategies(applicationContext);
	}
  
  	/**
  	 * 实现ApplicationContextAware接口,注册完成后会自动执行,调用初始化方法
  	 * WebFlux默认注册时调用的是空构造,注册完成后执行initStrategies()方法
  	 */
  	@Override
	public void setApplicationContext(ApplicationContext applicationContext) {
   
		initStrategies(applicationContext);
	}
  
  	protected void initStrategies(ApplicationContext context) {
   
    	// 获取HandlerMapping,详见1.1
		Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
				context, HandlerMapping.class, true, false);
		ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
		AnnotationAwareOrderComparator.sort(mappings);
		this.handlerMappings = Collections.unmodifiableList(mappings);

    	// 获取HandlerAdapter,详见1.2
		Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
				context, HandlerAdapter.class, true, false);
		this.handlerAdapters = new ArrayList<>(adapterBeans.values());
		AnnotationAwareOrderComparator.sort(this.handlerAdapters);

    	// 获取HandlerResultHandler,详见1.3
		Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
				context, HandlerResultHandler.class, true, false);
		this.resultHandlers = new ArrayList<>(beans.values());
		AnnotationAwareOrderComparator.sort(this.resultHandlers);
	}
}

1.1 HandlerMapping

HandlerMapping:处理器与访问路径的映射关系。WebFlux自动声明了三个实现类,分别为:

1、RequestMappingHandlerMapping:MVC语法模式下使用@RequestMapping注解注入。

2、RouterFunctionMapping:RouterFunctions语法模式下声明注入。

3、SimpleUrlHandlerMapping:URL直接对应Handler,WebFlux默认注入两个匹配路径:
1) /webjars/** -> ResourceWebHandler [classpath [META-INF/resources/webjars/]]
2) /** -> ResourceWebHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/]]

这里我们只分析RouterFunctions语法下的情况,即RouterFunctionMapping的获取,在WebFlux中RouterFunctionMapping的获取包括注册和初始化两个过程。

1.1.1 RouterFunctionMapping 注册

RouterFunctionMapping的注册在WebFluxConfigurationSupport中,属于WebFlux自动装配。

package org.springframework.web.reactive.config;
import ...

public class WebFluxConfigurationSupport implements ApplicationContextAware {
   

	...

	@Bean
	public RouterFunctionMapping routerFunctionMapping(ServerCodecConfigurer serverCodecConfigurer) {
   
		RouterFunctionMapping mapping = createRouterFunctionMapping();
		// 设定排序,在RequestMappingHandlerMapping之前
		mapping.setOrder(-1);
		// 设定消息读取器,会另开一篇专门介绍消息读取器和消息写入器
		mapping.setMessageReaders(serverCodecConfigurer.getReaders());
		// 配置Mapping跨域及Mapping路径匹配(下划线及大小写转换支持),这里一般都不设定,不做展开
		configureAbstractHandlerMapping(mapping, getPathMatchConfigurer());
		return mapping;
	}
	
	protected RouterFunctionMapping createRouterFunctionMapping() {
   
		return new RouterFunctionMapping();
	}
}

1.1.2 RouterFunctionMapping 初始化

RouterFunctionMapping类中实现InitializingBean接口的afterPropertiesSet()方法,在Spring注册完成后进行内部属性的初始化,为内部属性赋值,代码如下:

package org.springframework.web.reactive.function.server.support;
import ...

public class RouterFunctionMapping extends AbstractHandlerMapping implements InitializingBean {
    

	@Nullable
	private RouterFunction<?> routerFunction;
	private List<HttpMessageReader<?>> messageReaders = Collections.emptyList();

	@Override
	public void afterPropertiesSet() throws Exception {
   
		/**
		 * 设置messageReaders属性,这里在Sring注入时已经赋值,if内部不再执行。
		 * HttpMessageReader解释见1.1.2.1
		 */ 
		if (CollectionUtils.isEmpty(this.messageReaders)) {
   
			ServerCodecConfigurer codecConfigurer = ServerCodecConfigurer.create();
			this.messageReaders = codecConfigurer.getReaders();
		}

		/**
		 * 初始化routerFunction属性,详细内容见下方方法
		 * RouterFunction解释见1.1.2.2
		 */  
		if (this.routerFunction == null) {
   
			initRouterFunctions();
		}
		
		if (this.routerFunction != null) {
   
			// 通配路径转换,暂不展开
			RouterFunctions.changeParser(this.routerFunction, getPathPatternParser());
		}
	}
	
	protected void initRouterFunctions() {
   
		// 获取RouterFunction列表
		List<RouterFunction<?>> routerFunctions = routerFunctions();
		// 累加构建并赋值,即RouterFunction对象嵌套,这里不做展开
		this.routerFunction = routerFunctions.stream()
			.reduce(RouterFunction::andOther).orElse(null);
		// 日志记录
		logRouterFunctions(routerFunctions);
	}

	private List<RouterFunction<?>> routerFunctions() {
   
		// 从Spring中获取RouterFunction,即WebFlux使用时声明的RouterFunction,示例见1.1.2.3
		return obtainApplicationContext()
				.getBeanProvider(RouterFunction.class)
				.orderedStream()
				.map(router -> (RouterFunction<?>) router)
				.collect(Collectors.toList());
	}
}
1.1.2.1 属性类型解析:HttpMessageReader

HttpMessageReader:
消息读取器,即定义读取器支持的媒体类型以及如何读取请求参数或请求体数据。核心代码如下:

package org.springframework.http.codec;
import ...

public interface HttpMessageReader<T> {
   

	/**
	 * 设定消息读取器支持的媒体类型
	 */
	List<MediaType> getReadableMediaTypes();
	
	/**
	 * 是否可读取
	 * elementType:数据对象类型
	 * mediaType:请求媒体类型
	 */
	boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType);

	/**
	 * getReadableMediaTypes() 方法重载,默认实现
	 * 先判定当前数据类型是否支持,支持则调用子类getReadableMediaTypes(),不支持则返回空集合
	 */
	default List<MediaType> getReadableMediaTypes(ResolvableType elementType) {
   
		return (canRead(elementType, null) ? getReadableMediaTypes() : Collections.emptyList());
	}

	/**
	 * 从ReactiveHttpInputMessage中读取并解析为Flux对象
	 */
	Flux<T> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints);
	
	/**
	 * 从ReactiveHttpInputMessage中读取并解析为Mono对象
	 */
	Mono<T> readMono(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints);

	/**
	 * 方法重载 - Flux读取
	 * ServerHttpRequest 继承 ReactiveHttpInputMessage
	 */
	default Flux<T> read(ResolvableType actualType, ResolvableType elementType, ServerHttpRequest request,
			ServerHttpResponse response, Map<String, Object> hints) {
   
		return read(elementType, request, hints);
	}
	
	/**
	 * 方法重载 - Mono读取
	 * ServerHttpRequest 继承 ReactiveHttpInputMessage
	 */
	default Mono<T> readMono(ResolvableType actualType, ResolvableType elementType, ServerHttpRequest request,
			ServerHttpResponse response, Map<String, Object> hints) {
   

		return readMono(elementType, request, hints);
	}
}
1.1.2.2 属性类型解析:RouterFunction

函数式接口,表示获取请求路径所对应的处理器方法对象,即:HandlerFunction。
RouterFunction定义route()方法,子类通过实现route()方法来获取请求路径所对应的处理器方法对象。同时,RouterFunction中也定义了一些默认方法,实现对RouterFunction组合操作。具体RouterFunction的组合会再开一篇进行具体分析。RouterFunction核心代码如下:

package org.springframework.web.reactive.function.server;
import ...

@FunctionalInterface
public interface RouterFunction<T extends ServerResponse> {
   

	// 获取请求路径所对应的处理器方法对象
	Mono<HandlerFunction<T>> route(ServerRequest request);
	
	...
}
1.1.2.3 声明RouterFunction示例
@Configuration
public class UserRouting {
   
private final UserHandler userHandler;

    @Autowired
    public UserRouting(UserHandler userHandler) {
   
        this.userHandler = userHandler;
    }

    @Bean
    public RouterFunction<ServerResponse> userRouter() {
   
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值