springboot定时服务

上一篇文章【修改定时时间,定时任务及时生效】  是定时任务与功能项目共用一个;

我目前所在公司的定时服务是专门有一个项目处理,然后定时查询库里面的定时信息配置。

话不多说,上程序

数据库设置

create table SCHEDULER_JOB
(id       VARCHAR2(32) not null,job_name VARCHAR2(200),cron     VARCHAR2(100),method_name varchar2(200),bean_name varchar2(200),remark varchar2(50),type varchar2(4) default '是否有参数 01否 02是'
)

实体类 SchedulerJob

package com.example.demo.entity;public class SchedulerJob {private String id;//任务名称private String jobName;//表达式private String cron;//方法名称private String methodName;//bean名称private String beanName;//备注(方法的参数)private String remark;//类型 是否有参数 01否 02是private String type;//todo get/set方法
}

SchedulerJobMapper

import com.example.demo.entity.SchedulerJob;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface SchedulerJobMapper {List<SchedulerJob> queryList();
}

SchedulerJobMapper.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.SchedulerJobMapper"><resultMap type="com.example.demo.entity.SchedulerJob" id="resultMap"><result property="id" 			column="ID"/><result property="jobName" 		column="JOB_NAME"/><result property="cron"		column="CRON"/><result property="methodName"		column="METHOD_NAME"/><result property="beanName"		column="BEAN_NAME"/><result property="remark"		column="REMARK"/><result property="type"		column="TYPE"/></resultMap><select id="queryList" resultMap="resultMap">select ID,JOB_NAME,CRON,METHOD_NAME,BEAN_NAME,REMARK,TYPE from  scheduler_job</select></mapper>

JobRegisterService 用分布式锁定时查询定时任务

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;@Service
public class JobRegisterService {private static final Logger logger = LoggerFactory.getLogger(JobRegisterService.class);@Autowiredprivate RedisLockRegistry redisLockRegistry;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate JobService jobService;@Scheduled(cron = "0 0/2 * * * ?")public void startTaskJob() {Lock lock = redisLockRegistry.obtain("lock");try {boolean flag = lock.tryLock(10L, TimeUnit.SECONDS);ValueOperations<String, Object> map = redisTemplate.opsForValue();if (flag) {Object taskStatus = map.get("taskStatus");if (taskStatus != null && taskStatus.toString().equals("Y")) {jobService.clearAllJob();return;}map.set("taskStatus", "Y");redisTemplate.expire("taskStatus", 1L, TimeUnit.MINUTES);jobService.timeTask();} else {jobService.clearAllJob();}} catch (Exception e) {logger.error("获取锁异常:", e);} finally {lock.unlock();}}
}

JobService  查询数据库,并为每个job设置对应的表达式cron

