spring request的处理过程

在spring项目中,一个request过来后,都经过了哪些步骤才到controller那里呢?

下面直接亮出结论,有兴趣的可以继续往下读(当然了,只是粗略的记录,要想深刻理解,还需要自己一步步跟进去看)。

1、经过servlet框架的filter

2、进入FrameworkServlet#processRequest(...)(spring的),经过若干层会进入到DispatcherServlet.doDispatch(),这个是重点

2.1 在这个dispatch里面,先从众多的HandlerMapping(如RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping)里获取第一个不为nullHandlerExecutionChain,每个HandlerMapping都实现接口

HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

2.2  然后执行 HandlerExecutionChain.applyPreHandle() ,这个嘛就是 interceptor。

2.3 接着执行HandlerAdapter.handle(),这个嘛,进入HanderAdapter,@Valid注解检查、aop都在这里,抛出的异常不会传给interceptor,但是会传给@ControllerAdvice这个注解修饰的那个处理器,详细的可看下文。

2.4 如果没异常抛出来的话(被aop吃掉的异常不算)最后执行HandlerExecutionChain.applyPostHandle(),这个也是interceptor。

3、然后基本就没了偷笑


先贴上几个图,辅助理解





RequestMappingHandlerMapping的处理过程如下


查找匹配的某个controller方法的过程如下:



调用@ControllerAdvice修饰的处理器如下:




一、HandlerMapping——是接口

HandlerMapping是个接口,代表着具有如下功能的类:即从给定的HttpServletRequest,找到合适Handler。其作用就是返回一个HandlerExecutionChain

常见的有RequestMappingHandlerMappingSimpleUrlHandlerMapping。第一个就是通过扫描spring@RequestMapping注解来得到映射关系。

一个HandlerMapping通过HandlerExecutionChain的形式返回当前requestHandlerAdapter(及其对应的HandlerInterceptorHandlerInterceptorpreHandlepostHandle分别在在HandlerAdapter的之前和之后执行(都是按定义顺序挨个执行))。


二、HandlerExecutionChain——是个类

beanFactory里没有这样类型的bean,用到的时候就new一个。

包含一个HandlerAdapter和多个HandlerInterceptor,每个请求都会对应到一个具体的方法,HandlerAdapter则包装了那个方法,而HandlerInterceptor就是在执行HandlerAdapter之前需要执行的一些interceptor(aop还在HandlerAdapter里面)。


三、RequestMappingHandlerAdapter——是个类

beanFactory里有一个这个类型的bean

内部成员有HttpMessageConverterHandlerMethodArgumentResolverHandlerMethodReturnValueHandler,分别用于处理被调方法的入参和返回值,HttpMessageConverter是代表具体的转换动作的类。

RequestResponseBodyMethodProcessor同时实现了HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler

RequestMappingHandlerAdapter有个afterPropertiesSet(),里面有个getDefaultArgumentResolvers,代码里写死了只添加默认的HandlerMethodArgumentResolver。加上只查找第一个supportHandlerMethodArgumentResolver。所以要想包装RequestResponseBodyMethodProcessor的行为,只能自定义一个注解,并且自定义一个HandlerAdapter,也就是要自定义一个HandlerMapping



四、HandlerMethodArgumentResolver

HandlerAdapter.handle(),这个方法里是按如下的层级结构执行的。
HandlerAdapter#handle(HttpServletRequest request, HttpServletResponse response, Object handler)
AbstractHandlerMethodAdapter.handler(HttpServletRequest request, HttpServletResponse response, Object handler)
	RequestMappingHandlerAdapter.handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
		RequestMappingHandlerAdapter.invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
			ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs)
				InvocableHandlerMethod.invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs)
					InvocableHandlerMethod.getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs)
						// HandlerMethodArgumentResolverComposite代理了多个HandlerMethodArgumentResolver,每次选出一个何时的出来进行解析。RequestResponseBodyMethodProcessor就是其中之一
						HandlerMethodArgumentResolverComposite.resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
							// 下面这个在RequestResponseBodyMethodProcessor#resolveArgument(…)里;在调用下面这个之前,先调用HttpMessageConverter得到参数值,然后准备校验。
							AbstractMessageConverterMethodArgumentResolver.validateIfApplicable(WebDataBinder binder, MethodParameter methodParam)
								…
								进入SpringValidatorAdapter.validate(Object target, Errors errors, Object... validationHints)
										// org.hibernate.validator.internal.engine
										ValidatorImpl.validate(T object, Class<?>... groups)
										这里面有个临时变量ValueContext.currentValidatable,这个属性的值是BeanMetaDataManager.getBeanMetaData( object.getClass() ) 这个里面取的是编译时的类型,这个object就是某个参数,而非运行时。
											ValidatorImpl.validateCascadedConstraints(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext)
												里面拿到一个属性的value后,应该通过value.getClass()来重新计算设定类类型,这样可以支持泛型。而非直接调用Cascadable(PropertyMetaData).getTypeArgumentsConstraints()


五、RequestResponseBodyMethodProcessor

beanFactory里没有这个类型的bean,用到的时候就new一个。

这个类同时实现HandlerMethodReturnValueHandlerHandlerMethodArgumentResolver。内部成员有HttpMessageConverter,这个是从beanFactory里取的。

使用HttpMessageConverter处理加了@RequestBody@ResponseBody注解的那些方法入参和返回值。

如果入参还加了@Valid注解,那么还会执行相应的校验,如果校验失败,会抛出异常MethodArgumentNotValidException,该异常不会被aop捕获(因为还未进入aop呢)且HTTP RESPONSE的状态是400

若要修改,则包装RequestResponseBodyMethodProcessor.resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory);即可。









  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值