最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring mvc DispatcherServlet之前端控制器架構(gòu)詳解

 更新時(shí)間:2018年04月14日 10:52:52   作者:一天不進(jìn)步,就是退步  
這篇文章主要為大家詳細(xì)介紹了spring mvc DispatcherServlet之前端控制器架構(gòu),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前端控制器是整個(gè)MVC框架中最為核心的一塊,它主要用來(lái)攔截符合要求的外部請(qǐng)求,并把請(qǐng)求分發(fā)到不同的控制器去處理,根據(jù)控制器處理后的結(jié)果,生成相應(yīng)的響應(yīng)發(fā)送到客戶端。前端控制器既可以使用Filter實(shí)現(xiàn)(Struts2采用這種方式),也可以使用Servlet來(lái)實(shí)現(xiàn)(spring MVC框架)。

DispatcherServlet 作為前置控制器是web服務(wù)器的入口,是spring mvc最重要的一個(gè)類(lèi),通過(guò)它的生命周期可以加深對(duì)web服務(wù)器的理解。

servlet的生命周期

首先我們回憶一下servlet的生命周期:

Servlet生命周期分為三個(gè)階段:【Servlet生命周期與工作原理詳解

  1.初始化階段  調(diào)用init()方法。Servlet被裝載后,Servlet容器創(chuàng)建一個(gè)Servlet實(shí)例并且調(diào)用Servlet的init()方法進(jìn)行初始化。在Servlet的整個(gè)生命周期內(nèi),init()方法只被調(diào)用一次。

  2.響應(yīng)客戶請(qǐng)求階段  調(diào)用service()方法

  3.終止階段  調(diào)用destroy()方法

Servlet初始化階段

  在下列時(shí)刻Servlet容器裝載Servlet:

  1.Servlet容器啟動(dòng)時(shí)自動(dòng)裝載某些Servlet,實(shí)現(xiàn)它只需要在web.XML文件中的<Servlet></Servlet>之間添加如下代碼:  

<loadon-startup>1</loadon-startup>
  2.在Servlet容器啟動(dòng)后,客戶首次向Servlet發(fā)送請(qǐng)求

  3.Servlet類(lèi)文件被更新后,重新裝載Servlet

DispatcherServlet的結(jié)構(gòu)

復(fù)習(xí)了上述知識(shí)后我們來(lái)看看DispatcherServlet的結(jié)構(gòu):

DispatcherServlet繼承自抽象類(lèi):FrameworkServlet,間接繼承了HttpServlet (FrameworkServlet繼承自HttpServletBean,而HttpServletBean繼承自HttpServlet )

Servlet的初始化

 protected void initStrategies(ApplicationContext context) {
 initMultipartResolver(context); //文件上傳解析,如果請(qǐng)求類(lèi)型是multipart將通過(guò)MultipartResolver進(jìn)行文件上傳解析;
 initLocaleResolver(context); //本地化解析
 initThemeResolver(context);   //主題解析
 initHandlerMappings(context); //通過(guò)HandlerMapping,將請(qǐng)求映射到處理器
 initHandlerAdapters(context); //通過(guò)HandlerAdapter支持多種類(lèi)型的處理器
 initHandlerExceptionResolvers(context); //如果執(zhí)行過(guò)程中遇到異常將交給HandlerExceptionResolver來(lái)解析
 initRequestToViewNameTranslator(context); //直接解析請(qǐng)求到視圖名
 initViewResolvers(context); //通過(guò)ViewResolver解析邏輯視圖名到具體視圖實(shí)現(xiàn)
 initFlashMapManager(context); //flash映射管理器
 }

servlet如何處理請(qǐng)求:

servlet的service方法處理http請(qǐng)求。

FrameworkServlet.java 定義了servlet的service和destroy方法,如下所示:

 /**
 * Override the parent class implementation in order to intercept PATCH
 * requests.
 */
 @Override
 protected void service(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {

 String method = request.getMethod();
 if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {
  processRequest(request, response);
 }
 else {
  super.service(request, response);
 }
 }

我們知道http請(qǐng)求類(lèi)型有七種(外加一個(gè)option選項(xiàng)),定義如下:

public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE

}

