如何在SpringWEB项目或者Springboot启动时直接执行业务代码(三种方式)

8 篇文章 0 订阅
6 篇文章 0 订阅
我的博客原文链接

前言

通常的我们的项目开发中,经常会遇到那种在服务一启动就需要自动执行一些业务代码的情况。比如将数据库中的配置信息或者数据字典之类的缓存到redis,或者在服务启动的时候将一些配置化的定时任务开起来。关于spring mvc或者springboot如何在项目启动的时候就执行一些代码,方法其实有很多,我这边介绍一下我使用过的三种。

1、@PostConstruct 注解

从Java EE5规范开始,Servlet中增加了两个影响Servlet生命周期的注解,@PostConstruct@PreDestroy,这两个注解被用来修饰一个非静态的void()方法。@PostConstruct会在所在类的构造函数执行之后执行,在init()方法执行之前执行。(@PreDestroy注解的方法会在这个类的destory()方法执行之后执行。)

  • 使用示例:在Spring容器加载之后,我需要启动定时任务去做任务的处理(我的定时任务采用的是读取数据库配置的方式)。在这里我使用@PostConstruct 指定了需要启动的方法。
@Component // 注意 这里必须有
public class StartAllJobInit {

    protected Logger logger = LoggerFactory.getLogger(getClass().getName());
    @Autowired
    JobInfoService jobInfoService;

    @Autowired
    JobTaskUtil jobTaskUtil;

    @PostConstruct // 构造函数之后执行
    public void init(){
        System.out.println("容器启动后执行");
        startJob();
    }

    public void startJob() {
        List<JobInfoBO> list = jobInfoService.findList();
        for (JobInfoBO jobinfo :list) {
            try {
                if("0".equals(jobinfo.getStartWithrun())){
                    logger.info("任务{}未设置自动启动。", jobinfo.getJobName());
                    jobInfoService.updateJobStatus(jobinfo.getId(), BasicsConstantManual.BASICS_SYS_JOB_STATUS_STOP);
                }else{
                    logger.info("任务{}设置了自动启动。", jobinfo.getJobName());
                    jobTaskUtil.addOrUpdateJob(jobinfo);
                    jobInfoService.updateJobStatus(jobinfo.getId(), BasicsConstantManual.BASICS_SYS_JOB_STATUS_STARTING);
                }
            } catch (SchedulerException e) {
                logger.error("执行定时任务出错,任务名称 {} ", jobinfo.getJobName());
            }
        }
    }
}
2、实现CommandLineRunner接口并重写run()方法

CommandLineRunner接口文档描述如下:

/**
 * Interface used to indicate that a bean should <em>run</em> when it is contained within
 * a {@link SpringApplication}. Multiple {@link CommandLineRunner} beans can be defined
 * within the same application context and can be ordered using the {@link Ordered}
 * interface or {@link Order @Order} annotation.
 * <p>
 * If you need access to {@link ApplicationArguments} instead of the raw String array
 * consider using {@link ApplicationRunner}.
 *
 * @author Dave Syer
 * @see ApplicationRunner
 */
public interface CommandLineRunner {

	/**
	 * Callback used to run the bean.
	 * @param args incoming main method arguments
	 * @throws Exception on error
	 */
	void run(String... args) throws Exception;

}

如上所说:接口被用作加入Spring容器中时执行run(String… args)方法,通过命令行传递参数。SpringBoot在项目启动后会遍历所有实现CommandLineRunner的实体类并执行run方法,多个实现类可以并存并且根据order注解排序顺序执行。这边还有个ApplicationRunner接口,但是接收参数是使用的ApplicationArguments。这边不再赘述。

同样是启动时执行定时任务,使用这种方式我的写法如下:

@Component // 注意 这里必须有
//@Order(2) 如果有多个类需要启动后执行 order注解中的值为启动的顺序
public class StartAllJobInit implements CommandLineRunner {

    protected Logger logger = LoggerFactory.getLogger(getClass().getName());
    @Autowired
    JobInfoService jobInfoService;

    @Autowired
    JobTaskUtil jobTaskUtil;

