什么是拦截器?
拦截器是指通过统一拦截从浏览器发往服务器的请求来完成功能的增强。
使用场景:解决请求的共性问题(如:乱码问题、权限验证问题等),比如网页中一些页面是需要登陆过后才可以浏览的,这样我们就不用在每个请求中判断是否登陆,这样就解决了代码重复的问题。
使用原则:处理所有请求的共同问题
1.拦截器的实现
编写拦截器类实现HandlerInterceptor接口
2.拦截器的方法介绍
prehandle方法,在请求被处理之前进行调用(处理请求之前)
posthandle方法,在请求被处理之后进行调用(处理请求后,渲染页面前)
after Completion方法,在请求结束之后才进行调用(视图渲染结束了,请求处理完毕)
这里举一个登陆认证的拦截器的例子
3.spring-mvc.xml拦截器配置
<!--6.拦截器 --> <mvc:interceptors> <!-- 后台登陆认证拦截器 --> <mvc:interceptor> <!-- /**表示admin请求下的所有url包括子url路径 --> <mvc:mapping path="/admin/**" /> <!-- 登陆请求就不用拦截了 --> <mvc:exclude-mapping path="/admin/adminuserlogin"/> <bean class="com.smxy.study.interceptor.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
4. LoginInterceptor.java
package com.smxy.study.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; /** * * @Description:后台登陆拦截器 * @author Bush罗 * @date 2018年4月24日 * */ public class LoginInterceptor implements HandlerInterceptor { // 进入 Handler方法之前执行 // 用于身份认证、身份授权 // 比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub System.out.println("======处理请求之前======"); // 判断session HttpSession session = request.getSession(); // 从session中取出用户身份信息 String adminid = (String) session.getAttribute("adminid"); System.out.println(adminid); if (adminid != null) { // 身份存在,放行 return true; } // 执行这里表示用户身份需要认证,跳转登陆页面 String str = "<span class='glyphicon glyphicon-exclamation-sign' aria-hidden='true'></span>"; request.setAttribute("message", str + "请您先登录"); request.getRequestDispatcher("/admin/index.jsp").forward(request, response); // return false表示拦截,不向下执行 return false; } // 进入Handler方法之后,返回modelAndView之前执行 // 应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } // 执行Handler完成执行此方法 // 应用场景:统一异常处理,统一日志处理 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub } }
如果有多个拦截器,它的preHandle执行顺序是按照你xml的配置顺序来执行的。postHandle,afterCompletion则相反。
例如有两个拦截器1和2,那么方法的执行顺序就是
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle
HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion
可以看出preHandle方法按顺序执行,postHandle和afterCompletion按拦截器配置的逆向顺序执行。
拦截器1放行,拦截器2 preHandle才会执行。
拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行。
只要有一个拦截器不放行,postHandle不会执行。
拦截器和过滤器的区别
过滤器 Filter依赖于Servlet容器,基于回调函数,过滤范围大。
拦截器 Interceptor赖于框架容器,基于反射机制,只过滤请求。
拦截器只能对 action 请求起作用,而过滤器则可以对几乎所有的请求起作用
拦截器可以访问 action 上下文、值栈里的对象,而过滤器不能
在 action 的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一 次 .
总结
拦截器可以处理Web应用中请求的一些通用性问题。
共性问题在拦截器中处理,可以减少重复代码,便于维护。