• SpringBoot Application事件监听的实现方案(动态写入yml)



    有的时候,人这一辈子大多数时间都是在干没有意义的事情

    事件监听

    SpringBoot Application共支持6种事件监听,按顺序分别是:

    1. ApplicationStartingEvent:在Spring最开始启动的时候触发
    2. ApplicationEnvironmentPreparedEvent:在Spring已经准备好上下文但是上下文尚未创建的时候触发
    3. ApplicationPreparedEvent:在Bean定义加载之后、刷新上下文之前触发
    4. ApplicationStartedEvent:在刷新上下文之后、调用application命令之前触发
    5. ApplicationReadyEvent:在调用applicaiton命令之后触发
    6. ApplicationFailedEvent:在启动Spring发生异常时触发

    另外:

    ApplicationRunnerCommandLineRunner的执行在第五步和第六步之间
    Bean的创建在第三步和第四步之间
    在启动类中,执行SpringApplication.run()方法后的代码,会在第六步后执行

    动态加载配置

    这里通过不写yml,监听ApplicationEnvironmentPreparedEvent来实现,动态添加yml中的配置

    PropertiesListener2

    import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
    import org.springframework.context.ApplicationListener;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.ConfigurableEnvironment;
    import org.springframework.core.env.PropertiesPropertySource;
    import org.springframework.core.env.PropertySource;
    
    @Configuration
    public class PropertiesListener2 implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
        @Override
        public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
            ConfigurableEnvironment environment = event.getEnvironment();
            Properties props = new Properties();
            props.put("server.tomcat.threads.min-spare", 100);
            // 设置启动端口
            props.put("server.port", 8105);
            environment.getPropertySources().addFirst(new PropertiesPropertySource("myProps", props));
            PropertySource<?> myProps = PropertiesPropertySource.named("myProps");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    spring.factories

    # 监听 ApplicationEvent 事件
    org.springframework.context.ApplicationListener=com.thread.conf.PropertiesListener2
    
    • 1
    • 2

    在这里插入图片描述

    在开发中,可以将一些公共不会经常变化的配置在公共模块中通过ApplicationEnvironmentPreparedEvent进行加载,这样就不用在每个模块中去做配置

    例如tomcat的配置

    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        ConfigurableEnvironment environment = event.getEnvironment();
        Properties props = new Properties();
        //工作线程的最小数量
        props.put("server.tomcat.threads.min-spare", 50);
    
        //Tomcat线程池最大工作线程数
        props.put("server.tomcat.threads.max", 200);
    
        //超过maxThread数量,最大等待数
        props.put("server.tomcat.accept-count", 100);
    
        //服务器在任何给定时间接受和处理的最大连接数。一旦达到限制,操作系统仍然可以根据“acceptCount”属性接受连接,默认:8192
        //一瞬间最多能够处理的并发连接数,一个线程可以处理多个连接
        props.put("server.tomcat.max-connections", 10000);
    
        environment.getPropertySources().addFirst(new PropertiesPropertySource("myProps", props));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    或者通过实现接口的方式自定义 Tomcat(供别的模块使用时,记得在spring.factories中配置)

    @Configuration
    public class TomcatConnectionCustomizer implements TomcatConnectorCustomizer{
    
        /**
         * 配置类: {@link org.springframework.boot.autoconfigure.web.ServerProperties}
         *
         * 查看线程数命令
         * pstree -p pid | wc -l
         */
        @Override
        public void customize(Connector connector) {
            connector.setPort(8105);
            // 连接协议处理器. 默认: org.apache.coyote.http11.Http11NioProtocol
            connector.setAttribute("protocol", "org.apache.coyote.http11.Http11Nio2Protocol");
    
            /* 参数设置-方式1 */
    //        connector.setAttribute("minSpareThreads", 100);
    //        connector.setAttribute("maxThreads", 800);
    
            /* 参数设置-方式2 */
            Http11NioProtocol protocolHandler = (Http11NioProtocol) connector.getProtocolHandler();
            // 最小工作线程数, 默认: 10(适当增大一些, 以便应对突然增长的访问量)
            protocolHandler.setMinSpareThreads(100);
            // 最大线程数, 默认: 200(4核8g内存, 线程数经验值800, 操作系统做线程之间的切换调度是有系统开销的, 所以不是越多越好)
            protocolHandler.setMaxThreads(800);
            // 等待队列长度, 默认100
            protocolHandler.setAcceptCount(1000);
            // 最大连接数, 默认: 10000
            protocolHandler.setMaxConnections(10000);
            // 连接超时时间, 默认: 60000
            protocolHandler.setConnectionTimeout(100);
            // 默认: 1
            protocolHandler.setAcceptorThreadCount(10);
            // 30秒内没有请求则服务端自动断开keepalive链接
            protocolHandler.setKeepAliveTimeout(300000);
            // 当客户端发送超过10000个请求则自动断开keepalive链接
            protocolHandler.setMaxKeepAliveRequests(10000);
        }
    }
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
  • 相关阅读:
    VVICAPI接口解析,实现根据关键词取商品列表
    计算机毕业设计ssm高校会议室管理系统w169g系统+程序+源码+lw+远程部署
    Seata服务的搭建、Seata AT模式演示
    《动手学深度学习 Pytorch版》 8.4 循环神经网络
    Attention注意力机制学习(二)------->一些注意力网络整理
    Flink-CEP快速入门
    dubbo原理
    什么FPGA开发板入门学习比较好?
    RR调度是什么
    Demo版菜刀
  • 原文地址:https://blog.csdn.net/weixin_43847283/article/details/126321914