SpringBoot 中配置 Servlet、Filter、Listener

news/2025/2/22 5:30:22

servletfilterlistener">

在SpringBoot应用中,嵌入式的 Servlet 3.0+ 容器不会直接使用 ServletContainerInitializer 和 WebApplicationInitializer,即通过以上两个接口实现的 Servlet、Filter、Listener 配置都是无效的,这是为了防止第三方代码的设计损坏应用程序,原文如下

Embedded servlet containers will not directly execute the Servlet 3.0+ javax.servlet.ServletContainerInitializer interface, or Spring’s org.springframework.web.WebApplicationInitializer interface. This is an intentional design decision intended to reduce the risk that 3rd party libraries designed to run inside a war will break Spring Boot applications.

If you need to perform servlet context initialization in a Spring Boot application, you should register a bean that implements the org.springframework.boot.context.embedded.ServletContextInitializer interface. The single onStartup method provides access to the ServletContext, and can easily be used as an adapter to an existing WebApplicationInitializer if necessary.

综上,可以采取以下配置

servletcontextinitializer">配置策略一:ServletContextInitializer

由官方原文可知,我们可以使用替代方案:ServletContextInitializer,示例如下

@Configuration
public class GoServletContextInitializer implements ServletContextInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        //配置 Log4j Config Listener  
        servletContext.setInitParameter("log4jConfigLocation", "classpath:config/properties/log4j.properties");  
        servletContext.addListener(Log4jConfigListener.class);  
          
          
        //配置 CharacterEncodingFilter
        FilterRegistration.Dynamic characterEncodingFilter =
                servletContext.addFilter("characterEncodingFilter", CharacterEncodingFilter.class);
        characterEncodingFilter.setInitParameter("encoding", "UTF-8");
        characterEncodingFilter.setInitParameter("forceEncoding", "true");
        characterEncodingFilter.addMappingForUrlPatterns(
                EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE),
                false, "/*");
          
          
        //配置 statViewServlet  
        StatViewServlet statViewServlet = new StatViewServlet();
        ServletRegistration.Dynamic dynamic = servletContext.addServlet(
                "statViewServlet", statViewServlet);
        dynamic.setLoadOnStartup(2);
        dynamic.addMapping("/druid/*");
    }
}

亲测,即使将 Spring Boot 打包成 war,并部署到 Tomcat 8.5,这份配置也是有效的


servletcontextinitializer-的延伸">配置策略二:ServletContextInitializer 的延伸

请看类继承体系

原理:最下边的三个子类会自动在运行时注册 Servlet、Listener、Filter(一定要将其定义为 Spring 容器的 Bean)

  1. ServletRegistrationBean:在Servlet容器初始化时,向 ServletContext 注册一个自定义的 Servlet
  2. ServletListenerRegistrationBean:在Servlet容器初始化时,向 ServletContext 注册一个自定义的 ServletContextListener
  3. AbstractFilterRegistrationBean:(模板方法模式)通过模板方法 getFilter(),将 Filter 的构建过程延迟到子类,并在Servlet容器初始化时,向 ServletContext 注册该 Filter。开发者可以定义一个子类来重写该模板方法,以配置一个自定义的 Filter。

Servlet 配置示例

@Configuration
public class ServletConfig {

    //配置 StatViewServlet
    @Bean
    public ServletRegistrationBean servletRegistration0() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet());
        registration.addUrlMappings("/druid/*");
        registration.setLoadOnStartup(0);
        return registration;
    }
}

Filter 配置示例

@Configuration
public class FilterConfig {

    //配置 CharacterEncodingFilter
    @Bean
    public FilterRegistrationBean filterRegistration1() {
        FilterRegistrationBean registration = new FilterRegistrationBean(new CharacterEncodingFilter());
        registration.addUrlPatterns("/*");

        Map<String, String> initParameters = Maps.newHashMap();
        initParameters.put("encoding", "UTF-8");
        initParameters.put("forceEncoding", "true");
        registration.setInitParameters(initParameters);
        
        return registration;
    }
}

