zoukankan      html  css  js  c++  java
  • spring boot启动初始化数据的多种方式

    场景

        在日常的项目中,经常会有一些需求,是在项目启动过程中,启动后,或者满足特定条件,初始化一些数据,或者从数据库读取一些配置初始化,又或从数据库读取一些热点数据到redis进行初始化缓存。

       本文提供一些常见的实现,以及在项目启动的不同阶段加载的实现方式。

    项目启动中

          方式一:实现说明:本实例是初始化一个Word的词库,使用的static静态代码块,实现原理为@Component + static代码块, spring boot项目在启动过程中,会扫描@Component 并初始化相应的类,类的初始化过程会运行静态代码块。

    @Component
    public class WordInitConfig {
        static {
            WordSegmenter.segWithStopWords("初始化分词");
        }
    }
    

      方式二:实现说明:本实例实现项目启动过程中加载配置信息,并缓存到redis, 这里使用的是 @PostConstruct(),该注解会在类调用构造函数之前调用,但是初始化当前配置类的时候,MallSettingMapper.class, RedisService.class, SettingRefreshService.class这些类可能还未加载或实例化,所以这里需要配合@ConditionalOnBean注解实现

    @Component
    @ConditionalOnBean({MallSettingMapper.class, RedisService.class, SettingRefreshService.class})
    public class SettingInitConfig  {
    
        @Autowired
        private SettingRefreshService settingRefreshService;
    
    
        @PostConstruct()
        private void refresh(){
            settingRefreshService.refreshRedis();
        }
    
    }
    

      

    项目启动后

           实现说明:这里还是以上面加载配置到redis缓存为例子,这里我们需要准确知道项目启动的时间,所以我们要借助spring内置的监听器,监听事件ApplicationReadyEvent,这里还有其他事件比如ApplicationFailedEvent、ApplicationStartingEvent等,对应application context加载的各阶段,如果需要自定义事件,也可以参考《基于Redis队列实现《二》——点对点模式》

    @Component
    public class SettingInitConfig implements ApplicationListener<ApplicationReadyEvent> {
    
        @Autowired
        private SettingRefreshService settingRefreshService;
    
        @Override
        public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) 
        {
            settingRefreshService.refreshRedis();
        }
    
    }
    

      

    特定条件或者配置

           实现说明:这里实现的场景比较复杂一些,本例子实现的类似starter的机制,在集成第三方插件时,比较常见。这里做的是一个ES全文搜索集成方案,由于整个方案改动比较大,持续时间比较长,而中途又需要发布生产,这里希望达到目标是即使生产读取不到相关ES配置,或者通过配置动态开关。这里主要基于 @ConditionalOnProperty实现

    1. 增加配置 elasticsearch.active 开关

    #开启elasticsearch
    elasticsearch:
      hostname: 192.168.9.79
      port: 9200
      active: false
    

    2. 增加配置类 EsConfig

    @Configuration
    @ConditionalOnProperty(prefix="elasticsearch",name = "active", havingValue = "true")
    public class EsRestClientConfig {
    
        @Value("${elasticsearch.hostname}")
        private String hostname;
    
        @Value("${elasticsearch.port}")
        private int port;
    
        private String schema = "http";
        private int connectTimeOut = 1000;
        private int socketTimeOut = 30000;
        private int connectionRequestTimeOut = 500;
        private int maxConnectNum = 100;
        private int maxConnectPerRoute = 100;
        private HttpHost httpHost;
        private boolean uniqueConnectTimeConfig = true;
        private boolean uniqueConnectNumConfig = true;
        private RestClientBuilder builder;
    
        private RestClient client;
    
        @Lazy
        @Bean(autowire = Autowire.BY_NAME, name = "restClient")
        public RestClient client() {
            httpHost = new HttpHost(hostname, port, schema);
            builder = RestClient.builder(httpHost);
            if (uniqueConnectTimeConfig) {
                setConnectTimeOutConfig();
            }
            if (uniqueConnectNumConfig) {
                setMutiConnectConfig();
            }
            return builder.build();
        }
    
        /**
         * 异步httpclient的连接延时配置
         */
        public void setConnectTimeOutConfig() {
            builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
                @Override
                public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
                    requestConfigBuilder.setConnectTimeout(connectTimeOut);
                    requestConfigBuilder.setSocketTimeout(socketTimeOut);
                    requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
                    return requestConfigBuilder;
                }
            });
        }
    
    
        /**
         * 异步httpclient的连接数配置
         */
        public void setMutiConnectConfig() {
            builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                @Override
                public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                    httpClientBuilder.setMaxConnTotal(maxConnectNum);
                    httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
                    return httpClientBuilder;
                }
            });
        }
    
        /**
         * 关闭连接
         */
        public void close() {
            if (client != null) {
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

      

     

  • 相关阅读:
    [zz]Mesos的分析4 支持Hadoop任务级调度
    代理设计模式
    spring初始化
    SpringAOP的切点的声明格式
    SpringAOP的介绍
    SpringIOC创建对象的单例和多例模式
    动态代理
    SpringIOC的自动注入
    SpringAOP的注解方式实现
    cglib动态代理实现流程
  • 原文地址:https://www.cnblogs.com/liuyq/p/15011858.html
Copyright © 2011-2022 走看看