• 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 执行情况)。

     

     

     

     

     

     

     

  • 相关阅读:
    第二次会议记录(2021.7.19)
    第一次会议记录(2021.7.8)
    软件工程助教工作总结
    Linux下的常用命令
    GPIO输出——使用固件库点亮LED 宏定义遇到的问题
    STM32 GPIO BRR和BSRR寄存器
    snprintf()函数使用方法
    结构体元素偏移量宏的定义及解析
    函数指针&回调函数Callback
    解析#define NULL ((void *)0)——野指针,空指针和 void*
  • 原文地址:https://www.cnblogs.com/SacredOdysseyHD/p/9062463.html
Copyright © 2020-2023  润新知