Spring MVC拦截器
Interceptor
拦截器(Interceptor)用于对URL请求进行前置/后置过滤
Interceptor与Filter用途相似,但实现方式不同
Interceptor底层基于Spring AOP面向切面编程实现
拦截器开发流程
- Maven依赖
servlet-api
- 实现
HandlerInterceptor
接口 applicationContext
配置过滤地址
HandlerInterceptor
preHandle - 前置执行处理
postHandle - 目标资源已经被SpringMVC框架处理:
afterCompletion - 响应文本以产生
1.引入依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
2.实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(request.getRequestURL() + "前置处理已完成");
return true; //如果为true会送达给后面的拦截器,fakse当前请求会被阻止直接返回给客户端
}
@Override
//目标资源被处理成功,但是没有产生相应文本之前
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println(request.getRequestURL() + "目标处理成功");
}
@Override
//当目标响应文本产生以后
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println(request.getRequestURL() + "响应内容已产生");
}
}
3.applicationContext配置过滤地址
<mvc:interceptors>
<mvc:interceptor>
<!--对哪些地址进行拦截-->
<mvc:mapping path="/**"/>
<!--对URL进行处理-->
<bean class="com.huazll.restful.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
Interceptor使用技巧
<mvc:interceptors>
<mvc:interceptor>
<!--对哪些地址进行拦截-->
<mvc:mapping path="/**"/>
<!--只对前缀为/restful的RRL进行拦截-->
<mvc:mapping path="/restful/**"/>
<!--exclude-mapping:过滤以下URL文件-->
<mvc:exclude-mapping path="/**.js"/>
<mvc:exclude-mapping path="/**.css"/>
<!--只过滤前缀为/resources/...的RUL-->
<mvc:exclude-mapping path="/resources/**"/>
<!--对URL进行处理-->
<bean class="com.huazll.restful.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
执行顺序
Filter和Interceptor的区别
- Filter接口在javax.Servlet包下面。Interceptor定义在org.Springframework.web.Servlet中
- Filter基于Filter接口中的doFilter回调函数,时Servlet容器支持的;而Interceptor基于Java本身的反射机制(AOP思想),时Spring框架支持的
- Filter是依赖于Servlet容器的,没有Servlet容器就无法回调doFilter方法,而Interceptor与Servlet无关;
- Filter的过滤范围比Interceptor大,Filter除了过滤请求外通过通配符可以保护页面、图片、文件等,而Interceptor智能过滤请求,只对请求起作用,在请求之前开始,在请求完成后结束(如被拦截,不执行请求)。
- Filter的过滤一般在加载的时候在init()方法声明,而Inteceptor可以通过在xml生命是guest请求还是user请求,来辨别是否过滤。
- Interceptor可以访问请求上下文、值栈里的对象,而Filter不能。
- 在请求的生命周期中,拦截器可以被多次调用,而过滤器智能在容器初始化被调用一次。
开发用户流量拦截器
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%thread] %d %level %logger{10} - %msg%n</pattern>
</encoder>
</appender>
<appender name="accessHistoryLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志滚动策略:按时间滚动-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>E:/logs/history/%d.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>[%thread] %d %level %logger{10} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="console"/>
</root>
<!--打印当前类的运行日志,不向控制台打印。使用accessHistoryLog进行记录-->
<logger name="com.huazll.restful.interceptor.AccessHistoryInterceptor" level="INFO" additivity="false">
<appender-ref ref="accessHistoryLog"/>
</logger>
</configuration>
public class AccessHistoryInterceptor implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(AccessHistoryInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
StringBuilder log = new StringBuilder();
//获取用户IP
log.append(request.getRemoteAddr());
log.append("|");
//获取用户访问URL
log.append(request.getRequestURL());
log.append("|");
//获取用户客户端名称
log.append(request.getHeader("user-agent"));
logger.info(log.toString());
return true;
}
}
SpringMVC处理流程
Handler:处理器,在计算机中也叫句柄。可以认为是控制器(Controller)或拦截器(Interceptor)
执行链:
浏览器发送URL请求经过DispacherServlet拦截处理,交由SpringMVC进行处理。查找Handler并返回执行链,将执行链返回给DispacherServlet再向HandlerAdapter,根据类型执行对应方法,执行Controller的方法返会ModelAndView被HandlerAdapter接收并返回给DispacherServlet。DispacherServlet会判断ModelAndView被哪个模板引擎处理,根据View中的配置返回对应的视图解析器返回给DispacherServlet,根据ModelAndView中的数据组成HTML片段返回给浏览器