为什么Springboot能够在没有XML文件的情况下注入DispatchServlet对象,主要是依靠DispatcherServletAutoConfiguration
这个配置类,该配置类位于
org.springframework.boot.autoconfigure.web.servlet 这个包的下面,该配置类的上面有三个注解:
@AutoConfigureOrder(-2147483648)
@AutoConfiguration(
after = {ServletWebServerFactoryAutoConfiguration.class}
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({DispatcherServlet.class})
1.@AutoConfigureOrder:value为加载的顺序,顺序越小越早加载,负数也可以。
2.@AutoConfiguration:表示根据spring.factories文件自动装载,其中的after参数表示要在某个类装载之后才能装载。
3.@ConditionalOnWebApplication:表示只有Spring为web服务的时候,该类才能生效,其中type代表着web服务的类型。
4.@ConditionalOnClass:表示当项目中存在某个类时,该类才能生效,value为某个类的class对象。
从上面的注解可以看出,当我们创建的Srping应用为SERVLET类型的web服务,且当前的项目中包含DispatcherServlet类时,该类才能当做配置类加载到Spring的IOC容器中。
DispatcherServletAutoConfiguration
这个配置类中包含有四个子类:
1.
DispatcherServletRegistrationCondition:用于表示 DispatcherServletRegistration 注入时的条件。
2. DefaultDispatcherServletCondition:用于表示默认的DisPatcherServlet对象的注入条件。
3.DispatcherServletRegistrationConfiguration: 用于将DispatcherServletRegistration对象注入到IOC容器中。
4. DispatcherServletConfiguration: 用于将DispatcherServlet对象注入到IOC容器中。
通过全局搜索可知DispatcherServlet类位于 org.springframework.web.servlet 包中。
DispatcherServlet 的构造函数有两种:
public DispatcherServlet() {
this.setDispatchOptionsRequest(true);
}
public DispatcherServlet(WebApplicationContext webApplicationContext) {
super(webApplicationContext);
this.setDispatchOptionsRequest(true);
}
其中带参的构造函数主要是为了传入多个Servlet共享的Web上下文。
在 DispatcherServlet 类中有一个onRefresh方法,该方法在Springboot启动过程中刷新上下文的时候会运行的时候会运行,源码如下所示:
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
// 初始化文件上传解析器
//文件上传解析器作用:对上传的文件数据进行解析
this.initMultipartResolver(context);
// 初始化地区解析器
// 地区解析器作用:通过上传的请求解析客户端所在的地区,实现多语言即国际化
this.initLocaleResolver(context);
// 初始化主题解析器
// 主题解析器作用:用于解析客户端所使用Spring主题,将参数转化为对应的值传给前端
this.initThemeResolver(context);
// 初始化映射处理器
// 映射处理器作用:根据请求中的url找到对应的处理器链(HandlerExecutionChain,1个处理器+多个拦截器)
this.initHandlerMappings(context);
// 初始化适配处理器
// 适配处理器作用:用于执行处理器对象中的处理方法,并将处理后的结果包装成ModelView类型的对象返回
this.initHandlerAdapters(context);
// 初始化异常处理器
// 异常处理器作用:用于处理处理请求的过程中发生的异常,返回一个ModelView对象
this.initHandlerExceptionResolvers(context);
// 初始化视图转换器
// 视图转换器作用:根据请求解析对应视图的名称,用于填充ModeAndView中的view成员变量
this.initRequestToViewNameTranslator(context);
// 初始化视图解析器
// 视图解析器作用:将ModelAndView中视图的名称解析成View对象,然后赋值给view成员变量,最终DispatcherServlet会调用View对象中的render方法,将对应的视图返回给前端
this.initViewResolvers(context);
// 用于在重定向之前存储一些数据,重定向之后也可以获取
this.initFlashMapManager(context);
}
由源码可以看出,DispatcherServlet的onRefresh方法主要是将ApplicationContext(IOC容器)中一些有用的对象加载到成员变量中。
DispatcherServlet主要是在doDispatch方法中调用上述初始化的对象,doDispatch的源码如下:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// 根据请求获取对应的处理器链
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
// 根据处理器获取适配器
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
// 执行拦截器中的preHandle()方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 利用适配器调用处理器中的处理方法来处理请求(Conreoller中的方法),并且返回一个ModelAndView对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 根据请求获取视图的名称(调用视图解析器)
this.applyDefaultViewName(processedRequest, mv);
// 执行拦截器中的postHandle()方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
// 调用拦截器中的afterCompletion()方法,并且调用了View对象的render()方法将视图返回给前端
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
// 内部调用了afterCompletion()方法,就算报异常也会调用afterCompletion()方法
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
// 内部调用了afterCompletion()方法,就算报异常也会调用afterCompletion()方法
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
在Web上下文中还存在着一些前置过滤器和后置过滤器,因此SpringMVC在处理请求的过程中,前置过滤器会对请求进行预处理,然后再交给DispatcherServlet对象处理,后置过滤器会在视图返回给用户之前对响应进行预处理。