Spring Boot 过滤器 拦截器 监听器

简介: 本文介绍了Spring Boot中的过滤器、拦截器和监听器的实现与应用。通过Filter接口和FilterRegistrationBean类,开发者可实现对请求和响应的数据过滤;使用HandlerInterceptor接口,可在控制器方法执行前后进行处理;利用各种监听器接口(如ServletRequestListener、HttpSessionListener等),可监听Web应用中的事件并作出响应。文章还提供了多个代码示例,帮助读者理解如何创建和配置这些组件,适用于构建更高效、安全和可控的Spring Boot应用程序。

Filter 过滤器

Spring Boot的过滤器用于对数据进行过滤处理。通过Spring Boot的过滤器,程序开发人员不仅可以对用户通过URL地址发送的请求进行过滤处理(例如,过滤一些错误的请求或者请求中的敏感词等),而且可以对服务器返回的数据进行过滤处理(例如,压缩响应信息等)。

使用 FilterRegistrationBean类 实现过滤器

实现过滤器类

如果一个类实现了一个继承Filter 接口的类,那么这个类就可以做为自定义的过滤器。

Filter 接口一共有三个方法

1、init() 方法  初始化过滤器配置  有默认的init方法,可以不重写

2、doFilter() 方法 过滤器的具体行为,abstract 方法,需要自己实现

3、destroy() 方法 销毁过滤器  有默认的destroy方法,可以不重写

下面这段代码实现了一个过滤器类,此过滤器的作用是判断用户是否登录,若没有登录则用请求转发器,将请求转发至/login页面,浏览器的URL不会改变,只会改变当前页面的内容。

java

体验AI代码助手

代码解读

复制代码

public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        // 多态
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        // 从请求消息中获取用户信息
        Object user = request.getSession().getAttribute("user");
        if(user != null) {
            // 如果用户不为空 则继续过滤器链的下一个过滤器。
            filterChain.doFilter(request, servletResponse);
        }
        else{
            // 如果用户为空则 使用请求转发器 将请求转发到`login`页面   给了两个参数,request 和 response 包含一个请求所有的信息
            request.getRequestDispatcher("/login").forward(request, servletResponse);
        }
        
    }
}

配置过滤器类

实现了一个过滤器类后,还需要配置这个过滤器类

以下代码实现了配置过滤器, FilterConfig 是一个配置过滤器的类,类中的方法会注册过滤器,FilterConfig类的命名随意,这个类中的方法注册了一个 FilterRegistrationBean 对象,由Bean的相关概念可知,不管在那个地方,在Spring Boot 的生命周期的初始化阶段,只要一个FilterRegistrationBean 对象被注册了,那么这个过滤器就被配置好了。

观察代码, bean.setFilter 方法就是配置此过滤器中的具体过滤器,当前过滤器配置的过滤器就是上文中实现的过滤器。

一个类中可以实现许多过滤器,此即为 FilterConfig 类名的由来。

java

体验AI代码助手

代码解读

复制代码

@Configuration
public class FilterConfig {
    //
    @Bean
    public FilterRegistrationBean getFilter() {
        FilterRegistrationBean bean = new FilterRegistrationBean<>();
        bean.setFilter(new LoginFilter());
        bean.addUrlPatterns("/main/*"); // 过滤 /main/* 下的所有子路径
        bean.setName("loginfilter");  // 设置过滤器的名称
        return bean;
    }
}

使用 @WebFilter 实现过滤器

WebFilter 实现过滤器的原理与FilterRegistrationBean 实现原理相同,不过更简单,但是功能也更少,推荐使用第一种。

由上文可知,只要这个类实现了Filter接口并且将这个类在Spring Boot 生命周期的初始阶段注册即可实现过滤器。

@WebFilter 注解可以注册Bean,同时配置urlPatterns;

java

体验AI代码助手

代码解读

复制代码

