## 拦截器
Interceptor 在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。比如日志,安全等。一般拦截器方法都是通过动态代理的方式实现。可以通过它来进行权限验证,或者判断用户是否登陆,或者是像12306 判断当前时间是否是购票时间。
新建一个RestInterceptor
```
@Slf4j
public class RestInterceptor extends HandlerInterceptorAdapter {
private static final String START_TIME = "requestStartTime";
//preHandle在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制等处理;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//根据请求信息判断是否需要拦截
String url = request.getRequestURI();
Map parameterMap = request.getParameterMap();
log.info("request start. url:{}", url);
long start = System.currentTimeMillis();
request.setAttribute(START_TIME, start);
return true;
}
//postHandle在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView;
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
String url = request.getRequestURI().toString();
long start = (Long) request.getAttribute(START_TIME);
long end = System.currentTimeMillis();
log.info("request finished. url:{}, cost:{}", url, end - start);
}
//afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面),可以根据ex是否为null判断是否发生了异常,进行日志记录;
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
String url = request.getRequestURI();
long start = (Long) request.getAttribute(START_TIME);
long end = System.currentTimeMillis();
log.info("request completed. url:{}, cost:{}", url, end - start);
}
}
```
新建一个RestInterceptorConfig配置类进行注册
```
@Configuration
public class RestInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new RestInterceptor()).addPathPatterns("/*");
}
}
```
RestInterceptorConfig配置类有下面4种配置方式:
* implements WebMvcConfigurer : 不会覆盖@EnableAutoConfiguration关于WebMvcAutoConfiguration的配置
* @EnableWebMvc + implements WebMvcConfigurer : 会覆盖@EnableAutoConfiguration关于WebMvcAutoConfiguration的配置
* extends WebMvcConfigurationSupport :会覆盖@EnableAutoConfiguration关于WebMvcAutoConfiguration的配置
* extends DelegatingWebMvcConfiguration :会覆盖@EnableAutoConfiguration关于WebMvcAutoConfiguration的配置
##### spring2.0 WebMvcConfigurationadpter 已经弃用了
关于@EnableWebMvc,WebMvcConfigurationSupport,WebMvcConfigurer和WebMvcConfigurationAdapter区别访问:[Link](http://520htt.com/archives/webmvcconfigurationsupport)
关于继承WebMvcConfigurationSupport静态资源不可以访问:[Link](http://520htt.com/archives/webmvcconfigurationsupport)
## 过滤器
Filter是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
##### 方法一
新建一个RestFilter
```
@WebFilter(urlPatterns = "/*", filterName = "RestFilter")
@Slf4j
public class RestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("RestFilter --- init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("RestFilter --- doFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
log.info("RestFilter --- destroy");
}
}
```
在SpringbootApplication上面添加`@ServletComponentScan`注解
```
@ServletComponentScan
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
```
##### 方法二(推荐)
同RestFilter.class一样但是不要加`@WebFilter`,也不需要在SpringbootApplication类加`@ServletComponentScan`通过配置类实现
```
@Slf4j
public class RestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("RestFilter --- init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("RestFilter --- doFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
log.info("RestFilter --- destroy");
}
}
```
配置类
```
@Configuration
public class RestFilterConfig {
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new RestFilter());
filterRegistrationBean.setName("RestFilter");
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}
```
#### `@WebFilter`注解说明:
上源码
```
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebFilter {
String description() default "";
/**Filter显示名*/
String displayName() default "";
/**配置参数*/
WebInitParam[] initParams() default {};
/**Filter名称*/
String filterName() default "";
String smallIcon() default "";
String largeIcon() default "";
/**指定对哪些Servlet进行过滤*/
String[] servletNames() default {};
/**指定拦截的路径*/
String[] value() default {};
/**指定拦截的路径*/
String[] urlPatterns() default {};
/**指定Filter对哪种方式的请求进行过滤*/
DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST};
/**指定Filter是否支持异步模式*/
boolean asyncSupported() default false;
}
```
## 监听器
listener是servlet规范中定义的一种特殊类。用于监听servletContext、HttpSession和servletRequest等域对象的创建和销毁事件。监听域对象的属性发生修改的事件。用于在事件发生前、发生后做一些必要的处理。其主要可用于以下方面:1、统计在线人数和在线用户2、系统启动时加载初始化信息3、统计网站访问量4、记录用户访问路径。
监听器就是监听某个对象的的状态变化的组件
## 监听器的相关概念:
事件源:被监听的对象 ----- 三个域对象 request session servletContext
监听器:监听事件源对象 事件源对象的状态的变化都会触发监听器 ----
yao
注册监听器:将监听器与事件源进行绑定
响应行为:监听器监听到事件源的状态变化时 所涉及的功能代码 ---- 程序员编写代码

方法一:
监控 Request
新建RequestListener继承ServletRequestListener
```
@WebListener
@Slf4j
public class RequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent sce) {
HttpServletRequest request = (HttpServletRequest) sce.getServletRequest();
log.info("RequestListener----init---->"+request.getRequestURI());
}
@Override
public void requestDestroyed(ServletRequestEvent sce) {
HttpServletRequest request = (HttpServletRequest) sce.getServletRequest();
log.info("RequestListener---desroyed----> "+request.getRequestURI());
}
}
```
使用`@WebListener`注解实现,使用@WebListener与@WebFilter要在主类上面添加`@ServletComponentScan`注解
通过访问:http://localhost:8080/可以看到
```
···
RequestListener----init---->/
···
RequestListener---desroyed----> /
```
session监控
新建SessionListener 继承 HttpSessionListener
```
@WebListener
@Slf4j
public class SessionListener implements HttpSessionListener {
@Override
public void sessionCreated(javax.servlet.http.HttpSessionEvent se) {
log.info("SessionListener----init---->"+se.getSession().getAttribute("user"));
}
@Override
public void sessionDestroyed(javax.servlet.http.HttpSessionEvent se) {
log.info("SessionListener---desroyed----> "+se.getSession().getAttribute("user"));
}
}
```
在RestController新建两个请求控制Session的新建和销毁查看日志
```
@GetMapping("/CreateSession")
public String CreateSession(HttpSession Session) {
Session.setAttribute("user", "jackgeeks");
return "CreateSession";
}
@GetMapping("/DestroySession")
public String DestroySession(HttpSession Session) {
Session.invalidate();
return "DestroySession";
}
```
方法二
Context监控
新建ContextListener继承ServletContextListener
```
@Slf4j
public class ContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
log.info("ContextListener--init .. ");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("ContextListener---desroyed .. ");
}
}
```
通过配置类
```
@Configuration
public class ContextListenerConfig {
@Bean
public ServletListenerRegistrationBean ListenerTow(){
ServletListenerRegistrationBean<ContextListener>servletListenerRegistrationBean = new ServletListenerRegistrationBean<>(new ContextListener());
return servletListenerRegistrationBean;
}
}
```
服务器启动后会打印日志
```
ContextListener--init ..
```
#### 自定义监听器
新建ApplicationListener通过`@EventListener`定义监控器
```
@Slf4j
@Component
public class MyApplicationListener {
@EventListener
public void onApplicationEvent(String event) {
log.info("MyApplicationListener接收到事件"+event);
}
}
```
在RestController新建一个/Event git请求发发布事件
```
@GetMapping("/Event")
public String Event() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyApplicationListener.class);
System.out.println("发布事件");
context.publishEvent("event");
context.close();
return "发布事件";
}
```
## 获取源码公众号回复: Interceptor


SpringBoot2.0学习之Interceptor,Filter,listener