赞
踩
在spring项目中,一个request过来后,都经过了哪些步骤才到controller那里呢?
下面直接亮出结论,有兴趣的可以继续往下读(当然了,只是粗略的记录,要想深刻理解,还需要自己一步步跟进去看)。
1、经过servlet框架的filter
2、进入FrameworkServlet#processRequest(...)(spring的),经过若干层会进入到DispatcherServlet.doDispatch(),这个是重点
2.1 在这个dispatch里面,先从众多的HandlerMapping(如RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping)里获取第一个不为null的HandlerExecutionChain,每个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是个接口,代表着具有如下功能的类:即从给定的HttpServletRequest,找到合适Handler。其作用就是返回一个HandlerExecutionChain。
常见的有RequestMappingHandlerMapping、SimpleUrlHandlerMapping。第一个就是通过扫描spring的@RequestMapping注解来得到映射关系。
一个HandlerMapping通过HandlerExecutionChain的形式返回当前request的HandlerAdapter(及其对应的HandlerInterceptor,HandlerInterceptor的preHandle和postHandle分别在在HandlerAdapter的之前和之后执行(都是按定义顺序挨个执行))。
在beanFactory里没有这样类型的bean,用到的时候就new一个。
包含一个HandlerAdapter和多个HandlerInterceptor,每个请求都会对应到一个具体的方法,HandlerAdapter则包装了那个方法,而HandlerInterceptor就是在执行HandlerAdapter之前需要执行的一些interceptor。(aop还在HandlerAdapter里面)。
在beanFactory里有一个这个类型的bean。
内部成员有HttpMessageConverter、HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler,分别用于处理被调方法的入参和返回值,HttpMessageConverter是代表具体的转换动作的类。
RequestResponseBodyMethodProcessor同时实现了HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler。
RequestMappingHandlerAdapter有个afterPropertiesSet(),里面有个getDefaultArgumentResolvers,代码里写死了只添加默认的HandlerMethodArgumentResolver。加上只查找第一个support的HandlerMethodArgumentResolver。所以要想包装RequestResponseBodyMethodProcessor的行为,只能自定义一个注解,并且自定义一个HandlerAdapter,也就是要自定义一个HandlerMapping。
- 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()

在beanFactory里没有这个类型的bean,用到的时候就new一个。
这个类同时实现HandlerMethodReturnValueHandler、HandlerMethodArgumentResolver。内部成员有HttpMessageConverter,这个是从beanFactory里取的。
使用HttpMessageConverter处理加了@RequestBody和@ResponseBody注解的那些方法入参和返回值。
如果入参还加了@Valid注解,那么还会执行相应的校验,如果校验失败,会抛出异常MethodArgumentNotValidException,该异常不会被aop捕获(因为还未进入aop呢)且HTTP RESPONSE的状态是400。
若要修改,则包装RequestResponseBodyMethodProcessor.resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory);即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。