您的位置:首页 > 编程语言 > Java开发

spring request的处理过程

2018-03-05 22:21 211 查看
在spring项目中,一个request过来后,都经过了哪些步骤才到controller那里呢?
下面直接亮出结论,有兴趣的可以继续往下读(当然了,只是粗略的记录,要想深刻理解,还需要自己一步步跟进去看)。
1、经过servlet框架的filter
2、进入FrameworkServlet#processRequest(...)(spring的),经过若干层会进入到DispatcherServlet.doDispatch(),这个是重点
2.1 在这个dispatch里面,先从众多的HandlerMapping里获取第一个不为null的HandlerExecutionChain,每个HandlerMapping都实现接口HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
2.2 然后执行HandlerExecutionChain.applyPreHandle(),这个嘛就是interceptor。2.3 接着执行HandlerAdapter.handle(),这个嘛,进入HanderAdapter,Valid注解检查、aop都在这里,详细的可看下文。
2.4 如果没异常抛出来的话(被aop吃掉的异常不算)最后执行HandlerExecutionChain.applyPostHandle(),这个也是interceptor。
3、然后基本就没了



先贴上几个图,辅助理解















一、HandlerMapping——是接口

HandlerMapping是个接口,代表着具有如下功能的类:即从给定的HttpServletRequest,找到合适Handler。其作用就是返回一个HandlerExecutionChain。常见的有RequestMappingHandlerMapping、SimpleUrlHandlerMapping。第一个就是通过扫描spring的@RequestMapping注解来得到映射关系。一个HandlerMapping通过HandlerExecutionChain的形式返回当前request的HandlerAdapter(及其对应的HandlerInterceptor,HandlerInterceptor的preHandle和postHandle分别在在HandlerAdapter的之前和之后执行(都是按定义顺序挨个执行))。

二、HandlerExecutionChain——是个类

在beanFactory里没有这样类型的bean,用到的时候就new一个。包含一个HandlerAdapter和多个HandlerInterceptor,每个请求都会对应到一个具体的方法,HandlerAdapter则包装了那个方法,而HandlerInterceptor就是在执行HandlerAdapter之前需要执行的一些interceptor。(aop还在HandlerAdapter里面)。

三、RequestMappingHandlerAdapter——是个类

在beanFactory里有一个这个类型的bean。内部成员有HttpMessageConverter、HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler,分别用于处理被调方法的入参和返回值,HttpMessageConverter是代表具体的转换动作的类。RequestResponseBodyMethodProcessor同时实现了HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler。RequestMappingHandlerAdapter有个afterPropertiesSet(),里面有个getDefaultArgumentResolvers,代码里写死了只添加默认的HandlerMethodArgumentResolver。加上只查找第一个support的HandlerMethodArgumentResolver。所以要想包装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一个。这个类同时实现HandlerMethodReturnValueHandler、HandlerMethodArgumentResolver。内部成员有HttpMessageConverter,这个是从beanFactory里取的。使用HttpMessageConverter处理加了@RequestBody和@ResponseBody注解的那些方法入参和返回值。如果入参还加了@Valid注解,那么还会执行相应的校验,如果校验失败,会抛出异常MethodArgumentNotValidException,该异常不会被aop捕获(因为还未进入aop呢)且HTTP RESPONSE的状态是400。若要修改,则包装RequestResponseBodyMethodProcessor.resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory);即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: