思惟導圖學習 | 第十篇:java學習中級篇(框架),讓Spring再也不難懂(mvc篇)

寫在前面

生活就像海洋,只有意志堅強的人才能到達彼岸。php

已經好久沒有發文章了呀,想必你們都掛念我了,哈哈。html

溫故而知新,今天一塊兒來複習一下spring mvc的內容吧。前端

首先咱們看下一個MVC的完整的思惟導圖

完整Spring MVC思惟導圖

spring mvc簡介與運行原理

Spring的模型-視圖-控制器(MVC)框架是圍繞一個DispatcherServlet來設計的,這個Servlet會把請求分發給各個處理器,並支持可配置的處理器映射、視圖渲染、本地化、時區與主題渲染等,甚至還能支持文件上傳。java

Spring MVC流程

  • (1) Http請求:客戶端請求提交到DispatcherServletpython

  • (2) 尋找處理器:由DispatcherServlet控制器查詢一個或多個HandlerMapping,找處處理請求的Controllergit

  • (3) 調用處理器:DispatcherServlet將請求提交到Controller程序員

  • (4)(5)調用業務處理和返回結果:Controller調用業務邏輯處理後,返回ModelAndViewweb

  • (6)(7)處理視圖映射並返回模型: DispatcherServlet查詢一個或多個ViewResoler視圖解析器,找到ModelAndView指定的視圖。面試

  • (8) Http響應:視圖負責將結果顯示到客戶端。spring

主要註解

spring mvc註解

ContextLoaderListener

在講ContextLoaderListener以前,首先來了解一下web.xml的做用。

  • 一個web中能夠沒有web.xml文件,也就是說,web.xml文件並非web工程必須的。web.xml文件是用來初始化配置信息:好比Welcome頁面、servletservlet-mappingfilterlistener、啓動加載級別等。當你的web工程沒用到這些時,你能夠不用web.xml文件來配置你的Application

  • 當要啓動某個web項目時,服務器軟件或容器如(tomcat)會第一步加載項目中的web.xml文件,經過其中的各類配置來啓動項目,只有其中配置的各項均無誤時,項目才能正確啓動。web.xml有多項標籤,在其加載的過程當中順序依次爲:context-param >> listener >> fileter >> servlet。(同類多個節點以出現順序依次加載)

web.xml加載過程

spring mvc啓動過程大體分爲兩個過程:

  • ContextLoaderListener初始化,實例化IoC容器,並將此容器實例註冊到ServletContext中。

  • DispatcherServlet初始化。

web.xml配置

其中ContextLoaderListener監聽器它實現了ServletContextListener這個接口,在web.xml配置這個監聽器,啓動容器時,就會默認執行它實現的方法。在ContextLoaderListener中關聯了ContextLoader這個類,因此整個加載配置過程由ContextLoader來完成。

  • ContextLoaderListenerweb.xml中的配置
<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- 配置contextConfigLocation初始化參數 -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value></context-param>
<!-- 配置ContextLoaderListerner -->
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</pre>

ServletContextListener 接口有兩個方法:contextInitialized,contextDestroyed

DispatcherServlet

Spring MVC框架,與其餘不少webMVC框架同樣:請求驅動;全部設計都圍繞着一箇中央Servlet來展開,它負責把全部請求分發到控制器;同時提供其餘web應用開發所須要的功能。不過Spring的中央處理器,DispatcherServlet,能作的比這更多。

下圖展現了Spring Web MVCDispatcherServlet處理請求的工做流。熟悉設計模式的朋友會發現,DispatcherServlet應用的其實就是一個「前端控制器」的設計模式(其餘不少優秀的web框架也都使用了這個設計模式)。

  • 流程圖

spring mvc處理請求的流程

  • web.xml中的配置
<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- servlet定義 -->
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
    <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
</pre>

其中

  • load-on-startup:表示啓動容器時初始化該Servlet

  • url-pattern:表示哪些請求交給Spring Web MVC處理, 「/」 是用來定義默認servlet映射的。也能夠如「*.html」表示攔截全部以html爲擴展名的請求。

Spring MVC中,每一個DispatcherServlet都持有一個本身的上下文對象WebApplicationContext,它又繼承了根(root)WebApplicationContext對象中已經定義的全部bean。這些繼承的bean能夠在具體的Servlet實例中被重載,在每一個Servlet實例中你也能夠定義其scope下的新bean

WebApplicationContext繼承自ApplicationContext,它提供了一些web應用常常須要用到的特性。它與普通的ApplicationContext不一樣的地方在於,它支持主題的解析,而且知道它關聯到的是哪一個servlet(它持有一個該ServletContext的引用)

DispatcherServlet繼承結構

spring mvc同時提供了不少特殊的註解,用於處理請求和渲染視圖等。DispatcherServlet初始化的過程當中會默認使用這些特殊bean進行配置。若是你想指定使用哪一個特定的bean,你能夠在web應用上下文WebApplicationContext中簡單地配置它們。

特殊bean

其中,經常使用的ViewResolver的配置。以jsp做爲視圖爲例

<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- 對模型視圖名稱的解析,即在模型視圖名稱添加先後綴 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" /></bean>
</pre>

配置上傳文件限制MultipartResolver

<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- 上傳限制 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     <!-- 上傳文件大小限制爲31M,31*1024*1024 -->
     <property name="maxUploadSize" value="32505856"/></bean>
</pre>

applicationContext.xml中的標籤

applicationContext.xml配置文件標籤

文件上傳

前面說到DispatcherServlet中有個特殊的Bean叫MultipartResolver,可用於限制文件的上傳大小等。當解析器MultipartResolver完成處理時,請求便會像其餘請求同樣被正常流程處理。

  • 表單