FrameworkServlet的service()處理不同的請(qǐng)求,我們以常見(jiàn)的post來(lái)說(shuō)明:

 /**
 * Process this request, publishing an event regardless of the outcome.
 * <p>The actual event handling is performed by the abstract
 * {@link #doService} template method.
 */
 protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {

 long startTime = System.currentTimeMillis();
 Throwable failureCause = null;

 LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
 LocaleContext localeContext = buildLocaleContext(request);

 RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
 ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
 asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

 initContextHolders(request, localeContext, requestAttributes);

 try {
  doService(request, response);
 }
 catch (ServletException ex) {
  failureCause = ex;
  throw ex;
 }
 catch (IOException ex) {
  failureCause = ex;
  throw ex;
 }
 catch (Throwable ex) {
  failureCause = ex;
  throw new NestedServletException("Request processing failed", ex);
 }

 finally {
  resetContextHolders(request, previousLocaleContext, previousAttributes);
  if (requestAttributes != null) {
  requestAttributes.requestCompleted();
  }

  if (logger.isDebugEnabled()) {
  if (failureCause != null) {
   this.logger.debug("Could not complete request", failureCause);
  }
  else {
   if (asyncManager.isConcurrentHandlingStarted()) {
   logger.debug("Leaving response open for concurrent processing");
   }
   else {
   this.logger.debug("Successfully completed request");
   }
  }
  }

  publishRequestHandledEvent(request, startTime, failureCause);
 }
 }

FrameworkServlet 抽象定義了處理流程,留待子類(lèi)來(lái)實(shí)現(xiàn)該方法,完成具體的請(qǐng)求處理。

/**
 * Subclasses must implement this method to do the work of request handling,
 * receiving a centralized callback for GET, POST, PUT and DELETE.
 * <p>The contract is essentially the same as that for the commonly overridden
 * {@code doGet} or {@code doPost} methods of HttpServlet.
 * <p>This class intercepts calls to ensure that exception handling and
 * event publication takes place.
 * @param request current HTTP request
 * @param response current HTTP response
 * @throws Exception in case of any kind of processing failure
 * @see javax.servlet.http.HttpServlet#doGet
 * @see javax.servlet.http.HttpServlet#doPost
 */
 protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
  throws Exception;

具體實(shí)現(xiàn)如下:

 /**
 * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
 * for the actual dispatching.
 */
 @Override
 protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
 if (logger.isDebugEnabled()) {
  String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
  logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
   " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
 }

 // Keep a snapshot of the request attributes in case of an include,
 // to be able to restore the original attributes after the include.
 Map<String, Object> attributesSnapshot = null;
 if (WebUtils.isIncludeRequest(request)) {
  attributesSnapshot = new HashMap<String, Object>();
  Enumeration<?> attrNames = request.getAttributeNames();
  while (attrNames.hasMoreElements()) {
  String attrName = (String) attrNames.nextElement();
  if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
   attributesSnapshot.put(attrName, request.getAttribute(attrName));
  }
  }
 }

 // Make framework objects available to handlers and view objects.
 request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
 request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
 request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
 request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

 FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
 if (inputFlashMap != null) {
  request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
 }
 request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
 request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

 try {
  doDispatch(request, response);
 }
 finally {
  if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
  return;
  }
  // Restore the original attribute snapshot, in case of an include.
  if (attributesSnapshot != null) {
  restoreAttributesAfterInclude(request, attributesSnapshot);
  }
 }
 }

重頭戲,作為請(qǐng)求分發(fā)器的實(shí)現(xiàn):

功能:1. 把請(qǐng)求分發(fā)到handler(按照配置順序獲取servlet的映射關(guān)系獲取handler);2. 根據(jù)servlet已安裝的  HandlerAdapters 去查詢第一個(gè)能處理的handler;3. handler激發(fā)處理請(qǐng)求

 /**
 * Process the actual dispatching to the handler.
 * <p>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.
 * <p>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.
  mappedHandler = getHandler(processedRequest);
  if (mappedHandler == null || mappedHandler.getHandler() == null) {
   noHandlerFound(processedRequest, response);
   return;
  }

  // Determine handler adapter for the current request.
  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()) {
   logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
   }
   if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
   return;
   }
  }

  if (!mappedHandler.applyPreHandle(processedRequest, response)) {
   return;
  }

  try {
   // Actually invoke the handler.
   mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  }
  finally {
   if (asyncManager.isConcurrentHandlingStarted()) {
   return;
   }
  }

  applyDefaultViewName(request, mv);
  mappedHandler.applyPostHandle(processedRequest, response, mv);
  }
  catch (Exception ex) {
  dispatchException = ex;
  }
  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);
  }
 }
 }

servlet銷(xiāo)毀

 /**
 * Close the WebApplicationContext of this servlet.
 * @see org.springframework.context.ConfigurableApplicationContext#close()
 */
 @Override
 public void destroy() {
 getServletContext().log("Destroying Spring FrameworkServlet '" + getServletName() + "'");
 // Only call close() on WebApplicationContext if locally managed...
 if (this.webApplicationContext instanceof ConfigurableApplicationContext && !this.webApplicationContextInjected) {
  ((ConfigurableApplicationContext) this.webApplicationContext).close();
 }
 }


小結(jié):

