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.mzph.cn/news/137653.shtml

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

相关文章

一个“Hello, World”Flask应用程序

如果您访问Flask网站&#xff0c;会看到一个非常简单的示例应用程序&#xff0c;只有5行代码。为了不重复那个简单的示例&#xff0c;我将向您展示一个稍微复杂一些的示例&#xff0c;它将为您编写大型应用程序提供一个良好的基础结构。 应用程序将存在于包中。在Python中&…

AIGC:使用生成对抗网络GAN实现MINST手写数字图像生成

1 生成对抗网络 生成对抗网络&#xff08;Generative Adversarial Networks, GAN&#xff09;是一种非常经典的生成式模型&#xff0c;它受到双人零和博弈的启发&#xff0c;让两个神经网络在相互博弈中进行学习&#xff0c;开创了生成式模型的新范式。从 2017 年以后&#x…

论文浅尝 | 基于对多条思维链的元推理实现智能问答

笔记整理&#xff1a;屠铭尘&#xff0c;浙江大学硕士&#xff0c;研究方向为知识图谱 链接&#xff1a;https://arxiv.org/abs/2304.13007 1. 动机 1.1 Chain of Thought的诞生 尽管大语言模型在许多自然语言处理任务上表现出色&#xff0c;但由于其本质是token by token的类似…

使用easyui前端框架快速构建一个crud应用

本篇文章将会详细介绍jquery easyui前端框架的使用&#xff0c;通过创建一个crud应用来带大家快速掌握easyui的使用。 easyui是博主最喜欢的前端框架&#xff0c;没有之一&#xff0c;因为它提供了多种主题&#xff0c;而且有圆润的各种组件。 目录 一、快速开始 二、准备工作…

小程序如何设置下单提示语句

下单提示会展示在购物车和提交订单页面&#xff0c;它可以帮助商家告知客户事项&#xff0c;提高用户体验和减少错误操作。例如提示&#xff1a;商品是否包邮、某些区域是否发货、商品送达时间等等。 在小程序管理员后台->配送设置处&#xff0c;填写下单提示。在设置下单提…

Java自学第8课:电商项目(3) - 重新搭建环境

由于之前用的jdk和eclipse&#xff0c;以及mysql并不是视频教程所采用的&#xff0c;在后面运行源码和使用作者提供源码时&#xff0c;总是报错&#xff0c;怀疑&#xff1a; 1 数据库有问题 2 jdk和引入的jar包不匹配 3 其他什么未知的错误&#xff1f; 所以决定卸载jdk e…

SQL入门语句

MySQL和SQL的区别是什么&#xff1f;之间是什么关系&#xff1f; SQL&#xff08;Structured Query Language&#xff09;是用于管理和操作关系型数据库&#xff08;RDBMS&#xff09;的标准语言。SQL还可以用于这些RDBMS&#xff1a;MySQL、Oracle、Microsoft SQL Server、Pos…

Kafka中遇到的错误:

1、原因&#xff1a;kafka是一个去中心化结果的&#xff0c;所以在启动Kafka的时候&#xff0c;每一个节点上都需要启动。 启动的命令&#xff1a;kafka-server-start.sh -daemon /usr/local/soft/kafka_2.11-1.0.0/config/server.properties

AMESim 2021安装教程

主要是AMESim的安装 写在前面&#xff0c;由于项目需要&#xff0c;需要自学AMESim&#xff0c;因此需要安装这个软件&#xff0c;目前仅仅安装使用&#xff0c;还不涉及到与MATLAB的联合仿真&#xff0c;老板说用 RT LAB半实物仿真平台&#xff0c;但是简单搜了一下&#xff0…

Flutter笔记:绘图示例 - 一个简单的(Canvas )时钟应用

Flutter笔记 绘图示例 - 一个简单的&#xff08;Canvas &#xff09;时钟应用 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_2855…

如何记录血压的波动情况

