SpringBoot整合Web过滤器、监听器、拦截器

在这里插入图片描述

一、过滤器

过滤器是一个基于Servlet的程序,它先于Servlet或JSP执行,因此常常被用作请求前的信息检查,修改编码,重定向请求路径等功能。
在这里插入图片描述
SpringBoot定义一个web过滤器只需要其继承HttpFilter类,并在类上使用@WebFilter注解声明过滤路径。

@Slf4j
@WebFilter("/*") // 过滤器路径
public class MessageFilter extends HttpFilter {

    public void doFilter(HttpServletRequest request, HttpServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        log.info("[MessageFilter] 请求地址:" + request.getRequestURI());
        chain.doFilter(request, response);
    }

}

由于SpringBoot默认采用内嵌的tomcat,所以需要在启动类上添加@ServletComponentScan注解进行web组件的扫描。

@SpringBootApplication
@ServletComponentScan // 扫描Servlet组件
public class StartSpringBoot {
    public static void main(String[] args) {
        SpringApplication.run(StartSpringBoot.class, args);
    }
}

通过浏览器访问:http://localhost:8080/hello

发现控制台打出过滤器日志,说明过滤器配置成功:
在这里插入图片描述

在实际的项目开发中,一个访问路径前可能存在多个过滤器组成的过滤链。传统的Java WEB项目会有一个web.xml的配置文件,可以在其中配置过滤器的过滤路径,如果一个访问路径在多个过滤器的过滤路径下,那么过滤器的执行顺序就和配置文件的编写顺序有关了:

  <!-- 过滤顺序:谁的写在上面,谁先被过滤 -->
  <filter>
    <filter-name>Filter1</filter-name>
    <filter-class>com.it.filter.Filter1</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>Filter1</filter-name>
    <url-pattern>/*</url-pattern> <!-- 过滤所有 -->
  </filter-mapping>
  
  <filter>
    <filter-name>Filter2</filter-name>
    <filter-class>com.it.filter.Filter2</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>Filter2</filter-name>
    <url-pattern>/*</url-pattern> <!-- 过滤所有 -->
  </filter-mapping>

以上面的配置为例,如果要访问:http://localhost:8080/hello,那么一定会是以下的顺序:

浏览器
Filter1
Filter2
处理请求的Action

而SpringBoot的目标就是减少传统java web项目繁杂的配置文件,配置信息可以在application.yml中编写,也可以自定义配置类,通过代码的方式进行配置。
删除MessageFilter类上的@WebFilter注解:

@Slf4j
public class MessageFilter extends HttpFilter {

    public void doFilter(HttpServletRequest request, HttpServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        log.info("[MessageFilter] 请求地址:" + request.getRequestURI());
        chain.doFilter(request, response);
    }

}

再编写一个ValidateFilter:

@Slf4j
public class ValidateFilter extends HttpFilter {
    public void doFilter(HttpServletRequest request, HttpServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        log.info("[ValidateFilter] 请求地址:" + request.getRequestURI());
        chain.doFilter(request, response);
    }
}

编写一个配置类控制Filter的执行顺序:

@Configuration
public class WebFilterConfig {

    /**
     * 配置MessageFilter的执行顺序
     * @return FilterRegistrationBean
     */
    @Bean
    public FilterRegistrationBean getMessageRegistration() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new MessageFilter()); // 过滤器类实例对象
        filterRegistrationBean.setName("MessageFilter"); // 过滤器名
        filterRegistrationBean.addUrlPatterns("/*"); // 过滤路径
        filterRegistrationBean.setOrder(2); // 执行顺序
        return filterRegistrationBean;
    }
    
    @Bean
    public FilterRegistrationBean getValidateRegistration() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new ValidateFilter());
        filterRegistrationBean.setName("ValidateFilter");
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setOrder(5);
        return filterRegistrationBean;
    }
}

通过FilterRegistrationBean 类的order属性可以指定过滤器的执行顺序,order值越小则越先执行。
直接访问:http://localhost:8080/发现ValidateFilter比MessageFilter先执行。
在这里插入图片描述

二、监听器

监听器就是监听某个对象的的状态变化的组件,按照被监听的对象可划分为:ServletRequest域 、HttpSession域、 ServletContext域。按照监听的内容可分为:域对象的创建与销毁、域对象的属性变化。

ServletRequestServletRequestServletRequest
域对象的创建与销毁ServletContextListenerHttpSessionListenerServletRequestListener
域对象的属性变化ServletContextAttributeListenerHttpSessionAttributeListenerServletRequestAttributeListener

以监听Servlet初始化为例,定义一个监听器类并实现ServletContextListener接口,在类上添加@WebListener注解。

