在 Spring 框架中,Spring MVC 是其 Web 應用程序開發的一個強大模型-視圖-控制器(MVC)的實現。它提供了對請求進行映射、模型數據綁定、ViewResolver 和 RESTful web services 等許多功能的支持。本文將探討如何通過 Spring MVC 的自定義攔截器和異常處理來增強應用程序的安全性和健壯性。
自定義攔截器的配置和使用
1. 什麼是攔截器?
在 Spring MVC 中,攔截器(Interceptor)是一種可以在一個方法執行前後進行干預的對象。它們可以用於身份驗證、記錄日誌、緩存管理或任何其他需要在多個請求之間共享的信息。默認情況下,Spring MVC 提供了一些內置的攔截器,例如 HandlerMappingHandlerAdapter 鏈中的預處理器和後處理器。然而,有時候我們需要自定義這些行爲,這時就需要創建自己的攔截器類。
2. 創建自定義攔截器
要創建一個新的攔截器,需要繼承 `HandlerInterceptor` 接口並實現它的三個抽象方法:
public interface HandlerInterceptor<O extends Object> {
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
}
這三個方法的含義如下:
- `preHandle()`: 在控制器方法被調用之前執行。返回 true 表示允許繼續執行,false 則阻止執行。
- `postHandle()`: 在控制器方法完成之後但視圖渲染之前執行。
- `afterCompletion()`: 在整個請求處理完成後執行,無論是否發生異常。
3. 配置自定義攔截器
在 Spring XML 配置文件中,我們可以使用 “ 標籤來註冊我們的自定義攔截器:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 省略了其他的 bean 定義以保持簡潔 -->
<!-- 添加自定義攔截器 -->
<mvc:interceptors>
<bean id="myCustomInterceptor" class="com.example.MyCustomInterceptor"/>
</mvc:interceptors>
<!-- 將攔截器與特定的 URL 路徑關聯起來 -->
<mvc:interceptor>
<mvc:mapping path="/admin/**" />
<ref bean="myCustomInterceptor" />
</mvc:interceptor>
</beans>
在上述示例中,我們定義了一個名爲 `myCustomInterceptor` 的 Bean,它是我們的自定義攔截器類的實例。我們還爲這個攔截器指定了哪些URL路徑應該受到它的影響——在這個例子中,所有以 “/admin/” 開頭的URL都會被攔截。
異常處理
1. Spring MVC 中的異常處理概述
當程序運行時拋出異常,如果未被捕獲,將會導致錯誤頁面顯示給用戶。爲了提供一個更加友好的用戶體驗,我們應該捕獲異常並在控制層優雅地處理它們。Spring MVC 爲我們提供了一種機制來實現這一點。
2. @ExceptionHandler
你可以通過使用 `@ExceptionHandler` 註解的方法來處理特定類型的異常。以下是如何使用 `@ExceptionHandler` 的例子:
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
// 假設這是一個帶有@ControllerAdvice註解的類
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler({IllegalArgumentException.class}) // 處理 IllegalArgumentException 及其子類
public ResponseEntity handleValidationExceptions(HttpServletRequest request, Throwable exception) {
return new ResponseEntity(new ErrorMessage(exception.getMessage()), HttpStatus.BAD_REQUEST);
}
// 爲不同的異常類型編寫更多的 @ExceptionHandler 方法
}
在上述代碼中,`GlobalExceptionHandler` 類作爲全局異常處理程序,它會捕獲並響應任何匹配到指定的異常類型的請求。在這種情況下,`handleValidationExceptions` 方法將被調用,並且會返回一個包含錯誤消息的 JSON 對象和一個HTTP狀態碼。
3. @ControllerAdvice
`@ControllerAdvice` 註釋告訴 Spring 應用上下文中的每個控制器可以使用此類中的 @ExceptionHandler 和其他方法。這意味着你不必在你的控制器中顯式聲明異常處理邏輯,而是可以將它們集中在一個地方。
4. 自定義錯誤頁面
除了使用 `@ExceptionHandler` 之外,你還可以設置自定義錯誤頁面,這樣當發生未處理的異常時,用戶就會看到一個定製的錯誤頁而不是默認的 HTTP 500 頁面。這可以通過在 HTML 模板中放置特定的錯誤頁面或者在 `DispatcherServlet` 的 `errorPages` 屬性中指定它們來完成。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 省略了其他的 bean 定義以保持簡潔 -->
<!-- 指定錯誤的靜態資源路徑 -->
<mvc:resources mapping="/errors/**" location="/WEB-INF/errors/" />
<!-- DispatcherServlet 配置 -->
<mvc:annotation-driven>
<mvc:default-servlet-handler/>
<mvc:resources mapping="/css/**" location="/css/" cache-period="3600"/>
<mvc:resources mapping="/js/**" location="/js/" cache-period="3600"/>
<mvc:resources mapping="/images/**" location="/images/" cache-period="3600"/>
<mvc:resources mapping="/favicon.ico" location="/favicon.ico"/>
<mvc:resources mapping="/robots.txt" location="/robots.txt"/>
<mvc:resources mapping="/fonts/**" location="/fonts/"/>
<mvc:resources mapping="/swagger-ui.html" location="classpath:/META-INF/resources/"/>
<mvc:resources mapping="/v2/api-docs" location="classpath:/META-INF/resources/"/>
<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>
<mvc:resources mapping="/doc/**" location="file:" + yourDocsFolderPath + "/"/>
</mvc:annotation-driven>
<!-- 其他配置 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 更多配置... -->
</beans>
在上面的示例中,我們定義了一個名爲 `/errors/**` 的資源映射,這將使 DispatcherServlet 查找位於 `/WEB-INF/errors/` 目錄下的任何資源作爲錯誤頁面。因此,如果你想要定製化錯誤頁面,只需要在這些目錄下放置相應的HTML或其他格式的文件即可。