上海网站建设q479185700強,上海企业推广,上海专业做网站推广的公司,有哪些做外贸的网站前段时间公司项目用到了 定时任务 所以写了一篇定时任务的文章 #xff0c;浏览量还不错 #xff0c; Springboot 整合定时任务 )
所以就准备写第二篇#xff0c; 如果你是一名Java工程师#xff0c;你也可以会看到如下的页面 #xff0c;去添加定时任务
定时任务展示 :… 前段时间公司项目用到了 定时任务 所以写了一篇定时任务的文章 浏览量还不错 Springboot 整合定时任务 )
所以就准备写第二篇 如果你是一名Java工程师你也可以会看到如下的页面 去添加定时任务
定时任务展示 : 很显然他们只是披着不同的皮而已本质上都是定时任务 , 也就是将所有的任务数据 交给了 Spring 进行管理 最后 将 任务Job信息 以及 参数传递的信息 对外进行暴露 cron 的输入值 然后交给数据库去进行 传参 这里我们来演示下 上面做到流程
环境搭建
我们需要配置一个任务 这玩意 简单说 就是你要做什么事情 然后你要做这件事你需要 用到定时任务 所有 你就得 去实现人家第三方的库 这里我们用 quartz , 当然类似的还有很多很多,只是为了方便演示 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-quartz/artifactId/dependency在第一次使用之前首先我们需要生成一下quartz 自带默认的表 大概会生成11 张的样子 把yaml配置文件中的 initialize-schema: always 配置的 always 属性意思是: 每次初始化都会重新生成表(执行一次删除执行一次创建)生成后可以修改为 never 修改下列初始化结构的 yaml 属性 : initialize-schema: always : 重复生成 你每次 都会重新生成never: 不生成
所以你第一次可以用 always 后面你就改成 never 就行了
spring:## quartz定时任务,采用数据库方式quartz:job-store-type: jdbcinitialize-schema: embedded#定时任务启动开关true-开 false-关auto-startup: true#延迟1秒启动定时任务startup-delay: 1s#启动时更新己存在的Joboverwrite-existing-jobs: trueproperties:org:quartz:scheduler:instanceName: MySchedulerinstanceId: AUTOjobStore:class: org.springframework.scheduling.quartz.LocalDataSourceJobStoredriverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegatetablePrefix: QRTZ_isClustered: falsemisfireThreshold: 12000clusterCheckinInterval: 15000threadPool:class: org.quartz.simpl.SimpleThreadPoolthreadCount: 1threadPriority: 5threadsInheritContextClassLoaderOfInitializingThread: true 如果你不想自己去生成也可以去执行这个包下面的sql
我们在创建一张业务的表方便待会弄增删改查
创建SQL CREATE TABLE sys_quartz_job (id varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,create_by varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 创建人,create_at datetime DEFAULT NULL COMMENT 创建时间,del_flag int DEFAULT NULL COMMENT 删除状态,update_by varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 修改人,update_at datetime DEFAULT NULL COMMENT 修改时间,job_class_name varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 任务类名,cron_expression varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT cron表达式,parameter varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 参数,meeting_record_id int DEFAULT NULL COMMENT 会议室记录id,description varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 描述,status int DEFAULT NULL COMMENT 状态 0正常 -1停止,PRIMARY KEY (id) USING BTREE
) ENGINEInnoDB DEFAULT CHARSETutf8mb3 ROW_FORMATDYNAMIC;
加上这张表我们就有了12 张表 其他都是 框架自带的一张我们自己生成的
编写MVC 代码
首先写一个类 你继承了人家quartz 的Job就可以用人家的功能就这么简单然后你已经有了一个任务了
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
Component
public class QuartzDemoJob implements Job {static int i 0;Autowiredprivate QuartzDemoService quartzDemoService;public QuartzDemoJob() {}Autowired //这里不能直接注入因为Autowired注入是Spring的注入要求注入对象与被注入对象都是在SpringIOC容器中存在public QuartzDemoJob(QuartzDemoService quartzDemoService) {this.quartzDemoService quartzDemoService;}TransactionalOverridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {// 编写 service 逻辑}public static String dateToStr(java.util.Date date, String strFormat) {SimpleDateFormat sf new SimpleDateFormat(strFormat);return sf.format(date);}public static Date strToSqlDate(String strDate, String dateFormat) {SimpleDateFormat sf new SimpleDateFormat(dateFormat);Date date null;try {date sf.parse(strDate);} catch (ParseException e) {e.printStackTrace();}return new Date(date ! null ? date.getTime() : 0);}
}你有了这个任务之后 你现在需要 交给Spring 进行管理 所以你需要搞个配置 这你看了我上篇文章 就明白了 吧 首先我们简单点 Job就是任务 说人话就是你要做的事 你把你要做的事写了个类然后给Spring 进行管理 配置一下 所以我们现在把 Job弄到配置类里面去
Beanpublic JobDetailFactoryBean jobDetailFactoryBean(){JobDetailFactoryBean factoryBeannew JobDetailFactoryBean();//关联我们自己的Job类factoryBean.setJobClass(QuartzDemoJob.class); //QuartzDemoJob的实例化并没有经过Spring的处理// Spring的注入是要求注入的对象和被注入的对象都要在Spring的IOC容器中return factoryBean;}完整 代码 : Configuration
public class QuartzCoreConfig {/*** 1、创建Job对象*/Beanpublic JobDetailFactoryBean jobDetailFactoryBean(){JobDetailFactoryBean factoryBeannew JobDetailFactoryBean();//关联我们自己的Job类factoryBean.setJobClass(QuartzDemoJob.class); //QuartzDemoJob的实例化并没有经过Spring的处理// Spring的注入是要求注入的对象和被注入的对象都要在Spring的IOC容器中return factoryBean;}/*** 2、创建Trigger对象* Cron Trigger*/Beanpublic CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){CronTriggerFactoryBean factoryBeannew CronTriggerFactoryBean();//关联JobDetail对象factoryBean.setJobDetail(Objects.requireNonNull(jobDetailFactoryBean.getObject()));//设置触发时间factoryBean.setCronExpression(0/2 * * * * ?); //每2秒触发一次 分钟小时天月星期
// factoryBean.setCronExpression(0 0-59 0-22 * * ?); //在每天0-22点期间的每1分钟触发return factoryBean;}/*** 3、创建Scheduler*/Beanpublic SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean, MyadaptableJobFactory myadaptableJobFactory){SchedulerFactoryBean factoryBeannew SchedulerFactoryBean();//关联triggerfactoryBean.setTriggers(cronTriggerFactoryBean.getObject());factoryBean.setJobFactory(myadaptableJobFactory); //调用myadaptableJobFactory把对象注入到SpringIOC容器中return factoryBean;}
}上面的流程图大概说下关联
SchedulerFactoryBean : 就是调度器的意思 CronTriggerFactoryBean : 就是 触发器的意思 JobDetailFactoryBean : 定时任务
在自己搞个工厂 将 quartz 手动创建一个实例 /*** 2. 编写工厂模式 加载进Spring*/
Component(myadaptableJobFactory) //将该类实例化使得可以直接用
public class MyadaptableJobFactory extends AdaptableJobFactory {//AutowireCapableBeanFactory可以将一个对象添加到Spring IOC容器中并且完成该对象注入Autowiredprivate AutowireCapableBeanFactory autowireCapableBeanFactory;//该方法将实例化的任务对象手动的添加到SpringIOC容器中并且完成对象的注入Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {Object object super.createJobInstance(bundle);//将object对象添加到Spring IOC容器中并完成注入this.autowireCapableBeanFactory.autowireBean(object);return object;}
}
上面我们做了三部
配置一个任务将任务加载进行了Spring创建了个工厂自己注入
接下来完成三层 架构 MVC搞个Controller 只是提供思路自己把他写完哈 RestController
RequestMapping(/sys/quartzJob)
Slf4j
Api(tags 定时任务接口)
public class QuartzJobController {Autowiredprivate IQuartzJobService quartzJobService;Autowiredprivate Scheduler scheduler;/*** 分页列表查询** param quartzJob* param pageNo* param pageSize* param req* return*/RequestMapping(value /list, method RequestMethod.GET)public Result? queryPageList(QuartzJob quartzJob, RequestParam(name pageNo, defaultValue 1) Integer pageNo,RequestParam(name pageSize, defaultValue 10) Integer pageSize, HttpServletRequest req) {QueryWrapperQuartzJob queryWrapper new QueryWrapper();queryWrapper.select();PageQuartzJob page new PageQuartzJob(pageNo, pageSize);IPageQuartzJob pageList quartzJobService.page(page, queryWrapper);return Result.ok(pageList);}/*** 添加定时任务** param quartzJob* return*///RequiresRoles(admin)RequestMapping(value /add, method RequestMethod.POST)public Result? add(RequestBody QuartzJob quartzJob) {quartzJobService.saveAndScheduleJob(quartzJob);return Result.ok(创建定时任务成功);}/*** 更新定时任务** param quartzJob* return*///RequiresRoles(admin)RequestMapping(value /edit, method {RequestMethod.PUT, RequestMethod.POST})public Result? eidt(RequestBody QuartzJob quartzJob) {try {quartzJobService.editAndScheduleJob(quartzJob);} catch (SchedulerException e) {log.error(e.getMessage(), e);return Result.error(更新定时任务失败!);}return Result.ok(更新定时任务成功!);}/*** 通过id删除** param id* return*///RequiresRoles(admin)RequestMapping(value /delete, method RequestMethod.DELETE)public Result? delete(RequestParam(name id, required true) String id) {QuartzJob quartzJob quartzJobService.getById(id);if (quartzJob null) {return Result.error(未找到对应实体);}quartzJobService.deleteAndStopJob(id);return Result.ok(删除成功!);}/*** 批量删除** param ids* return*///RequiresRoles(admin)RequestMapping(value /deleteBatch, method RequestMethod.DELETE)public Result? deleteBatch(RequestParam(name ids, required true) String ids) {if (ids null || .equals(ids.trim())) {return Result.error(参数不识别);}for (String id : Arrays.asList(ids.split())) {QuartzJob job quartzJobService.getById(id);quartzJobService.deleteAndStopJob(id);}return Result.ok(删除定时任务成功!);}/*** 暂停定时任务** param id* return*///RequiresRoles(admin)GetMapping(value /pause)ApiOperation(value 停止定时任务)public ResultObject pauseJob(RequestParam(name id) String id) {QuartzJob job quartzJobService.getById(id);if (job null) {return Result.error(定时任务不存在);}quartzJobService.pause(job);return Result.ok(停止定时任务成功);}/*** 启动定时任务** param id* return*///RequiresRoles(admin)GetMapping(value /resume)ApiOperation(value 启动定时任务)public ResultObject resumeJob(RequestParam(name id) String id) {QuartzJob job quartzJobService.getById(id);if (job null) {return Result.error(定时任务不存在);}quartzJobService.resumeJob(job);//scheduler.resumeJob(JobKey.jobKey(job.getJobClassName().trim()));return Result.ok(启动定时任务成功);}/*** 通过id查询** param id* return*/RequestMapping(value /queryById, method RequestMethod.GET)public Result? queryById(RequestParam(name id, required true) String id) {QuartzJob quartzJob quartzJobService.getById(id);return Result.ok(quartzJob);}/*** 导出excel** param request* param quartzJob*/RequestMapping(value /exportXls)public ModelAndView exportXls(HttpServletRequest request, QuartzJob quartzJob) {// Step.1 组装查询条件
// QueryWrapperQuartzJob queryWrapper QueryGenerator.initQueryWrapper(quartzJob, request.getParameterMap());
// // Step.2 AutoPoi 导出Excel
// ModelAndView mv new ModelAndView(new JeecgEntityExcelView());
// ListQuartzJob pageList quartzJobService.list(queryWrapper);
// // 导出文件名称
// mv.addObject(NormalExcelConstants.FILE_NAME, 定时任务列表);
// mv.addObject(NormalExcelConstants.CLASS, QuartzJob.class);
// //获取当前登录用户
// //update-begin---author:wangshuai ---date:20211227 for[JTC-116]导出人写死了------------
// LoginUser user (LoginUser) SecurityUtils.getSubject().getPrincipal();
// mv.addObject(NormalExcelConstants.PARAMS, new ExportParams(定时任务列表数据, 导出人: user.getRealname(), 导出信息));
// //update-end---author:wangshuai ---date:20211227 for[JTC-116]导出人写死了------------
// mv.addObject(NormalExcelConstants.DATA_LIST, pageList);return null;}/*** 通过excel导入数据** param request* param response* return*/RequestMapping(value /importExcel, method RequestMethod.POST)public Result? importExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {MultipartHttpServletRequest multipartRequest (MultipartHttpServletRequest) request;MapString, MultipartFile fileMap multipartRequest.getFileMap();// 错误信息ListString errorMessage new ArrayList();int successLines 0, errorLines 0;for (Map.EntryString, MultipartFile entity : fileMap.entrySet()) {// 获取上传文件对象MultipartFile file entity.getValue();ImportParams params new ImportParams();params.setTitleRows(2);params.setHeadRows(1);params.setNeedSave(true);try {ListQuartzJob listQuartzJobs ExcelImportUtil.importExcel(file.getInputStream(), QuartzJob.class, params);//add-begin-author:taoyan date:20210909 for:导入定时任务并不会被启动和调度需要手动点击启动才会加入调度任务中 #2986for (QuartzJob job : listQuartzJobs) {job.setStatus(CommonConstant.STATUS_DISABLE);}ListString list ImportExcelUtil.importDateSave(listQuartzJobs, IQuartzJobService.class, errorMessage, CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME);//add-end-author:taoyan date:20210909 for:导入定时任务并不会被启动和调度需要手动点击启动才会加入调度任务中 #2986errorLines list.size();successLines (listQuartzJobs.size() - errorLines);
// } catch (Exception e) {
// log.error(e.getMessage(), e);
// return Result.error(文件导入失败);
// } finally {
// try {
// file.getInputStream().close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// }return Result.ok();}/*** 立即执行** param id* return*///RequiresRoles(admin)GetMapping(/execute)public Result? execute(RequestParam(name id, required true) String id) {QuartzJob quartzJob quartzJobService.getById(id);if (quartzJob null) {return Result.error(未找到对应实体);}try {quartzJobService.execute(quartzJob);} catch (Exception e) {//e.printStackTrace();log.info(定时任务 立即执行失败 e.getMessage());return Result.error(执行失败!);}return Result.ok(执行成功!);}} Data
TableName(sys_quartz_job)
public class QuartzJob implements Serializable {private static final long serialVersionUID 1L;/*** id*/TableId(type IdType.ASSIGN_ID)private java.lang.String id;/*** 创建人*/private java.lang.String createBy;/*** 创建时间*/JsonFormat(timezone GMT8, pattern yyyy-MM-dd HH:mm:ss)DateTimeFormat(pattern yyyy-MM-dd HH:mm:ss)private java.util.Date createTime;/*** 删除状态*/private java.lang.Integer delFlag;/*** 修改人*/private java.lang.String updateBy;/*** 修改时间*/JsonFormat(timezone GMT8, pattern yyyy-MM-dd HH:mm:ss)DateTimeFormat(pattern yyyy-MM-dd HH:mm:ss)private java.util.Date updateTime;/*** 任务类名*/Excel(name 任务类名, width 40)private java.lang.String jobClassName;/*** cron表达式*/Excel(name cron表达式, width 30)private java.lang.String cronExpression;/*** 参数*/Excel(name 参数, width 15)private java.lang.String parameter;/*** 描述*/Excel(name 描述, width 40)private java.lang.String description;/*** 状态 0正常 -1停止*/Excel(name 状态, width 15)private java.lang.Integer status;}Mapperjava
Mapper
public interface QuartzJobMapper extends BaseMapperQuartzJob {/*** 根据jobClassName查询* param jobClassName 任务类名* return*/public ListQuartzJob findByJobClassName(Param(jobClassName) String jobClassName);} xml
xml
?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.example.schduletest.mapper.QuartzJobMapper!-- 根据jobClassName查询 --select idfindByJobClassName resultTypecom.example.schduletest.entity.QuartzJobselect * from sys_quartz_job where job_class_name #{jobClassName}/select
/mapper Service java
package com.example.schduletest.service;import com.example.schduletest.entity.QuartzJob;
import org.quartz.SchedulerException;import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;/*** Description: 定时任务*/
public interface IQuartzJobService extends IServiceQuartzJob {/*** 通过类名寻找定时任务* param jobClassName 类名* return ListQuartzJob*/ListQuartzJob findByJobClassName(String jobClassName);/*** 保存定时任务* param quartzJob* return boolean*/boolean saveAndScheduleJob(QuartzJob quartzJob);/*** 编辑定时任务* param quartzJob* return boolean* throws SchedulerException*/boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException;/*** 删除定时任务* param id* return boolean*/boolean deleteAndStopJob(String id);/*** 恢复定时任务* param quartzJob* return*/boolean resumeJob(QuartzJob quartzJob);/*** 执行定时任务* param quartzJob* throws Exception*/void execute(QuartzJob quartzJob) throws Exception;/*** 暂停任务* param quartzJob* throws SchedulerException*/void pause(QuartzJob quartzJob);
}
所有依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.7.5/versionrelativePath/ !-- lookup parent from repository --/parentgroupIdcom.example/groupIdartifactIdSchdule-Test/artifactIdversion0.0.1-SNAPSHOT/versionnameSchdule-Test/namedescriptionDemo project for Spring Boot/descriptionpropertiesjava.version8/java.version/propertiesdependencies!--Spring tx 坐标--dependencygroupIdorg.springframework/groupIdartifactIdspring-tx/artifactId/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdscoperuntime/scope/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.1.1/version/dependencydependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.4.3.1/version/dependency!-- 下一节需要用到的定时任务依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-quartz/artifactId/dependency!-- Spring 官方自带了依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdcn.afterturn/groupIdartifactIdeasypoi-annotation/artifactIdversion4.4.0/version/dependencydependencygroupIdme.zhengjie/groupIdartifactIdeladmin-system/artifactIdversion2.6/version/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/project
完整yaml
server:port: 8080
spring:datasource:name: mydburl: jdbc:mysql://localhost:3306/test?allowMultiQueriestrueuseUnicodetruecharacterEncodingUTF-8useSSLfalseserverTimezoneAsia/Shanghaiusername: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driverquartz:job-store-type: jdbc#定时任务启动开关true-开 false-关auto-startup: true#延迟1秒启动定时任务startup-delay: 1s#启动时更新己存在的Joboverwrite-existing-jobs: trueproperties:org:quartz:scheduler:instanceName: MySchedulerinstanceId: AUTOjobStore:class: org.springframework.scheduling.quartz.LocalDataSourceJobStoredriverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegatetablePrefix: QRTZ_isClustered: falsemisfireThreshold: 12000clusterCheckinInterval: 15000threadPool:class: org.quartz.simpl.SimpleThreadPoolthreadCount: 1threadPriority: 5threadsInheritContextClassLoaderOfInitializingThread: truejdbc:initialize-schema: nevermybatis:mapper-locations: classpath:Mapper/*.xml #注意一定要对应mapper映射xml文件的所在路径type-aliases-package: com.example.schduletest.entity # 注意对应实体类的路径
这是 本篇文章项目 结构 感谢大家的学习 尾声:
终归本质来说第三方框架 最后集成在业务层面也大致只不过是个增删改查 只不过 在业务层面不同而已例如我们只是在新增的时候通过调度器创建了一个 Job public boolean saveAndScheduleJob(QuartzJob quartzJob) {// DB设置修改quartzJob.setDelFlag(1);boolean success this.save(quartzJob);if (success) {if (NORMAL.equals(quartzJob.getStatus())) {// 定时器添加this.schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());}}return success;}博客项目演示层面 只是做了一个Demo : 更多 具体详情使用细节 请关注 源码实现细节