在tomcat中,web.xml是项目的描述文件:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- DispatcherServlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
首先定义了一个Servlet容器,DispatcherServlet在MVC中起到了分发请求的作用,定义了匹配的url的规则。
然后定义了一个监听器ContextLoaderListener,负责IoC容器在web环境的加载。
(宿主环境便是ServletContext)
IoC容器的启动
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
private ContextLoader contextLoader;
...
// 如果ServletContext发生变化是,会触发相应的事件
// Context创建时执行
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = this.createContextLoader();
if(this.contextLoader == null) {
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
...
}
public class ContextLoader {
...
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
// 判断根上下文是否存在
throw new IllegalStateException("Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!");
} else {
Log logger = LogFactory.getLog(ContextLoader.class);
servletContext.log("Initializing Spring root WebApplicationContext");
long startTime = System.currentTimeMillis();
try {
if(this.context == null) {
// 创建WebApplicationContext
this.context = this.createWebApplicationContext(servletContext);
}
if(this.context instanceof ConfigurableWebApplicationContext) {
// 双亲IoC容器的建立 this.configureAndRefreshWebApplicationContext((ConfigurableWebApplicationContext)this.context, servletContext);
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader err = Thread.currentThread().getContextClassLoader();
if(err == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
} else if(err != null) {
currentContextPerThread.put(err, this.context);
}
return this.context;
}
...
}
}
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
// 决定根上下文的类型
Class contextClass = this.determineContextClass(sc);
if(!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
} else {
ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
return wac;
}
}
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
if(ObjectUtils.identityToString(wac).equals(wac.getId())) {
String parent = sc.getInitParameter("contextId");
if(parent != null) {
wac.setId(parent);
} else if(sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getServletContextName()));
} else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
ApplicationContext parent1 = this.loadParentContext(sc);
wac.setParent(parent1);
wac.setServletContext(sc);
String initParameter = sc.getInitParameter("contextConfigLocation");
if(initParameter != null) {
wac.setConfigLocation(initParameter);
}
this.customizeContext(sc, wac);
wac.refresh();
}
...
}
WebApplicationContext
public interface WebApplicationContext extends ApplicationContext {
// 为了存取根上下文而设置的常量
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
String SCOPE_REQUEST = "request";
String SCOPE_SESSION = "session";
String SCOPE_GLOBAL_SESSION = "globalSession";
String SCOPE_APPLICATION = "application";
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
ServletContext getServletContext();
}
默认WebApplicationContext为XmlWebApplicationContext
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
// 默认路径和后缀
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
...
// 和分析IoC源码时的loadBeanDefinitions函数一样,在refresh()时启动
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// IoC的定位、载入和注册
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
// 对bean进行解析、加载、注册,参考ioc
this.loadBeanDefinitions(beanDefinitionReader);
}
// 多个配置文件
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = this.getConfigLocations();
if(configLocations != null) {
String[] var6 = configLocations;
int var5 = configLocations.length;
for(int var4 = 0; var4 < var5; ++var4) {
String configLocation = var6[var4];
reader.loadBeanDefinitions(configLocation);
}
}
}
// Resource的位置
protected String[] getDefaultConfigLocations() {
return this.getNamespace() != null?new String[]{"/WEB-INF/" + this.getNamespace() + ".xml"}:new String[]{"/WEB-INF/applicationContext.xml"};
}
}
DispatcherServlet上下文初始化:
FrameworkServlet继承HttpServletBean,初始化的时候执行。
HttpServletBean初始化init()
public final void init() throws ServletException {
try {
HttpServletBean.ServletConfigPropertyValues ex = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ServletContextResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
this.initBeanWrapper(bw);
bw.setPropertyValues(ex, true);
}
...
// 子类实现
this.initServletBean();
}
FramworkServlet实现的initServletBean方法
protected final void initServletBean() throws ServletException {
long startTime = System.currentTimeMillis();
// 初始化上下文
try {
this.webApplicationContext = this.initWebApplicationContext();
this.initFrameworkServlet();
}
...
}
//
protected WebApplicationContext initWebApplicationContext() {
// WebApplicationContextUtils静态类获取上下文
// 使用这个根上下文作文当前mvc上下文的双亲上下文
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
WebApplicationContext wac = null;
if(this.webApplicationContext != null) {
wac = this.webApplicationContext;
if(wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext attrName = (ConfigurableWebApplicationContext)wac;
if(!attrName.isActive()) {
if(attrName.getParent() == null) {
attrName.setParent(rootContext);
}
this.configureAndRefreshWebApplicationContext(attrName);
}
}
}
if(wac == null) {
wac = this.findWebApplicationContext();
}
if(wac == null) {
wac = this.createWebApplicationContext(rootContext);
}
if(!this.refreshEventReceived) {
this.onRefresh(wac);
}
if(this.publishContext) {
String attrName1 = this.getServletContextAttributeName();
this.getServletContext().setAttribute(attrName1, wac);
...
}
return wac;
}
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
return this.createWebApplicationContext((ApplicationContext)parent);
}
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
Class contextClass = this.getContextClass();
if(!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Fatal initialization error in servlet with name \'" + this.getServletName() + "\': custom WebApplicationContext class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext");
} else {
ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
// 设置双亲上下文,就是ContextLoader建立的上下文
wac.setParent(parent);
wac.setConfigLocation(this.getContextConfigLocation());
this.configureAndRefreshWebApplicationContext(wac);
return wac;
}
}
WebApplicationContextUtils
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
DispatcherServlet 的作用,初始化部分如HandlerMapping、ViewResolver等和分发请求。
public class DispatcherServlet extends FrameworkServlet {
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";
public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";
public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver";
public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator";
public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";
public static final String FLASH_MAP_MANAGER_BEAN_NAME = "flashMapManager";
public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName() + ".CONTEXT";
public static final String LOCALE_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".LOCALE_RESOLVER";
public static final String THEME_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_RESOLVER";
public static final String THEME_SOURCE_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_SOURCE";
public static final String INPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".INPUT_FLASH_MAP";
public static final String OUTPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".OUTPUT_FLASH_MAP";
public static final String FLASH_MAP_MANAGER_ATTRIBUTE = DispatcherServlet.class.getName() + ".FLASH_MAP_MANAGER";
public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound";
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
protected static final Log pageNotFoundLogger = LogFactory.getLog("org.springframework.web.servlet.PageNotFound");
private static final UrlPathHelper urlPathHelper = new UrlPathHelper();
private static final Properties defaultStrategies;
private boolean detectAllHandlerMappings = true;
private boolean detectAllHandlerAdapters = true;
private boolean detectAllHandlerExceptionResolvers = true;
private boolean detectAllViewResolvers = true;
private boolean cleanupAfterInclude = true;
private MultipartResolver multipartResolver;
private LocaleResolver localeResolver;
private ThemeResolver themeResolver;
private List<HandlerMapping> handlerMappings;
private List<HandlerAdapter> handlerAdapters;
private List<HandlerExceptionResolver> handlerExceptionResolvers;
private RequestToViewNameTranslator viewNameTranslator;
private FlashMapManager flashMapManager;
private List<ViewResolver> viewResolvers;
static {
try {
ClassPathResource ex = new ClassPathResource("DispatcherServlet.properties", DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(ex);
} catch (IOException var1) {
throw new IllegalStateException("Could not load \'DispatcherServlet.properties\': " + var1.getMessage());
}
}
public DispatcherServlet() {
}
public DispatcherServlet(WebApplicationContext webApplicationContext) {
super(webApplicationContext);
}
public void setDetectAllHandlerMappings(boolean detectAllHandlerMappings) {
this.detectAllHandlerMappings = detectAllHandlerMappings;
}
public void setDetectAllHandlerAdapters(boolean detectAllHandlerAdapters) {
this.detectAllHandlerAdapters = detectAllHandlerAdapters;
}
public void setDetectAllHandlerExceptionResolvers(boolean detectAllHandlerExceptionResolvers) {
this.detectAllHandlerExceptionResolvers = detectAllHandlerExceptionResolvers;
}
public void setDetectAllViewResolvers(boolean detectAllViewResolvers) {
this.detectAllViewResolvers = detectAllViewResolvers;
}
public void setCleanupAfterInclude(boolean cleanupAfterInclude) {
this.cleanupAfterInclude = cleanupAfterInclude;
}
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}
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);
}
private void initMultipartResolver(ApplicationContext context) {
try {
this.multipartResolver = (MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class);
} catch (NoSuchBeanDefinitionException var2) {
this.multipartResolver = null;
}
}
private void initLocaleResolver(ApplicationContext context) {
try {
this.localeResolver = (LocaleResolver)context.getBean("localeResolver", LocaleResolver.class);
} catch (NoSuchBeanDefinitionException var2) {
this.localeResolver = (LocaleResolver)this.getDefaultStrategy(context, LocaleResolver.class);
}
}
private void initThemeResolver(ApplicationContext context) {
try {
this.themeResolver = (ThemeResolver)context.getBean("themeResolver", ThemeResolver.class);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Using ThemeResolver [" + this.themeResolver + "]");
}
} catch (NoSuchBeanDefinitionException var2) {
this.themeResolver = (ThemeResolver)this.getDefaultStrategy(context, ThemeResolver.class);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Unable to locate ThemeResolver with name \'themeResolver\': using default [" + this.themeResolver + "]");
}
}
}
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if(this.detectAllHandlerMappings) {
Map hm = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if(!hm.isEmpty()) {
this.handlerMappings = new ArrayList(hm.values());
OrderComparator.sort(this.handlerMappings);
}
} else {
try {
HandlerMapping hm1 = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm1);
} catch (NoSuchBeanDefinitionException var3) {
;
}
}
if(this.handlerMappings == null) {
this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
}
}
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
if(this.detectAllHandlerAdapters) {
Map ha = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if(!ha.isEmpty()) {
this.handlerAdapters = new ArrayList(ha.values());
OrderComparator.sort(this.handlerAdapters);
}
} else {
try {
HandlerAdapter ha1 = (HandlerAdapter)context.getBean("handlerAdapter", HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha1);
} catch (NoSuchBeanDefinitionException var3) {
;
}
}
if(this.handlerAdapters == null) {
this.handlerAdapters = this.getDefaultStrategies(context, HandlerAdapter.class);
}
}
private void initHandlerExceptionResolvers(ApplicationContext context) {
this.handlerExceptionResolvers = null;
if(this.detectAllHandlerExceptionResolvers) {
Map her = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
if(!her.isEmpty()) {
this.handlerExceptionResolvers = new ArrayList(her.values());
OrderComparator.sort(this.handlerExceptionResolvers);
}
} else {
try {
HandlerExceptionResolver her1 = (HandlerExceptionResolver)context.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);
this.handlerExceptionResolvers = Collections.singletonList(her1);
} catch (NoSuchBeanDefinitionException var3) {
;
}
}
if(this.handlerExceptionResolvers == null) {
this.handlerExceptionResolvers = this.getDefaultStrategies(context, HandlerExceptionResolver.class);
}
}
private void initRequestToViewNameTranslator(ApplicationContext context) {
try {
this.viewNameTranslator = (RequestToViewNameTranslator)context.getBean("viewNameTranslator", RequestToViewNameTranslator.class);
} catch (NoSuchBeanDefinitionException var2) {
this.viewNameTranslator = (RequestToViewNameTranslator)this.getDefaultStrategy(context, RequestToViewNameTranslator.class);
}
}
private void initViewResolvers(ApplicationContext context) {
this.viewResolvers = null;
if(this.detectAllViewResolvers) {
Map vr = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
if(!vr.isEmpty()) {
this.viewResolvers = new ArrayList(vr.values());
OrderComparator.sort(this.viewResolvers);
}
} else {
try {
ViewResolver vr1 = (ViewResolver)context.getBean("viewResolver", ViewResolver.class);
this.viewResolvers = Collections.singletonList(vr1);
} catch (NoSuchBeanDefinitionException var3) {
;
}
}
if(this.viewResolvers == null) {
this.viewResolvers = this.getDefaultStrategies(context, ViewResolver.class);
}
}
private void initFlashMapManager(ApplicationContext context) {
try {
this.flashMapManager = (FlashMapManager)context.getBean("flashMapManager", FlashMapManager.class);
} catch (NoSuchBeanDefinitionException var2) {
this.flashMapManager = (FlashMapManager)this.getDefaultStrategy(context, FlashMapManager.class);
}
}
public final ThemeSource getThemeSource() {
return this.getWebApplicationContext() instanceof ThemeSource?(ThemeSource)this.getWebApplicationContext():null;
}
public final MultipartResolver getMultipartResolver() {
return this.multipartResolver;
}
protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
List strategies = this.getDefaultStrategies(context, strategyInterface);
if(strategies.size() != 1) {
throw new BeanInitializationException("DispatcherServlet needs exactly 1 strategy for interface [" + strategyInterface.getName() + "]");
} else {
return strategies.get(0);
}
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
String key = strategyInterface.getName();
String value = defaultStrategies.getProperty(key);
if(value == null) {
return new LinkedList();
} else {
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
ArrayList strategies = new ArrayList(classNames.length);
String[] var10 = classNames;
int var9 = classNames.length;
for(int var8 = 0; var8 < var9; ++var8) {
String className = var10[var8];
try {
Class err = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
Object strategy = this.createDefaultStrategy(context, err);
strategies.add(strategy);
} catch (ClassNotFoundException var13) {
throw new BeanInitializationException("Could not find DispatcherServlet\'s default strategy class [" + className + "] for interface [" + key + "]", var13);
} catch (LinkageError var14) {
throw new BeanInitializationException("Error loading DispatcherServlet\'s default strategy class [" + className + "] for interface [" + key + "]: problem with class file or dependent class", var14);
}
}
return strategies;
}
}
protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {
return context.getAutowireCapableBeanFactory().createBean(clazz);
}
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if(this.logger.isDebugEnabled()) {
String attributesSnapshot = urlPathHelper.getRequestUri(request);
this.logger.debug("DispatcherServlet with name \'" + this.getServletName() + "\' processing " + request.getMethod() + " request for [" + attributesSnapshot + "]");
}
HashMap attributesSnapshot1 = null;
if(WebUtils.isIncludeRequest(request)) {
this.logger.debug("Taking snapshot of request attributes before include");
attributesSnapshot1 = new HashMap();
Enumeration inputFlashMap = request.getAttributeNames();
label90:
while(true) {
String attrName;
do {
if(!inputFlashMap.hasMoreElements()) {
break label90;
}
attrName = (String)inputFlashMap.nextElement();
} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
attributesSnapshot1.put(attrName, request.getAttribute(attrName));
}
}
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
FlashMap inputFlashMap1 = this.flashMapManager.retrieveAndUpdate(request, response);
if(inputFlashMap1 != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap1));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
this.doDispatch(request, response);
} finally {
if(attributesSnapshot1 != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot1);
}
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
try {
boolean var25 = false;
ModelAndView err;
try {
label276: {
processedRequest = this.checkMultipart(request);
mappedHandler = this.getHandler(processedRequest, false);
if(mappedHandler != null && mappedHandler.getHandler() != null) {
HandlerAdapter ex1 = this.getHandlerAdapter(mappedHandler.getHandler());
String var26 = request.getMethod();
boolean isGet = "GET".equals(var26);
if(isGet || "HEAD".equals(var26)) {
long interceptors = ex1.getLastModified(request, mappedHandler.getHandler());
if(this.logger.isDebugEnabled()) {
String interceptor = urlPathHelper.getRequestUri(request);
this.logger.debug("Last-Modified value for [" + interceptor + "] is: " + interceptors);
}
if((new ServletWebRequest(request, response)).checkNotModified(interceptors) && isGet) {
return;
}
}
HandlerInterceptor[] var27 = mappedHandler.getInterceptors();
int i;
HandlerInterceptor var28;
if(var27 != null) {
for(i = 0; i < var27.length; interceptorIndex = i++) {
var28 = var27[i];
if(!var28.preHandle(processedRequest, response, mappedHandler.getHandler())) {
this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, (Exception)null);
return;
}
}
}
err = ex1.handle(processedRequest, response, mappedHandler.getHandler());
if(err != null && !err.hasView()) {
err.setViewName(this.getDefaultViewName(request));
}
if(var27 == null) {
break label276;
}
i = var27.length - 1;
while(true) {
if(i < 0) {
break label276;
}
var28 = var27[i];
var28.postHandle(processedRequest, response, mappedHandler.getHandler(), err);
--i;
}
}
this.noHandlerFound(processedRequest, response);
return;
}
} catch (ModelAndViewDefiningException var20) {
this.logger.debug("ModelAndViewDefiningException encountered", var20);
err = var20.getModelAndView();
} catch (Exception var21) {
Object handler = mappedHandler != null?mappedHandler.getHandler():null;
err = this.processHandlerException(processedRequest, response, handler, var21);
var25 = err != null;
}
if(err != null && !err.wasCleared()) {
this.render(err, processedRequest, response);
if(var25) {
WebUtils.clearErrorRequestAttributes(request);
}
} else if(this.logger.isDebugEnabled()) {
this.logger.debug("Null ModelAndView returned to DispatcherServlet with name \'" + this.getServletName() + "\': assuming HandlerAdapter completed request handling");
}
this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, (Exception)null);
}
...
finally {
if(processedRequest != request) {
this.cleanupMultipart(processedRequest);
}
}
}
protected LocaleContext buildLocaleContext(final HttpServletRequest request) {
return new LocaleContext() {
public Locale getLocale() {
return DispatcherServlet.this.localeResolver.resolveLocale(request);
}
public String toString() {
return this.getLocale().toString();
}
};
}
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
if(this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if(!(request instanceof MultipartHttpServletRequest)) {
return this.multipartResolver.resolveMultipart(request);
}
this.logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, this typically results from an additional MultipartFilter in web.xml");
}
return request;
}
protected void cleanupMultipart(HttpServletRequest request) {
if(request instanceof MultipartHttpServletRequest) {
this.multipartResolver.cleanupMultipart((MultipartHttpServletRequest)request);
}
}
/** @deprecated */
@Deprecated
protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
return this.getHandler(request);
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Iterator var3 = this.handlerMappings.iterator();
HandlerExecutionChain handler;
do {
if(!var3.hasNext()) {
return null;
}
HandlerMapping hm = (HandlerMapping)var3.next();
handler = hm.getHandler(request);
} while(handler == null);
return handler;
}
protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception {
if(pageNotFoundLogger.isWarnEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
pageNotFoundLogger.warn("No mapping found for HTTP request with URI [" + requestUri + "] in DispatcherServlet with name \'" + this.getServletName() + "\'");
}
response.sendError(404);
}
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
Iterator var3 = this.handlerAdapters.iterator();
HandlerAdapter ha;
do {
if(!var3.hasNext()) {
throw new ServletException("No adapter for handler [" + handler + "]: Does your handler implement a supported interface like Controller?");
}
ha = (HandlerAdapter)var3.next();
} while(!ha.supports(handler));
return ha;
}
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
ModelAndView exMv = null;
Iterator var7 = this.handlerExceptionResolvers.iterator();
while(var7.hasNext()) {
HandlerExceptionResolver handlerExceptionResolver = (HandlerExceptionResolver)var7.next();
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
if(exMv != null) {
break;
}
}
if(exMv != null) {
if(exMv.isEmpty()) {
return null;
} else {
if(!exMv.hasView()) {
exMv.setViewName(this.getDefaultViewName(request));
}
WebUtils.exposeErrorRequestAttributes(request, ex, this.getServletName());
return exMv;
}
} else {
throw ex;
}
}
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
if(mv.isReference()) {
view = this.resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if(view == null) {
throw new ServletException("Could not resolve view with name \'" + mv.getViewName() + "\' in servlet with name \'" + this.getServletName() + "\'");
}
} else {
view = mv.getView();
if(view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name \'" + this.getServletName() + "\'");
}
}
view.render(mv.getModelInternal(), request, response);
}
protected String getDefaultViewName(HttpServletRequest request) throws Exception {
return this.viewNameTranslator.getViewName(request);
}
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception {
Iterator var6 = this.viewResolvers.iterator();
while(var6.hasNext()) {
ViewResolver viewResolver = (ViewResolver)var6.next();
View view = viewResolver.resolveViewName(viewName, locale);
if(view != null) {
return view;
}
}
return null;
}
private void triggerAfterCompletion(HandlerExecutionChain mappedHandler, int interceptorIndex, HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
if(mappedHandler != null) {
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
if(interceptors != null) {
for(int i = interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, mappedHandler.getHandler(), ex);
} catch (Throwable var10) {
this.logger.error("HandlerInterceptor.afterCompletion threw exception", var10);
}
}
}
}
}
private void restoreAttributesAfterInclude(HttpServletRequest request, Map<?, ?> attributesSnapshot) {
this.logger.debug("Restoring snapshot of request attributes after include");
HashSet attrsToCheck = new HashSet();
Enumeration attrNames = request.getAttributeNames();
while(true) {
String attrName;
do {
if(!attrNames.hasMoreElements()) {
Iterator var6 = attrsToCheck.iterator();
while(var6.hasNext()) {
attrName = (String)var6.next();
Object attrValue = attributesSnapshot.get(attrName);
if(attrValue == null) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Removing attribute [" + attrName + "] after include");
}
request.removeAttribute(attrName);
} else if(attrValue != request.getAttribute(attrName)) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Restoring original value of attribute [" + attrName + "] after include");
}
request.setAttribute(attrName, attrValue);
}
}
return;
}
attrName = (String)attrNames.nextElement();
} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
attrsToCheck.add(attrName);
}
}
}
HandlerMapping :
为Http请求找到相应的Controller控制器,从而使controller去完成设计好的数据处理工作:
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if(this.detectAllHandlerMappings) {
// 默认为true,从所有IoC容器中取Bean
Map hm = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if(!hm.isEmpty()) {
this.handlerMappings = new ArrayList(hm.values());
OrderComparator.sort(this.handlerMappings);
}
} else {
try {
HandlerMapping hm1 = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm1);
} catch (NoSuchBeanDefinitionException var3) {
;
}
}
// 未找到handlerMappings ,则为Servlet 设置一个默认的Mapping
// 默认值均在DispatcherServlet.propertise文件中
if(this.handlerMappings == null) {
this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
if(this.logger.isDebugEnabled()) {
this.logger.debug("No HandlerMappings found in servlet \'" + this.getServletName() + "\': using default");
}
}
}
在DispatcherServlet中,使用List存储HandlerMapping,每一个HandlerMapping表示URL到controller的映射
public interface HandlerMapping {
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";
// 实际上返回的是HandlerExecutionChain,它不仅包含Handler本身,还包含处理此请求的拦截器链
HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception;
}
HandlerExecutionChain :
public class HandlerExecutionChain {
private final Object handler;
private HandlerInterceptor[] interceptors;
private List<HandlerInterceptor> interceptorList;
...
}
HandlerMapping的注册:
public void initApplicationContext() throws BeansException {
super.initApplicationContext();
this.registerHandlers(this.urlMap);
}
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
String url;
Object handler;
if(urlMap.isEmpty()) {
this.logger.warn("Neither \'urlMap\' nor \'mappings\' set on SimpleUrlHandlerMapping");
} else {
for(Iterator var3 = urlMap.entrySet().iterator(); var3.hasNext(); this.registerHandler(url, handler)) {
Entry entry = (Entry)var3.next();
url = (String)entry.getKey();
handler = entry.getValue();
if(!url.startsWith("/")) {
url = "/" + url;
}
if(handler instanceof String) {
handler = ((String)handler).trim();
}
}
}
}
// ==================================================================
// AbstractUrlHandlerMapping
private final Map<String, Object> handlerMap = new LinkedHashMap();
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
Assert.notNull(urlPath, "URL path must not be null");
Assert.notNull(handler, "Handler object must not be null");
Object resolvedHandler = handler;
if(!this.lazyInitHandlers && handler instanceof String) {
String mappedHandler = (String)handler;
if(this.getApplicationContext().isSingleton(mappedHandler)) {
resolvedHandler = this.getApplicationContext().getBean(mappedHandler);
}
}
Object mappedHandler1 = this.handlerMap.get(urlPath);
if(mappedHandler1 != null) {
if(mappedHandler1 != resolvedHandler) {
throw new IllegalStateException("Cannot map " + this.getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + this.getHandlerDescription(mappedHandler1) + " mapped.");
}
} else if(urlPath.equals("/")) {
if(this.logger.isInfoEnabled()) {
this.logger.info("Root mapping to " + this.getHandlerDescription(handler));
}
this.setRootHandler(resolvedHandler);
} else if(urlPath.equals("/*")) {
if(this.logger.isInfoEnabled()) {
this.logger.info("Default mapping to " + this.getHandlerDescription(handler));
}
this.setDefaultHandler(resolvedHandler);
} else {
this.handlerMap.put(urlPath, resolvedHandler);
if(this.logger.isInfoEnabled()) {
this.logger.info("Mapped URL path [" + urlPath + "] onto " + this.getHandlerDescription(handler));
}
}
}
HandlerExecutionChain获取:
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = this.getHandlerInternal(request);
if(handler == null) {
// 默认处理
handler = this.getDefaultHandler();
}
if(handler == null) {
return null;
} else {
if(handler instanceof String) {
String handlerName = (String)handler;
handler = this.getApplicationContext().getBean(handlerName);
}
return this.getHandlerExecutionChain(handler, request);
}
}
protected abstract Object getHandlerInternal(HttpServletRequest var1) throws Exception;
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);
Iterator var6 = this.mappedInterceptors.iterator();
while(var6.hasNext()) {
MappedInterceptor mappedInterceptor = (MappedInterceptor)var6.next();
if(mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
return chain;
}
DispatcherServlet处理Http请求:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if(this.logger.isDebugEnabled()) {
String attributesSnapshot = urlPathHelper.getRequestUri(request);
this.logger.debug("DispatcherServlet with name \'" + this.getServletName() + "\' processing " + request.getMethod() + " request for [" + attributesSnapshot + "]");
}
HashMap attributesSnapshot1 = null;
if(WebUtils.isIncludeRequest(request)) {
this.logger.debug("Taking snapshot of request attributes before include");
attributesSnapshot1 = new HashMap();
Enumeration inputFlashMap = request.getAttributeNames();
label90:
while(true) {
String attrName;
do {
if(!inputFlashMap.hasMoreElements()) {
break label90;
}
attrName = (String)inputFlashMap.nextElement();
} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
attributesSnapshot1.put(attrName, request.getAttribute(attrName));
}
}
// 设定上下文等相关属性
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
FlashMap inputFlashMap1 = this.flashMapManager.retrieveAndUpdate(request, response);
if(inputFlashMap1 != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap1));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
// 分派Http请求
this.doDispatch(request, response);
} finally {
if(attributesSnapshot1 != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot1);
}
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
try {
boolean var25 = false;
ModelAndView err;
try {
label276:
processedRequest = this.checkMultipart(request);
// 根据请求,获取HandlerExecutionChain
mappedHandler = this.getHandler(processedRequest, false);
if(mappedHandler != null && mappedHandler.getHandler() != null) {
HandlerAdapter ex1 = this.getHandlerAdapter(mappedHandler.getHandler());
String var26 = request.getMethod();
boolean isGet = "GET".equals(var26);
if(isGet || "HEAD".equals(var26)) {
long interceptors = ex1.getLastModified(request, mappedHandler.getHandler());
if(this.logger.isDebugEnabled()) {
String interceptor = urlPathHelper.getRequestUri(request);
this.logger.debug("Last-Modified value for [" + interceptor + "] is: " + interceptors);
}
if((new ServletWebRequest(request, response)).checkNotModified(interceptors) && isGet) {
return;
}
}
// 为注册拦截器配置预处理方法
// 调用handler拦截器
HandlerInterceptor[] var27 = mappedHandler.getInterceptors();
int i;
HandlerInterceptor var28;
if(var27 != null) {
for(i = 0; i < var27.length; interceptorIndex = i++) {
var28 = var27[i];
if(!var28.preHandle(processedRequest, response, mappedHandler.getHandler())) {
this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, (Exception)null);
return;
}
}
}
// 执行handler,实际上触发Controller的handlerRequest方法
err = ex1.handle(processedRequest, response, mappedHandler.getHandler());
//
if(err != null && !err.hasView()) {
err.setViewName(this.getDefaultViewName(request));
}
if(var27 == null) {
break label276;
}
i = var27.length - 1;
while(true) {
if(i < 0) {
break label276;
}
var28 = var27[i];
var28.postHandle(processedRequest, response, mappedHandler.getHandler(), err);
--i;
}
}
this.noHandlerFound(processedRequest, response);
return;
}
} catch (ModelAndViewDefiningException var20) {
this.logger.debug("ModelAndViewDefiningException encountered", var20);
err = var20.getModelAndView();
} catch (Exception var21) {
Object handler = mappedHandler != null?mappedHandler.getHandler():null;
err = this.processHandlerException(processedRequest, response, handler, var21);
var25 = err != null;
}
// 使用视图对ModelAndView的数据展现
if(err != null && !err.wasCleared()) {
this.render(err, processedRequest, response);
if(var25) {
WebUtils.clearErrorRequestAttributes(request);
}
} else if(this.logger.isDebugEnabled()) {
this.logger.debug("Null ModelAndView returned to DispatcherServlet with name \'" + this.getServletName() + "\': assuming HandlerAdapter completed request handling");
}
this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, (Exception)null);
} catch (Exception var22) {
this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, var22);
throw var22;
} catch (Error var23) {
NestedServletException ex = new NestedServletException("Handler processing failed", var23);
this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
} finally {
if(processedRequest != request) {
this.cleanupMultipart(processedRequest);
}
}
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Iterator var3 = this.handlerMappings.iterator();
HandlerExecutionChain handler;
// 循环1
do {
if(!var3.hasNext()) {
return null;
}
// 从HandlerExecutionChain 取 HandlerMapping
HandlerMapping hm = (HandlerMapping)var3.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name \'" + this.getServletName() + "\'");
}
handler = hm.getHandler(request);
} while(handler == null);
return handler;
}
HandlerAdapter适配器:
DispatcherServlet通过HandlerAdapter检查这个Handler的合法性。
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
Iterator var3 = this.handlerAdapters.iterator();
// 对所有adapter进行匹配
HandlerAdapter ha;
do {
if(!var3.hasNext()) {
throw new ServletException("No adapter for handler [" + handler + "]: Does your handler implement a supported interface like Controller?");
}
ha = (HandlerAdapter)var3.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler adapter [" + ha + "]");
}
} while(!ha.supports(handler));
return ha;
}
如何判断Handler是不是Controller接口,如SimpleControllerHandlerAdapter:
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public SimpleControllerHandlerAdapter() {
}
// 判断合法性
public boolean supports(Object handler) {
return handler instanceof Controller;
}
// 执行Handler
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;
}
}
Spring MVC视图的呈现:
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
// 定位视图
if(mv.isReference()) {
view = this.resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if(view == null) {
throw new ServletException("Could not resolve view with name \'" + mv.getViewName() + "\' in servlet with name \'" + this.getServletName() + "\'");
}
} else {
view = mv.getView();
if(view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name \'" + this.getServletName() + "\'");
}
}
if(this.logger.isDebugEnabled()) {
this.logger.debug("Rendering view [" + view + "] in DispatcherServlet with name \'" + this.getServletName() + "\'");
}
// 调用view实现对数据进行呈现,并通过HttpResponse把视图呈现给Http客户端
view.render(mv.getModelInternal(), request, response);
}