springMVC4(16)拦截器解析与登陆拦截模拟

在SpringMVC中,我们会常常使用到拦截器,尽管SpringAOP也能帮我们实现强大的拦截器功能,但在Web资源供给上。却没有SpringMVC来得方便快捷。


使用SpringMVC拦截器的核心应用场景是依据我们的实际需求,个性化定制拦截器,再对特定url进行拦截处理。
而自己定义拦截器。首先须要我们实现HandlerInterceptor拦截器接口。以下是它的定义:

package org.springframework.web.servlet;  
public interface HandlerInterceptor {  
    //在控制器方法调用前运行
    //返回值为是否中断。true,表示继续运行(下一个拦截器或处理器)
    //false则会中断兴许的全部操作。所以我们须要使用response来响应请求
    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;  
}  

非常多时候,我们仅仅须要实现以上三个方法的随意一个或两个。这个时候我们能够选择继承HandlerInterceptorAdapter。

它实现了AsyncHandlerInterceptor接口,为每一个方法提供了空实现,这样。我们就能够依据需求重写自己用到的拦截方法就可以。具体定义例如以下:

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        return true;
    }

    @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 {
    }

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

}

相对于HandlerInterceptor,HandlerInterceptorAdapter多了一个实现方法afterConcurrentHandlingStarted()。它来自HandlerInterceptorAdapter的直接实现类AsyncHandlerInterceptor,AsyncHandlerInterceptor接口直接继承了HandlerInterceptor。并新添了afterConcurrentHandlingStarted()方法用于处理异步请求,当Controller中有异步请求方法的时候会触发该方法时,异步请求先支持preHandle、然后运行afterConcurrentHandlingStarted。异步线程完毕之后运行preHandle、postHandle、afterCompletion。

以下我们以登陆请求为例。编写我们的自己定义拦截器:

public class LoginInterceptor extends HandlerInterceptorAdapter {

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception { 
  // 获得请求路径的uri
  String uri = request.getRequestURI();

  // 进入登录页面,推断session中是否有key。有的话重定向到首页。否则进入登录界面
  if(uri.contains("login")) {
      if(request.getSession().getAttribute("user") != null) {
         response.sendRedirect(request.getContextPath());//默认跟路径为首页
      } else {
         return true;//继续登陆请求
      }
  }

  // 其它情况推断session中是否有key,有的话继续用户的操作
  if(request.getSession().getAttribute("user") != null) {
      return true;
  }

  // 最后的情况就是进入登录页面
  response.sendRedirect(request.getContextPath() + "/login");
  return false;
  }
}

以下是我们的拦截器配置:

<mvc:interceptors>
  <mvc:interceptor><!--配置局部拦截器,须要满足下列路径条件-->
    <mvc:exclude-mapping path="/user/logout"/><!--注销-->
    <mvc:exclude-mapping path="/home/"/><!--在home中定义了无须登陆的方法请求,直接过滤拦截-->
    <mvc:mapping path="/**"/>
    <bean class="com.mvc.interceptor..LoginInterceptor"/><!--自己定义拦截器注冊-->
  </mvc:interceptor>
  <!-- 我们能够直接在者注冊自己定义拦截器Bean来配置全局拦截器,会对全部请求拦截-->
</mvc:interceptors>

在我们的拦截中,假设配置了多个拦截器,会形成一条拦截器链。运行顺序相似于AOP,前置拦截先定义的先运行。后置拦截和完结拦截(afterCompletion)后注冊的后运行,关于拦截器的运行顺序的深入理解可參考我的还有一篇文章《 spring学习笔记(12)@AspectJ研磨分析[3]增强织入顺序实例具体解释》

posted on 2017-08-07 15:52  yjbjingcha  阅读(222)  评论(0编辑  收藏  举报

导航