SpringMVC中session使用&&攔截器&&亂碼處理&&異常處理

### 1. 使用Sessionjava

一般,會在Session中存放:web

1. 客戶端(用戶)的身份標識,一般是用戶的id;
2. 使用頻率很是高的數據,例如顯示在頁面中的用戶名、頭像等;
3. 其它的不便於使用其它存儲方案來存取或傳遞的數據。spring

關於Session的使用,和`ModelMap`幾乎同樣,即在處理請求的方法中添加`HttpSession`參數,並在方法體中操做該參數對象便可。數據庫

### 2. 攔截器:Interceptor瀏覽器

Spring MVC中的攔截器(Interceptor)與Java EE中的過濾器(Filter)比較類似,能夠對某些請求嘗試攔截,由開發者自行編寫攔截的邏輯,使得某些請求能夠執行,而某些請求將不容許執行,實現統一管理的效果。mvc

在使用時,必須先自定義攔截器類,實現`HandlerInterceptor`接口,而後在Spring的配置文件中進行配置。app

當實現`HandlerInterceptor`接口後,須要重寫3個未實現的方法,其中,`public boolean preHandle()`方法是起到攔截做用的,在運行在控制器以前的,該方法的返回值是boolean類型的,表示是否放行,即返回true則放行,返回false則攔截!一旦攔截,控制器方法將不會被執行,而且攔截器中剩下的2個方法也不會被執行,若是經過瀏覽器進行訪問,界面將顯示一片空白!框架

注意:即便執行重定向語法,若是攔截器`return true;`,依然會執行控制器中的方法和攔截器中另2個方法,則沒有攔截效果,因此,當符合攔截條件時,應該`return false;`。編碼

關於攔截器的配置大體以下:url

<!-- 攔截器鏈 -->
    <mvc:interceptors>
        <!-- 第1個攔截器 -->
        <mvc:interceptor>
            <!-- 攔截路徑 -->
            <mvc:mapping path="/user/index.do"/>
            <!-- 攔截器類 -->
            <bean class="cn.tedu.spring.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
        <!-- 第2個攔截器 -->
        <!-- 第3個攔截器 -->
        <!-- 第N個攔截器 -->
    </mvc:interceptors>

即:SpringMVC是支持**攔截器鏈**的,在同一個項目中,容許存在多個攔截器,造成攔截器鏈,多個攔截器的執行前後順序取決於配置的前後順序。

在配置每個攔截器的`<mvc:interceptor>`節點中,`<mvc:mapping>`節點用於配置須要攔截的路徑,該節點能夠存在若干個,例如:

<mvc:interceptor>
        <!-- 攔截路徑 -->
        <mvc:mapping path="/user/index.do"/>
        <mvc:mapping path="/user/logout.do"/>
        <!-- 攔截器類 -->
        <bean class="cn.tedu.spring.interceptor.LoginInterceptor"></bean>
    </mvc:interceptor>

而且,在配置路徑時,是支持通配符的,例如:

<mvc:mapping path="/user/*"/>

即:例如`/user/reg.do`、`/user/login.do`、`/user/handle_reg.do`等這些路徑都在攔截範圍以內!

可是,須要注意的是:1個星號表示的通配符只能匹配1層路徑,例如`/user/*`不能夠匹配到`/user/news/list.do`這樣的路徑!若是要匹配若干層路徑,可使用2個星號,例如配置爲`/user/**`。

除此之外,在配置時,還能夠添加`<mvc:exclude-mapping>`節點,以配置例外,例如:

<!-- 攔截路徑 -->
    <mvc:mapping path="/user/*"/>
    <!-- 添加例外 -->
    <mvc:exclude-mapping path="/user/reg.do"/>
    <mvc:exclude-mapping path="/user/login.do"/>
    <mvc:exclude-mapping path="/user/handle_reg.do"/>
    <mvc:exclude-mapping path="/user/handle_login.do"/>


關於`<mvc:exclude-mapping>`的配置方式,與`<mvc:mapping>`相同,也可使用通配符。

以上`<mvc:mapping>`也能夠理解爲**攔截名單**,而`<mvc:exclude-mapping>`就是**白名單**。

以上配置是必須有前後順序的,`<mvc:mapping>`必須在最前,其次是`<mvc:exclude-mapping>`,最後是攔截器`<bean>`。

僅在攔截範圍以內的,纔會觸發攔截器執行(不管最終是攔截仍是放行),若是某路徑不在攔截範圍以內(包含被添加到例外的),將根本就不觸發攔截器的執行。

### 3. SpringMVC項目的亂碼解決方案

整個SpringMVC框架默認使用的編碼都是ISO-8859-1,是不支持中文的,因此,在`DispatcherServlet`接收到請求的那一刻起,數據的編碼就已是ISO-8859-1,爲了修改編碼,只能經過過濾器(Filter)來設置,在SpringMVC中也定義好了`CharacterEncodingFilter`,用於設置字符編碼,因此,當使用SpringMVC時,應該在`web.xml`中配置該過濾器,併爲這個過濾器類的`encoding`屬性設置編碼值:

<filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

### 4. SpringMVC處理異常

控制器是向客戶端進行響應的組件,若是在控制器中的代碼運行時出現異常,應該進行處理,若是不處理異常,則會按照默認的方式處理,有幾處問題:

1. 對於沒有計算機開發相關基礎的用戶而言,體驗不好(界面上顯示的錯誤徹底看不懂);
2. 對於掌握了計算機開發相關技術的用戶而言,可能從中獲取當前項目的某些實現細節(異常的跟蹤信息中會顯示某些類、方法的名稱等),致使項目的部份內容外泄;
3. 其它問題。

因此,在控制器中,應該對可能存在的異常進行處理!注意:此處的「處理」不包括使用`throw`拋出,而是經過`try...catch`相似的方式捕獲並在`catch`代碼塊中進行處理,例如:

@RequestMapping("null.do") public String showNull( String username, ModelMap modelMap) { try { username.length(); } catch (NullPointerException e) { String message = "您的操做有誤,未提交必要的參數,請<a href=input.do>從新提交</a>!"; modelMap.addAttribute("msg", message); return "error"; } return null; }

因爲異常出現的頻率可能較高,或者,在多個不一樣的請求中均可能出現,那麼,在每一個方法中都進行處理,是不現實的,也不便於代碼的管理!

在SpringMVC中,提供了2種統一處理異常的作法:

**1. 經過SimpleMappingExceptionResolver**

在Spring的配置文件中,對`SimpleMappingExceptionResolver`進行配置,肯定異常與轉發的頁面的映射便可:

<!-- 處理異常 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.NullPointerException">error</prop>
                <prop key="java.lang.StringIndexOutOfBoundsException">oob</prop>
                <prop key="java.lang.RuntimeException">runtime</prop>
            </props>
        </property>
    </bean>


使用這種作法時,若是出現異常,框架將自動轉發到對應的頁面,開發者難以對異常出現的緣由做出針對性的處理!因此,這種作法只適合比較粗糙的、大概的處理異常!

同時,這種作法固定使用轉發來顯示錯誤提示頁面,沒法更改成其它方式的響應!

**2. 使用@ExceptionHandler**

在控制器類中,能夠自定義處理異常的方法,並在方法以前添加`@ExceptionHandler`註解,該方法的設計規則與處理請求的方法大體相同,區別在於參數不能夠隨便寫,必須包含1個異常類型的參數,

 @ExceptionHandler public String handleException(Exception e) { if (e instanceof NullPointerException) { return "error"; } else if (e instanceof StringIndexOutOfBoundsException) { return "oob"; } return "exception"; }

> 使用`@ExceptionHandler`以前,必須保證在Spring配置文件中已經配置了註解驅動,即`<mvc:annotation-driven />`。

在使用`@ExceptionHandler`註解時,能夠在註解中添加屬性的配置,以肯定所處理的異常的範圍,例如:

@ExceptionHandler(IndexOutOfBoundsException.class)

通過以上配置,僅`IndexOutOfBoundsException`及其子孫類異常會被接下來的方法進行處理,而其它異常的出現,並不會致使對應的方法被執行!

在控制器中,容許同時存在多個處理異常的方法!

處理異常的方法僅能做用於當前控制器類中的請求!若是某個處理異常的方法的代碼但願被通用,能夠將這個處理異常的方法寫在控制器類的基類中。

以上兩種統一處理異常的方式是能夠同時存在的!且第2種方式的優先級高於第1種方式。

**附:常見異常**

 Throwable Error OutOfMemoryError Exception SqlException IOException FileNotFoundException RuntimeException NullPointException ClassCastException ArithmeticException IndexOutOfBoundsException ArrayIndexOutOfBoundsException


### 【附】 攔截器和過濾器的區別

過濾器(Filter)是Java EE體系中的,而攔截器(Interceptor)是SpringMVC中的;

過濾器是在全部的Servlet以前執行的,而攔截器的初次執行是在DispatcherServlet以後、在Controller以前執行的;

過濾器的過濾範圍只能在web.xml中經過<url-pattern>這1個節點來配置,而攔截器能夠配置多個攔截路徑,且能夠添加例外,配置更加靈活;

全部的請求均可以被過濾器進行處理,卻只有交由DispatcherServlet分發的請求才可能被攔截器處理!

### 【附】 字符編碼問題 / 出錯時的亂碼問題

在不考慮某些編碼不支持中文的狀況下,使用了支持中文的編碼,仍會出現亂碼的緣由只有1個:存和取的時候使用了不一樣的編碼。

因此,解決方案就是:整個項目涉及的全部位置所有使用相同的編碼!

一般,須要指定編碼的位置有:1. 項目的源代碼,例如某個String類型數據的值;2. 顯示界面的組件所使用的編碼,例如HTML/JSP使用的編碼;3. 數據存儲位置使用的編碼,例如數據庫中的編碼;4. 數據傳輸過程當中使用的編碼,例如請求、響應,或數據庫鏈接的URL。

相關文章
相關標籤/搜索