1. 程式人生 > 實用技巧 >【SpringMVC】國際化&檔案的上傳&使用攔截器&異常處理

【SpringMVC】國際化&檔案的上傳&使用攔截器&異常處理

國際化

國際化概述

  • 預設情況下,SpringMVC 根據 Accept-Language 引數判斷客戶端的本地化型別。
  • 當接受到請求時,SpringMVC 會在上下文中查詢一個本地化解析器(LocalResolver),找到後使用它獲取請求 所對應的本地化型別資訊。
  • SpringMVC 還允許裝配一個動態更改本地化型別的攔截器,這樣通過指定一個請求引數就可以控制單個請求的本地化型別。

SessionLocaleResolver & LocaleChangeInterceptor 工作原理

本地化解析器和本地化攔截器

  • AcceptHeaderLocaleResolver:根據 HTTP 請求頭的 Accept-Language 引數確定本地化型別,如果沒有顯式定義本地化解析器, SpringMVC 使用該解析器。
  • CookieLocaleResolver:根據指定的 Cookie 值確定本地化型別
  • SessionLocaleResolver:根據 Session 中特定的屬性確定本地化型別
  • LocaleChangeInterceptor:從請求引數中獲取本次請求對應的本地化型別。
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
<mvc:interceptors>
  <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>

檔案上傳

  • Spring MVC 為檔案上傳提供了直接的支援,這種支援是通過即插即用的 MultipartResolver 實現的。Spring 用 Jakarta Commons FileUpload 技術實現了一個 MultipartResolver 實現類:CommonsMultipartResovler
  • Spring MVC 上下文中預設沒有裝配 MultipartResovler,因此預設情況下不能處理檔案的上傳工作,如果想使用 Spring 的檔案上傳功能,需現在上下文中配置 MultipartResolver

配置 MultipartResolver

  • defaultEncoding: 必須和使用者 JSP 的 pageEncoding 屬性一致,以便正確解析表單的內容
  • 為了讓 CommonsMultipartResovler 正確工作,必須先 將 Jakarta Commons FileUpload 及 Jakarta Commons io 的類包新增到類路徑下。
<bean id="multipartResolver" class="org.springframework.web.mutipart.commons.CommonsMultipartResolver">
  <property name="defaultEncoding" value="UTF-8"></property>
  <property name="maxUploadSize" value="5242880"></property>
</bean>

檔案上傳示例

<form method="post" action="hello/upload.action" enctype="multipart/form-data">
  Desc:<input type="text" name="desc"/>
  File:<input type="file" name="file"/>
</form>
@RequestMapping("/upload")
public String upload(@RequestParam("desc") String desc,@RequestParam("file") multipartFile file) throws Exception {
    if(!file.isEmpty()) {
        System.out.println("desc");
        file.transferTo(new File("d:\\temp\\" + file.getOriginalFilename()));
    }
    return "success";
}

自定義攔截器

Spring MVC也可以使用攔截器對請求進行攔截處理,使用者可以自定義攔截器來實現特定的功能,自定義的攔截器必須實現HandlerInterceptor介面

  • preHandle():這個方法在業務處理器處理請求之前被呼叫,在該方法中對使用者請求 request 進行處理。如果程式設計師決定該攔截器對請求進行攔截處理後還要呼叫其他的攔截器,或者是業務處理器去進行處理,則返回true;如果程式設計師決定不需要再呼叫其他的元件 去處理請求,則返回false。
  • postHandle():這個方法在業務處理器處理完請求後,但是DispatcherServlet 向客戶端返回響應前被呼叫,在該方法中對 使用者請求request進行處理。
  • afterCompletion():這個方法在 DispatcherServlet 完全處理完請求後被呼叫,可以在該方法中進行一些資源清理的操作。

攔截器方法執行順序

配置自定義攔截器

<mvc:interceptors>
  <!-- 攔截所有資源 -->
  <bean class="com.nemo.springmvc.interceptors.HelloInterceptor"></bean>
  <!-- 攔截指定資源 -->
  <mvc:interceptor>
    <mvc:mapping path="/emps"/>
    <bean class="com.nemo.springmvc.interceptors.HelloInterceptor2"></bean>
  </mvc:interceptor>
  <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>

異常處理

  • Spring MVC 通過 HandlerExceptionResolver 處理程式的異常,包括 Handler 對映、資料繫結以及目標方法執行時發生的異常。
  • SpringMVC 提供的 HandlerExceptionResolver 的實現類

HandlerExceptionResolver

DispatcherServlet 預設裝配的 HandlerExceptionResolver:

  • 沒有使用 <mvc:annotation-driven/> 配置:
  • 使用了 <mvc:annotation-driven/> 配置:

ExceptionHandlerExceptionResolver

  • 主要處理 Handler 中用 @ExceptionHandler 註解定義的方法。
  • @ExceptionHandler 註解定義的方法優先順序問題:例如發生的是NullPointerException,但是宣告的異常有 RuntimeException 和 Exception,此候會根據異常的最近繼承關係找到繼承深度最淺的那個 @ExceptionHandler 註解方法,即標記了 RuntimeException 的方法
  • ExceptionHandlerMethodResolver 內部若找不到@ExceptionHandler 註解的話,會找 @ControllerAdvice 中的@ExceptionHandler 註解方法

ResponseStatusExceptionResolver

  • 在異常及異常父類中找到 @ResponseStatus 註解,然後使用這個註解的屬性進行處理。
  • 定義一個 @ResponseStatus 註解修飾的異常類
  • 若在處理器方法中丟擲了上述異常: 若ExceptionHandlerExceptionResolver 不解析述異常。由於觸發的異常 UnauthorizedException 帶有@ResponseStatus 註解。因此會被ResponseStatusExceptionResolver 解析到。最後響應HttpStatus.UNAUTHORIZED 程式碼給客戶端。HttpStatus.UNAUTHORIZED 代表響應碼401,無許可權。關於其他的響應碼請參考 HttpStatus 列舉型別原始碼。

DefaultHandlerExceptionResolver

對一些特殊的異常進行處理,比如NoSuchRequestHandlingMethodException、HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException 等。

SimpleMappingExceptionResolver

如果希望對所有異常進行統一處理,可以使用 SimpleMappingExceptionResolver,它將異常類名對映為檢視名,即發生異常時使用對應的檢視報告異常

<bean id="SimpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  <property name="exceptionMappings">
    <props>
      <prop key="java.lang.ArithmeticException">error</prop>
    </props>
  </property>
</bean>