赞
踩
HandlerAdapter是具体使用Handler来干活的,每个HandlerAdapter封装了一种Handler的具体使用方法。
通过上面的类图,我们可以发现HandlerAdapter接口一共只有六个子类,而且只有AbstractHandlerMethodAdapter和RequestMappingHandlerAdapter是两层,其实这两个类也是在实际工作中使用最多的,我们后面具体分析。
其实,在Spring4.3之前,还有一个AnnotationMethodHandlerAdapter 实现类,在4.3版本被打上弃用标签,在5.0之后就移除了该类。而HandlerFunctionAdapter类则是从Spring5.2开始引入的,主要用来处理响应式的请求。
HandlerAdapter 接口非常简单,只有三个方法,各个方法的含义如下所示:
public interface HandlerAdapter {
//判断是否对应的handler处理器
boolean supports(Object handler);
//核心方法,实际调用handler处理器,并返回处理结果的方法
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
//获取HttpServletRequest对象上一次修改时间的方法
long getLastModified(HttpServletRequest request, Object handler);
}
在HandlerAdapter类结构中,SimpleControllerHandlerAdapter、SimpleServletHandlerAdapter、HttpRequestHandlerAdapter三个类主要用来适配哪些处理情况比较单一的情况,所以这几个类的实现也比较简单。这里以SimpleControllerHandlerAdapter为例,分析它的实现逻辑。
public class SimpleControllerHandlerAdapter implements HandlerAdapter { //只支持实现了org.springframework.web.servlet.mvc.Controller接口的处理器 @Override public boolean supports(Object handler) { return (handler instanceof Controller); } //调用处理器中的方法进行处理 @Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response); } //返回HttpServletRequest上一次更新时间 @Override public long getLastModified(HttpServletRequest request, Object handler) { if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } }
在SimpleControllerHandlerAdapter 实现类中,代码非常简单。其中核心的handle()方法,因为实现Controller接口的处理器方法,只有handleRequest()一个方法,且参数和返回值也非常明确,所以可以直接调用处理器的方法即可。其中,Controller 接口的代码如下:
@FunctionalInterface
public interface Controller {
@Nullable
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
SimpleServletHandlerAdapter用来处理Servlet类型的处理器,HttpRequestHandlerAdapter用来处理实现了HttpRequestHandler接口的处理器,处理逻辑和SimpleControllerHandlerAdapter基本上是一样的,这里不在具体分析了。
RequestMappingHandlerAdapter类继承于AbstractHandlerMethodAdapter抽象类,是在实际工作中使用最多的一种方式,这种方式主要用来处理通过 @RequestMapping注解实现的HandlerMethod类型的处理器。这种方式的处理器,支持自定义的参数和返回值,所以处理器的参数的个数、类型都不确定,返回值的类型也可以由用户来自定义。灵活多变的用法,就带来了这种底层实现的复杂度,其中定义了很多参数解析、返回值解析的方法,用来保证这种灵活性。这一节内容我们先学习RequestMappingHandlerAdapter类的核心处理逻辑:
抽象类AbstractHandlerMethodAdapter继承了WebContentGenerator类,并实现了HandlerAdapter和Ordered两个接口。其中,WebContentGenerator类提供了一些遍历的通用方法,比如设置或获取当前request支持的方法集合,初始化或者获取设置“Cache-Control”的方法等。HandlerAdapter是核心接口,Ordered接口主要是为了给多个HandlerAdapter类提供一个排序的依据。类定义如下:
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
//内容省略
}
在抽象类中,实现了HandlerAdapter接口的三个方法,同时又定义了另外三个方法,交由子类实现了。首先,supports()方法实现:判断是否是HandlerMethod类型,然后再调用定义的抽象方法supportsInternal()进行判断,实现如下:
@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
然后,handle()方法的实现:直接调用定义的抽象方法handleInternal(),交由子类进行实现,其中第三个参数,代表处理器,直接转化成了HandlerMethod类型。
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
最后,getLastModified()方法的实现:也是直接交给了抽象方法getLastModifiedInternal(),并把处理器转换成了HandlerMethod类型。实现如下:
@Override
public final long getLastModified(HttpServletRequest request, Object handler) {
return getLastModifiedInternal(request, (HandlerMethod) handler);
}
所以,在抽象类AbstractHandlerMethodAdapter中没有实现实际的业务处理,只是通过继承WebContentGenerator类提供了一些便利的方法,然后提供了排序功能,其他逻辑都交由了子类RequestMappingHandlerAdapter来实现,下面我们开始分析RequestMappingHandlerAdapter类的实现逻辑。
RequestMappingHandlerAdapter类是HandlerAdapter结构中最复杂的类,尤其是其中使用到了很多的参数解析、返回值解析、Model构建、HttpMessageConverter等组件。这里我们先分析RequestMappingHandlerAdapter类的设计和实现:
属性字段:
//过滤有注解@InitBinder的方法 public static final MethodFilter INIT_BINDER_METHODS = method -> AnnotatedElementUtils.hasAnnotation(method, InitBinder.class); //过滤有注解@ModelAttribute且没有@RequestMapping注解的方法 public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method -> (!AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) && AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class)); //自定义参数参数解析器集合 @Nullable private List<HandlerMethodArgumentResolver> customArgumentResolvers; //该类是一个特殊的参数解析类,其中保存了所有参数解析器的集合,并提供了参数解析的方法(实际上由其他解析器实现)。 @Nullable private HandlerMethodArgumentResolverComposite argumentResolvers; //处理注解@InitBinder中参数的解析器集合 @Nullable private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers; //自定义返回值解析器集合 @Nullable private List<HandlerMethodReturnValueHandler> customReturnValueHandlers; //特殊的返回值解析器,类似HandlerMethodArgumentResolverComposite @Nullable private HandlerMethodReturnValueHandlerComposite returnValueHandlers; //视图解析器集合 @Nullable private List<ModelAndViewResolver> modelAndViewResolvers; //判断request请求的MediaType类型处理解析处理工具,包括了文件扩展名处理的相关方法 private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager(); //HttpMessageConverter结合,用来处理器request和response之间消息的转换 private List<HttpMessageConverter<?>> messageConverters; //保存@RequestBodyAdvice或@ResponseBodyAdvice注解的方法,用来预处理请求或返回值 private List<Object> requestResponseBodyAdvice = new ArrayList<>(); //初始化WebDataBinder的回调接口,WebDataBinder类用于绑定request参数到JavaBean对象 @Nullable private WebBindingInitializer webBindingInitializer; //异步或响应式处理参数省略…… //设置redirect场景下,是否使用默认的Model private boolean ignoreDefaultModelOnRedirect = false; //缓存注解@SessionAttributes的策略或时间 private int cacheSecondsForSessionAttributeHandlers = 0; //Session属性处理器的工具 private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); //参数名称处理器 private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); //beanFactory @Nullable private ConfigurableBeanFactory beanFactory; //缓存Session属性处理工具类SessionAttributesHandler private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64); //缓存处理器类中@InitBinder注解的方法 private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64); //缓存全局的@InitBinder注解的方法 private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>(); //缓存处理器类中@ModelAttribute注解且没有@RequestMapping注解的方法 private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64); //缓存全局的@ModelAttribute注解且没有@RequestMapping注解的方法 private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>();
属性字段的初始化:
public RequestMappingHandlerAdapter() {
this.messageConverters = new ArrayList<>(4);
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
try {
this.messageConverters.add(new SourceHttpMessageConverter<>());
}
catch (Error err) {
// Ignore when no TransformerFactory implementation is available
}
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}
@Override public void afterPropertiesSet() { //初始化全局的三个变量modelAttributeAdviceCache、initBinderAdviceCache、requestResponseBodyAdvice initControllerAdviceCache(); //初始化argumentResolvers参数,其中getDefaultArgumentResolvers()中定义了一些常用的参数解析器,并提供了自定义参数解析器的载入。 if (this.argumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } //初始化initBinderArgumentResolvers,通过getDefaultInitBinderArgumentResolvers()获取默认的解析器 if (this.initBinderArgumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } //初始化returnValueHandlers,通过getDefaultReturnValueHandlers()方法获取返回值解析器 if (this.returnValueHandlers == null) { List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } }
在initControllerAdviceCache()方法中,完成了modelAttributeAdviceCache、initBinderAdviceCache、requestResponseBodyAdvice三个属性的初始化。其中,initBinderAdviceCache属性缓存了全局定义的@InitBinder注解方法;modelAttributeAdviceCache属性缓存了全局定义的@ModelAttribute注解且没有@RequestMapping注解方法;而requestResponseBodyAdvice缓存了实现了RequestBodyAdvice或ResponseBodyAdvice接口的类。
private void initControllerAdviceCache() { if (getApplicationContext() == null) { return; } //首先,获取带有注解 @ControllerAdvice的所有的类 List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); List<Object> requestResponseBodyAdviceBeans = new ArrayList<>(); //遍历带有注解 @ControllerAdvice的类 for (ControllerAdviceBean adviceBean : adviceBeans) { Class<?> beanType = adviceBean.getBeanType(); if (beanType == null) { throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean); } //查询beanType类中,所有的带有@ModelAttribute注解且没有@RequestMapping注解的方法,并存储到对应的属性中 Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS); if (!attrMethods.isEmpty()) { this.modelAttributeAdviceCache.put(adviceBean, attrMethods); } //查询beanType类中,所有带有@InitBinder注解的方法,并存储到对应的属性中 Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS); if (!binderMethods.isEmpty()) { this.initBinderAdviceCache.put(adviceBean, binderMethods); } //判断当前beanType是否实现了RequestBodyAdvice或ResponseBodyAdvice接口,并存储到定义的局部变量中,后面在存储到requestResponseBodyAdvice变量的最前面 if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) { requestResponseBodyAdviceBeans.add(adviceBean); } } if (!requestResponseBodyAdviceBeans.isEmpty()) { this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans); } //日志处理 if (logger.isDebugEnabled()) { int modelSize = this.modelAttributeAdviceCache.size(); int binderSize = this.initBinderAdviceCache.size(); int reqCount = getBodyAdviceCount(RequestBodyAdvice.class); int resCount = getBodyAdviceCount(ResponseBodyAdvice.class); if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) { logger.debug("ControllerAdvice beans: none"); } else { logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize + " @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice"); } } }
其他属性字段,大都通过getXXX/setXXX方法实现对应属性的获取和设置,这里不再粘贴代码。
核心方法实现
在该类中实现了抽象类中定义的三个方法,其中getLastModifiedInternal()和supportsInternal()方法,只是进行了简单的返回,代码如下:
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {
return -1;
}
在RequestMappingHandlerAdapter类中,handleInternal()方法是用来实现逻辑处理的方法,真正的处理请求又通过调用invokeHandlerMethod()方法进行实现,我们下面逐步分析该方法的实现逻辑:
@Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; //判断是否支持当前request的方法,该方法在WebContentGenerator类中定义,通过内置的supportedMethods属性来进行判断 checkRequest(request); // 判断是否需要在同一会话上启用序列化调用,即序列化来自同一客户端的并行调用。 if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) {//需要序列化执行 //核心的处理方法,后面详细分析 mav = invokeHandlerMethod(request, response, handlerMethod); } } else {//不需要序列化执行 mav = invokeHandlerMethod(request, response, handlerMethod); } } else {//不需要序列化执行 mav = invokeHandlerMethod(request, response, handlerMethod); } //处理请求是否缓存的配置,通过设置响应的HTTP Header实现,实际的实现方法都是在WebContentGenerator类中定义的 if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
invokeHandlerMethod()方法实现了真正的请求处理逻辑,这个方法是该类中最核心最复杂的方法,因为在这里真正实现了从参数解析、处理器逻辑调用、返回值处理等工作,同时为了实现这一系列的功能,使用了很多的组件。代码如下:
@Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { //封装了request, response两个对象 ServletWebRequest webRequest = new ServletWebRequest(request, response); try { //获取创建WebDataBinder实例的工厂类,其中WebDataBinder类用于绑定request参数到JavaBean对象 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); //获取创建Model实例的工厂类,用于Model对象的初始化工作 ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); //根据handlerMethod创建ServletInvocableHandlerMethod实例,而ServletInvocableHandlerMethod本来就继承于HandlerMethod类,只是增加了参数解析、处理器方法调用、返回值解析等逻辑,后续专门分析该类 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); //为invocableMethod实例设置参数解析器 if (this.argumentResolvers != null) { invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } //为invocableMethod实例设置返回值解析器 if (this.returnValueHandlers != null) { invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } //设置前面获取的创建WebDataBinder实例的工厂类 invocableMethod.setDataBinderFactory(binderFactory); //设置参数名称处理器 invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); //创建ModelAndViewContainer对象,该对象承担着整个请求过程中数据的传递工作 ModelAndViewContainer mavContainer = new ModelAndViewContainer(); //初始化"input" flash 属性 mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); //初始化Model的属性 modelFactory.initModel(webRequest, mavContainer, invocableMethod); //设置Redirect场景下,是否使用默认的Model 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()) { Object result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); LogFormatUtils.traceDebug(logger, traceOn -> { String formatted = LogFormatUtils.formatValue(result, !traceOn); return "Resume with async result [" + formatted + "]"; }); invocableMethod = invocableMethod.wrapConcurrentResult(result); } //调用处理器的处理逻辑,在分析ServletInvocableHandlerMethod时,再详细分析,这里只需要知道通过该方法,实现了处理逻辑,并把返回结果存储到了mavContainer实例中了。 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } //构建通用的返回对象ModelAndView实例 return getModelAndView(mavContainer, modelFactory, webRequest); } finally { //设置当前请求已被处理的标识 webRequest.requestCompleted(); } }
前面,介绍了invokeHandlerMethod()方法的核心处理逻辑,下面,我们开始分析其中一些组件的初始化或创建方式。首先,我们分析WebDataBinderFactory创建方法getDataBinderFactory()。
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception { //获取处理器对应的beanType Class<?> handlerType = handlerMethod.getBeanType(); //首先从缓存中获取beanType对应类中,带有注解@InitBinder的方法的集合 Set<Method> methods = this.initBinderCache.get(handlerType); if (methods == null) {//没有的话,然后通过MethodIntrospector.selectMethods()方法获取,并设置到缓存中 methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS); this.initBinderCache.put(handlerType, methods); } List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>(); // 遍历全局的带有注解@InitBinder的方法的集合(在afterPropertiesSet()已经初始化),把符合要求的方法通过createInitBinderMethod()方法创建成InvocableHandlerMethod实例并设置相关属性,并将实例对象添加到局部变量initBinderMethods中 this.initBinderAdviceCache.forEach((clazz, methodSet) -> { if (clazz.isApplicableToBeanType(handlerType)) { Object bean = clazz.resolveBean(); for (Method method : methodSet) { initBinderMethods.add(createInitBinderMethod(bean, method)); } } }); //遍历当前beanType类中带有注解@InitBinder的方法的集合,进行类似全局变量的处理, for (Method method : methods) { Object bean = handlerMethod.getBean(); initBinderMethods.add(createInitBinderMethod(bean, method)); } //创建ServletRequestDataBinderFactory实例对象,通过构造函数创建 return createDataBinderFactory(initBinderMethods); }
然后,ModelFactory工厂类的创建和WebDataBinderFactory类的创建思路,基本一直,这里不再重复分析。然后,是创建ServletInvocableHandlerMethod实例的方法createInvocableHandlerMethod(),直接通过构造函数实现,代码如下:
protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {
return new ServletInvocableHandlerMethod(handlerMethod);
}
最后,又通过调用getModelAndView()方法,实现了根据ModelAndViewContainer实例,创建保存视图和模型对象的ModelAndView实例。具体实现如下:
@Nullable private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { //更新参数到Model modelFactory.updateModel(webRequest, mavContainer); //判断是否已经被处理完成 if (mavContainer.isRequestHandled()) { return null; } ModelMap model = mavContainer.getModel(); //创建ModelAndView 实例 ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (!mavContainer.isViewReference()) {//当不是使用引用时(即不是视图名称的字符串时),设置视图 mav.setView((View) mavContainer.getView()); } if (model instanceof RedirectAttributes) {//判断是否是Redirect类型 //设置flash相关属性 Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); if (request != null) { RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } } return mav; }
至此,我们基本上分析了完了RequestMappingHandlerAdapter类中的相关代码,其中涉及到的ServletInvocableHandlerMethod类及其处理过程调用、WebDataBinder类、ModelAndViewContainer类和Model类、参数解析器、返回值解析器等组件并没有深入组件内部展开进行分析,后续我们将逐步分析这些组件的初始化过程和使用的逻辑。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。