import com.alibaba.fastjson.JSON;
import com.example.demo.entity.SchedulerJob;
import com.example.demo.mapper.SchedulerJobMapper;
import com.example.demo.util.DateUtils;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service
@Transactional
public class JobService {private static final Logger logger = LoggerFactory.getLogger(JobService.class);@Autowiredprivate Scheduler scheduler;@Autowiredprivate SchedulerJobMapper schedulerJobMapper;public void timeTask() {//查询数据库存在需要定时的任务logger.info("任务重置开始,查询数据...");List<SchedulerJob> schedulerJobList = schedulerJobMapper.queryList();if (schedulerJobList != null) {try {scheduler.clear();logger.info("任务重置开始,旧的任务清理");schedulerJobList.forEach(this::addJob);} catch (Exception e) {logger.error("调用错误:", e);}}}public void addJob(SchedulerJob schedulerJob) {try {//作业名称JobKey jobKey = JobKey.jobKey(schedulerJob.getJobName());//设置触发时间CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(schedulerJob.getCron());//触发建立Trigger trigger = TriggerBuilder.newTrigger().withIdentity(schedulerJob.getJobName()).withSchedule(cronScheduleBuilder).forJob(jobKey).build();if (trigger != null && trigger.getStartTime() != null) {logger.info("作业【{}】启动时间为{}", schedulerJob.getJobName(), DateUtils.formatDate(trigger.getStartTime(), DateUtils.DATETIME_FORMAT));} else {logger.info("作业【{}】启动时间为空", schedulerJob.getJobName());}//建立作业JobDetail jobDetail = JobBuilder.newJob(QuartzFactory.class).withIdentity(schedulerJob.getJobName()).build();jobDetail.getJobDataMap().put("schedulerJob", schedulerJob);//调度作业scheduler.scheduleJob(jobDetail, trigger);if (!scheduler.isShutdown()) {scheduler.start();}} catch (Exception e) {logger.error("添加作业失败[schedulerJob={}]", JSON.toJSONString(schedulerJob), e);}}/*** 清除任务*/public void clearAllJob() throws SchedulerException {logger.info("清除任务...");scheduler.clear();}
}

QuartzFactory 定时任务工厂 根据method_name找到对应的映射信息,并执行该方法

import com.example.demo.constant.SchedulerJobTypeEnum;
import com.example.demo.entity.SchedulerJob;
import com.example.demo.util.SpringContextUtil;
import org.apache.commons.lang.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;@Component
public class QuartzFactory implements Job {private static final Logger logger = LoggerFactory.getLogger(QuartzFactory.class);@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {//获取调度数据SchedulerJob schedulerJob = (SchedulerJob) jobExecutionContext.getMergedJobDataMap().get("schedulerJob");//获取对应的beanObject obj = SpringContextUtil.getObj(schedulerJob.getBeanName());try {if (obj == null) {throw new Exception("找不到该类");}if (StringUtils.isEmpty(schedulerJob.getType()) || SchedulerJobTypeEnum.NO.getCode().equals(schedulerJob.getType())) {Method method = obj.getClass().getMethod(schedulerJob.getMethodName());method.invoke(obj);} else {Method method = obj.getClass().getMethod(schedulerJob.getMethodName(), String.class);method.invoke(obj, schedulerJob.getRemark());}} catch (Exception e) {logger.error("定时任务获取映射异常:", e);}}
}

SpringContextUtil 上下文工具

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;@Component
public class SpringContextUtil implements ApplicationContextAware {//spring 上下文实例对象private static ApplicationContext context;// 根据class获取对象实例public static <T> T getObj(Class<T> tClass) {return context.getBean(tClass);}// 根据配置的 bean name 获取对象实例public static Object getObj(String beanName) {return context.getBean(beanName);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {context = applicationContext;}
}

RedisLockConfig Redis分布式锁配置bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.integration.redis.util.RedisLockRegistry;@Configuration
public class RedisLockConfig {@Beanpublic RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {//第一个参数redisConnectionFactory//第二个参数registryKey,分布式锁前缀,设置为项目名称会好些//该构造方法对应的分布式锁,默认有效期是60秒.可以自定义return new RedisLockRegistry(redisConnectionFactory, "demo");}
}

SchedulerConfig 定时任务配置bean

import org.quartz.Scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;import java.io.IOException;@Configuration
public class SchedulerConfig {@Beanpublic Scheduler scheduler() throws Exception {Scheduler scheduler = schedulerFactoryBean().getScheduler();return scheduler;}@Beanpublic SchedulerFactoryBean schedulerFactoryBean() throws IOException {SchedulerFactoryBean factory = new SchedulerFactoryBean();factory.setSchedulerName("Test_Scheduler");//覆盖已存在的任务factory.setOverwriteExistingJobs(true);// 延迟10s执行 防止发生系统未启动完成 定时任务却已经开始的情况factory.setStartupDelay(10);return factory;}
}

SchedulerJobTypeEnum 定时任务类型枚举

public enum SchedulerJobTypeEnum {NO("01", "否"),YES("02", "是");private String code;private String value;SchedulerJobTypeEnum(String code, String value) {this.code = code;this.value = value;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}
}

DateUtils 时间处理工具类

import org.apache.commons.lang.time.DateFormatUtils;import java.util.Date;public class DateUtils {public static final String DATE_FORMAT = "yyyy-MM-dd";public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";public static final String TIME_FORMAT = "HH:mm:ss";/*** 常用的时间格式.*/private static String[] parsePatterns = {"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss","yyyy-MM-dd HH:mm","HH:mm:ss"};/*** 得到当前日期字符串.*/public static String getDate() {return getDate(DateUtils.DATE_FORMAT);}public static String getDate(String pattern) {return DateFormatUtils.format(new Date(), pattern);}/*** 得到当前时间字符串.*/public static String getTime() {return formatDate(new Date(), DateUtils.TIME_FORMAT);}/*** 得到当前日期和时间字符串.*/public static String getDateTime() {return formatDate(new Date(), DateUtils.DATETIME_FORMAT);}/*** 获取日期时间字符串,默认格式为(yyyy-MM-dd).*/public static String formatDate(Date date, Object... pattern) {String formatDate = null;if (pattern != null && pattern.length > 0) {formatDate = DateFormatUtils.format(date, pattern[0].toString());} else {formatDate = DateFormatUtils.format(date, DateUtils.DATE_FORMAT);}return formatDate;}
}

TestSchedulerJobService 定义的定时任务方法

import com.example.demo.util.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;@Service
public class TestSchedulerJobService {private static final Logger logger = LoggerFactory.getLogger(TestSchedulerJobService.class);public void test() {String dateTime = DateUtils.getDateTime();logger.info("当前时间={}", dateTime);}public void test1(String param) {String dateTime = DateUtils.getDateTime();logger.info("当前时间1={},参数={}", dateTime, param);}
}

数据库补充数据

【注意:】数据库中bean_Name存储的是bean名称(默认类名首字母小写)

job_name和method_name数据值一样即可