/*
* 这是一个记录一个URL点击次数的过滤器,其中有一个context,这里面的count 记录了点击次数, 此点击次数与客户端无关
* 因此可以推断出,Spring Boot 的 context 是与具体的 URL 绑定的, 这个 URL 是在配置过滤器类时设置好的。
* 点击次数与Spring Boot 有关,因此,关闭Spring Boot context 中的数据会丢失, 需要记录在数据库中。
* */

@Component
@WebFilter(urlPatterns = "/user/click_count/")
public class CountFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 获取上下文
        ServletContext context = filterConfig.getServletContext();
        // 将count的值初始化为 0
        // 这是会自己创建新的count 还是这个Filter 里面本来就有的
        context.setAttribute("count", 0);

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        ServletContext context = request.getServletContext();
        Integer count = (Integer) context.getAttribute("count");
        // 每一次请求都会经过过滤器, 每一次都会导致 count 加一
        count = count + 1;
        context.setAttribute("count", count);

        filterChain.doFilter(servletRequest, servletResponse);

    }
}

拦截器

拦截器可以在控制器类中的方法被执行前和被执行后对请求做一些处理。 拦截器可以形成链,如果链中的某一个节点断开,则整个链断开。

拦截器和过滤器的执行时间不同。

一个类如果实现了HandlerInterceptor接口,就能够实现自定义的拦截器

1、preHandle()方法

preHandle()方法会在控制器类中的方法被执行之前、对请求进行处理时被执行,preHandle()方法的语法如下:

2、postHandle()方法

postHandle()方法会在控制器类中的方法被执行之后、对请求进行处理时被执行,

3、afterCompletion()方法

afterCompletion()方法在整个请求结束之后被执行

创建一个拦截器

java

体验AI代码助手

代码解读

复制代码


public class MyInterceptor implements HandlerInterceptor {
    // 此函数是请求进入 controller 之前的处理程序 返回为真,请求正常进行,返回为假,则请求断开
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if(handler instanceof HandlerMethod){
            HandlerMethod method = (HandlerMethod)handler;
            System.out.println("1、请求访问的方法是:" + method.getMethod().getName() + "()"); // 输出请求方法
            Object value = request.getAttribute("value"); // 读取请求的某个属性,默认为null
            System.out.println("执行方法前:value="+value);
            return true;
        }
        return false;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        Object value = request.getAttribute("value");
        System.out.println("2、执行方法后:value="+value);
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        request.removeAttribute("value");
        System.out.println("3、整个请求都执行完毕,在此做一些资源释放工作");
    }
}

注册拦截器

注册拦截器是通过 继承WebMvcConfigurer 接口并重写 addInterceptors 方法 实现的。

这里发现拦截器并没有像过滤器一样注册在Spring Boot 的Bean容器中, 而是与URL地址绑定,与URL请求处理函数一样。

java

体验AI代码助手

代码解读

复制代码

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration regist = registry.addInterceptor(new MyInterceptor());
        regist.addPathPatterns("/test/login"); // 拦截 /test/login
    }
}

至此,拦截器创建并注册好了。

客户端请求通过拦截器流程。

  1. 进入 preHandler 程序
  2. 执行处理从此请求的 Controller 程序
  3. 进入 postHandler 程序
  4. 在客户端请求完成之后 执行 afterCompletion 程序

监听器

在开发Spring Boot项目的过程中,监听器用于监听并处理指定的事件。在一个Spring Boot项目中,可以包含一个或者多个监听器。如果一个Spring Boot项目包含多个监听器,那么这些监听器的类型既可以是相同的,也可以是不同的。

ServletRequestListener接口

ServletRequestListener接口可以监听请求的初始化与销毁

requestInitialized(ServletRequestEvent sre):请求初始化时触发。

requestDestroyed(ServletRequestEvent sre):请求被销毁时触发。

HttpSessionListener接口

HttpSessionListener接口可以监听session的创建与销毁

