赞
踩
本文仅了解源码内容即可。
web.xml是web项⽬的配置⽂件,⼀般的web⼯程都会⽤到web.xml来Listener,Filter,Servlet等, Spring框架从3.1版本开始⽀持Servlet3.0, DispatcherServlet, 实现不再使⽤web.xml
init() 具体代码如下:
- @Override
- public final void init() throws ServletException {
- try {
- // ServletConfigPropertyValues 是静态内部类,使⽤ ServletConfig 获取
- web.xml 中配置的参数
- PropertyValues pvs = new
- ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
- // 使⽤ BeanWrapper 来构造 DispatcherServlet
- BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
- ResourceLoader resourceLoader = new
- ServletContextResourceLoader(getServletContext());
- bw.registerCustomEditor(Resource.class, new
- ResourceEditor(resourceLoader, getEnvironment()));
- initBeanWrapper(bw);
- bw.setPropertyValues(pvs, true);
- } catch (BeansException ex) {}
- // 让⼦类实现的⽅法,这种在⽗类定义在⼦类实现的⽅式叫做模版⽅法模式
- initServletBean();
- }

- /**
- * Overridden method of {@link HttpServletBean}, invoked after any bean
- properties
- * have been set. Creates this servlet's WebApplicationContext.
- */
- @Override
- protected final void initServletBean() throws ServletException {
- getServletContext().log("Initializing Spring " + getClass().getSimpleName()
- + " '" + getServletName() + "'");
- if (logger.isInfoEnabled()) {
- logger.info("Initializing Servlet '" + getServletName() + "'");
- }
- long startTime = System.currentTimeMillis();
- try {
- //创建ApplicationContext容器
- this.webApplicationContext = initWebApplicationContext();
- initFrameworkServlet();
- }
- catch (ServletException | RuntimeException ex) {
- logger.error("Context initialization failed", ex);
- throw ex;
- }
- if (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";
- logger.debug("enableLoggingRequestDetails='" +
- this.enableLoggingRequestDetails +
- "': request parameters and headers will be " + value);
- }
- if (logger.isInfoEnabled()) {
- logger.info("Completed initialization in " + (System.currentTimeMillis()
- - startTime) + " ms");
- }
- }

源码跟踪技巧:
在阅读框架源码的时候, ⼀定要抓住关键点, 找到核⼼流程.切忌从头到尾⼀⾏⼀⾏代码去看, ⼀个⽅法的去研究, ⼀定要找到关键流程, 抓住关键点, 先在宏观上对整个流程或者整个原理有⼀个认识, 有精⼒再去研究其中的细节
初始化web容器的过程中, 会通过onRefresh 来初始化SpringMVC的容器
- protected WebApplicationContext initWebApplicationContext() {
- //...
- if (!this.refreshEventReceived) {
- //初始化Spring MVC
- synchronized (this.onRefreshMonitor) {
- onRefresh(wac);
- }
- }
- return wac;
- }
- @Override
- protected void onRefresh(ApplicationContext context) {
- initStrategies(context);
- }
- /**
- * Initialize the strategy objects that this servlet uses.
- * <p>May be overridden in subclasses in order to initialize further strategy
- objects.
- */
- protected void initStrategies(ApplicationContext context) {
- initMultipartResolver(context);
- initLocaleResolver(context);
- initThemeResolver(context);
- initHandlerMappings(context);
- initHandlerAdapters(context);
- initHandlerExceptionResolvers(context)
- initRequestToViewNameTranslator(context);
- initViewResolvers(context);
- initFlashMapManager(context);
- }

