赞
踩
public interface WebApplicationInitializer {
void onStartup(ServletContext servletContext) throws ServletException;
}
public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
registerDispatcherServlet(servletContext);
}
protected void registerDispatcherServlet(ServletContext servletContext) {
//此处往servletContext添加DispatcherServlet实例
//并为DispatcherServlet添加过滤器
}
public abstract class AbstractAnnotationConfigDispatcherServletInitializer
extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createRootApplicationContext() {
...
}
@Override
protected WebApplicationContext createServletApplicationContext() {
...
}
//用来创建根ApplicationContext和ServletApplicationContext容器时,需要注入的组件字类节数组
protected abstract Class<?>[] getRootConfigClasses();
protected abstract Class<?>[] getServletConfigClasses();
}
static {
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
}
}
DispatcherServlet.properties 策略文件的内容
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
public abstract class HttpServletBean extends HttpServlet
implements EnvironmentCapable, EnvironmentAware {
@Override
public final void init() throws ServletException {
initServletBean();
}
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
@Override
protected final void initServletBean() throws ServletException {
this.webApplicationContext = initWebApplicationContext();
}
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
// A context instance was injected at construction time -> use it
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
if (!cwac.isActive()) {
...
//刷新,调用cwac.refresh()方法
//触发了ContextRefreshListener.onApplicationEvent方法
//调用FrameworkServlet.this.onApplicationEvent方法
//调用子类,即DispatcherServlet.onRefresh方法
configureAndRefreshWebApplicationContext(cwac);
}
}
}
...
return wac;
}
public void onApplicationEvent(ContextRefreshedEvent event) {
this.refreshEventReceived = true;
onRefresh(event.getApplicationContext());
}
protected void onRefresh(ApplicationContext context) {
// 调用子类,即DispatcherServlet.onRefresh方法
}
private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
FrameworkServlet.this.onApplicationEvent(event);
}
}
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
//判断Spring容器是否存在MultipartResolver,LocaleResolver,ThemeResolver,不存在打印日志
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
//默认行为,加载容器的hadlerMappings,handlerAdapters,handlerExceptionResolvers,并排序
//不存在则加载策略文件
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
//容器中加载名为viewNameTranslator的解析器,
//如果找不到,从策略文件加载第一个Translator,即
//org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
initRequestToViewNameTranslator(context);
/默认行为,加载容器的viewResolvers,并排序
//不存在则加载策略文件
initViewResolvers(context);
//容器中加载名为flashMapManager,
//不存在的话,同上处理,找策略文件中第一个
initFlashMapManager(context);
}
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//往request设置setAttribute,将当前环境(本地化解析器,主题解析器等)给request,方法mvc框架其他组件可以获取到。
...
try {
//真实调用
doDispatch(request, response);
}
finally {
//为request设置WebAsyncManager属性
//如果是同步请求,恢复请求前的属性
...
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//判断request头部ContentType是否以"multipart/"开头,来标记是否为附件上传
processedRequest = checkMultipart(request);
//是否附件请求标记
multipartRequestParsed = (processedRequest != request);
//
// 从handlerMappings(RequestMappingHanderMapping,策略文件的handlerMapping类已经过时了),获取HandlerExecutionChain
//HandlerExecutionChain(包含一个handlerMethod,以及一堆handlerInterceptor)
mappedHandler = getHandler(processedRequest);
//找不到handlerMethod时,根据标是否抛出异常,还是直接response.sendError
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// 根据handerMethod找到HandlerAdapter(RequestMappingHandlerAdapter)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 修改 last-modified 头部,如果支持的话.
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;
}
}
// 调用所有HandlerInterceptor的preHandle()方法,如果返回false,不处理请求
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 核心:::::通过RequestMappingHandlerAdapter的handle方法,处理请求逻辑,返回ModelView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//从viewNameTranslator中获取默认视图名,并设置到mv中
applyDefaultViewName(request, mv);
//调用所有HandlerInterceptor的postHandle()方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
//渲染请求结果
//从ModelView中获取View
//view.render(model,req,resp)渲染
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
//调用handerExecutionChain的afterCompletion
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
//调用handerExecutionChain的afterCompletion
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// 调用handerExecutionChain的applyAfterConcurrentHandlingStarted,实现异步拦截
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// 如果为附件请求,清理现场
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
注:从DispatcherServlet.properties知道默认的HandlerMapping实现类已经注解了@Deprecated,从注释头部得知,建议使用RequestMappingHandlerMapping类。Spring-Webmvc模块中,提供了@EnableWebMvc,它导入了@Import(DelegatingWebMvcConfiguration.class)DelegatingWebMvcConfiguration类,而DelegatingWebMvcConfiguration类继承了WebMvcConfigurationSupport,WebMvcConfigurationSupport又注入了RequestMappingHandlerMapping实例,如下面代码。所以可以通过注解@EnableWebMvc,向容器注入RequestMappingHandlerMapping实例。
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping();
handlerMapping.setOrder(0);
handlerMapping.setInterceptors(getInterceptors());
//注入内容协商管理器handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager());
PathMatchConfigurer configurer = getPathMatchConfigurer();
if (configurer.isUseSuffixPatternMatch() != null) {
handlerMapping.setUseSuffixPatternMatch(configurer.isUseSuffixPatternMatch());
}
if (configurer.isUseRegisteredSuffixPatternMatch() != null) {
handlerMapping.setUseRegisteredSuffixPatternMatch(configurer.isUseRegisteredSuffixPatternMatch());
}
if (configurer.isUseTrailingSlashMatch() != null) {
handlerMapping.setUseTrailingSlashMatch(configurer.isUseTrailingSlashMatch());
}
if (configurer.getPathMatcher() != null) {
handlerMapping.setPathMatcher(configurer.getPathMatcher());
}
if (configurer.getUrlPathHelper() != null) {
handlerMapping.setUrlPathHelper(configurer.getUrlPathHelper());
}
return handlerMapping;
}
注:RequestMappingHandlerMapping间接实现了InitializingBean接口,重写afterPropertiesSet,代码如下
@Override
public void afterPropertiesSet() {
if (this.useRegisteredSuffixPatternMatch) {
this.fileExtensions.addAll(this.contentNegotiationManager.getAllFileExtensions());
}
//调用父类
super.afterPropertiesSet();
}
@Override
public void afterPropertiesSet() {
initHandlerMethods();//初始化handlerMethods
}
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
//收集所有注解了@Controller或@RequestMapping的方法
for (String beanName : beanNames) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX) &&
isHandler(getApplicationContext().getType(beanName))){
detectHandlerMethods(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
下节将细化介绍DispatcherServlet的getHandler(HttpServletRequest request)方法为入口进行源码剖析,将了解到
- 如何获取到handlerMethod
- 如何获取handlerInterceptor
- 如何创建handlerExecutionChain
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。