Listener 配置示例

@Configuration
public class ListenerConfig {

    //配置 RequestContextListener
    @Bean
    public ServletListenerRegistrationBean<RequestContextListener> listenerRegistration3() {
        return new ServletListenerRegistrationBean<>(
            new RequestContextListener());
    }
}

SpringBoot 中配置 Servlet、Filter、Listener源码  OnRefresh()中 调用createWeb()....调用ServletWebServerApplicationContext.selfInitialize方法中getServletContextInitializerBeans中完成从spring容器中把Servlet、Filter、Listener封装成ServletContextInitializer接口实例,后再调用ServletContextInitializer的实例方法onStartUp,完成Servlet、Filter、Listener配置。

 


http://www.niftyadmin.cn/n/5861634.html

相关文章

Flutter 中的单例模式

传统&#xff1a; class RouterManager {// 单例模式static final RouterManager _instance RouterManager._internal();factory RouterManager() {return _instance;}RouterManager._internal(); }传递参数进行初始化时&#xff1a; class RouterManager {// 私有静态实例&a…

C/C++高性能Web开发框架全解析:2025技术选型指南

一、工业级框架深度解析&#xff08;附性能实测&#xff09; 1. Drogon v2.1&#xff1a;异步框架性能王者 核心架构&#xff1a; Reactor 非阻塞I/O线程池&#xff08;参考Nginx模型&#xff09; 协程实现&#xff1a;基于Boost.Coroutine2&#xff08;兼容C11&#xff09;…

简单说一下什么是RPC

部分内容来源&#xff1a;JavaGuide RPC是什么 RPC是远程调用 RPC的原理 RPC的五个部分 为了能够帮助小伙伴们理解 RPC 原理&#xff0c;我们可以将整个 RPC 的核心功能看作是下面 5 个部分实现的&#xff1a; 客户端&#xff08;服务消费端&#xff09;&#xff1a;调用…

solidity之Foundry安装配置(一)

一门面向合约的高级编程语言&#xff0c;主要用来编写以太坊只能合约。 Solidity受C语言&#xff0c;Python和js影响&#xff0c;但为编译成为以太坊虚拟机字节码在EVM上执行&#xff0c;很多特性和限制都和EVM相关。 Solidity 是静态类型语言&#xff0c;支持继承、库、自定义…

蓝桥杯核心内容

核心内容 数学 质数与筛质数&#xff0c;分解质因数 分解质因数 所有的数都可以写成有限个数相乘质数&#xff1a;可以写成1✖本身&#xff08;如131✖13&#xff09;合数&#xff1a;ab1✖...✖bn-》把乘数里面是合数的再分&#xff08;如b3是合数-》b3c1✖c2&#xff09;进…

Ubuntu22.04 - etcd的安装和使用

目录 介绍安装Etcd安装etcd的客户端使用 介绍 Etcd 是一个 golang 编写的分布式、高可用的一致性键值存储系统&#xff0c;用于配置共享和服务发现等。它使用 Raft 一致性算法来保持集群数据的一致性&#xff0c;且客户端通过长连接watch 功能&#xff0c;能够及时收到数据变化…

【MySQL】第八弹---全面解析数据库表的增删改查操作:从创建到检索、排序与分页

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】 目录 1 表的增删改查 1.1 Create 1.1.1 单行数据 全列插入 1.1.2 多行数据 指定列插入 1.1.3 插入否则更新 1.1.4 替…

图表控件Aspose.Diagram入门教程:使用 Python 将 VSDX 转换为 PDF

将VSDX转换为PDF可让用户轻松共享图表。PDF 文件保留原始文档的布局和设计。它们广泛用于演示文稿、报告和文档。在这篇博文中&#xff0c;我们将探讨如何在 Python 中将 VSDX 转换为 PDF。 本文涵盖以下主题&#xff1a; Python VSDX 到 PDF 转换器库使用 Python 将 VSDX 转…