1.初始化⽂件上传解析器MultipartResolver: 从应⽤上下⽂中获取名称为multipartResolver的Bean,如果没有名为multipartResolver的Bean,则没有提供上传⽂件的解析器2.初始化区域解析器LocaleResolver: 从应⽤上下⽂中获取名称为localeResolver的Bean,如果没有这个Bean,则默认使⽤AcceptHeaderLocaleResolver作为区域解析器3.初始化主题解析器ThemeResolver: 从应⽤上下⽂中获取名称为themeResolver的Bean,如果没有这个Bean,则默认使⽤FixedThemeResolver作为主题解析器4.初始化处理器映射器HandlerMappings: 处理器映射器作⽤,1)通过处理器映射器找到对应的处理器适配器,将请求交给适配器处理;2)缓存每个请求地址URL对应的位置(Controller.xxx⽅法);如果在ApplicationContext发现有HandlerMappings,则从ApplicationContext中获取到所有的HandlerMappings,并进⾏排序;如果在ApplicationContext中没有发现有处理器映射器,则默认BeanNameUrlHandlerMapping作为处理器映射器5.初始化处理器适配器HandlerAdapter: 作⽤是通过调⽤具体的⽅法来处理具体的请求;如果在 ApplicationContext发现有handlerAdapter,则从ApplicationContext中获取到所有的HandlerAdapter,并进⾏排序;如果在ApplicationContext中没有发现处理器适配器,则默认 SimpleControllerHandlerAdapter作为处理器适配器6.初始化异常处理器解析器HandlerExceptionResolver: 如果在ApplicationContext发现有handlerExceptionResolver,则从ApplicationContext中获取到所有的HandlerExceptionResolver,并进⾏排序;如果在ApplicationContext中没有发现异常处理器解析器,则不设置异常处理器7.初始化RequestToViewNameTranslator: 其作⽤是从Request中获取viewName,从ApplicationContext发现有viewNameTranslator的Bean,如果没有,则默认使⽤DefaultRequestToViewNameTranslator8.初始化视图解析器ViewResolvers: 先从ApplicationContext中获取名为viewResolver的Bean如果没有,则默认InternalResourceViewResolver作为视图解析器9.初始化FlashMapManager: 其作⽤是⽤于检索和保存FlashMap(保存从⼀个URL重定向到另⼀个URL时的参数信息),从ApplicationContext发现有flashMapManager的Bean,如果没有,则默认使⽤DefaultFlashMapManager
- 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;
- Exception dispatchException = null;
- try {
- processedRequest = this.checkMultipart(request);
- multipartRequestParsed = processedRequest != request;
- //1. 获取执⾏链
- //遍历所有的 HandlerMapping 找到与请求对应的Handler
- mappedHandler = this.getHandler(processedRequest);
- if (mappedHandler == null) {
- this.noHandlerFound(processedRequest, response);
- return;
- }
- //2. 获取适配器
- //遍历所有的 HandlerAdapter,找到可以处理该 Handler 的
- HandlerAdapter
- 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;
- }
- }
- //3. 执⾏拦截器preHandle⽅法
- if (!mappedHandler.applyPreHandle(processedRequest, response))
- {
- return;
- }
-
- //4. 执⾏⽬标⽅法
- mv = ha.handle(processedRequest, response,
- mappedHandler.getHandler());
- if (asyncManager.isConcurrentHandlingStarted()) {
- return;
- }
- this.applyDefaultViewName(processedRequest, mv);
- //5. 执⾏拦截器postHandle⽅法
- mappedHandler.applyPostHandle(processedRequest, response, mv);
- } catch (Exception var20) {
- dispatchException = var20;
- } catch (Throwable var21) {
- dispatchException = new NestedServletException("Handler
- dispatch failed", var21);
- }
- //6. 处理视图, 处理之后执⾏拦截器afterCompletion⽅法
- this.processDispatchResult(processedRequest, response,
- mappedHandler, mv, (Exception)dispatchException);
- } catch (Exception var22) {
- //7. 执⾏拦截器afterCompletion⽅法
- this.triggerAfterCompletion(processedRequest, response,
- mappedHandler, var22);
- } catch (Throwable var23) {
- 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);
- }
- }
- }

HandlerAdapter 主要⽤于⽀持不同类型的处理器(如 Controller、HttpRequestHandler 或者Servlet 等),让它们能够适配统⼀的请求处理流程。这样,Spring MVC 可以通过⼀个统⼀的接⼝来处理来⾃各种处理器的请求。
- boolean applyPreHandle(HttpServletRequest request, HttpServletResponse
- response) throws Exception {
- for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex =
- i++) {
- // 获取项⽬中使⽤的拦截器 HandlerInterceptor
- HandlerInterceptor interceptor =
- (HandlerInterceptor)this.interceptorList.get(i);
- if (!interceptor.preHandle(request, response, this.handler)) {
- this.triggerAfterCompletion(request, response, (Exception)null);
- return false;
- }
- }
- return true;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。