    @Override
    public void run(String... args) {
        List<JobInfoBO> list = jobInfoService.findList();
        for (JobInfoBO jobinfo :list) {
            try {
                if("0".equals(jobinfo.getStartWithrun())){
                    logger.info("任务{}未设置自动启动。", jobinfo.getJobName());
                    jobInfoService.updateJobStatus(jobinfo.getId(), BasicsConstantManual.BASICS_SYS_JOB_STATUS_STOP);
                }else{
                    logger.info("任务{}设置了自动启动。", jobinfo.getJobName());
                    jobTaskUtil.addOrUpdateJob(jobinfo);
                    jobInfoService.updateJobStatus(jobinfo.getId(), BasicsConstantManual.BASICS_SYS_JOB_STATUS_STARTING);
                }
            } catch (SchedulerException e) {
                logger.error("执行定时任务出错,任务名称 {} ", jobinfo.getJobName());
            }
        }
    }
}
3、使用ContextRefreshedEvent事件(上下文件刷新事件)

ContextRefreshedEvent 官方在接口上的doc说明

Event raised when an {@code ApplicationContext} gets initialized or refreshed.

ContextRefreshedEvent是Spring的ApplicationContextEvent一个实现,ContextRefreshedEvent 事件会在Spring容器初始化完成后以及刷新时触发。

在这里我需要在springboot程序启动之后加载配置信息和字典信息到Redis缓存中去,我可以这样写:

@Component // 注意 这个也是必须有的注解 三种都需要 使spring扫描到这个类并交给它管理
public class InitRedisCache implements ApplicationListener<ContextRefreshedEvent> {
    static final Logger logger = LoggerFactory
            .getLogger(InitRedisCache.class);

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private SysDictService sysDictService;


    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        logger.info("-------加载配置信息 start-------");
        sysConfigService.loadConfigIntoRedis();
        logger.info("-------加载配置信息 end-------");

        logger.info("-------加载字典信息 start-------");
        sysDictService.loadDictIntoRedis();
        logger.info("-------加载字典信息 end-------");
    }
}

注意:这种方式在springmvc-spring的项目中使用的时候会出现执行两次的情况。这种是因为在加载spring和springmvc的时候会创建两个容器,都会触发这个事件的执行。这时候只需要在onApplicationEvent方法中判断是否有父容器即可。

@Override  
  public void onApplicationEvent(ContextRefreshedEvent event) {  
      if(event.getApplicationContext().getParent() == null){//root application context 没有parent,他就是老大.  
           //需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。  
      }  
  }  
总结

以上,就是我在实际开发中常用的三种,在项目启动时执行代码的方式,开发者可以根据不同的使用情况选择合适的方法去执行自己的业务逻辑。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Spring Boot 是一个用于快速构建 Java 应用程序的框架。虽然一般被用于构建 Web 项目,但它也可以用来构建非 Web 项目。下面我将详细介绍如何使用 Spring Boot 构建非 Web 项目。 1. 首先,你需要创建一个 Spring Boot 项目。可以使用 Spring Initializr(https://start.spring.io/)来快速生成一个基本的 Spring Boot 项目结构。选择合适的项目元数据(例如,项目语言、构建工具、依赖项)并生成项目。 2. 接下来,你可以根据你的需要添加各种依赖项。例如,如果你需要操作数据库,你可以添加 Spring Data JPA 或 MyBatis 等依赖项。如果你需要发送电子邮件,你可以添加 Spring Mail 依赖项。你可以在 Maven 或 Gradle 的配置文件中添加这些依赖项。 3. 在你的项目中创建一个入口类。这个类必须是一个带有 `main` 方法的可执行类。你可以在这个类中初始化 Spring Boot 应用程序,并配置一些必要的配置和组件。 4. 你可以使用 Spring Boot 的自动配置功能,它可以根据你的依赖项自动配置各种组件。例如,如果你使用了 Spring Data JPA,Spring Boot 将自动配置和创建 EntityManagerFactory 和 TransactionManager。 5. 开发你的业务逻辑代码。你可以创建各种 Service、Repository、Controller 等类,并在这些类中实现你的业务逻辑。 6. 运行你的 Spring Boot 项目。你可以通过运行入口类中的 `main` 方法来启动应用程序。Spring Boot 将根据你的配置启动一个嵌入式的 Servlet 容器,并初始化你的应用程序。 总之,使用 Spring Boot 构建非 Web 项目与构建 Web 项目的步骤类似,只是不需要添加 Web 相关的依赖项和组件。你可以根据你的需要选择并配置合适的依赖项,并编写你的业务逻辑代码。最后通过运行入口类来启动你的应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值