sessionCreated(HttpSessionEvent se):session已经被加载及初始化时触发。

sessionDestroyed(HttpSessionEvent se):session被销毁后触发。

ServletContextListener接口

ServletContextListener接口可以监听上下文的初始化与销毁.

contextInitialized(ServletContextEvent sce):上下文初始化时触发

contextDestroyed(ServletContextEvent sce):上下文被销毁时触发。

ServletRequestAttributeListener接口

ServletRequestAttributeListener接口可以监听请求属性发生的增、删、改事件.

attributeAdded(ServletRequestAttributeEvent srae):请求添加新属性时触发。

attributeRemoved(ServletRequestAttributeEvent srae):请求删除旧属性时触发。

attributeReplaced(ServletRequestAttributeEvent srae):请求修改旧属性时触发。

HttpSessionAttributeListener接口

HttpSessionAttributeListener接口可以监听session属性发生的增、删、改事件.

attributeAdded(HttpSessionBindingEvent se):session添加新属性时触发。

attributeRemoved(HttpSessionBindingEvent se):session删除旧属性时触发。

attributeReplaced(HttpSessionBindingEvent se):session修改旧属性时触发。

ServletContextAttributeListener接口

ServletContextAttributeListener接口可以监听上下文属性发生的增、删、改事件.

attributeAdded(ServletContextAttributeEvent scae):上下文添加新属性时触发。

attributeRemoved(ServletContextAttributeEvent scae):上下文删除旧属性时触发。

attributeReplaced(ServletContextAttributeEvent scae):上下文修改旧属性时触发。

HttpSessionBindingListener接口

HttpSessionBindingListener接口可以为开发者自定义的类添加session绑定监听,当session保存或移除此类的对象时触发此监听。 

valueBound(HttpSessionBindingEvent event):当session通过setAttribute()方法保存对象时,触发该对象的此方法。

valueUnbound(HttpSessionBindingEvent event):当session通过removeAttribute()方法移除对象时,触发该对象的此方法。

HttpSessionActivationListener接口

HttpSessionActivationListener接口可以为开发者自定义的类添加序列化监听,当保存在session中的自定义类对象被序列化或反序列化时触发此监听。此监听通常会配合HttpSessionBindingListener监听一起使用。

sessionWillPassivate(HttpSessionEvent se):自定义对象被序列化之前触发。

sessionDidActivate(HttpSessionEvent se):自定义对象被反序列化之后触发。

对象变成字节序列的过程被称为序列化,例如将内存中的对象保存到硬盘文件中,这个过程也被称为passivate、钝化、持久化;字节序列变成对象的过程被称为反序列化,例如从文件中读取数据并封装成一个对象并保存在内存中,这个过程也被称为activate、活化。

自定义监听器,监听每一个前端请求的URL、IP和session id

session id是由服务器随机生成的,每个session的session id都不一样。但只要用户不关闭浏览器,用户的session id就不会改变。

java

体验AI代码助手

代码解读

复制代码

@Component
public class MyRequestListener implements ServletRequestListener {
    public void requestInitialized(ServletRequestEvent sre) {
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        String ip = request.getRemoteAddr();
        String url = request.getRequestURI();
        String sessionId = request.getSession().getId();
        System.out.println("IP:"+ip);
        System.out.println("url:"+url);
        System.out.println("sessionId:"+sessionId);
    }

    public void requestDestroyed(ServletRequestEvent sre) {
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        String sessionId = request.getSession().getId();
        System.out.println("sessionId:"+sessionId + "的请求已销毁");
    }
}


转载来源:https://juejin.cn/post/7389913087471599668

