一:springMvc启动流程:
1.1 容器一启动或者关闭,会触发监听器:ServletContextListener 的事件(实现 EventListener接口),ServletContextListener接口含有两个方法:
contextInitialized()以及 contextDestroyed() 分别是容器(tomcat)启动以及销毁时调用。其他实现了ServletContextListener接口的,都能监听到此事件。如 ShutdownListener:专门监听关闭事件以及 ContextLoadListener : springMvc的web.xml中需要配置该监听器,
<!-- Spring配置文件开始 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring配置文件结束 -->
主要是用于监听spring配置文件初始化情况
1.2 DispatcherServlet启动时,加载配置:
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
里面的 initThemeResolver 初始化主题解析:后台代码:
<!--theme-->
<bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource">
<!--加载资源-->
<property name="basenamePrefix" value="theme."/>
</bean>
<!-- 【可选】 -->
<!-- 默认情况下,使用的是 FixedThemeResolver 来确定主题名字,默认名字为 theme -->
<!-- 可以根据实际情况配置为 SessionThemeResovler/CookieThemeResolver -->
<bean id="themeResolver" class="org.springframework.web.servlet.theme.SessionThemeResolver">
<!--默认主题文件的名字是 "xxxx",如果不设置,名为 theme-->
<property name="defaultThemeName" value="default"/>
</bean>
package com.oukele.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ThemeResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
public class ThemeController {
//将theme注入容器中
@Autowired
private ThemeResolver themeResolver;
/**
* 返回一个页面
* */
@GetMapping(path = "/th")
public String getPage(){
return "theme1";
}
/**
*请求方式:GET
* 参数:theme
* 请求url:/th/对应主题的文件
*/
@RequestMapping(path = "th/{theme}",method = RequestMethod.GET)
public String theme1(@PathVariable("theme") String themeStr,HttpServletRequest request,HttpServletResponse response){
themeResolver.setThemeName(request,response, themeStr);
return "redirect:/th";
}
}
二:解析 initHandlerMappings(路径映射)
2.1 通过 context 获取 DispatcherServlet 的属性 private List<HandlerMapping> handlerMappings;
其中 handlerMappings 初始化后类型有四个:RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping(0,1),应该是用于初始化 handlerMapping的策略
三:解析 initHandlerAdapters
3.1 通过 context 转化的 beanFactory 中获取 DispatcherServlet 的属性 private List<HandlerAdapter> handlerAdapters;
其中 handlerAdapters 初始化后的类型(策略)有:RequestMappingHandlerAdapter、HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter
四:解析 initHandlerExceptionResolvers
4.1 通过 context 转化的 beanFactory 中获取 DispatcherServlet 的属性 private List<HandlerExceptionResolver> handlerExceptionResolvers;
其中 handlerExceptionResolvers初始化后的类型(策略)有:ExceptionHandlerExceptionResolvers、ResponseStatusExceptionResolvers、DefaultHandlerExceptionResolvers、SimpleMappingExceptionResolvers
五:解析 initViewResolvers
属性为:private List<ViewResolver> viewResolvers;
其中 viewResolver初始化后的类型(策略)有:
默认viewResolver 解析后 ,会包含设置的前后缀:
其中的前后缀是通过配置:
<bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:order="1">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="contentType" value="text/html"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
来获取到的,默认加载此实现类。
所有请求都是先到达 DispatcherServlet,(调用其父类 FrameworkServlet 的service方法,从而)调用其 doDispatch()方法来进行处理
try {
this.doService(request, response);
} catch (ServletException var17) {
然后获取 HandlerExecutionChain 对象:
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
在这个过程中,先通过 httpServletReqest 对象获取 HandlerMethod 对象 :形式:
public java.util.Map com.bestpay.bigdata.ops.web.controller.IndexController.getPermAndBtList()
该handlerMethod包含该类所在的controller以及方法,并从beanFactory中通过类名获取实例:handler
初始化过程:
private HandlerMethod(HandlerMethod handlerMethod, Object handler) {
Assert.notNull(handlerMethod, "HandlerMethod is required");
Assert.notNull(handler, "Handler object is required");
this.bean = handler;
this.beanFactory = handlerMethod.beanFactory;
this.method = handlerMethod.method;
this.bridgedMethod = handlerMethod.bridgedMethod;
this.parameters = handlerMethod.parameters;
}
也就是说 handlerMethod对象中的属性 this.bean就是上面解析出来的handler, this.method 就是通过request获取
的方法,以及parameters等等
代码:
public HandlerMethod createWithResolvedBean() {
Object handler = this.bean;
if (this.bean instanceof String) {
String beanName = (String)this.bean;
handler = this.beanFactory.getBean(beanName);
}
this.bean 就是当前请求(request)获取的类,如:indexController
此时下面 的handler就是上面返回的 handlerMethod对象
return this.getHandlerExecutionChain(handler, request);
该方法内部:
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler);
chain.addInterceptors(this.getAdaptedInterceptors());
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
通过new HandlerExecutionChain(hanler)构造包装
public HandlerExecutionChain(Object handler, HandlerInterceptor[] interceptors) {
this.interceptorIndex = -1;
if (handler instanceof HandlerExecutionChain) {
HandlerExecutionChain originalChain = (HandlerExecutionChain)handler;
this.handler = originalChain.getHandler();
把原先的 handlerMethod对象,封装成自身的一个属性 handler(包装在handlerExecutionChain对象在,也叫handler)
然后通过方法:
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
获取 handlerAdapter 对象,过程:循环 上述三种类型的 handlerAdapter,然后通过下面代码:
Iterator var2 = this.handlerAdapters.iterator();
HandlerAdapter ha;
this.logger.trace("Testing handler adapter [" + ha + "]");
}
} while(!ha.supports(handler));
public boolean supports(Object handler) {
return handler instanceof HttpRequestHandler;
}
return handler instanceof Servlet;
}
return handler instanceof Controller
}
也就是循环判断三种类型,当前的 handler(也就是上面的 handlerMethod)是哪种类型的handler,获取对应类型
的 handlerAdapter