本節內容:html
Spring Web MVC 的處理器攔截器相似於Servlet開發中的過濾器Filter,用於對處理器進行預處理和後處理。好比進入某個SpringMVC的某個方法前須要判斷用戶是否登陸,這個確定不可能在每一個方法裏都寫。java
本身寫類,實現HandlerInterceptor接口,以下:web
Interceptor1.javaspring
package com.wisedu.springmvc.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class Interceptor1 implements HandlerInterceptor{ // Controller執行前調用此方法 // 返回true表示繼續執行,返回false停止執行 // 這裏能夠加入登陸校驗、權限攔截等 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { System.out.println("方法前 1"); return true; //true就是放過,false就是不經過 } // controller執行後但未返回視圖前調用此方法 // 這裏可在返回用戶前對模型數據進行加工處理,好比這裏加入公用信息以便頁面顯示 public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { System.out.println("方法後 1"); } // controller執行後且視圖返回後調用此方法 // 這裏可獲得執行controller時的異常信息 // 這裏可記錄操做日誌 public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { System.out.println("頁面渲染後 1"); } }
Interceptor2.java瀏覽器
package com.wisedu.springmvc.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class Interceptor2 implements HandlerInterceptor{ public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("方法前 2"); return false; } public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { System.out.println("方法後 2"); } public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { System.out.println("頁面渲染後 2"); } }
在springmvc.xml中添加配置:session
<!--springmvc攔截器--> <mvc:interceptors> <!--能夠配置多個攔截器--> <mvc:interceptor> <!-- 全部的請求都進入攔截器 --> <mvc:mapping path="/**" /> <!-- 配置本身編寫的具體的攔截器 --> <bean class="com.wisedu.springmvc.interceptor.Interceptor1" /> </mvc:interceptor> <mvc:interceptor> <!-- 全部的請求都進入攔截器 --> <mvc:mapping path="/**" /> <!-- 配置具體的攔截器 --> <bean class="com.wisedu.springmvc.interceptor.Interceptor2" /> </mvc:interceptor> <!--若是配置多個攔截器,好比上面配置了兩個,每一個攔截器裏有3個方法,那麼執行的順序是: 攔截器1的方法前1 (前提時這個方法前1放行,若是方法前1不放行,下面全部的都不會執行,包括Controller層也進不去) 攔截器2的方法前2 攔截器2的方法後2 攔截器1的方法後1 攔截器2的頁面渲染後2 攔截器1的頁面渲染後1 若是方法前1放行,方法前2不放行,運行結果是 方法前1 方法前2 頁面渲染後1 --> </mvc:interceptors>
啓動項目,瀏覽器訪問地址:http://127.0.0.1:8080/itemList.actionmvc
控制檯打印以下:app
方法前 1 方法前 2 方法後 2 方法後 1 頁面渲染後 2 頁面渲染後 1
1. Interceptor1的preHandler方法返回false,Interceptor2返回truejsp
啓動項目,瀏覽器訪問地址:http://127.0.0.1:8080/itemList.actionide
控制檯打印以下:
方法前1
從日誌看出第一個攔截器的preHandler方法返回false後第一個攔截器只執行了preHandler方法,其它兩個方法沒有執行,第二個攔截器的全部方法不執行,且Controller也不執行了。
2. Interceptor1的preHandler方法返回true,Interceptor2返回false
啓動項目,瀏覽器訪問地址:http://127.0.0.1:8080/itemList.action
控制檯打印以下:
方法前 1 方法前 2 頁面渲染後 1
從日誌看出第二個攔截器的preHandler方法返回false後第一個攔截器的postHandler沒有執行,第二個攔截器的postHandler和afterCompletion沒有執行,且controller也不執行了。
【總結】:
preHandle按攔截器定義順序調用
postHandler按攔截器定義逆序調用
afterCompletion按攔截器定義逆序調用
postHandler在攔截器鏈內全部攔截器返成功調用
afterCompletion只有preHandle返回true才調用
1. 處理流程
(1)有一個登陸頁面,須要寫一個Controller訪問登陸頁面
(2)登陸頁面有一提交表單的動做。須要在Controller中處理。
(3)攔截器。
2. 編寫登陸jsp
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <form action="${pageContext.request.contextPath }/user/login.action"> <label>用戶名:</label> <br> <input type="text" name="username"> <br> <label>密碼:</label> <br> <input type="password" name="password"> <br> <input type="submit"> </form> </body> </html>
3. 用戶登錄Controller
UserController.java
package com.wisedu.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.http.HttpSession; /** * Created by jkzhao on 1/18/18. */ @Controller @RequestMapping("user") public class UserController { /** * 跳轉到登陸頁面 * * @return */ @RequestMapping(value = "login", method = RequestMethod.GET) public String login() { return "login"; } /** * 用戶登陸 * * @param username * @param password * @param session * @return */ @RequestMapping(value = "login", method = RequestMethod.POST) public String login(String username, String password, HttpSession session) { // 校驗用戶登陸 System.out.println(username); System.out.println(password); // 把用戶名放到session中 session.setAttribute("username", username); return "redirect:/item/itemlist.action"; } }
4. 編寫攔截器
LoginHandlerInterceptor.java
package com.wisedu.springmvc.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Created by jkzhao on 1/18/18. */ public class LoginHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { // 從request中獲取session HttpSession session = httpServletRequest.getSession(); // 從session中獲取username Object username = session.getAttribute("username"); // 判斷username是否爲null if (username != null) { // 若是不爲空則放行 return true; } else { // 若是爲空則跳轉到登陸頁面 httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/user/login.action"); } return false; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
5. 配置攔截器
只能攔截商品的url,因此須要修改ItemController,讓全部的請求都必須以item開頭,以下圖:
在springmvc.xml配置攔截器:
<mvc:interceptor> <!-- 配置商品被攔截器攔截 --> <mvc:mapping path="/item/**" /> <!-- 配置具體的攔截器 --> <bean class="com.wisedu.springmvc.interceptor.LoginHandlerInterceptor" /> </mvc:interceptor>