springmvc拦截器

来源:互联网 发布:effective java 第3版 编辑:程序博客网 时间:2024/06/02 03:15

前言

最近在门户网站中需要做登录验证,里面简单用到了拦截器。对于拦截器想必大家不会陌生,这里主要和大家一起总结一下对springmvc拦截器的使用。拦截器在日常开发中也是经常用到,比如日志记录,登录权限验证,模块方法程序性能检测等等。这里主要结合几个小例子来和大家一起总结一下springmvc拦截器的使用。

springmvc拦截器简单小配置

这里主要是讲解springmvc的拦截器,所以springmvc环境配置是必不可少的,具体配置不是这里的重点,不再赘述。springmvc中的拦截器最主要的是需要在springmvc配置文件中配置你自定义的拦截器。

<mvc:interceptors>        <mvc:interceptor>            <mvc:mapping path="/InterceptorController/test" />           <bean class="com.aiqinhai.base.controller.DetectInterceptor"></bean>        </mvc:interceptor>   </mvc:interceptors>

上面的拦截器,匹配拦截InterceptorController/test请求,当请求路径和上面的路径匹配时。就会执行上面自定义的拦截器类,也就是上面的bean。对于那个自定义拦截器bean需要实现HandlerInterceptor接口,或者继承HandlerInterceptorAdapter拦截器适配器抽象类,这里是用到了适配器模式的一种用法,对于后者,如果你不需要使用HandlerInterceptor接口中每一个方法,只是想使用其中的某一个或者两个,继承拦截器适配器是可以实现的。上面只是简单定义了一个拦截器,springmvc拦截器是可以定义多个的。具体的拦截步骤后面再详细介绍。

HandlerInterceptor接口介绍

在HandlerInterceptor接口中主要是有三个抽象方法

public interface HandlerInterceptor {      boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception;      void postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView)throws Exception;      void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex)  throws Exception;  } 

preHandle方法主要是在被拦截的处理器方法执行之前开始执行,通常可以做一些权限控制之类的的验证。
postHandle方法,主要是在被拦截的处理器方法执行之后,但是返回的视图渲染之前,在这期间进行执行。在这个方法中,modelAndView被用来对一些数据进行修改或者处理,例如可以保存一些数据进行。
afterCompletion方法是在被拦截的方法处理之后,执行的方法,通常是做一些资源的释放和处理工作,类似try-catch-finally中的finally语句块。

多个拦截器的执行顺序问题

在springmvc中的配置问题中,配置两个拦截器

<mvc:interceptors>        <mvc:interceptor>            <mvc:mapping path="/InterceptorController/test" />           <bean class="com.aiqinhai.base.controller.InterceptorDemo1"></bean>        </mvc:interceptor>     <mvc:interceptor>            <mvc:mapping path="/InterceptorController/test" />           <bean class="com.aiqinhai.base.controller.InterceptorDemo2"></bean>        </mvc:interceptor>    </mvc:interceptors>

自定义拦截器一的具体代码如下

/*** * @ClassName: InterceptorDemo1* @Description: TODO(拦截器一  测试拦截器执行顺序)* @author 爱琴孩*/public class InterceptorDemo1 implements HandlerInterceptor{    @Override    public boolean preHandle(HttpServletRequest request,            HttpServletResponse response, Object handler) throws Exception {        // TODO Auto-generated method stub        System.out.println("这里是preHandle1");        return true;    }    @Override    public void postHandle(HttpServletRequest request,            HttpServletResponse response, Object handler,            ModelAndView modelAndView) throws Exception {        // TODO Auto-generated method stub        System.out.println("这里是postHandle1");    }    @Override    public void afterCompletion(HttpServletRequest request,            HttpServletResponse response, Object handler, Exception ex)            throws Exception {        // TODO Auto-generated method stub        System.out.println("这里是afterCompletion1");    }}

拦截器二的代码和上面类似就不列出了。如果拦截器一和拦截器二中的preHandle都是return true。当请求的路径和上面的路径匹配时,那么自定义中拦截器方法将会执行,对应各个方法执行顺序如下图所示。
这里写图片描述
如果拦截一中的preHandle是return true,第二个拦截器是return false。情况又是怎样呢,结果见下图
这里写图片描述
对于上面的两种情况,对于两个自定义拦截器中的多个方法具体执行顺序,当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 ,可以参见下图理解
这里写图片描述

简单性能监测小案例

可以在springmvc的配置文件中,定义一个拦截器,然后在拦截器的preHandle方法中记录一下开始时间,然后在afterCompletion方法中记录一下结束时间,这样就可以监测一下具体的被拦截处理器方法执行的具体时间,这里需要注意的一点是,记录时间在多线程中可能不是线程安全的,这里需要用ThreadLocal来将时间绑定在当前线程之中,这样每个线程的时间就不会相互干扰。具体代码如下

/** * * @ClassName: DetectInterceptor* @Description: TODO(利用拦截器测试性能)* @author 爱琴孩 */public class DetectInterceptor extends HandlerInterceptorAdapter{    private  NamedThreadLocal<Long>  threadLocalStartTime=new NamedThreadLocal<Long>("time");    @Override    public boolean preHandle(HttpServletRequest request,            HttpServletResponse response, Object handler) throws Exception {        // TODO Auto-generated method stub        long startTime=System.currentTimeMillis();        threadLocalStartTime.set(startTime);        return true;    }    @Override    public void afterCompletion(HttpServletRequest request,            HttpServletResponse response, Object handler, Exception ex)            throws Exception {        // TODO Auto-generated method stub        long endTime=System.currentTimeMillis();        long startTime=threadLocalStartTime.get();        long costTime=endTime-startTime;        System.out.println("这个业务逻辑花费的时间是"+costTime+"毫秒!");    }}

上面自定义的拦截器是继承了拦截器适配器,只需要重写preHandle和afterCompletion方法。具体测试结果如下
这里写图片描述

简单登录验证拦截器

如果用户没有登录就,直接跳转到登录页面,如果已经登录执行请求对应的处理器,配置文件中的拦截器和上面类似就不贴代码了,主要看看拦截器中的具体实现。

/*** * @ClassName: LoginInterceptor* @Description: TODO(设置权限,只有登录之后的人才能查看具体信息)* @author 爱琴孩*/public class LoginInterceptor  extends HandlerInterceptorAdapter{    @Override    public boolean preHandle(HttpServletRequest request,            HttpServletResponse response, Object handler) throws Exception {        try {            HttpSession se = request.getSession();            TUser user=(TUser) se.getAttribute("loginUserInfo");            if(user==null){                System.out.println("未登录!");                request.getRequestDispatcher("/WEB-INF/views/login.jsp").forward(request, response);                  return false;            }else{                return true;            }        } catch (Exception e) {            // TODO: handle exception            e.printStackTrace();        }        // TODO Auto-generated method stub        return false;    }}

上面只是调用了preHandle方法,所以只需要继承HandlerInterceptorAdapter拦截器适配器ok了。具体效果,大家可以自己试一试。

总结

上面就是对springmvc拦截器的简单小总结,能力有限,如有错误,还请各位大佬指正!

原创粉丝点击