一、拦截器配置和测试:
1)定义两个拦截器,(要实现HandlerInterceptor接口)
HandlerInterceptor1:
1 package com.cy.interceptor; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 6 import org.springframework.web.servlet.HandlerInterceptor; 7 import org.springframework.web.servlet.ModelAndView; 8 9 public class HandlerInterceptor1 implements HandlerInterceptor{ 10 11 //进入 Handler方法之前执行 12 //用于身份认证、身份授权 13 //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行 14 @Override 15 public boolean preHandle(HttpServletRequest request, 16 HttpServletResponse response, Object handler) throws Exception { 17 System.out.println("HandlerInterceptor1--------------------preHandle"); 18 19 //return false表示拦截,不向下执行 20 //return true表示放行 21 return true; 22 } 23 24 //进入Handler方法之后,返回modelAndView之前执行 25 //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图 26 @Override 27 public void postHandle(HttpServletRequest request, 28 HttpServletResponse response, Object handler, 29 ModelAndView modelAndView) throws Exception { 30 System.out.println("HandlerInterceptor1--------------------postHandle"); 31 } 32 33 //执行Handler完成执行此方法 34 //应用场景:统一异常处理,统一日志处理 35 @Override 36 public void afterCompletion(HttpServletRequest request, 37 HttpServletResponse response, Object handler, Exception ex) 38 throws Exception { 39 System.out.println("HandlerInterceptor1--------------------afterCompletion"); 40 } 41 }
HandlerInterceptor2:
1 public class HandlerInterceptor2 implements HandlerInterceptor{ 2 3 @Override 4 public boolean preHandle(HttpServletRequest request, 5 HttpServletResponse response, Object handler) throws Exception { 6 System.out.println("HandlerInterceptor2--------------------preHandle"); 7 return true; 8 } 9 10 @Override 11 public void postHandle(HttpServletRequest request, 12 HttpServletResponse response, Object handler, 13 ModelAndView modelAndView) throws Exception { 14 System.out.println("HandlerInterceptor2--------------------postHandle"); 15 } 16 17 @Override 18 public void afterCompletion(HttpServletRequest request, 19 HttpServletResponse response, Object handler, Exception ex) 20 throws Exception { 21 System.out.println("HandlerInterceptor2--------------------afterCompletion"); 22 } 23 }
2)配置拦截器:
springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。
配置如下:
1 <!--拦截器 --> 2 <mvc:interceptors> 3 <!--多个拦截器,顺序执行 --> 4 <mvc:interceptor> 5 <!-- /**表示所有url包括子url路径 --> 6 <mvc:mapping path="/**"/> 7 <bean class="com.cy.interceptor.HandlerInterceptor1"></bean> 8 </mvc:interceptor> 9 <mvc:interceptor> 10 <mvc:mapping path="/**"/> 11 <bean class="com.cy.interceptor.HandlerInterceptor2"></bean> 12 </mvc:interceptor> 13 </mvc:interceptors>
另外配置的方法:
springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该拦截器。(一般不推荐使用)
1 <bean 2 class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> 3 <property name="interceptors"> 4 <list> 5 <ref bean="handlerInterceptor1"/> 6 <ref bean="handlerInterceptor2"/> 7 </list> 8 </property> 9 </bean> 10 <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/> 11 <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
3)测试:
测试多个拦截器各个方法的执行时机:
两个拦截器HandlerInterceptor1、2都放行,打印结果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle
HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion
总结:
preHandle方法按顺序执行,
postHandle和afterCompletion按拦截器配置的逆向顺序执行。
关于执行其实可以看图理解:
拦截器应用举例:
比如:统一日志处理拦截器,需要该 拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。
比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)
二、拦截器实现登陆认证:
需求:
1、用户请求url
2、拦截器进行拦截校验
如果请求的url是公开地址(无需登陆即可访问的url),让放行
如果用户session 不存在跳转到登陆页面
如果用户session存在放行,继续操作。
LoginController:
1 package com.cy.controller; 2 3 import javax.servlet.http.HttpSession; 4 5 import org.springframework.stereotype.Controller; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 8 @Controller 9 public class LoginController { 10 11 @RequestMapping("/login") 12 public String login(HttpSession session, String username, String password) throws Exception{ 13 // 调用service进行用户身份验证 14 // ... 15 16 // 在session中保存用户身份信息 17 session.setAttribute("username", username); 18 19 // 重定向到商品列表页面 20 return "redirect:items/findItems"; 21 } 22 23 // 退出 24 @RequestMapping("/logout") 25 public String logout(HttpSession session) throws Exception { 26 27 // 清除session 28 session.invalidate(); 29 30 return "redirect:items/findItems"; 31 } 32 }
LoginInterceptor:
1 package com.cy.interceptor; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 import javax.servlet.http.HttpSession; 6 7 import org.springframework.web.servlet.HandlerInterceptor; 8 import org.springframework.web.servlet.ModelAndView; 9 10 /** 11 * 登陆认证拦截器 12 * @author chengyu 13 * 14 */ 15 public class LoginInterceptor implements HandlerInterceptor{ 16 17 @Override 18 public boolean preHandle(HttpServletRequest request, 19 HttpServletResponse response, Object handler) throws Exception { 20 21 //获取请求的url 22 String url = request.getRequestURI(); 23 24 //判断url是否是公开 地址(实际使用时将公开 地址配置配置文件中) 25 //这里公开地址是登陆提交的地址 26 if(url.indexOf("login.action") >= 0){ 27 //如果进行登陆提交,放行 28 return true; 29 } 30 31 HttpSession session = request.getSession(); 32 String username = (String) session.getAttribute("username"); 33 if(username!=null){ 34 return true; 35 } 36 37 //执行这里表示用户身份需要认证,跳转登陆页面 38 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); 39 return false; 40 } 41 42 @Override 43 public void postHandle(HttpServletRequest request, 44 HttpServletResponse response, Object handler, 45 ModelAndView modelAndView) throws Exception { 46 } 47 @Override 48 public void afterCompletion(HttpServletRequest request, 49 HttpServletResponse response, Object handler, Exception ex) 50 throws Exception { 51 } 52 }
LoginInterceptor配置:
1 <!--拦截器 --> 2 <mvc:interceptors> 3 <!--多个拦截器,顺序执行 --> 4 <!-- 登陆认证拦截器 --> 5 <mvc:interceptor> 6 <mvc:mapping path="/**"/> 7 <bean class="com.cy.interceptor.LoginInterceptor"></bean> 8 </mvc:interceptor> 9 <mvc:interceptor> 10 <!-- /**表示所有url包括子url路径 --> 11 <mvc:mapping path="/**"/> 12 <bean class="com.cy.interceptor.HandlerInterceptor1"></bean> 13 </mvc:interceptor> 14 <mvc:interceptor> 15 <mvc:mapping path="/**"/> 16 <bean class="com.cy.interceptor.HandlerInterceptor2"></bean> 17 </mvc:interceptor> 18 </mvc:interceptors>
login.jsp:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 3 <html> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 6 <title>系统登陆</title> 7 </head> 8 <body> 9 <form action="${pageContext.request.contextPath }/login.action" method="post"> 10 用户账号:<input type="text" name="username" /><br/> 11 用户密码 :<input type="password" name="password" /><br/> 12 <input type="submit" value="登陆"/> 13 </form> 14 </body> 15 </html>