本文因篇章限制,僅僅介紹了請(qǐng)求處理的流程,沒(méi)有對(duì)代碼進(jìn)行深入的分析,接下來(lái)的文章將從細(xì)微處著手,分析spring的代碼之美。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式

    Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式

    這篇文章主要介紹了Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-04-04
  • Java網(wǎng)絡(luò)編程三要素及通信程序詳解

    Java網(wǎng)絡(luò)編程三要素及通信程序詳解

    這篇文章主要介紹了Java網(wǎng)絡(luò)編程三要素及通信程序詳解,Java網(wǎng)絡(luò)編程是在網(wǎng)絡(luò)通信協(xié)議下,實(shí)現(xiàn)網(wǎng)絡(luò)互連的不同計(jì)算機(jī)上運(yùn)行的程序間可以進(jìn)行數(shù)據(jù)交換,需要的朋友可以參考下
    2023-07-07
  • 使用Java 8中的Lambda表達(dá)式實(shí)現(xiàn)工廠模式

    使用Java 8中的Lambda表達(dá)式實(shí)現(xiàn)工廠模式

    這篇文章主要給大家介紹了使用Java 8中的Lambda表達(dá)式實(shí)現(xiàn)工廠模式的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-04-04
  • Java從ftp服務(wù)器上傳與下載文件的實(shí)現(xiàn)

    Java從ftp服務(wù)器上傳與下載文件的實(shí)現(xiàn)

    這篇文章主要給大家介紹了關(guān)于Java從ftp服務(wù)器上傳與下載文件的實(shí)現(xiàn)方法,最近項(xiàng)目中需要實(shí)現(xiàn)將文件先存放到ftp上,需要的時(shí)候再?gòu)膄tp上下載,做的過(guò)程中碰到了問(wèn)題,所以這里總結(jié)下,需要的朋友可以參考下
    2023-08-08
  • Spring Boot示例代碼整合Redis詳解

    Spring Boot示例代碼整合Redis詳解

    SpringBoot對(duì)常用的數(shù)據(jù)庫(kù)支持外,對(duì)NoSQL 數(shù)據(jù)庫(kù)也進(jìn)行了封裝自動(dòng)化,下面這篇文章主要給大家介紹了關(guān)于springboot使用redis的詳細(xì)步驟,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 利用POI讀取word、Excel文件的最佳實(shí)踐教程

    利用POI讀取word、Excel文件的最佳實(shí)踐教程

    Apache POI 是用Java編寫(xiě)的免費(fèi)開(kāi)源的跨平臺(tái)的 Java API,Apache POI提供API給Java程式對(duì)Microsoft Office格式檔案讀和寫(xiě)的功能。 下面這篇文章主要給大家介紹了關(guān)于利用POI讀取word、Excel文件的最佳實(shí)踐的相關(guān)資料,需要的朋友可以參考下。
    2017-11-11
  • 淺談java運(yùn)用注解實(shí)現(xiàn)對(duì)類(lèi)中的方法檢測(cè)的工具

    淺談java運(yùn)用注解實(shí)現(xiàn)對(duì)類(lèi)中的方法檢測(cè)的工具

    這篇文章主要介紹了淺談java運(yùn)用注解實(shí)現(xiàn)對(duì)類(lèi)中的方法檢測(cè)的工具,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • maven中更改jdk版本的方法實(shí)現(xiàn)

    maven中更改jdk版本的方法實(shí)現(xiàn)

    本文主要介紹了maven中更改jdk版本的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • Java中的Random和ThreadLocalRandom詳細(xì)解析

    Java中的Random和ThreadLocalRandom詳細(xì)解析

    這篇文章主要介紹了Java中的Random和ThreadLocalRandom詳細(xì)解析,Random 類(lèi)用于生成偽隨機(jī)數(shù)的流, 該類(lèi)使用48位種子,其使用線性同余公式進(jìn)行修改,需要的朋友可以參考下
    2024-01-01
  • Java用GDAL讀寫(xiě)shapefile的方法示例

    Java用GDAL讀寫(xiě)shapefile的方法示例

    Shapefile文件是描述空間數(shù)據(jù)的幾何和屬性特征的非拓?fù)鋵?shí)體矢量數(shù)據(jù)結(jié)構(gòu)的一種格式,由ESRI公司開(kāi)發(fā)。這篇文章給大家介紹了Java如何用GDAL讀寫(xiě)shapefile的方法示例,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。
    2016-12-12

最新評(píng)論

称多县| 湖北省| 宾川县| 拉孜县| 长乐市| 崇仁县| 灵璧县| 抚顺县| 齐齐哈尔市| 文昌市| 景德镇市| 柳江县| 大方县| 巢湖市| 琼海市| 巢湖市| 三亚市| 苗栗县| 和田市| 盖州市| 佛学| 静安区| 乐陵市| 科技| 通州市| 肃宁县| 红桥区| 荣成市| 方正县| 金昌市| 古蔺县| 苏尼特左旗| 黔西县| 济阳县| 墨玉县| 安庆市| 赤城县| 通江县| 商河县| 遂宁市| 龙游县|