Spring Boot 2系列(二十七):Listener, Filter, Interceptor
Listener 监听器,Filter 过滤器,Interceptor 拦截器是 Java Web领域非常重要的三大神器(组件),会经常使用到。
关注这三个的知识点本篇不做描述,主要记录在Spring Boot框架中这三大组件的使用。
前面文章也有提到:Spring事件监听,SpringMVC之HandlerInterceptor拦截器, Spring Boot实践系列(二十二):Web相关配置详解 。
官方文档:Spring Boot -> Application Events and Listeners,Spring Boot -> Servlets, Filters, Listeners, Spring Boot -> Add a Servlet, Filter, or Listener to an Application。
Spring Boot
在 Spring Boot 框架中,将自定义的 Servlet, Filter, Listener 注册为 Spring Bean有两种方式:
- Spring Boot框架中在自定义的 Servlet, Filter, Listener 三大组件类上添加
@Component 或 @Configuration
注解将监听器注册为 Spring Bean, 可调用 IoC 容器的产资源(Bean)。 - 在自定义的 Servlet, Filter, Listener 类上添加
@WebServlet, @WebFilter, @WebListener
注解,会自动将自定义三大给件类注册为 Servlet 组件并启动。
注意:如果使用的是 Spring Boot 内嵌的 Servlet 容器,还需要在使用了@Configuration
注解的类上添加@ServletComponentScan
注解; 如果部署在外部独立的Servlet 容器,则不需要**@ServletComponentScan**注解,由独立容器的内部发现机制将自定义的三大组件类注册为 Servlet组件。
@ServletComponentScan注解,是在使用 Spring Boot 内嵌的 Servlet 容器时需要添加,用于是启用扫描使用了**@WebServlet, @WebFilter, @WebListener**注解的类并将之注册为 Servlet 组件, 可通过value
或basePackages
属性指定自定义的 Servlet, Filter, Listener 所在的包路径, 就会自动将该包下使用了 @WebServlet, @WebFilter, @WebListener 注解的自定义类注册 Servlet 组件; 默认情况下会从 @ServletComponentScan
注解所在类的包开始扫描,所以很多时候直接把这个注解放在启动入口类上。
Listener
Listener是 Servlet 规范,由 Servlet 容器提供支持,随Servlet容器启动就启动监听, 监听到事件时,在监听器里面相应的方法里执行处理。
Servlet 提供的3个基本监听器接口:ServletContextListener,ServletRequestListener,HttpSessionListener,使用时实现用到的接口,重写里面的方法 。
- 根据创建的Session数统计在线人数
根据 Session 统计 Web 站点的计在线人数并不十分准确, 若用户离线了但 Session 仍在有效期内则认为这个用户仍在线。
1 | /** |
- 容器启动监听器,执行初始化操作
因上面的统计在线用户数是存在Redis
中, 如果系统宕机或崩溃是不会清空引在线用户数的值的,会存在较大误差。所在在系统起动时重置下。如果是单机系统,可以将计算的用户数放到ServletContext
域中。
1 | /** |
Filter
Filter过滤器是 Servlet 规范,由 Servlet 容器提供支持,在 Servlet 之前和之后起作用,无法调用 Spring IOC 中的资源。
基础知识,参考 Servlet 编写过滤器
Interceptor
Interceptor 是 Spring 提从的组件,由 Spring 框架提供支持,由 Spring 管理,可在拦截器中注入 IoC 中的资源。
- 登录拦截器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31/**
* @ClassName LoginInterceptor
* @Description 登录验证拦截器
**/
public class LoginInterceptor implements HandlerInterceptor {
private static final Logger log = LoggerFactory.getLogger(LoginInterceptor.class);
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
HttpSession session = httpServletRequest.getSession();
// 判断是否登录
if (null != session.getAttribute("SESSION_USER_OBJ")) {
return true;
} else {
httpServletResponse.sendRedirect("/user/toLogin");
return false;
}
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
} - 配置拦截器和放行路径
注:新的 Spring 5.0 是实现WebMvcConfigurer
接口,WebMvcConfigurerAdapter 已标注为过期。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class WebConfig implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login");
}
/*
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册自定义拦截器,添加拦截路径和排除拦截路径
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/index")
.excludePathPatterns("/user/register")
.excludePathPatterns("/user/login")
.excludePathPatterns("/error");
}
*/
public LoginInterceptor loginInterceptor() {
return new LoginInterceptor();
}
}
三大神器的执行顺序:监听电话 -> 过滤垃圾信号 -> 拦截恐怖事件,任务处理完则原路返回。
注意
在注册 监听器、过滤器或拦截器时,最好是先通过 @Bean
注解将其声明为 Bean,注册时调用申请为 Bean 的方法 来使用。
因为这三大组件在注册时先于 Bean 注册,如果在这三大给件里注入了其它 Bean,在引用时就会报空指针。例如,在拦截器里注入了 RedisTemplate,在 WebMvcConfigurer 添加拦截器时,使用 new 的方式,则
参考
Spring Boot 2系列(二十七):Listener, Filter, Interceptor
http://blog.gxitsky.com/2018/08/14/SpringBoot-27-listener-filter-interceptor/