springMVC 拦截器

Spring MVC 自定义拦截器

Spring MVC 自定义拦截器

一、拦截器

    Interceptor 拦截功能基于 java 的动态代理实现。

    SpringMVC中的Interceptor拦截器是链式的,可以同时存在。

    在spring 框架之中,实现自定义拦截类,可以实现

    第一种是实现HandlerInterceptor接口,

    第二种是实现WebRequestInterceptor接口

(1)HandlerInterceptor 接口实现

@Slf4j  //lombok
@Component
public class AuthorityIntercept implements HandlerInterceptor{
    /**
     *在进入 Controller 之前调用
     *
     * true : 调用当前请求的 Controller 中的方法
     *          或 下一个拦截器
     * false : 请求结束,不会进入到 Controller 层
     *
     * handler : (HandlerMethod) 封装了请求控制层的 Bean 实例
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
throws Exception {         HandlerMethod handlerMethod = (HandlerMethod) handler;         //日志记录         String methodName = handlerMethod.getMethod().getName();         Class _class = handlerMethod.getBeanType();         String className = _class.getSimpleName();         Map<String,String[]> parameterMap = request.getParameterMap();         StringBuilder sb = new StringBuilder();         for (Map.Entry<String, String[]> entry: parameterMap.entrySet()) {             // == ""  易精确的查找             String key = entry.getKey();             String [] parameter = entry.getValue();             String value = Arrays.asList(parameter).toString();             sb.append("key :").append(key).append(",").append("value : ").append(value);         }         log.info("request  className :{} methodName :{}, parameter :{}",className,methodName,sb);         //不拦截 user login 的方法,(无法登入)         //也可以在 dispatcher-servlet.xml 进行配置 exclude        if (methodName.equals("UserManageController") && className.equals("login")){            return true;        }         User user = null;         String loginToken = LoginCookieUtil.readLoginCookieValue(request);         if (StringUtils.isNotBlank(loginToken)){             user = JacksonUtil.stringToObject(SharedRedisPoolUtil.get(loginToken),User.class);         }         if (user == null || user.getRole() != Const.Role.ROLE_ADMIN) {             //返回false.即不会调用controller里的方法 需要返回设置格式            // 这里要添加reset,否则报异常 getWriter() has already been called for this response.             response.reset();             //这里要设置编码,否则会乱码             response.setCharacterEncoding("UTF-8");             // 这里要设置返回值的类型,因为全部是json接口。             response.setContentType("application/json;charset=UTF-8");             PrintWriter out = response.getWriter();             if (user == null){                 out.print(JacksonUtil.objectToString(ServerResponse.createByErrorMessage("拦截器拦截,请登入")));             }else{                 out.print(JacksonUtil.objectToString(ServerResponse.createByErrorMessage("拦截器拦截,用户无权限操作")));             }         }         return true;     }     /**      *  Controller 执行之后调用      */     @Override     public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, 
Object handler, ModelAndView modelAndView) throws Exception {         System.out.println("postHandle");     }     //DispatcherServlet 渲染了对应的视图之后执行,这个方法的主要作用是用于进行资源清理的工作。     @Override     public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
 Object o, Exception e) throws Exception {         System.out.println("afterCompletion");     } }             

(2)dispatcher-servlet.xml 配置

 <!-- 声明拦截器 -->
    <mvc:interceptors>
        <!-- 使用 bean 定义一个 Interceptor,直接定义在 mvc:interceptors 下面的 Interceptor 将拦截所有的请求 -->
        <mvc:interceptor>
            <!--
                /manage/**  包含子路径
                /manage/*   当前路径
                /         web 项目根路径
            -->
            <mvc:mapping path="/manage/**" />
            <!-- 对登入不拦截 -->
            <mvc:exclude-mapping path="/manage/user/login.do"/>
            <!-- 定义在 mvc:interceptor 下面的 Interceptor,表示对特定的请求进行拦截 -->
            <bean class="com.mmall.controller.Intercept.AuthorityIntercept"/>

        </mvc:interceptor>
    </mvc:interceptors>

(3)拦截器的执行顺序

<!-- 配置拦截器 -->
<mvc:interceptors>
    <!-- 多个拦截器,按顺序执行 -->        
    <mvc:interceptor>
        <mvc:mapping path="/**"/> <!-- 表示拦截所有的url包括子url路径 -->
        <bean class="ssm.interceptor.HandlerInterceptor1"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="ssm.interceptor.HandlerInterceptor2"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="ssm.interceptor.HandlerInterceptor3"/>
    </mvc:interceptor>
</mvc:interceptors>        

    1、三个拦截器都可以通过 true

        

         当所有拦截器都放行的时候,preHandle方法是按照配置的顺序执的;而另外两个方法按照配置的顺序逆向执行的。

 

    2、最后一个拦截器不可以通过 

         

       1. 由于拦截器1和2放行,所以拦截器3的preHandle才能执行。也就是说前面的拦截器放行,后面的拦截器才能执行preHandle。 
  2. 拦截器3不放行,所以其另外两个方法没有被执行。即如果某个拦截器不放行,那么它的另外两个方法就不会背执行。 
  3. 只要有一个拦截器不放行,所有拦截器的postHandle方法都不会执行,但是只要执行过preHandle并且放行的,就会执行afterCompletion方法。

    3、三个拦截器都不可以通过

         

        只执行了第一个拦截器的preHandle方法,因为都不放行,所以没有一个执行postHandle方法和afterCompletion方法。

 

    拦截器执行顺序总结:

    拦截器放行的时候,会进入下一个拦截器的preHandle方法(按照配置的顺序执行)或者进入 controller 层方法执行 ,

preHandle 所有的方法执行完,另外两个方法得到执行的前提式 preHandle 返回图 true ,因此,

另外两个方法按照配置的顺序逆向执行的(根据实际 preHandle 执行情况)。

 

 

 

 

 

 

 

 

 

posted @ 2018-05-20 08:49  TigerExpensive  阅读(238)  评论(0编辑  收藏  举报