处理器拦截器相似于servlet开发中的filter,用于对处理器进行预处理和后处理。前端
定义拦截器,实现HandlerInterceptor这个接口java
接口的实现须要导入包import org.springframework.web.servlet.HandlerInterceptor;web
这个包不能导错,否则不能自动添加方法。spring
代码:浏览器
package com.jch.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 HandlerInterceptor1 implements HandlerInterceptor{ /** * 进入handler方法以前执行 * 用于身份认证,身份校验 * 好比身份认证,若是认证不经过表示当前用户没有登陆,须要此方法拦截不在向下执行 */ @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { // TODO Auto-generated method stub return false; } /** * 进入handler以后,返回modelandview以前执行 * 应用场景从modelandview出发,将共用的模型数据(好比菜单导航)在这里传到视图,也能够在这里统一制定视图 */ @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { // TODO Auto-generated method stub } /** * 执行handler完成执行此方法 * 应用场景:统一异常处理,统一日志处理 */ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { // TODO Auto-generated method stub } }
SpringMVC拦截器针对HandlerMapping进行拦截器设置session
若是在某个HandlerMapping中配置拦截,通过该HandlerMapping映射成功的handler最终使用该拦截器。mvc
通常不推荐使用,配置过于麻烦app
SpringMVC配置相似全局的拦截器,SpringMVC框架将配置的相似全局的拦截器注入到每个HandlerMapping中框架
测试多个拦截器各个方法的执行时机jsp
代码;
package com.jch.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 HandlerInterceptor1 implements HandlerInterceptor{ /** * 进入handler方法以前执行 * 用于身份认证,身份校验 * 好比身份认证,若是认证不经过表示当前用户没有登陆,须要此方法拦截不在向下执行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub System.out.println("这是第1个拦截器,preHandle方法"); return false; } /** * 进入handler以后,返回modelandview以前执行 * 应用场景从modelandview出发,将共用的模型数据(好比菜单导航)在这里传到视图,也能够在这里统一制定视图 */ @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { // TODO Auto-generated method stub System.out.println("这是第1个拦截器,postHandle方法"); } /** * 执行handler完成执行此方法 * 应用场景:统一异常处理,统一日志处理 */ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { // TODO Auto-generated method stub System.out.println("这是第1个拦截器, afterCompletion方法"); } }
将两个return都改成true
在浏览器中随意访问一个路由看效果:
这是第1个拦截器,preHandle方法
这是第2个拦截器,preHandle方法
这是第2个拦截器,postHandle方法
这是第1个拦截器,postHandle方法
这是第2个拦截器,afterCompletion方法
这是第1个拦截器, afterCompletion方法
总结:
preHandle方法按顺序执行
postHandle方法和afterCompletion方法按拦截器配置的逆向顺序执行
结果:
这是第1个拦截器,preHandle方法
这是第2个拦截器,preHandle方法
这是第1个拦截器, afterCompletion方法
总结:
拦截器1放行,拦截器的preHandle方法才会执行
拦截器2的preHandle方法不放行,拦截器2的postHandle方法和afterCompletion方法不会执行。
只要有一个拦截器拦截不放行postHandle方法都不会执行
结果:
这是第1个拦截器,preHandle方法
总结:
拦截器1 preHandle方法不放行,postHandle方法和afterCompletion方法都不会执行
拦截器1 preHandle方法不放行,拦截器2不执行。
根据测试结果,对拦截器应用。
好比:
统一日志处理拦截器,须要该拦截器preHandler必定要放行,且将它放在拦截器连接中的第一个位置。
登陆认证的拦截器,放在拦截器连接中的第一个位置
权限校验拦截器,放在登陆校验拦截器以后。(由于登陆经过后才校验权限)
一、 用户请求URL
二、 拦截器进行校验
若是请求的URL是公开地址(无需登陆就能访问的URL),让放行。、
若是用户session不存在跳转到登陆界面
若是用户session存在,继续操做
package com.jch.controller; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class LoginController { // 登陆 @RequestMapping("login.jch") public String login(HttpSession session , String username , String password) { // 调用service进行用户身份验证 // ...这里假设验证经过 // 在session中保存用户身份信息 session.setAttribute("username", username); return "redirect:/register.jch"; // /为项目根目录 } // 退出登陆 @RequestMapping("logout.jch") public String login(HttpSession session) { // 清楚session数据 session.invalidate(); return "redirect:/login.jch"; } }
package com.jch.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class LoginInterceptor implements HandlerInterceptor{ /** * 进入handler方法以前执行 * 用于身份认证,身份校验 * 好比身份认证,若是认证不经过表示当前用户没有登陆,须要此方法拦截不在向下执行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub // 获取请求的URL String url = request.getRequestURI(); // 判断是不是公开地址(实际使用将公开地址配置在配置文件中)这里公开地址就是登陆提交的地址 if(url.indexOf("login.jch")>=0) { // 若是要登陆提交,那么放行 return true; } // 判断session HttpSession session = request.getSession(); String username = (String)session.getAttribute("username"); if(username != null) { // 有身份信息,放行 return true; } // 身份验证不经过跳转到登陆界面 request.getRequestDispatcher("/views/home/login.jsp").forward(request, response); System.out.println("这是第1个拦截器,preHandle方法"); return false; } /** * 进入handler以后,返回modelandview以前执行 * 应用场景从modelandview出发,将共用的模型数据(好比菜单导航)在这里传到视图,也能够在这里统一制定视图 */ @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { // TODO Auto-generated method stub System.out.println("这是第1个拦截器,postHandle方法"); } /** * 执行handler完成执行此方法 * 应用场景:统一异常处理,统一日志处理 */ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { // TODO Auto-generated method stub System.out.println("这是第1个拦截器, afterCompletion方法"); } }
在springmvc的前端控制器配置文件中配置interceptor拦截器
<!-- 配置拦截器 --> <mvc:interceptors> <!-- 多个拦截器,顺序执行 --> <!-- 登陆认证拦截器 --> <mvc:interceptor> <mvc:mapping path="/**"/><!-- 标识拦截全部的URL包括全部的子URL --> <bean class="com.jch.interceptor.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
启动Tomcat查看测试结果。