相关文章
|
6月前
|
Java 数据安全/隐私保护 微服务
微服务——SpringBoot使用归纳——Spring Boot中使用监听器——Spring Boot中自定义事件监听
本文介绍了在Spring Boot中实现自定义事件监听的完整流程。首先通过继承`ApplicationEvent`创建自定义事件,例如包含用户数据的`MyEvent`。接着,实现`ApplicationListener`接口构建监听器,用于捕获并处理事件。最后,在服务层通过`ApplicationContext`发布事件,触发监听器执行相应逻辑。文章结合微服务场景,展示了如何在微服务A处理完逻辑后通知微服务B,具有很强的实战意义。
367 0
|
6月前
|
缓存 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot中使用监听器——监听器介绍和使用
本文介绍了在Spring Boot中使用监听器的方法。首先讲解了Web监听器的概念,即通过监听特定事件(如ServletContext、HttpSession和ServletRequest的创建与销毁)实现监控和处理逻辑。接着详细说明了三种实际应用场景:1) 监听Servlet上下文对象以初始化缓存数据;2) 监听HTTP会话Session对象统计在线用户数;3) 监听客户端请求的Servlet Request对象获取访问信息。每种场景均配有代码示例,帮助开发者理解并应用监听器功能。
393 0
|
6月前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot中使用拦截器——拦截器使用实例
本文主要讲解了Spring Boot中拦截器的使用实例,包括判断用户是否登录和取消特定拦截操作两大场景。通过token验证实现登录状态检查,未登录则拦截请求;定义自定义注解@UnInterception实现灵活取消拦截功能。最后总结了拦截器的创建、配置及对静态资源的影响,并提供两种配置方式供选择,帮助读者掌握拦截器的实际应用。
201 0
|
6月前
|
前端开发 JavaScript Java
微服务——SpringBoot使用归纳——Spring Boot中使用拦截器——拦截器的快速使用
本文介绍了在Spring Boot中使用拦截器的方法,包括拦截器的基本原理、定义与配置步骤。拦截器是AOP的一种实现,主要用于拦截对动态资源的请求,如判断用户权限或结合WebSocket使用。文章详细讲解了通过实现`HandlerInterceptor`接口来自定义拦截器,并重写`preHandle`、`postHandle`和`afterCompletion`三个核心方法。
1102 0
|
9月前
|
缓存 安全 Java
Spring高手之路26——全方位掌握事务监听器
本文深入探讨了Spring事务监听器的设计与实现,包括通过TransactionSynchronization接口和@TransactionalEventListener注解实现事务监听器的方法,并通过实例详细展示了如何在事务生命周期的不同阶段执行自定义逻辑,提供了实际应用场景中的最佳实践。
251 2
Spring高手之路26——全方位掌握事务监听器
|
10月前
|
监控 Java 数据安全/隐私保护
如何用Spring Boot实现拦截器:从入门到实践
如何用Spring Boot实现拦截器:从入门到实践
453 5
|
11月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
186 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
11月前
|
设计模式 Java Spring
Spring Boot监听器的底层实现原理
Spring Boot监听器的底层实现原理主要基于观察者模式(也称为发布-订阅模式),这是设计模式中用于实现对象之间一对多依赖的一种常见方式。在Spring Boot中,监听器的实现依赖于Spring框架提供的事件监听机制。
248 1
|
前端开发 JavaScript Java
Spring Boot中使用拦截器
本节主要介绍了 Spring Boot 中拦截器的使用,从拦截器的创建、配置,到拦截器对静态资源的影响,都做了详细的分析。Spring Boot 2.0 之后拦截器的配置支持两种方式,可以根据实际情况选择不同的配置方式。最后结合实际中的使用,举了两个常用的场景,希望读者能够认真消化,掌握拦截器的使用。
|
缓存 Java 数据库
Spring Boot中使用监听器
系统的介绍了监听器原理,以及在 Spring Boot 中如何使用监听器,列举了监听器的三个常用的案例,有很好的实战意义。最后讲解了项目中如何自定义事件和监听器,并结合微服务中常见的场景,给出具体的代码模型,均能运用到实际项目中去,希望读者认真消化。