handler 执行
之前的文章介绍到,当根据请求找到对应的handler之后,会根据这个handler找到对应的HandlerAdapter,解析来会调用handle方法来处理请求
// DispatcherServlet.java
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
handle
接下来看下HandlerAdapter是如何执行的
当调用handle时,主要会调用handleInternal方法
// RequestMappingHandlerAdapter.java
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// Execute invokeHandlerMethod in synchronized block if required.
// 判断是否设置了synchronizeOnSession
// 如果设置了,那么对于同一个session,会同步执行
// 默认这个是关闭的
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
接下来看下invokeHandlerMethod
handler处理请求返回ModelAndView就是在这个地方进行的
// RequestMappingHandlerAdapter.java
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
// WebDataBinder的工厂, WebDataBinder用来将web请求中的参数绑定到java对象上
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
// 如果指定了HandlerMethodArgumentResolverComposite,那么设置到invocableMethod上
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
// 如果指定了HandlerMethodReturnValueHandlerComposite,那么设置到invocableMethod上
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
// 这里会将通过使用@SessionAttributes注解指定的session属性,设置到model中
// 另外会执行@ModelAttributes注解的方法,在真正执行处理逻辑之前,将一些属性添加到model中
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()) {
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);
}
// 执行处理逻辑
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
// 获取ModelAndView
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
getDataBinderFactory
// RequestMappingHandlerAdapter.java
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
// 返回handler的类型
Class<?> handlerType = handlerMethod.getBeanType();
// 获取当前handler可以使用的属性编辑器,包括全局的和当前handler自有的
// @InitBinder用来为当前handler指定使用的属性编辑器,即如何将请求中的参数转换为java对象
Set<Method> methods = this.initBinderCache.get(handlerType);
if (methods == null) {
methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
this.initBinderCache.put(handlerType, methods);
}
List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
// Global methods first
// 首先会获取全局的InitBinder,即在使用了@ControllerAdvice注解的类中使用了@InitBinder注解的方法,将这些InitBinder添加到initBinderMethods集合中
this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
// 判断指定的ControllerAdvice是否能够作用到当前类
// 通过@ControllerAdvice注解的basePackage basePackageClass assignableType annontation等属性来判断
if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
Object bean = controllerAdviceBean.resolveBean();
for (Method method : methodSet) {
initBinderMethods.add(createInitBinderMethod(bean, method));
}
}
});
// 处理当前handler中使用了@InitBinder注解的方法
for (Method method : methods) {
Object bean = handlerMethod.getBean();
initBinderMethods.add(createInitBinderMethod(bean, method));
}
return createDataBinderFactory(initBinderMethods);
}
接着看下createInitBinderMethod方法,该方法用来对当前bean和待执行的方法创建一个InvocableHanderMethod
// RequestMappingHandlerAdapter.java
private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {
InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);
if (this.initBinderArgumentResolvers != null) {
binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
}
binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));
binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
return binderMethod;
}
getModelFactory
和上面相同的方法来处理@ModelAttribute注解
// RequestMappingHandlerAdapter.java
private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
Class<?> handlerType = handlerMethod.getBeanType();
Set<Method> methods = this.modelAttributeCache.get(handlerType);
if (methods == null) {
methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
this.modelAttributeCache.put(handlerType, methods);
}
List<InvocableHandlerMethod> attrMethods = new ArrayList<>();
// Global methods first
this