Maven依赖servlet-api
实现HandlerInterceptor接口
package com.imooc.restful.interceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springFramework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
//preHandle()方法;return true表示继续向后执行,return false表示停止向后执行;返回响应
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(request.getRequestURL() ; ;-准备执行;);
// response.getWriter().print(;[];);
return true;
}
//postHandel()方法执行时机是在目标方法处理完成;执行了“return”代码后;相应文本产生之前执行
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() ; ;-响应内容已产生;);
}
}
applicationContext配置过滤地址
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path=;/**;/>
<mvc:exclude-mapping path=;/resources/**;/>
<bean class=;com.imooc.restful.interceptor.AccessHistoryInterceptor;/>
</mvc:interceptor>
</mvc:interceptors>
对于资源的过滤与排除;
网页中每一次发送URL的时都是通过服务器调用Spring MVC解析功能获取资源;但是访问这些资源时;符合拦截器中的/**规则所有都会被拦截;虽然在applicationContext中配置了屏蔽静态资源的default-servlet-handler;但是拦截器不受影响;实际工作中不希望对Js等静态资源进行处理;需要拦截器将不需要的URL排除;我们可以通过规范静态资源的存放位置;固定的工程目录resources;;这样在使用“绝对路径”访问静态资源时可以有统一的“前缀”来放行资源;或者拦截某些前缀的访问资源。
<mvc:interceptors>
<mvc:interceptor>
<mvc:exclude-mapping path=;/resources/**;/>
<mvc:mapping path=;/restful/**;/>
<mvc:mapping path=;/webapi/**;/>
<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.imooc.restful.interceptor.MyInterceptor;/>
</mvc:interceptor>
</mvc:interceptors>
当有多个拦截器时;各个拦截器的执行顺序;
注意;
请求按照顺序执行;响应按照倒序执行。
如果第一个拦截器前置就失败;那后续拦截器和所有的后置方法都消失;前置方法相当于阻断器。
使用拦截器;采集用户基础数据;ip、访问时间、使用的设备;;思路;使用日志组件打印出访问者基础信息;并保存到日志文件。
<dependency>
<groupId>ch.QOS.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<?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>
<!--如何保存logback信息到文件中?-->
<!--RollingFileAppender产生按天滚动的日志文件 按天向文件进行写入-->
<appender name=;accessHistoryLog; class=;ch.qos.logback.core.rolling.RollingFileAppender;>
<!--RollingFileAppender滚动策略-->
<rollingPolicy class=;ch.qos.logback.core.rolling.TimeBasedRollingPolicy;>
<!--文件保存路径 %d表示当前日期插入文件名 文件扩展名为log-->
<fileNamePattern>d:/logs/history.%d.log</fileNamePattern>
</rollingPolicy>
<!--日志输出格式-->
<encoder>
<pattern>
<!--线程名称、产生时间、日志级别、哪一个类的日志{名字太长会压缩}-->
[%thread %d %level %logger{10} - %msg%n]
</pattern>
</encoder>
</appender>
<!--当前日志最低输出debug级别-->
<root level=;debug;>
<appender-ref ref=;console;/>
</root>
<!--AccessHistoryIntercepto类产生的日志都会存放于上述路径-->
<!--additivity设置是否叠加;如果true不仅会存放文件还会向console进行打印-->
<logger name=;com.imooc.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 配置需要向日志打印的具体内容是什么
*/
StringBuilder log = new StringBuilder();
//增加访问用户的ip地址 通过方法request.getRemoteAddr()
log.append(request.getRemoteAddr());
log.append(;|;);
//用户访问的地址
log.append(request.getRequestURL());
log.append(;|;);
//用户客户端环境保存在;user-agent;请求头中
log.append(request.getHeader(;user-agent;));
log.append(;|;);
logger.info(log.toString());
return true;
}
}
1.所有的URL请求都会被DispatcherServlet(中央处理器)拦截;然后交由SpringMVC进行处理;DispatcherServlet做的第一件事是查找Handler(处理器;也叫句柄);本质是拦截器或Controller的统称
2.查找句柄的任务交由HandlerMapper(处理器映射器)完成的;通过访问的URL得到执行链;执行链也就是该请求URL要经过哪些拦截器;被哪些Controller处理.3.HandlerMapper只会获取执行链;但不会处理;而是返回执行链给DispatcherServlet;Dispatcher向HandlerAdapter(处理器适配器)发送Handler执行请求;Adapter根据handler的类型(Interceptor/Controller)执行不同的方法
4.例如假如执行Controller的方法;则会返回一个ModelAndView对象;DispatcherServlet会根据对象中url的模板引擎选择对应的ViewResolver(视图解析器);然后视图解析器会根据ModelAndView对象中的url进行视图对象创建;并返回给DispatcherSerlvet
请求;Adapter根据handler的类型(Interceptor/Controller)执行不同的方法
4.例如假如执行Controller的方法;则会返回一个ModelAndView对象;DispatcherServlet会根据对象中url的模板引擎选择对应的ViewResolver(视图解析器);然后视图解析器会根据ModelAndView对象中的url进行视图对象创建;并返回给DispatcherSerlvet
5.DispathcerServlet根据View对象;把Model中的数据与View对象进行渲染;最终得到HTML;随着响应返回给客户端浏览器;这样一个完整的SpringMVC的流程就完成了。
Spring-Boot-+-Flowable-快速实现工作流