实际应用中,我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求。

CommandLineRunner 

为了解决这样的问题,Spring Boot 为我们提供了一个方法,通过实现接口 CommandLineRunner 来实现。

很简单,只需要一个类就可以,无需其他配置。 
创建实现接口 CommandLineRunner 的类

package org.springboot.sample.runner;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

/**
 * 服务启动执行
 *
 * @author   单红宇(365384722)
 * @myblog  
 * @create    2016年1月9日
 */
@Component
public class MyStartupRunner1 implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println(">>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<");
    }

}

Spring Boot应用程序在启动后,会遍历CommandLineRunner接口的实例并运行它们的run方法。也可以利用@Order注解(或者实现Order接口)来规定所有CommandLineRunner实例的运行顺序。

如下我们使用@Order 注解来定义执行顺序。

package org.springboot.sample.runner;

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 服务启动执行
 *
 * @author   单红宇(365384722)
 * @myblog  
 * @create    2016年1月9日
 */
@Component
@Order(value=2)
public class MyStartupRunner1 implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println(">>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作 11111111 <<<<<<<<<<<<<");
    }

}
package org.springboot.sample.runner;

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 服务启动执行
 *
 * @author   单红宇(365384722)
 * @myblog  
 * @create    2016年1月9日
 */
@Component
@Order(value=1)
public class MyStartupRunner2 implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println(">>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作 22222222 <<<<<<<<<<<<<");
    }

}

启动程序后,控制台输出结果为:

>>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作 22222222 <<<<<<<<<<<<<
>>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作 11111111 <<<<<<<<<<<<<

根据控制台结果可判断,@Order 注解的执行优先级是按value值从小到大顺序。

方法二:在过滤器(Filter)和 监听器(Listener)中加载初始化


过滤器(Filter)文件

MyFilter.java

package org.springboot.sample.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

/**
 * 使用注解标注过滤器
 * @WebFilter将一个实现了javax.servlet.Filter接口的类定义为过滤器
 * 属性filterName声明过滤器的名称,可选
 * 属性urlPatterns指定要过滤 的URL模式,也可使用属性value来声明.(指定要过滤的URL模式是必选属性)
 * 
 * @author   单红宇(365384722)
 * @myblog  
 * @create    2016年1月6日
 */
@WebFilter(filterName="myFilter",urlPatterns="/*")
public class MyFilter implements Filter {

    @Override
    public void destroy() {
        System.out.println("过滤器销毁");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("执行过滤操作");
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        System.out.println("过滤器初始化");
    }

}

ServletContext监听器(Listener)文件

MyServletContextListener.java

package org.springboot.sample.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * 使用@WebListener注解,实现ServletContextListener接口
 *
 * @author   单红宇(365384722)
 * @myblog  
 * @create    2016年1月6日
 */
@WebListener
public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContex初始化");
        System.out.println(sce.getServletContext().getServerInfo());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContex销毁");
    }

}

ServletContext监听器(Listener)文件

MyHttpSessionListener.java

package org.springboot.sample.listener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 监听Session的创建与销毁
 *
 * @author   单红宇(365384722)
 * @myblog  
 * @create    2016年1月6日
 */
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("Session 被创建");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("ServletContex初始化");
    }

}

注意不要忘记在 SpringBootSampleApplication.java 上添加 @ServletComponentScan 注解。

在启动的过程中我们会看到输出:

ServletContex初始化
Apache Tomcat/8.0.30
过滤器初始化

方法三:在SpringBoot主启动类中嵌套加载初始操作代码


  

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ImportResource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication(scanBasePackages={"com.ceiec"})
@EnableTransactionManagement
@EnableCaching
@ImportResource("classpath:consumer.xml")
public class WebInsightApplication {

	public static void main(String[] args) {
		SpringApplication.run(WebInsightApplication.class, args);
		SystemInit.init();
	}

}


  

public class SystemInit {

    /** 记录用户每次请求时间:key为userId,value为请求时间毫秒值 */
    private static Map<String, Object> requestTime = new HashMap<String, Object>();

    public static Map<String, Object> getRequestTime() {
        return requestTime;
    }

    /**
     * 系统初始化
     */
    public static void init() {
        //清空本地用户登陆token缓存
        RedisUtils.delete(ERedisDomain.TOKEN_LOGIN_USER);

        //初始化ES连接池
        ESUtils.initClient();

        //启动系统主线程
        SystemThread thread = new SystemThread();
        thread.setDaemon(true);
        thread.start();
    }
}