SpringMVC 拦截器的使用

 

拦截器主要用于拦截用户请求,并做相应的处理,十分常用。

 

拦截器的常见用法:

  • 判断用户是否登录。比如购物网站用户将商品添加到购物车时,用拦截器判断用户是否登录,如未登录,则不能将商品添加到购物车(转到登录页面)。
  • 进行权限验证。验证已登录的用户是否有相应的操作权限。
  • 记录请求信息的日志。

 

 


 

 

拦截器的使用步骤

(1)编写拦截器类

实现拦截器有2种方式:

  • 实现HandlerInterceptor接口(常用),或继承HandlerInterceptor接口的实现类
  • 实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类

 

 

HandlerInterceptor接口的三个方法:

  • boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

      在controller中的业务方法之前执行,返回值表示是否有后续操作。

      true——继续执行后续操作;

      fasle——不再执行后续操作,即不再执行此拦截器的代码、不再执行后续的其它拦截器,不再调用controller中的业务方法来处理请求。

 

  • void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)

    在controller中业务方法调用之后、视图解析之前执行。

    可对Model、View作出进一步修改。

 

  • void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

    在视图渲染结束之后执行,即在整个请求完成后执行,可以做一些资源清理、日志记录的工作。

 

三个方法对应在三个时间点进行拦截处理。一般我们只使用preHandler()。

 

 

完整的执行流程:

  • 调用preHandle(),如果返回true,继续往下执行;如果返回false,至此结束。
  • 调用controller中的业务方法
  • 调用postHandle()
  • 解析视图,渲染视图
  • 调用afterCompletion()

 

 

示例    将商品加入购物车,用拦截器验证用户是否已登录

新建包com.chy.interceptor,包下新建类LoginInterceptor:

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //session中有user的信息就通过,否则给出提示信息,重定向到登录页面
        HttpSession session = request.getSession();
        //登录成功时要将user放到session中
        User user = (User)session.getAttribute("user");
        if(user!=null)
            return true;
        //转发到登录页面
        request.setAttribute("msg","您尚未登录,请先登录!");
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

}

 

 


 

 

(2)在spring mvc的配置文件中配置要使用的拦截器

    <!--配置要使用的拦截器-->
    <mvc:interceptors>

         <!--一个interceptor配置一个拦截器 -->
        <mvc:interceptor>
            <!-- 要拦截的请求,**表示拦截该地址下的所有请求 -->
            <mvc:mapping path="/product/purchase/**" />
            <!-- 使用的拦截器类 -->
            <bean class="com.chy.interceptor.LoginInterceptor" />
        </mvc:interceptor>

        <mvc:interceptor>
            <!--拦截所有对controller中业务方法的请求-->
            <mvc:mapping path="/**" />
            <!--可指定不拦截的请求-->
            <mvc:exclude-mapping path=""/>
            <bean class="" />
        </mvc:interceptor>

    </mvc:interceptors>

 

拦截器是在业务方法调用前后进行拦截,拦截的前提是要调用业务方法,即拦截器只拦截对controller中业务方法的请求,不拦截对视图的直接请求。

 

<mvc:mapping />指定要拦截的业务方法,<mvc:exclude-mapping />指定<mvc:mapping />中的哪些路径不被拦截。

有顺序要求:

        <mvc:mapping path="" />
        <mvc:exclude-mapping path=""/>
        <bean class="" />

<mvc:exclude-mapping />可选。

 

 


 

 

 

多个拦截器的执行顺序

 

去的时候拦截器的执行顺序,和配置文件中拦截器的前后顺序一致。

回来的时候拦截器的执行顺序,和去的时候相反。

 

 

比如:

    <!--配置要使用的拦截器-->
    <mvc:interceptors>
         <!--拦截器1 -->
        <mvc:interceptor></mvc:interceptor>
        <!--拦截器2-->
        <mvc:interceptor></mvc:interceptor>
    </mvc:interceptors>

假设这2个拦截器都拦截相同的请求。

 

去的时候依次执行:拦截器1的preHandler()、拦截器2的preHandler(),和配置顺序相同;

回来的时候依次执行:拦截器2的postHandler()、拦截器1的postHandler();和配置顺序相反;

再次回来的时候依次执行:拦截器2的afterCompletion()、拦截器1的afterCompletion(),和配置顺序相反。

 

posted @ 2020-02-02 11:26  chy_18883701161  阅读(598)  评论(0编辑  收藏  举报