真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

SpringMVC工作原理的示例分析

小編給大家分享一下Spring MVC工作原理的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

創(chuàng)新互聯(lián)專注于企業(yè)營銷型網(wǎng)站建設(shè)、網(wǎng)站重做改版、壽光網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5響應(yīng)式網(wǎng)站、電子商務(wù)商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為壽光等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

應(yīng)用示例

在講工作原理之前,我們先看一個(gè)簡單的spring mvc(ssm)示例,以及實(shí)現(xiàn)的效果

工程代碼地址:ssm-web 

Spring MVC工作原理的示例分析

工程結(jié)構(gòu)與效果如上所示,我們不做過多的探究,我們打起精神往下看本篇的重點(diǎn)

工作原理

準(zhǔn)備 - 資源的加載與初始化

1、DispatcherServlet 靜態(tài)初始化

DispatcherServlet中有如下靜態(tài)塊

static {
 // Load default strategy implementations from properties file.
 // This is currently strictly internal and not meant to be customized
 // by application developers.
 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中的內(nèi)容讀取到DispatcherServlet的屬性:private static final Properties defaultStrategies中,DispatcherServlet.properties內(nèi)容如下

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

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

指定了DispatcherServlet策略接口的默認(rèn)實(shí)現(xiàn),后續(xù)DispatcherServlet初始化策略的時(shí)候會用到

2、interceptor定義的加載

spring啟動過程中會調(diào)用InterceptorsBeanDefinitionParser的parse方法來解析出我們自定義的interceptor定義,封裝成MappedInterceptor類型的bean定義,并放到spring容器中;我們可以簡單的認(rèn)為spring容器中已經(jīng)存在了我們自定義的interceptor的bean定義

3、DispatcherServlet初始化策略:initStrategies

DispatcherServlet的繼承圖如下

Spring MVC工作原理的示例分析

DispatcherServlet是一個(gè)Servlet,tomcat啟動過程中會調(diào)用其init方法,一串的調(diào)用后,會調(diào)用DispatcherServlet的initStrategies方法

protected void initStrategies(ApplicationContext context) {
 initMultipartResolver(context);
 initLocaleResolver(context);
 initThemeResolver(context);
 initHandlerMappings(context);
 initHandlerAdapters(context);
 initHandlerExceptionResolvers(context);
 initRequestToViewNameTranslator(context);
 initViewResolvers(context);
 initFlashMapManager(context);
}

實(shí)例化步驟1中的默認(rèn)實(shí)現(xiàn),并填充到DispatcherServlet各個(gè)屬性值中

4、DefaultAnnotationHandlerMapping的攔截器初始化

DispatcherServlet.properties種指定了兩個(gè)默認(rèn)的HandlerMapping:BeanNameUrlHandlerMapping、DefaultAnnotationHandlerMapping,這兩者的類繼承圖如下(我們暫時(shí)只關(guān)注DefaultAnnotationHandlerMapping)

Spring MVC工作原理的示例分析

DefaultAnnotationHandlerMapping間接實(shí)現(xiàn)了ApplicationContextAware,那么在DefaultAnnotationHandlerMapping實(shí)例初始化過程中,會調(diào)用setApplicationContext(ApplicationContext applicationContext)方法,一串調(diào)用后,會來到AbstractUrlHandlerMapping的initApplicationContext()

@Override
protected void initApplicationContext() throws BeansException {
 extendInterceptors(this.interceptors);
 detectMappedInterceptors(this.mappedInterceptors);
 initInterceptors();
}

初始化了DefaultAnnotationHandlerMapping的攔截器:interceptor

我們來看下具體的初始化過程,看看上面的順序是否只是我個(gè)人的臆想?

Spring MVC工作原理的示例分析

可以看到,初始化順序就是我們上面說的,不是我個(gè)人的意淫;此時(shí)的DefaultAnnotationHandlerMapping中有我們自定義的MyInterceptor。初始化過程我們需要關(guān)注的就是上述這些,下面我們一起看看具體請求的過程

請求的處理

請求從servlet的service開始,一路到DispatcherServlet的doDispatch,如下圖

Spring MVC工作原理的示例分析

doDispatch

/**
 * Process the actual dispatching to the handler. 將請求分發(fā)到具體的handler,也就是我們的controller
 * 

The handler will be obtained by applying the servlet's HandlerMappings in order.  * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters  * to find the first that supports the handler class.  * 

All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers  * themselves to decide which methods are acceptable.  * @param request current HTTP request  * @param response current HTTP response  * @throws Exception in case of any kind of processing failure  */ 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 {    processedRequest = checkMultipart(request);    multipartRequestParsed = processedRequest != request;    // Determine handler for the current request. 決定哪個(gè)handler來處理當(dāng)前的請求    // mappedHandler是由handler和interceptor集合組成的一個(gè)執(zhí)行鏈,有點(diǎn)類似FilterChain    mappedHandler = getHandler(processedRequest);    if (mappedHandler == null || mappedHandler.getHandler() == null) {     noHandlerFound(processedRequest, response);     return;    }    // Determine handler adapter for the current request. 決定哪個(gè)adapter來處理當(dāng)前的請求    // handlerMapping是找出適配的handler,而真正回調(diào)handler的是adapter    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());    // Process last-modified header, if supported by the handler.    String method = request.getMethod();    boolean isGet = "GET".equals(method);    if (isGet || "HEAD".equals(method)) {     long lastModified = ha.getLastModified(request, mappedHandler.getHandler());     if (logger.isDebugEnabled()) {      String requestUri = urlPathHelper.getRequestUri(request);      logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);     }     if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {      return;     }    }    // handler的前置處理,也就是調(diào)用適配當(dāng)前url的interceptor的preHandler方法    if (!mappedHandler.applyPreHandle(processedRequest, response)) {     return;    }    try {     // Actually invoke the handler. 真正調(diào)用handler     mv = ha.handle(processedRequest, response, mappedHandler.getHandler());    }    finally {     if (asyncManager.isConcurrentHandlingStarted()) {      return;     }    }    applyDefaultViewName(request, mv);    // handler的后置處理,也就是調(diào)用適配當(dāng)前url的interceptor的postHandler方法    mappedHandler.applyPostHandle(processedRequest, response, mv);   }   catch (Exception ex) {    dispatchException = ex;   }   // 處理handler返回的結(jié)果,會調(diào)用適配當(dāng)前url的interceptor的afterCompletion方法   // 這里會將響應(yīng)結(jié)果返回給請求者   processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);  }  catch (Exception ex) {   triggerAfterCompletion(processedRequest, response, mappedHandler, ex);  }  catch (Error err) {   triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);  }  finally {   if (asyncManager.isConcurrentHandlingStarted()) {    // Instead of postHandle and afterCompletion    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);    return;   }   // Clean up any resources used by a multipart request.   if (multipartRequestParsed) {    cleanupMultipart(processedRequest);   }  } }

handlerMapping具體如何找到匹配當(dāng)前url的handler(一般而言就是我們的controller)、handlerAdapter具體如何回調(diào)真正的handler,有興趣的可以自行去跟下,我就不跟了。我們具體看下processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 這個(gè)與我們最初的疑問有關(guān)

processDispatchResult

Spring MVC工作原理的示例分析

可以看到model中的persons會被設(shè)置到request的attributes中,然后轉(zhuǎn)發(fā)請求到show_person.jsp,轉(zhuǎn)發(fā)過程中request作用域的變量仍然有效,所以show_person.jsp中的jstl標(biāo)簽和el表達(dá)式能夠取到persons變量,最后將show_person.jsp中的內(nèi)容填充好之后的靜態(tài)內(nèi)容返回給請求者;至此就完成了一次請求的響應(yīng)

問題解答

回到我們開篇的疑問:Spring mvc是何時(shí)、何地、如何將Model中的屬性綁定到哪個(gè)作用域?想必大家已經(jīng)知道答案了

Controller中的model、ModelMap的注入由spring mvc完成,這個(gè)不是請求傳入的參數(shù),用于綁定變量到Servlet作用域;默認(rèn)情況下,在DispatcherServlet調(diào)用了真正的handler之后,將結(jié)果返回給請求者的過程中,將model、modelMap中的變量設(shè)置到了request的attributes中,轉(zhuǎn)發(fā)的過程中,request中的變量仍然有效,所以show_person.jsp中能取到persons這個(gè)變量,自此疑問得到解答

總結(jié)

1、Spring MVC工作原理圖

圖是用的別人的,具體是誰的我也不記得了(捂臉)

Spring MVC工作原理的示例分析

以上是“Spring MVC工作原理的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


分享文章:SpringMVC工作原理的示例分析
文章位置:http://weahome.cn/article/pcioje.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部