HandlerAdapter的结构图:
如上所示:总共五个实现类,有一个还被摒弃了,除了RequestMappingHandlerAdapter适配器,其他都很简单,只需要调用各自的方法就可以了。HttpReqeustHandlerAdapter、SimpleServletHandlerAdapter和SimpleControllerHandlerAdapter分别适配HttpRequestHandler、Servlet和Controller类型的Handler。方法很简单,源码举例一个其他类似。如下:
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public SimpleControllerHandlerAdapter() {
}
public boolean supports(Object handler) {
return handler instanceof Controller;
}
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return ((Controller)handler).handleRequest(request, response);
}
public long getLastModified(HttpServletRequest request, Object handler) {
return handler instanceof LastModified ? ((LastModified)handler).getLastModified(request) : -1L;
}
}
一、RequestMappingHandlerAdapter概述
主要分析RequestMappingAdapter类,RequestMappingAdapter继承AbstractHandlerMethodAdapter,后者分别调用三个模板方法由子类实现,其中supportsInternal还多加了一个判断Handler是否是HandlerMethod类型。源码:
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
private int order = 2147483647;
public AbstractHandlerMethodAdapter() {
super(false);
}
public void setOrder(int order) {
this.order = order;
}
public int getOrder() {
return this.order;
}
public final boolean supports(Object handler) {
//这里多加了是否是HandlerMethod方法,其他都使用模板方法
return handler instanceof HandlerMethod && this.supportsInternal((HandlerMethod)handler);
}
protected abstract boolean supportsInternal(HandlerMethod var1);
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return this.handleInternal(request, response, (HandlerMethod)handler);
}
@Nullable
protected abstract ModelAndView handleInternal(HttpServletRequest var1, HttpServletResponse var2, HandlerMethod var3) throws Exception;
public final long getLastModified(HttpServletRequest request, Object handler) {
return this.getLastModifiedInternal(request, (HandlerMethod)handler);
}
protected abstract long getLastModifiedInternal(HttpServletRequest var1, HandlerMethod var2);
}
接下来就看RequestMappingHandlerAdapter,这个可以说是SpringMVC中最复杂的组件它的supportsInternal直接返回true,只需要满足父类中的HandlerMethod类型的要求就可以了。getLastModifiedInternal直接返回-1;最重要的就是handlerInternal方法了,就是这个方法实际使用Handler处理请求。具体步骤有如下三步:
- 备好处理器所需要的参数(这个最难,参数的不确定性)
- 使用处理器处理请求 (这个比较简单,直接用反射调用handleMethod处理就可以了)
- 处理返回值,也就是将不同类型的返回值统一处理成ModelAndView类
1.备好处理器所需要的参数
1.1.备好参数需要考虑的问题:
- 1)都有哪些参数需要绑定?
解答:除了方法确定的参数,还有两个方法的参数需要绑定,那就是当前处理器相对应注释了@ModelAttribute和注释了@InitBinder的方法
- 2)参数的值的来源?
解答:有六个参数的来源:
request中相关的参数,主要包括url中的参数、post中过来的参数,以及请求头包含的值;
cookie中的参数
session中给的参数
设置到FlashMap中的参数,这种参数用于redirect的参数传递
SessionAttribute传递的参数,这类参数通过@SessionAttribute注释传递
通过相应的注释了@ModelAttribute的方法设置的参数
- 3)具体进行绑定的方法?
1.2 参数具体的解析
参数解析使用HandlerMethodArgumentResolver类型的组件完成的,不同类型的使用不同的ArgumentResolver来解析。有的Resolver内部使用了WebDataBinder,可以通过注释了@InitBinder的方法来初始化,注释了@InitBinder的方法也需要绑定参数,而且也是不确定的,所以@InitBinder注释的方法也需要ArgumentResolver来解析参数,使用的和Handler不同的一套ArgumentResolver,另外注释了ModelAttribute的方法也需要绑定参数,使用的和Handler使用的是同一套ArgumentResolver。
二、RequestMappingHandlerAdapter之器
主要是在方法afterProperties中,RequestMappingAdapter实现了InitializaingBean接口,所以在初始化这个bean时,会调用这个方法,这个方法主要初始化了argumentResolver,initBinderArgumentResolvers,returnVAlueHandlers以及@ControllerAdvice注释的类相关的modelAttributeAdviceCache、initBinderAdviceCache和responseBodyAdvice这六个属性。
知识集锦:
- argumentResolvers:用于处理器方法和注释了@ModelAttribute的方法设置参数
- initBinderArgumentResolvers:用于给注释了@initBinder的方法设置参数
- returnValueHandlers:用于将处理器的返回值处理为ModelAndView的类型
- modelAttributeAdviceCache和initBinderAdviceCache:分别用于缓存@ControllerAdvice注释的类里面注释了@ModelAttribute和@InitBinder方法,也就是全局的@ModelAttribute和InitBinder方法。
- requestResponseBodyAdvice:用来保存前面介绍过的实现了RequestBodyAdvice和ResponseBodyAdvice接口,可以修改接受到参数的类和返回的ResponseBody的类。
源码分析:
public void afterPropertiesSet() {
//初始化注释了@ControllerAdvice的类的三个属性
this.initControllerAdviceCache();
List handlers;
if (this.argumentResolvers == null) {
//初始化argumentResolvers
handlers = this.getDefaultArgumentResolvers();
this.argumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
}
if (this.initBinderArgumentResolvers == null) {
//初始化initBinderArgumentResolvers
handlers = this.getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
}
if (this.returnValueHandlers == null) {
//初始化returnValueHandlers
handlers = this.getDefaultReturnValueHandlers();
this.returnValueHandlers = (new HandlerMethodReturnValueHandlerComposite()).addHandlers(handlers);
}
}
//获取注释了@ControllerAdvice全局的属性
private void initControllerAdviceCache() {
if (this.getApplicationContext() != null) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Looking for @ControllerAdvice: " + this.getApplicationContext());
}
//获取到所有注释了@ControllerAdvice的bean
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(this.getApplicationContext());
//根据order排序
AnnotationAwareOrderComparator.sort(adviceBeans);
List<Object> requestResponseBodyAdviceBeans = new ArrayList();
Iterator var3 = adviceBeans.iterator();
while(var3.hasNext()) {
ControllerAdviceBean adviceBean = (ControllerAdviceBean)var3.next();
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
//查找注释了@ModelAttribute而且没有注释@RequestMapping的方法
Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
if (this.logger.isInfoEnabled()) {
this.logger.info("Detected @ModelAttribute methods in " + adviceBean);
}
}
//查找注释了@InitBinder的方法
Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(adviceBean, binderMethods);
if (this.logger.isInfoEnabled()) {
this.logger.info("Detected @InitBinder methods in " + adviceBean);
}
}
//查找实现了RequestBodyAdvice接口的类
if (RequestBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
if (this.logger.isInfoEnabled()) {
this.logger.info("Detected RequestBodyAdvice bean in " + adviceBean);
}
}
//查找实现了ResponseBodyAdvice接口的类
if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
if (this.logger.isInfoEnabled()) {
this.logger.info("Detected ResponseBodyAdvice bean in " + adviceBean);
}
}
}
//将查找的RequestBodyAdvice和ResponseBodyAdvice接口的类添加到requestResponseBodyAdvice属性中
if (!requestResponseBodyAdviceBeans.isEmpty()) {
this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
}
}
}
另外有三个getDefaultXXX方法,在和我三个方法都是十分相似的,看一个即可,如getDEfaultArgumentResolver,这个是用来设置ArgumentResolver属性,这是一个非常核心的属性。
源码:
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList();
//添加按注释解析参数的解析器,例如@RequestParam,@PathVariable等
resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(this.getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestPartMethodArgumentResolver(this.getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestHeaderMethodArgumentResolver(this.getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(this.getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(this.getBeanFactory()));
添加按类型解析的解析器
resolvers.add(new SessionAttributeMethodArgumentResolver());
resolvers.add(new RequestAttributeMethodArgumentResolver());
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(this.getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
//添加自定义参数解析器,主要用于解析自定义的类型,这个一般都用不上
if (this.getCustomArgumentResolvers() != null) {
resolvers.addAll(this.getCustomArgumentResolvers());
}
//这两个解析器可以解析所有类型的参数
resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
二、RequestMappingHandlerAdapter之用
RequestMappingHandlerAdapter的入口方法是handlerInternal,源码如下:
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse
response, HandlerMethod handlerMethod) throws Exception {
this.checkRequest(request);
ModelAndView mav;
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized(mutex) {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader("Cache-Control")) {
//判断是否有@SessionAttribute注释的参数
if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
} else {
this.prepareResponse(response);
}
}
return mav;
}
上面主要是invokeHandlerMethod方法和applyCacheSeconds,prepareResponse方法,
invokeHandlerMethod方法首先通过request和Response创建了ServletWebRequest类型的webRequest,在ArgumentResolver解析参数时使用的是webRequest。接着对WebDataBinderFactory、ModelFactory、ServletInvocableHandlerMethod这三个类的变量进行定义和初始化。源码:
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
Object result;
try {
WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory);
ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
if (!asyncManager.isConcurrentHandlingStarted()) {
ModelAndView var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
return var15;
}
result = null;
} finally {
webRequest.requestCompleted();
}
return (ModelAndView)result;
}
知识集锦:
WebDataBinderFactory:用来创建WebDataBinder------用于参数绑定,主要功能是实现参数跟String之间的类型转换,ArgumentResolver在进行参数解析过程中会用到WebDataBinder,另外ModelFactory更新Model时也会用到它。WebDataBinderFactory的创建过程就是讲符合条件的注释了@InitBinder的方法找出来,并使用他们新建出ServletRequestDataBinderFactory类型的WebDataBinderFactory。这里的InitBinder包含在@ControllerAdvice中和处理器自己包含的两种情况。
ModelFactory:用来处理Model的,主要包含两个功能:
在处理器具体处理器之前对Model进行初始化(将原来的SEssionAttributes中的值设置到Model;执行相应注释了@ModelAttribute的方法并设置到Model中;处理器注释了@ModelAttribute的参数如果同时在SessionAttributes中也配置了,而且mavContainer中还没有值,则ongoing全部SessionAttribute中查找并设置进去);
在处理完请求后对Model参数进行更新(先对SessionAttributes进行设置,设置跪着是如果处理器调用了SessionStatus#setComplete浙江SessionAttribute清空)
ServletInvocableHandlerMethod:它继承HandlerMethod,并且可以直接执行,实际的请求就是通过它来处理的,参数绑定、处理请求以及返回值处理都是在它里面完成的。