文章目錄
- 一、攔截器概述
-
- (一)攔截器的實作方式
- (二) 攔截器的配置
- 二、攔截器的執行流程
-
- (一)單個攔截器的執行流程
- (二)多個攔截器的執行流程
- 三、應用案列——使用者登入權限驗證
- 四、攔截器小結
一、攔截器概述
SpringMVC的攔截器(Interceptor)與java Servlet的過濾器(Filter)類似,用于攔截使用者的請求并且做出相應的處理。一般應用于權限認證、記錄請求資訊的日志、判斷使用者是否登陸等功能。
(一)攔截器的實作方式
一種是通過實作 Handlerlnterceptor 接口; 另一種是通過實作 WebRequestlnterceptor 接口。
以實作 Handlerlnterceptor 接口的定義方式為例,自定義攔截器類的代碼如下所示。
public class TestInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("preHandle方法在控制器處理請求方法前執行");
/**
* 傳回值為true表示繼續向下執行,false表示中斷後續操作
*/
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("postHandle 方法在控制器的處理請求方法調用之後,解析視圖之前執行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("afterCompletion 方法在視圖渲染結束之後執行,即最後執行");
}
}
• preHandler方法:該方法會在控制器方法前執行,其傳回值表示是否中斷後續操作。
• postHandle方法:該方法會在控制器方法調用之後,且解析視圖之前執行。 可以通過此 方法對請求域中的模型和視圖做出進一步的修改。
• afterCompletion方法:方法會在整個請求完成,即視圖渲染結束之後執行。 可以通過此方法實作一些資源清理、記錄曰志資訊等工作。
(二) 攔截器的配置
要使自定義的攔截器類生效,還需要在 Spring MVC 的配置檔案中進行配置。配置代碼如下:
<!-- 配置攔截器 -->
<mvc:interceptors>
<!-- 配置一個全局攔截器,攔截所有的請求 -->
<bean class="interceptor.LoginInterceptor"></bean>
<mvc:interceptor>
<!-- 配置攔截器的作用路徑 -->
<mvc:mapping path="/**"/>
<!-- 配置不需要攔截的路徑 -->
<mvc:exclude-mapping path=""/>
<!-- 定義在<mvc:interceptor>下面的,表示對比對路徑的請求才進行攔截 -->
<bean class="interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
注意:
1、攔截器bean類所放的位置決定攔截器是全局攔截器還是局部攔截器
2、<mvc:mapping path="/gotoTest"/>表示攔截以/gotoTest結尾的路徑
3、 mvc:interceptor 中的子元素必須嚴格按照 <:mvc:mapping … />、<mvc:exclude-mapping … />、<bean … />的順序。
二、攔截器的執行流程
(一)單個攔截器的執行流程
1、控制器類InterceptorController
@Controller
public class InterceptorController {
@RequestMapping("/gotoTest")
public String gotoTest() {
System.out.println("Controller正在測試攔截器,執行控制器的處理請求方法!");
return "test";
}
}
2、攔截器類
public class TestInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("preHandle方法在控制器處理請求方法前執行");
/**
* 傳回值為true表示繼續向下執行,false表示中斷後續操作
*/
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("postHandle 方法在控制器的處理請求方法調用之後,解析視圖之前執行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("afterCompletion 方法在視圖渲染結束之後執行,即最後執行");
}
}
3、Springmvc-servlet.xml
<!-- 使用掃描機制掃描控制器類 -->
<context:component-scan base-package="com.controller"></context:component-scan>
<!-- 配置視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置攔截器 -->
<mvc:interceptors>
<!-- 配置一個全局攔截器,攔截所有的請求 -->
<bean class="interceptor.LoginInterceptor"></bean>
</mvc:interceptors>
4、運作結果
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL1EFRNhXWE9EeRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2cDN4QTOwUTMzIzMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
(二)多個攔截器的執行流程
1、控制器和攔截器上同
2、Springmvc-servlet.xml檔案的配置
<mvc:interceptors>
<mvc:interceptor>
<!-- 配置攔截器的作用路徑 -->
<mvc:mapping path="/**"/>
<!-- 定義在<mvc:interceptor>下面的,表示對比對路徑的請求才進行攔截 -->
<bean class="interceptor.Interceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- 配置攔截器的作用路徑 -->
<mvc:mapping path="/gotoTest"/>
<bean class="interceptor.Interceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
3、運作結果
多個攔截器在執行的過程中,preHandle方法按照配置檔案中攔截器的配置順序執行,而postHandle和afterCompletion方法則按照配置檔案的反序執行。
三、應用案列——使用者登入權限驗證
1、建立POJO類
public class User {
private String uname;
private String upwd;
//省略getter和setter方法
}
2、建立控制器類
@Controller
public class UserController {
/**
* 登入頁面初始化
*/
@RequestMapping("/tologin")
public String initLogin() {
return "login";
}
/**
* 處理登入功能
*/
@RequestMapping("/login")
public String login(User user,Model model,HttpSession session) {
System.out.println("使用者名:"+user.getUname());
if("juhaijun".equals(user.getUname())
&&"123456".equals(user.getUpwd())) {
session.setAttribute("user", user);
return "redirect:main";
}
model.addAttribute("msg", "使用者名或密碼錯誤");
System.out.println("使用者名或密碼錯誤!");
return "login";
}
/**
* 跳轉到首頁面
*/
@RequestMapping("/main")
public String toMain() {
return "main";
}
/**
* 登出
*/
@RequestMapping("/logout")
public String logout(HttpSession session) {
// 清除session
session.invalidate();
return "login";
}
}
3、建立攔截器類
public class LoginInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 擷取登陸的url
String url= request.getRequestURI();
System.out.println("請求路徑為:"+url);
// 登入界面不進行攔截
if(url.indexOf("/tologin")>=0 || url.indexOf("/login")>=0) {
return true;
}
// 擷取session
HttpSession session = request.getSession();
Object obj = session.getAttribute("user");
if(obj != null) {
//處于登入狀态
return true;
}
// 未登入狀态
request.setAttribute("msg", "使用者還未登陸,請先登入");
request.getRequestDispatcher("/WEB-INF/views/login.jsp").forward(request, response);
return false;
}
}
4、建立jsp頁面——登入頁面和主界面
<body>
${msg }
<form action="${pageContext.request.contextPath }/login" method="post">
使用者名:<input type="text" name="uname"/>
密碼:<input type="password" name="upwd"/>
<input type="submit" value="登入"/>
</form>
</body>
<body>
目前使用者:${user.uname }<br>
<a href="${pageContext.request.contextPath }/logout">退出</a>
</body>
5、運作結果
四、攔截器小結
我們應當熟悉攔截器在單個執行和多個執行流程下的差別,着重掌握Springmvc配置檔案的配置流程。深入了解攔截器在上述應用案列中的作用。如有不足,多謝各位斧正。