目录
一、SpringMVC常用组件
1.DispatcherServlet
2.HandlerMapping
3.Handler
4.HandlerAdapter
5.ViewResolver
6.View
二、DispatcherServlet初始化过程
⚪FrameworkServlet 中的initServletBean方法(源码)
initServletBean中initWebApplicationContext 源码(创建IOC容器)
initWebApplicationContext中的onRefresh方法(源码)
DispatcherServlet中重写的 onRefresh方法(源码)
DispatcherServlet的初始化策略initStrategies (源码)
三、DispatcherServlet调用组件处理请求
⚪HttpServlet中对service方法进行了重写&重载编辑
⚪FrameWorkServlet中的service
四、SpringMVC的执行流程
前端控制器,不需要工程师开发,由框架提供
作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求
处理器映射器,不需要工程师开发,由框架提供
作用:根据请求的url、method等信息查找Handler,即控制器方法
处理器,需要工程师开发
作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理
处理器适配器,不需要工程师开发,由框架提供
作用:通过HandlerAdapter对处理器(控制器方法)进行执行
视图解析器,不需要工程师开发,由框架提供
作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、 RedirectView
视图
作用:将模型数据通过页面展示给用户
DispatcherServlet 本质上是一个 Servlet,所以天然的遵循 Servlet 的生命周期。
因此宏观上是 Servlet 生命周期来进行调度。
public final void init() throws ServletException {
PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
if (!pvs.isEmpty()) {
try {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
this.initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
} catch (BeansException var4) {
if (this.logger.isErrorEnabled()) {
this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4);
}
throw var4;
}
}
this.initServletBean();
}
protected void initServletBean() throws ServletException {
}
protected final void initServletBean() throws ServletException {
this.getServletContext().log("Initializing Spring " +
this.getClass().getSimpleName() +
" '" +
this.getServletName() +
"'");
if (this.logger.isInfoEnabled()) {
this.logger.info("Initializing Servlet '" +
this.getServletName() + "'");
}
long startTime = System.currentTimeMillis();
try {
//初始化SpringMVC的IOC容器
this.webApplicationContext = this.initWebApplicationContext();
this.initFrameworkServlet();
} catch (RuntimeException | ServletException var4) {
this.logger.error("Context initialization failed", var4);
throw var4;
}
if (this.logger.isDebugEnabled()) {
String value = this.enableLoggingRequestDetails ?
"shown which may lead to unsafe logging of potentially sensitive data" :
"masked to prevent unsafe logging of potentially sensitive data";
this.logger.debug("enableLoggingRequestDetails='" +
this.enableLoggingRequestDetails +
"': request parameters and headers will be " +
value);
}
if (this.logger.isInfoEnabled()) {
this.logger.info("Completed initialization in " +
(System.currentTimeMillis() - startTime) + " ms");
}
}
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
//设置当前SpringMVC的IOC容器的父容器
cwac.setParent(rootContext);
}
this.configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
wac = this.findWebApplicationContext();
}
if (wac == null) {
//创建IOC容器
wac = this.createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
synchronized(this.onRefreshMonitor) {
//刷新容器
this.onRefresh(wac);
}
}
if (this.publishContext) {
String attrName = this.getServletContextAttributeName();
//把SpringMVC容器共享到最大的域对象中
this.getServletContext().setAttribute(attrName, wac);
}
return wac;
}
protected void onRefresh(ApplicationContext context) {
}
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);
}
重写的service
根据请求方式的不用调用不同的方法
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String CRLF = "\r\n";
StringBuilder buffer = (new StringBuilder("TRACE ")).append(req.getRequestURI()).append(" ").append(req.getProtocol())
Enumeration reqHeaderEnum = req.getHeaderNames();
while(reqHeaderEnum.hasMoreElements()) {
String headerName = (String)reqHeaderEnum.nextElement();
buffer.append(CRLF).append(headerName).append(": ").append(req.getHeader(headerName));
}
buffer.append(CRLF);
int responseLength = buffer.length();
resp.setContentType("message/http");
resp.setContentLength(responseLength);
ServletOutputStream out = resp.getOutputStream();
out.print(buffer.toString());
}
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
重载的service
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
this.service(request, response);
} else {
throw new ServletException("non-HTTP request or response");
}
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
super.service(request, response);//调用HttpServlet中的方法
} else {
this.processRequest(request, response);
}
}
FrameWorkServlet将以下方法都进行了重写
protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (this.dispatchOptionsRequest || CorsUtils.isPreFlightRequest(request)) {
this.processRequest(request, response);
if (response.containsHeader("Allow")) {
return;
}
}
super.doOptions(request, new HttpServletResponseWrapper(response) {
public void setHeader(String name, String value) {
if ("Allow".equals(name)) {
value = (StringUtils.hasLength(value) ? value + ", " : "") + HttpMethod.PATCH.name();
}
super.setHeader(name, value);
}
});
}
protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (this.dispatchTraceRequest) {
this.processRequest(request, response);
if ("message/http".equals(response.getContentType())) {
return;
}
}
super.doTrace(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = this.buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor());
this.initContextHolders(request, localeContext, requestAttributes);
try {
this.doService(request, response);
} catch (IOException | ServletException var16) {
failureCause = var16;
throw var16;
} catch (Throwable var17) {
failureCause = var17;
throw new NestedServletException("Request processing failed", var17);
} finally {
this.resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
this.logResult(request, response, (Throwable)failureCause, asyncManager);
this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
}
}
1) 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获。
2) DispatcherServlet对请求URL(统一资源定位符)进行解析,得到请求资源标识符(URI),判断请求URI对应的映射:
⭐不存在
⭐存在则执行下面的流程
3) 根据该URI,调用HandlerMapping(处理器映射器)获得该Handler配置的所有相关的对象(包括Handler对象以及 Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。
4) DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter(处理器适配器)。
5) 如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法【正向】
6) 提取Request中的模型数据(请求报文),填充Handler入参,开始执行Handler(Controller)方法,处理请求。 在填充Handler的入参过程中,根据配置,Spring将帮你做一些额外的工作:
7) Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。
8) 此时将开始执行拦截器的postHandle(...)方法【逆向】。
9) 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行 HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model (向域对象共享数据)和View,来渲染视图。
10) 渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。
11) 将渲染结果返回给客户端。