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_study\project\restful\log\restful.%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处理流程

 

posted @ 2020-03-19 01:19  明王不动心  阅读(408)  评论(0编辑  收藏  举报