<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<form method="post" action="/form" enctype="multipart/form-data">
     <input type="text" name="name"/>
     <input type="file" name="file"/>
     <input type="submit"/></form>
</pre>
  • 控制器
<pre class="hljs java" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
@RequestMapping(path = "/form", method = RequestMethod.POST) 
public String handleFormUpload(
            @RequestParam("name") String name, 
            @RequestParam("file") MultipartFile file) {   
   if (!file.isEmpty()){          
           byte[] bytes = file.getBytes();   // store the bytes somewhere
          return "redirect:uploadSuccess";
        }    
          return "redirect:uploadFailure";
}
</pre>

異常處理

先來講下常見的異常處理有幾種方式,以下圖:

異常處理方式

Spring的處理器異常解析器HandlerExceptionResolver接口的實現負責處理各種控制器執行過程當中出現的異常。也是上面提到的,是DispatcherServlet中的特殊bean,能夠自定義配置處理。

某種程度上講,HandlerExceptionResolver與你在web應用描述符web.xml文件中能定義的異常映射(exception mapping)很相像,不過它比後者提供了更靈活的方式。好比它能提供異常被拋出時正在執行的是哪一個處理器這樣的信息。

  • HandlerExceptionResolver 提供resolveException接口
<pre class="hljs java" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
public interface HandlerExceptionResolver {  
    ModelAndView resolveException(  HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);  
}
</pre>
  • 在BaseController中使用 @ExceptionHandler註解處理異常
<pre class="hljs php" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">    @ExceptionHandler(Exception.class)    public Object exceptionHandler(Exception ex, HttpServletResponse response, 
              HttpServletRequest request) throws IOException {
        String url = "";
        String msg = ex.getMessage();
        Object resultModel = null;        try {            if (ex.getClass() == HttpRequestMethodNotSupportedException.class) {
                url = "admin/common/500";
                System.out.println("--------毛有找到對應方法---------");
            } else if (ex.getClass() == ParameterException.class) {//自定義的異常

            } else if (ex.getClass() == UnauthorizedException.class) {
                url = "admin/common/unauth";
                System.out.println("--------毛有權限---------");
            }

            String header = req.getHeader("X-Requested-With");
            boolean isAjax = "XMLHttpRequest".equalsIgnoreCase(header);
            String method = req.getMethod();
            boolean isPost = "POST".equalsIgnoreCase(method);            if (isAjax || isPost) {                return Message.error(msg);
            } else {
                ModelAndView view = new ModelAndView(url);
                view.addObject("error", msg);
                view.addObject("class", ex.getClass());
                view.addObject("method", request.getRequestURI());                return view;
            }
        } catch (Exception exception) {
            logger.error(exception.getMessage(), exception);            return resultModel;
        } finally {
            logger.error(msg, ex);
            ex.printStackTrace();
        }
    }</pre>
  • *在web.xml中處理異常 *
<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- 默認的錯誤處理頁面 -->
<error-page>
    <error-code>403</error-code>
    <location>/403.html</location></error-page><error-page>
    <error-code>404</error-code>
    <location>/404.html</location>
</error-page>
<!-- 僅僅在調試的時候注視掉,在正式部署的時候不能註釋 --><!-- 這樣配置也是能夠的,表示發生500錯誤的時候,轉到500.jsp頁面處理。 -->
<error-page> 
    <error-code>500</error-code> 
    <location>/500.html</location> 
</error-page> 
<!-- 這樣的配置表示若是jsp頁面或者servlet發生java.lang.Exception類型(固然包含子類)的異常就會轉到500.jsp頁面處理。 -->
<error-page> 
    <exception-type>java.lang.Exception</exception-type> 
    <location>/500.jsp</location> </error-page> <error-page> 
    <exception-type>java.lang.Throwable</exception-type> 
    <location>/500.jsp</location>
</error-page>
<!-- 當error-code和exception-type都配置時,exception-type配置的頁面優先級高及出現500錯誤,發生異常Exception時會跳轉到500.jsp-->
</pre>
  • 來一個問題:HandlerExceptionResolver和web.xml中配置的error-page會有衝突嗎?

解答:若是resolveException返回了ModelAndView,會優先根據返回值中的頁面來顯示。不過,resolveException能夠返回null,此時則展現web.xml中的error-page500狀態碼配置的頁面。 當web.xml中有相應的error-page配置,則能夠在實現resolveException方法時返回nullAPI文檔中對返回值的解釋:

return a corresponding ModelAndView to forward to, or null for default processing.

配套Ximnd學習導圖下載地址

java思惟導圖:https://gitee.com/1341541819.com/java_xmind/tree/master

寫在最後

歡迎關注喜歡、和點贊後續將推出更多的思惟導圖教程,敬請期待。 歡迎關注個人微信公衆號免費獲取更多更全的學習資源,視頻資料,技術乾貨! 歡迎掃碼關注 資源領取方式

公衆號回覆「學習」,拉你進程序員技術討論羣乾貨資源第一時間分享。

公衆號回覆「視頻」,領取800GJava視頻學習資源。 java學習全套 820G資源

公衆號回覆「全棧」,領取1T前端Java產品經理微信小程序Python等資源合集大放送。 全棧資料 java python 機器學習 產品經理 接近1T資源

公衆號回覆「慕課」,領取1T慕課實戰學習資源。 慕課實戰大全 php python 測試 後端 前端 前端 微信 1061G資源

公衆號回覆「實戰」,領取750G項目實戰學習資源。 先後端實戰項目 750實戰資源

公衆號回覆「面試」,領取8G面試實戰學習資源。 JAVA面試實戰視頻 傳智面試講解 8G面試資源

相關文章
相關標籤/搜索