 测试结果

 由此可看出,两个定时任务是按照数据库中配置的定时时间跑的。

具体定时任务时间等信息视情况而定!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/188212.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

语音识别与自然语言处理(NLP):技术前沿与未来趋势

语音识别与自然语言处理&#xff08;NLP&#xff09;&#xff1a;技术前沿与未来趋势 随着科技的快速发展&#xff0c;语音识别与自然语言处理&#xff08;NLP&#xff09;技术逐渐成为人工智能领域的研究热点。这两项技术的结合&#xff0c;使得机器能够更好地理解和处理人类语…

自主开发刷题应用网站H5源码(无需后端无需数据库)

该应用使用JSON作为题库的存储方式&#xff0c;层次清晰、结构简单易懂。 配套的word模板和模板到JSON转换工具可供使用&#xff0c;方便将题库从word格式转换为JSON格式。 四种刷题模式包括顺序刷题、乱序刷题、错题模式和背题模式&#xff0c;可以根据自己的需求选择适合的模…

arm2 day4

汇编编写流水灯 代码&#xff1a; LED流水灯现象&#xff1a;

浅谈高并发以及三大利器:缓存、限流和降级

引言 高并发背景 互联网行业迅速发展&#xff0c;用户量剧增&#xff0c;系统面临巨大的并发请求压力。 软件系统有三个追求&#xff1a;高性能、高并发、高可用&#xff0c;俗称三高。三者既有区别也有联系&#xff0c;门门道道很多&#xff0c;全面讨论需要三天三夜&#…

掌动智能性能压力测试优势有哪些

企业通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。本文将介绍性能压力测试的价值及主要优势! 一、性能压力测试的价值 1、评估系统能力&#xff1a;有助于参数的基准测试&#xff0c;可以度量系统的响应时间;还有助于检查系统是否可…

[工业自动化-12]:西门子S7-15xxx编程 - PLC从站 - ET200 SP系列详解

目录 一、概述 1.1 概述 二、系统组成 2.1 概述 2.2 与主站的通信接口模块 2.3 总线适配器 2.4 基座单元 2.5 电子模块 2.6 服务器模块 一、概述 1.1 概述 PLC ET200 SP 是西门子&#xff08;Siemens&#xff09;公司生产的一款模块化可编程逻辑控制器&#xff08;PL…

Linux输入与输出设备的管理

计算机系统中CPU 并不直接和设备打交道&#xff0c;它们中间有一个叫作设备控制器&#xff08;Device Control Unit&#xff09;的组件&#xff0c;例如硬盘有磁盘控制器、USB 有 USB 控制器、显示器有视频控制器等。这些控制器就像代理商一样&#xff0c;它们知道如何应对硬盘…

【MATLAB源码-第73期】基于matlab的OFDM-IM索引调制系统不同子载波数目误码率对比,对比OFDM系统。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 OFDM-IM索引调制技术是一种新型的无线通信技术&#xff0c;它将正交频分复用&#xff08;OFDM&#xff09;和索引调制&#xff08;IM&#xff09;相结合&#xff0c;以提高频谱效率和系统容量。OFDM-IM索引调制技术的基本思想…

嵌入式养成计划-52----ARM--开发板介绍--相关硬件基础内容介绍--GPIO讲解

一百三十一、开发板介绍 131.1 核心板介绍 131.2 拓展板 一百三十二、相关硬件基础内容介绍 132.1 PCB PCB&#xff08; Printed Circuit Board&#xff09;&#xff0c;中文名称为印制电路板&#xff0c;又称印刷线路板&#xff0c; 是重要的电子部件&#xff0c;是电子元器…

Direct3D粒子系统

粒子和点精灵 粒子(是种微小的物体,在数学上通常用点来表示其模型。所以显示粒子时,使用点图元(由 D3 DPRIMITIVETYPE类型的D3 DPT POINTLIST枚举常量表示)是一个很好的选择。但是光栅化时,点图元将被映射为一个单个像素。这样就无法为我们提供很大的灵活性,因为实际应用…

从windows iso文件中提取install.wim

1、首先从微软官方下载需要的windows镜像 https://www.microsoft.com/zh-cn/software-download/windows10/ 2、在下载的iso文件右键&#xff0c;打开压缩包&#xff0c;在sources文件夹下&#xff0c;应该就可以看到install.wim了。但似乎在最新的win10版本&#xff0c;微软采…

金字塔原理小节

目录 第1章 为什么要用金字塔结构 一、归类分组&#xff0c;将思想组织成金字塔 二、奇妙的数字“7” 三、归类分组搭建金字塔 四、找出逻辑关系&#xff0c;抽象概括 五、自上而下表达&#xff0c;结论先行 第1章 为什么要用金字塔结构 如果受众希望通过阅读你的文章、听…

Git系列之Git集成开发工具及git扩展使用

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《Git实战开发》。&#x1f3af;&#x1f3af; &a…

【启扬方案】启扬安卓屏一体机在医疗自助服务终端上的应用解决方案

为了解决传统医疗模式下的“看病难、看病慢”等问题&#xff0c;提高医疗品质、效率与效益&#xff0c;自助服务业务的推广成为智慧医疗领域实现信息化建设、高效运作的重要环节。 医疗自助服务终端是智慧医疗应用场景中最常见的智能设备之一&#xff0c;它通过与医院信息化系统…

使用MVS-GaN HEMT紧凑模型促进基于GaN的射频和高电压电路设计

标题&#xff1a;Facilitation of GaN-Based RF- and HV-Circuit Designs Using MVS-GaN HEMT Compact Model 来源&#xff1a;IEEE TRANSACTIONS ON ELECTRON DEVICES&#xff08;19年&#xff09; 摘要—本文阐述了基于物理的紧凑器件模型在研究器件行为细微差异对电路和系统…

SDWAN(Software Defined Wide Area Network)概述与优势分析

文章目录 SDWAN简介SDWAN技术优势简化网络部署和维护安全传输灵活网络拓扑极致体验 SD-WAN关联技术STUNIPsec智能选路SaaS路径优化 典型组网多总部分支组网云管理组网 推荐阅读 SDWAN简介 SDWAN&#xff08;Software Defined Wide Area Network&#xff0c;软件定义广域网&…

Java TCP服务端多线程接收RFID网络读卡器上传数据

本示例使用设备介绍&#xff1a;WIFI/TCP/UDP/HTTP协议RFID液显网络读卡器可二次开发语音播报POE-淘宝网 (taobao.com) import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; impor…

数据分析实战 | K-means算法——蛋白质消费特征分析

目录 一、数据及分析对象 二、目的及分析任务 三、方法及工具 四、数据读入 五、数据理解 六、数据准备 七、模型训练 ​编辑 八、模型评价 九、模型调参与预测 一、数据及分析对象 txt文件——“protein.txt”&#xff0c;主要记录了25个国家的9个属性&#xff0c;主…

“Redis与Spring整合及缓存优化“

文章目录 引言1. Spring整合Redis1.1. 为什么选择Redis作为缓存解决方案&#xff1f;Redis的特点和优势Redis与传统关系数据库的对比 1.2. Spring与Redis整合的基本步骤 2. Redis注解式缓存2.1. Spring提供的缓存注解介绍2.2. 使用注解实现方法级别的缓存 3. Redis的击穿、穿透…

软件工程的舞台上,《人月神话》的美学纷飞

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天给大家分享一本书&#xff1a;《人月神话》——软件工程的经典之作。 《人月神话》是一本具有深远影响力的软件工程著作&#xff0c;无论是软件开发者、管理者还是学习软件工程的人士&#xff0c;都能从中获得宝贵的启…