• Java——Spring MVC拦截器


    拦截器(Interceptor)用于对URL请求进行前置/后置过滤。

    Interceptor与Filter用途相似,但实现方式不同。

    Interceptor是SpringMVC的标准组件,Interceptor在被创建之后是天然运行在IOC容器之中的。、

    Filter是J2EE的标准组件,不同的Filter是由不同的容器厂商所实现的。

    Interceptor底层就是基于SpringAOP面向切面编程实现。

    拦截器开发流程:
      Maven依赖servlet-api
      实现HandlerLnterceptor接口
      applicationContext.xml拦截配置

    1.拦截器的基本使用

    (1)引入依赖包

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <!--防止servlet自带api与tomcat配置的api相互冲突-->
        <!--provided意味着只有在开发编译才会进行引用-->
        <scope>provided</scope>
    </dependency>

    (2)实现HandlerLnterceptor接口

    //拦截器必须要继承HandlerInterceptor接口
    public class MyInterceptor implements HandlerInterceptor {
        //同时必须实现以下三个方法
        //preHandler:前置执行处理
        //postHandle:目标资源已被SpringMVC框架处理,在return之后,但是还没有产生响应文本之前。
        //afterCompletion:响应文本已经产生,比如在jackson自动实现序列化之后
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println(request.getRequestURL() + "准备执行");
            //必须返回布尔值,true请求会继续向后方(拦截器或者控制器)传递,false请求被阻止,直接返回响应
            return true;
        }
    
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println(request.getRequestURL() + "目标处理成功");
        }
    
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println(request.getRequestURL() + "响应内容已产生");
        }
    }

    (3)applicationContext.xml拦截配置

    <mvc:interceptors>
        <mvc:interceptor>
            <!--对那些URL进行拦截-->
            <mvc:mapping path="/**"/>
            <!--拦截之后使用哪个class进行处理-->
            <bean class="com.ikidana.restful.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

    (4)结果测试

    如果访问:http://localhost:8080/restful/persons

    会出现如下信息:
    http://localhost:8080/restful/persons准备执行
    http://localhost:8080/restful/persons目标处理成功
    http://localhost:8080/restful/persons响应内容已产生

    2.Interceptor使用技巧

    (1)排除对静态资源的拦截

    只需要在applicationContext.xml中配置即可:

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <!--对那些资源不进行拦截-->
            <mvc:exclude-mapping path="/**.ico"/>
            <mvc:exclude-mapping path="/**.jpg"/>
            <mvc:exclude-mapping path="/**.gif"/>
            <mvc:exclude-mapping path="/**.js"/>
            <mvc:exclude-mapping path="/**.css"/>
            <bean class="com.ikidana.restful.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

    但是上面配置存在的问题是:配置项可能很多
    我们可以将所有静态文件全部放在一个目录下,这样拦截目录即可:

     下方就是拦截整个目录:
    <mvc:exclude-mapping path="/resources/**"/>
    针对某个前缀也是如此:
    <mvc:exclude-mapping path="/restful/**"/>

    (2)如果一个请求被多个拦截器拦截,会先执行哪一个了?

      如果我们配置多个拦截器:

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.ikidana.restful.interceptor.MyInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.ikidana.restful.interceptor.MyInterceptor1"/>
        </mvc:interceptor>
    </mvc:interceptors>

    如果访问http://localhost:8080/restful/persons这个URL:
    http://localhost:8080/restful/persons准备执行
    http://localhost:8080/restful/persons准备执行-1
    http://localhost:8080/restful/persons目标处理成功-1
    http://localhost:8080/restful/persons目标处理成功
    http://localhost:8080/restful/persons响应内容已产生-1
    http://localhost:8080/restful/persons响应内容已产生

    处理顺序并不完全按照实际的配置顺序:

     有点类似于python中的中间件

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(request.getRequestURL() + "准备执行");
        response.getWriter().println("拦截器返回");
        return false;
    }

    拦截器可以直接控制返回值。
    无论是拦截器或者中间件对于处理登陆注册都特别有用。

    3.用户基础信息采集拦截器开发

    (1)引入日志依赖

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>

    (2)配置日志格式,将其存储到目录

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <!--RollingFileAppender追加器用于生成按天滚动的日志文件-->
        <appender name="accessHistoryLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!--rollingPolicy滚动策略,TimeBasedRollingPolicy按照时间进行滚动-->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!--配置日志存储路径-->
                <fileNamePattern>C:java_studyproject
    estfullog
    estful.%d.log</fileNamePattern>
            </rollingPolicy>
            <!--定义日志输出的格式-->
            <encoder>
                <pattern>[%thread] %d %level %logger{10} - %msg%n</pattern>
            </encoder>
        </appender>
        <!--日志的最低输出级别为debug,输出地址为控制台-->
        <!--AccessHistoryInterceptor这个类所产生的日志都会使用下面标签所产生的规则-->
        <!--additivity是否向控制台输出,false在只会向指定规则下输出-->
        <logger name="com.ikidana.restful.interceptor.AccessHistoryInterceptor" level="info" additivity="false">
            <appender-ref ref="accessHistoryLog"/>
        </logger>
    </configuration>

    (3)创建拦截器,并填入信息

    public class AccessHistoryInterceptor implements HandlerInterceptor {
        //创建一个logger日志对象
        private Logger logger = (Logger) LoggerFactory.getLogger(AccessHistoryInterceptor.class);
    
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            StringBuilder log = new StringBuilder();
            log.append(request.getRemoteAddr());  //地址
            log.append("|");
            log.append(request.getRequestURL());  //URL
            log.append("|");
            log.append(request.getHeader("user-agent"));
            logger.info(log.toString());
            return true;
        }
    }

    (4)注册使用

    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.ikidana.restful.interceptor.AccessHistoryInterceptor"/>
    </mvc:interceptor>

    (5)效果

    4.SpringMVC处理流程

  • 相关阅读:
    jquery中的Ajax
    javascript 中状态改变触发事件
    关于sql 资源竞争死锁现象
    Attribute 特性
    JavaScript的垃圾回收
    委托和事件
    彻底弄懂AngularJS中的transclusion
    理解AngularJS中的依赖注入
    用postal.js在AngularJS中实现订阅发布消息
    AngularJS 1.3中的一次性数据绑定(one-time bindings)
  • 原文地址:https://www.cnblogs.com/yangmingxianshen/p/12521619.html
Copyright © 2020-2023  润新知