import pandas as pd from plotnine import * import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [Microsoft YaHei] 记录时间(time)、收缩压(SBP)、舒张压(DBP)&#xff1a; df pd.DataFrame({ time: [2023-11-01 08:30, 2023-11-02 21:00, 2023-11-0…

前端-第一部分-HTML

一.初识HTML 1.1 HTML 简介 HTML 全称为 HyperText Mark-up Language&#xff0c;翻译为超文本标签语言&#xff0c;标签也称作标记或者元素。HTML 是目前网络上应用最为广泛的技术之一&#xff0c;也是构成网页文档的主要基石之一。HTML文本是由 HTML 标签组成的描述性文本&a…

力扣最热一百题——每日温度

Python后面的文章&#xff0c;内容都比较多&#xff0c;但是同时我又想保持每天更新的速度&#xff0c;所以Python的文章我继续打磨打磨&#xff0c;先更新一篇算法的文章。 一身正气报国家&#xff0c;旁无乱境不恋她 ヾ(◍∇◍)&#xff89;&#xff9e; 力扣题号&#xff1a…

css呼吸效果实现

实现一个图片有规律的大小变化&#xff0c;呈现呼吸效果&#xff0c;怎么用CSS实现这个呼吸效果呢 一.实现 CSS实现动态效果可以使用动画( animation)来属性实现&#xff0c;放大缩小效果可以用transform: scale来实现&#xff0c;在这基础上有了动画&#xff0c;就可以设置一个…

ps人像怎么做渐隐的效果?

photoshop怎么制作人像渐隐的图片效果&#xff1f;渐隐效果需要使用渐变来实现&#xff0c;下面我们就来看看详细的教程。 首先&#xff0c;我们打开Photoshop&#xff0c;点击屏幕框选的【打开】&#xff0c;打开一张背景图片。 下面&#xff0c;我们点击左上角【文件】——【…

Exploration by random network distillation论文笔记

Exploration by Random Network Distillation (2018) 随机网络蒸馏探索 0、问题 这篇文章提出的随机网络蒸馏方法与Curiosity-driven Exploration by Self-supervised Prediction中提出的好奇心机制的区别&#xff1f; 猜想&#xff1a;本文是基于随机网络蒸馏提出的intrin…

楼宇天台视频AI智能监管方案,时刻保障居民安全

一、背景需求分析 我们经常能看到这样的新闻报道&#xff0c;小孩登上小区的天台玩耍&#xff0c;因为家长和物业人员发现得晚&#xff0c;没有及时制止&#xff0c;结果导致意外事故的发生。此前&#xff0c;在某小区就有居民拍下多名儿童在小区高层住宅的楼顶玩耍跳跃&#…

Pytorch R-CNN目标检测-汽车car

概述 目标检测(Object Detection)就是一种基于目标几何和统计特征的图像分割,它将目标的分割和识别合二为一,通俗点说就是给定一张图片要精确的定位到物体所在位置,并完成对物体类别的识别。其准确性和实时性是整个系统的一项重要能力。 R-CNN的全称是Region-CNN(区域卷积神经…

Nginx实现tcp代理并支持TLS加密实验

Nginx源码编译 关于nginx的搭建配置具体参考笔者之前的一篇文章&#xff1a;实时流媒体服务器搭建试验&#xff08;nginxrtmp&#xff09;_如何在线测试流媒体rtmp搭建成功了吗-CSDN博客中的前半部分&#xff1b;唯一变化的是编译参数&#xff08;添加stream模块并添加其对应ss…

无线城市WiFi解决方案【完整Word】

wx供重浩&#xff1a;创享日记 获取完整无水印高清Word版 文章目录 第1章 项目背景1.1“无线城市”的定义1.2 国内外“无线城市”发展概况1.3 典型案例分析1.4 建设无线城市的必要性1.5 无线城市能为政府带来的价值 第2章 项目需求分析2.1 无线城市的现状分析2.2 无线城市的总体…