@Slf4j
@WebListener
public class DefaultServletListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        log.info("[DefaultServletListener] " + sce.getServletContext().getServerInfo());
        log.info("[DefaultServletListener] " + sce.getServletContext().getRealPath("/"));
        log.info("[DefaultServletListener] " + sce.getServletContext().getVirtualServerName());
    }
}

由于使用了@WebListener注解,所以需要在SpringBoot启动类上添加@ServletComponentScan注解扫描Servlet组件。

@SpringBootApplication
@ServletComponentScan({"com.it.listener"})
public class StartSpringBoot {
    public static void main(String[] args) {
        SpringApplication.run(StartSpringBoot.class, args);
    }
}

启动项目,发现Servlet初始化监听生效:

在这里插入图片描述

三、拦截器

拦截器是基于java反射机制实现的java程序,其不依赖于Servlet 容器,通常用于service层方法调用前后的处理。
在这里插入图片描述

值得注意的是:

  1. 拦截器是基于 java 的反射机制的,因此拦截器可以访问 action 上下文、值栈里的对象,而过滤器是基于函数回调,不能访问。
  2. 拦截器只能对 action 请求起作用,而过滤器则可以对几乎所有的请求起作用。

SpringBoot整合拦截器只需要实现HandlerInterceptor接口。

@Slf4j
public class DefaultInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        log.info("------------------------------   DefaultInterceptor   ------------------------------");
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            log.info("[控制器实例]" + handlerMethod.getBean());
            log.info("[控制器类型]" + handlerMethod.getBeanType());
            log.info("[控制器方法]" + handlerMethod.getMethod());
        }
        log.info("------------------------------------------------------------------------------------");
        return true;
    }
}

定义好的拦截器需要在配置类中进行启用。

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    /**
     * 注册拦截器
     * @param registry InterceptorRegistry
     */
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getDefaultInterceptor()) // 添加拦截器
                .addPathPatterns("/**"); // 配置拦截器路径
    }

    @Bean
    public HandlerInterceptor getDefaultInterceptor() {
        return new DefaultInterceptor();
    }
}

启动项目,访问任意Action类:
在这里插入图片描述

四、AOP拦截器

基于AspectJ切面表达式实现的AOP处理是Spring的一个重要特性,AOP拦截器可以直接进行指定类结构的拦截处理。
SpringBoot如果想要使用AOP,则需要添加依赖支持:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.5.5</version>
</dependency>

新建IMessageService业务层接口和实现类:

public interface IMessageService {
    String echo(String message);
}
public class MessageServiceImpl implements IMessageService {
    @Override
    public String echo(String message){
        return "[echo] : " + message;
    }
}

再aspect包下新建ServiceAspect类并配置业务层环绕拦截。

@Slf4j
@Aspect
@Component
public class ServiceAspect { // AOP切面管理
    /**
     * service环绕切面
     * @param point
     * @throws Throwable
     */
    @Around("execution(* *..service..*.*(..))") // 配置所有service生效
    public Object aroundInvoke(ProceedingJoinPoint point) throws Throwable {
        log.info("[invoke before] " + Arrays.toString(point.getArgs()));
        Object obj = point.proceed(point.getArgs()); // 调用真实业务
        log.info("[invoke after] return: " + obj);
        return obj; // 业务执行的结果
    }
}

新建RestController测试AOP拦截结果:

@RestController
@RequestMapping("/message/*")
public class MessageAction {
    private final IMessageService messageService;

    public MessageAction(IMessageService messageService) {
        this.messageService = messageService;
    }

    @RequestMapping("/get")
    public String getMessage(String message) {
        return messageService.echo(message);
    }
}

访问:http://localhost:8080/message/get?message=hello,查看控制台日志:

在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Springboot拦截器过滤器监听器是用来处理请求和响应的组件。拦截器是基于Java的反射机制,可以在请求处理前后进行一些操作,比如记录日志、权限验证等。过滤器是基于Servlet规范的,可以在请求进入Servlet之前或响应返回给客户端之前进行一些操作,比如字符编码、请求过滤等。监听器是用来监听Web应用程序中的事件,比如ServletContext的创建和销毁、Session的创建和销毁等。\[1\] 在Springboot中,可以通过在application类上添加注解@SpringBootApplication和@ServletComponentScan来启用拦截器过滤器监听器。\[2\]拦截器过滤器监听器都是通过实现相应的接口来实现的。例如,创建一个过滤器可以通过实现Filter接口,并在@Component注解中添加@Order注解来指定过滤器的执行顺序。\[3\] 拦截器过滤器监听器Springboot中都可以起到不同的作用,可以根据具体需求选择使用哪种组件来处理请求和响应。 #### 引用[.reference_title] - *1* *2* [springBoot(6)---过滤器监听器拦截器](https://blog.csdn.net/yudiandemingzi/article/details/80399971)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [SpringBoot拦截器-过滤器-监听器](https://blog.csdn.net/weixin_45203607/article/details/120250823)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值