Серия анализов исходного кода SpringMVC:
- Анализ исходного кода SpringMVC (1) — процесс запуска
- Анализ исходного кода SpringMVC (2) — DispatcherServlet
- Анализ исходного кода SpringMVC (3) — HandleMapping
- Анализ исходного кода SpringMVC (4) — HandlerAdapter
- Анализ исходного кода SpringMVC (5) — HandlerExceptionResolver
- Анализ исходного кода SpringMVC (6) — асинхронный запрос
Процесс загрузки
Общий метод настройки в web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>CtrTimeOut</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
# spring的配置
<param-value>classpath:config/spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
# springmvc的配置
<param-value>classpath:config/spring/spring-controller.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
ContextLoadListener создает WebApplicationContext как контекст контейнера Spring
#org.springframework.web.context.ContextLoader
/**
* 根据xml配置创建applicationContext
*/
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
...
try {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
if (this.context == null) {//判空 (以注解方式配置时非空)
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
...
//读取contextConfigLocation配置并refresh()
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
//将applicationContext设置到servletContext中
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
...
return this.context;
}
}
DispatcherServlet создает WebApplicationContext как контекст springmvc и устанавливает контекст, созданный ContextLoadListener, в качестве своего родителя.
DispatcherServlet extends FrameworkServlet
#org.springframework.web.servlet.FrameworkServlet
@Override
protected final void initServletBean() throws ServletException {
...
try {
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
...
}
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
...
if (wac == null) {
//创建applicationContext
wac = createWebApplicationContext(rootContext);
}
...
return wac;
}
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
//XmlWebApplicationContext
Class<?> contextClass = getContextClass();
...
//创建applicationContext
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setEnvironment(getEnvironment());
//设置parent(ContextLoadListener中创建的applicationContext)
wac.setParent(parent);
//读取contextConfigLocation配置
wac.setConfigLocation(getContextConfigLocation());
//refresh()
configureAndRefreshWebApplicationContext(wac);
return wac;
}
Контекст приложения springmvc будет читать файл конфигурации.Давайте посмотрим на самый простой файл конфигурации.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
default-autowire="byName">
#springmvc容器扫描路径
<context:component-scan base-package="com.iflytek.ossp.ctrtimeout.controller"></context:component-scan>
#spring4新增的标签 主要是添加了默认的HandleMappin,ViewResolver,HandleAdapter
<mvc:annotation-driven />
</beans>
анализ конфигурации springMvc
Согласно пользовательскому механизму разбора схемы Spring, мы находим его на следующем рисунке.
http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
Вы можете видеть, что здесь определены все парсеры тегов mvc.
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("velocity-configurer", new VelocityConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
}
}
Давайте посмотрим, что делает анализатор AnnotationDrivenBeanDefinitionParser.
Процесс синтаксического анализа более сложен, благодаря аннотации мы можем узнать, что будут загружены следующие объекты
Процесс вызова DispatcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//1.调用handlerMapping获取handlerChain
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// 2.获取支持该handler解析的HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
...
// 3.使用HandlerAdapter完成handler处理
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 4.视图处理(页面渲染)
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
...
}
Обзор процесса:
- Вызовите HandleMapping, чтобы получить обработчик
- Вызовите HandleAdapter для выполнения процедуры дескриптора (вызов процедуры разрешения параметров)
- Вызов ViewResolver для просмотра разрешения
- визуализировать представление
上述图片来自网络
HandleMapping
определение: Управление сопоставлением обработки запросов
Аналогия заключается в том, чтобы получить обработчик (метод вашего контроллера), который может быть обработан в соответствии с путем вашего http-запроса.
/**
* Interface to be implemented by objects that define a mapping between
* requests and handler objects.
*/
public interface HandlerMapping {
//根据request获取处理链
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
Взяв за пример RequestMappingHandlerMapping, давайте посмотрим на его отношения наследования.
Вы можете видеть, что есть InitlizingBean (интерфейс жизненного цикла Spring), с него мы и начнем
#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
//1.
@Override
public void afterPropertiesSet() {
if (this.useRegisteredSuffixPatternMatch) {
this.fileExtensions.addAll(this.contentNegotiationManager.getAllFileExtensions());
}
super.afterPropertiesSet();
}
//4.
@Override
protected boolean isHandler(Class<?> beanType) {
return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
}
//6.
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = null;
RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
if (methodAnnotation != null) {
//组装映射信息
RequestCondition<?> methodCondition = getCustomMethodCondition(method);
info = createRequestMappingInfo(methodAnnotation, methodCondition);
RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
if (typeAnnotation != null) {
RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
}
}
return info;
}
#org.springframework.web.servlet.handler.AbstractHandlerMethodMapping
//2.
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
/**
* Scan beans in the ApplicationContext, detect and register handler methods.
* @see #isHandler(Class)
* @see #getMappingForMethod(Method, Class)
* @see #handlerMethodsInitialized(Map)
*/
//3.
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
//从容器中获取所有object类型名
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
for (String beanName : beanNames) {
//抽象,过滤(在RequestMappingHandlerMapping中根据Controller和RequestMapping注解过滤)
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX) &&
isHandler(getApplicationContext().getType(beanName))){
//探测类中定义的handler方法
detectHandlerMethods(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
//5.
protected void detectHandlerMethods(final Object handler) {
Class<?> handlerType =
(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());
final Map<Method, T> mappings = new IdentityHashMap<Method, T>();
final Class<?> userType = ClassUtils.getUserClass(handlerType);
//得到符合条件的handler方法
Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
@Override
public boolean matches(Method method) {
//抽象,得到映射信息(如RequestMappingInfo)
T mapping = getMappingForMethod(method, userType);
if (mapping != null) {
mappings.put(method, mapping);
return true;
}
else {
return false;
}
}
});
//注册handler方法
for (Method method : methods) {
registerHandlerMethod(handler, method, mappings.get(method));
}
}
Приведенный выше код является кодом для HandlerMapping для инициализации отношения сопоставления.
Обзор процесса:
- Получить все подклассы объектов
- Отфильтровать классы обработки дескрипторов на основе условий
- Разберите метод обработки, определенный в классе дескриптора.
- Сохраните проанализированное отношение сопоставления
Давайте взглянем на реализацию метода getHandler(Request) и посмотрим, как DispatcherServlet получает цепочку обработки.
#org.springframework.web.servlet.handler.AbstractHandlerMapping
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//抽象,调用子类实现得到一个handler(可以是任一对象,需要通过HandleAdapter来解析)
//RequestMappingInfoHandlerMapping中具体实现就是匹配请求路径和RequestMapping注解
Object handler = getHandlerInternal(request);
...
//包装handle成HandlerExecutionChain
return getHandlerExecutionChain(handler, request);
}
HandleAdapter
определение: Анализ и привязка параметров http-запроса в соответствии с информацией об обработчике, полученной с помощью HandlerMapping.getHandler().
Сначала взгляните на определение интерфейса HandlerAdapter.
public interface HandlerAdapter {
//判断是否支持该handler类型的解析
boolean supports(Object handler);
//参数解析 并调用handler完成过程调用
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
//用于处理http请求头中的last-modified
long getLastModified(HttpServletRequest request, Object handler);
}
Взяв в качестве примера RequestMappingHandlerAdapter, давайте сначала рассмотрим отношения наследования.
Я также видел реализацию интерфейса InitializingBean.
#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
@Override
public void afterPropertiesSet() {
// 1.初始化ControllerAdvice注解的对象
initControllerAdviceCache();
// 2.装载ArgumentResolver(默认+自定义)
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
//包装成一个Composite对象
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// 2.装载InitBinderArgumentResolvers(默认+自定义)
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
//包装成一个Composite对象
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// 3.装载ReturnValueHandlers(默认+自定义)
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
//包装成一个Composite对象
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
private void initControllerAdviceCache() {
//从容器中获取所有带有ControllerAdvices注解的类名 并包装成ControllerAdviceBean
List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
OrderComparator.sort(beans);
List<Object> responseBodyAdviceBeans = new ArrayList<Object>();
for (ControllerAdviceBean bean : beans) {
//筛选出带有ModelAttribute且不带RequestMapping注解的方法
Set<Method> attrMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
//保存到map中
this.modelAttributeAdviceCache.put(bean, attrMethods);
}
//筛选出带InitBinder注解的方法
Set<Method> binderMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
//保存到map中
this.initBinderAdviceCache.put(bean, binderMethods);
}
//如果该类同时实现了ResponseBodyAdvice接口 添加到结合中
if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
responseBodyAdviceBeans.add(bean);
}
}
//保存到全局变量中
if (!responseBodyAdviceBeans.isEmpty()) {
this.responseBodyAdvice.addAll(0, responseBodyAdviceBeans);
}
}
Обзор процесса:
- Загрузите объект, аннотированный с помощью ControllerAdvices
- Загрузить ArgumentResolvers (по умолчанию + пользовательский)
- Загрузить InitBinderArgumentResolvers (по умолчанию + пользовательский)
- Загрузить обработчики ReturnValueHandler (по умолчанию + пользовательский)
自定义拓展方式放后面说
Ниже приведен парсер по умолчанию для HandlerAdapter.
посмотриHandlerMethodReturnValueHandlerинтерфейс и интерфейс HandlerMethodArgumentResolver
//参数解析器
public interface HandlerMethodArgumentResolver {
//判断是否支持该参数的解析(根据类型,注解等)
boolean supportsParameter(MethodParameter parameter);
//对参数进行解析 得到解析结果
Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
}
//返回值解析器
public interface HandlerMethodReturnValueHandler {
//判断是否支持该返回值的解析(根据类型,注解等)
boolean supportsReturnType(MethodParameter returnType);
//对返回值进行解析
void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}
Выше приведен процесс инициализации HandlerAdapter.
DispatcherServlet вызывает процесс HandlerAdapter
//1.调用support()方法判断是否支持改handler的解析
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 如果是Get或Head请求 调用getLastModified()获取上次更新时间
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
//如果小于浏览器缓存更新时间 则直接返回 浏览器使用本地缓存
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
DispatcherServlet вызывает handleradapper, разделенный на три этапа.:
- Вызовите метод support(), чтобы определить, поддерживается ли синтаксический анализ измененного обработчика.
#org.springframework.web.servlet.DispatcherServlet
//在doDispatch()方法中调用了getHandlerAdapter(Object)方法来得到一个HandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
//调用HandlerAdapter.support()方法 判断是否支持该handler对象的解析
for (HandlerAdapter ha : this.handlerAdapters) {
...
if (ha.supports(handler)) {
return ha;
}
}
...
}
#org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter
@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
- Если это запрос Get или Head, вызовите getLastModified(), чтобы получить время последнего обновления.
如果小于浏览器缓存更新时间 则直接返回 浏览器使用本地缓存
#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
@Override
protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {
return -1;
}
- Вызвать метод handler() для завершения вызова процедуры (анализ параметра и анализ возвращаемого значения)
#org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter
@Override
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//对http协议缓存方面的请求头的处理(expire,cache-control)
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
// Always prevent caching in case of session attribute management.
checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
}
else {
// Uses configured default cacheSeconds setting.
checkAndPrepare(request, response, true);
}
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {//是否使用session锁
HttpSession session = request.getSession(false);
if (session != null) {
//得到互斥量
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {//执行过程调用
return invokeHandleMethod(request, response, handlerMethod);
}
}
}
//执行过程调用
return invokeHandleMethod(request, response, handlerMethod);
}
//根据HandlerMethod解析参数 并完成过程调用得到一个ModelAndView
private ModelAndView invokeHandleMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
//使用initBinderAdviceCache对@initBinder进行处理
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
// 使用modelAttributeAdviceCache对@ModelAttribute进行处理
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
//对异步的处理 暂时不管 TODO后面再分析
...
//1 完成过程调用
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
//2 包装ModelAndView
return getModelAndView(mavContainer, modelFactory, webRequest);
}
резюме процесса handle():
- Процесс выполнения вызывает requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
#org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod
public void invokeAndHandle(ServletWebRequest webRequest,
ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 1.1 参数解析 并完成过程调用
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
...
try {
//1.2 使用returnValueHandlers对返回结果进行处理 讲结果塞到mavContainer中 过程类似参数解析
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
}
#org.springframework.web.method.support.InvocableHandlerMethod
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//1.1.1 参数解析并得到绑定的结果
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
...
//1.1.2 反射完成过程调用
Object returnValue = doInvoke(args);
...
return returnValue;
}
private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//参数信息
MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
//调用HandlerMethodArgumentResolver#supportsParameter判断是否支持
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
//调用HandlerMethodArgumentResolver#resolveArgument进行解析
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
}
...
}
...
}
return args;
}
- Обернуть ModelAndView getModelAndView(mavContainer, modelFactory, webRequest);
//从mavContainer取出结果 包装成ModelAndView
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
modelFactory.updateModel(webRequest, mavContainer);
if (mavContainer.isRequestHandled()) {
return null;
}
ModelMap model = mavContainer.getModel();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
//如果是redirect请求
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
return mav;
}
На этом этапе анализируется вызывающий процесс HandlerAdapter.