springboot实现定时任务

时间:2022-05-10 07:53:03

说明:该定时任务架构:springboot + mybatis + mysql + 独立模块
业务逻辑:
1.时间写在数据库,便于修改
2.在执行任务的方法上加定时刷新注解
3.方法内去数据库中获取定时,然后与当前定时做比较,如果相同不做改变;如果不相同修改定时
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.hxh</groupId>
     <artifactId>demo</artifactId>
     <version>0.0.1-SNAPSHOT</version>
     <packaging>jar</packaging>
     <name>demo</name>
     <description>Demo project for Spring Boot</description>
     <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.0.2.RELEASE</version>
          <relativePath/> <!-- lookup parent from repository -->
     </parent>
     <properties>
          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
          <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
          <java.version>1.8</java.version>
     </properties>
     <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-data-redis</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-freemarker</artifactId>
          </dependency>
          <dependency>
              <groupId>org.mybatis.spring.boot</groupId>
               <artifactId>mybatis-spring-boot-starter</artifactId>
              <version>1.3.2</version>
          </dependency>
          <dependency>
              <groupId>mysql</groupId>
               <artifactId>mysql-connector-java</artifactId>
              <scope>5.1.0</scope>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>

          <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
              <dependency>
                  <groupId>com.alibaba</groupId>
                  <artifactId>druid</artifactId>
                  <version>1.0.31</version>
              </dependency>
          <dependency>
              <groupId>com.alibaba</groupId>
              <artifactId>fastjson</artifactId>
              <version>1.2.31</version>
          </dependency>


          <dependency>
              <groupId>org.quartz-scheduler</groupId>
              <artifactId>quartz</artifactId>
              <version>2.2.1</version>
          </dependency>
          <dependency>
              <groupId>org.quartz-scheduler</groupId>
              <artifactId>quartz-jobs</artifactId>

          </dependency>

          <dependency>
              <groupId>org.springframework</groupId>
               <artifactId>spring-context-support</artifactId>

          </dependency>
     </dependencies>
     <build>
          <plugins>
              <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
              </plugin>
          </plugins>
     </build>
</project>

application.properties

spring.datasource.name=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db_01?useSSL=false
spring.datasource.username=root
spring.datasource.password=hxh123456
mybatis.mapper-locations=classpath:mapper/*.xml
server.port=80



logging.level.root=INFO logging.level.org.hibernate=INFO logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE logging.level.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE logging.level.com.itmuch=DEBUG

定时任务工厂类

package com.example.demo.config;
import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import com.example.demo.task.ScheduleTask;
@Configuration
public class QuartzConfigration {
     /** * * @param task 需要執行的任務 * @return 定时任务工厂类 */
     @Bean(name = "jobDetail")
     public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduleTask task) {
          MethodInvokingJobDetailFactoryBean jobDetailFactoryBean = new MethodInvokingJobDetailFactoryBean();
          /* * 是否并发执行 * 例如每5s执行一次任务,但是当前任务还没有执行完,就已经过了5s了, * 如果此处为true,则下一个任务会执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行 */
          jobDetailFactoryBean.setConcurrent(false);

          jobDetailFactoryBean.setName("detail-name");//设置任务名字
          jobDetailFactoryBean.setGroup("a1");//设置任务分组,,这些属性都可以存储在数据库中,在多任务的时候使用 

          jobDetailFactoryBean.setTargetObject(task);//为需要执行的实体类对应的对象

          jobDetailFactoryBean.setTargetMethod("sing");//需要执行task类中的方法
          return jobDetailFactoryBean;

     }
     /** * Details:配置定时任务的触发器,也就是什么时候触发执行定时任务 * @param jobDetailFactoryBean * @return */
     @Bean(name = "jobTrigger")
     public CronTriggerFactoryBean cronJobTrigger(MethodInvokingJobDetailFactoryBean jobDetailFactoryBean) {

          CronTriggerFactoryBean triggerFactoryBean = new CronTriggerFactoryBean();

          triggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());

          triggerFactoryBean.setCronExpression("0 30 20 * * ?");// 初始时的cron表达式 

          triggerFactoryBean.setName("detail-name");

          return triggerFactoryBean;

     }

     /** * * @param trigger * @return */

     @Bean(name = "scheduler")
     public SchedulerFactoryBean schedulerFactory(Trigger trigger) {
          SchedulerFactoryBean bean = new SchedulerFactoryBean();
          // 用于quartz集群,QuartzScheduler 启动时更新己存在的Job 
          bean.setOverwriteExistingJobs(true);
          // 延时启动,应用启动1秒后 
          bean.setStartupDelay(1);
          // 注册触发器 
          bean.setTriggers(trigger);
          return bean;
     }
}

定时任务刷新定时类

package com.example.demo.task;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
importorg.springframework.stereotype.Component;
import com.example.demo.dao.QuartzDao;
import com.example.demo.entity.Config;
@Configuration 
@EnableScheduling 
@Component 
public class ScheduleRefreshDatabase {
     @Autowired
     private QuartzDao dao;

     @Resource(name = "jobDetail")
     private  JobDetail jobDetail;

     @Resource(name = "jobTrigger")
     private CronTrigger cronTrigger;

     @Resource(name = "scheduler")
     private Scheduler scheduler;


     @Scheduled(fixedRate = 30000)
     public void scheduleUpdateCronTrigger() throws SchedulerException, IOException {
          CronTrigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());
          String currentCron = trigger.getCronExpression();
          Config config = new Config();
          config.setId(1l);
          String searchCron = dao.findCron(config);

//        System.out.println(currentCron);
//        System.out.println(searchCron);

          if (currentCron.equals(searchCron)) {

//            URL url = new URL("http://localhost:8080/ssmredis2/redis/refurbish");
//            URLConnection openConnection = url.openConnection();
//            openConnection.connect();
//            InputStream inputStream = openConnection.getInputStream();
//            inputStream.close();
//            URL url2 = openConnection.getURL();
//            System.out.println(url2);

          } else {
               // 表达式调度构建器 
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron); 
            // 按新的cronExpression表达式重新构建trigger 
            trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey()); 
            trigger = trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey()) 
                    .withSchedule(scheduleBuilder).build(); 
            // 按新的trigger重新设置job执行 
            scheduler.rescheduleJob(cronTrigger.getKey(), trigger); 
            currentCron = searchCron; 
          }

定时任务方法实现类

package com.example.demo.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;


@Configuration
@Component
@EnableScheduling
public class ScheduleTask {
     private static Logger LOGGER = LoggerFactory.getLogger(ScheduleTask.class);

     public void sing() {
          LOGGER.info("Hello world, i'm sing a song!!!");

     }
}