当前位置: 首页 > news >正文

专业做网站app的公司哪家好百度指数名词解释

专业做网站app的公司哪家好,百度指数名词解释,做网站需要什么文件,富阳做网站方式Quartz简介 Job 表示一个工作,要执行的具体业务内容。 JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。 Trigger 代表一个调度参数的配置&#xf…

Quartz简介

Job 表示一个工作,要执行的具体业务内容

JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。

Trigger 代表一个调度参数的配置,什么时候去调。

Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。

案例

背景

系统中有一张自定义的定时任务表,需要实现动态的添加、修改、删除、启停定时任务等功能,定时任务里包含了业务需要执行的按设置周期执行的代码

由于不想使用Quartz的数据存储功能,所以下面实现里直接使用了这张自定义的表,以及使用了Quartz的任务调度触发功能

实现步骤

1. 引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId><version>2.7.18</version>
</dependency>

2. 添加配置类

@Configuration
public class ScheduleQuartzConfig {@Beanpublic Scheduler scheduler() throws SchedulerException {Scheduler scheduler = schedulerFactoryBean().getScheduler();return scheduler;}@Beanpublic SchedulerFactoryBean schedulerFactoryBean() {Properties properties = new Properties();properties.setProperty("org.quartz.threadPool.threadCount", "10");properties.setProperty("org.quartz.threadPool.threadNamePrefix","quartz_worker");SchedulerFactoryBean factory = new SchedulerFactoryBean();factory.setSchedulerName("QUARTZ_SCHEDULER");factory.setQuartzProperties(properties);return factory;}
}

3. 编写Job类

该类就是将来要定时执行的业务代码,具体代码路径根据实际情况规划即可,重点是继承 QuartzJobBean,重写 executeInternal 方法

//锁定机制,以确保在同一时间只有一个任务实例运行
@DisallowConcurrentExecution
public class MyJob extends QuartzJobBeanprivate final static Logger logger = LoggerFactory.getLogger(PushPvImitateDataJob.class);@Overrideprotected void executeInternal(JobExecutionContext context) throws JobExecutionException {//业务代码logger.info("开始执行业务代码了。。。");try {Thread.sleep(6000);} catch (InterruptedException e) {e.printStackTrace();}	logger.info("业务代码执行完成了!!!!");}
}

4. 编写定时任务表的实体类

ScheduleLog.java

@Data
public class ScheduleLog {private Integer id;private String name; //任务名称private String jobClassName; //任务的实现类 如:xxx.xxx.xx.MyJobprivate String cronExpression; //触发时机表达式,比如每5秒执行一次 0/5 * * * * ?private Integer status; //状态:0 启动 1 禁用private String remark;private Long createTime;private Long updateTime;private Long lastTime; //上一次执行时间private Long nextTime; //下一次执行时间private String lastTimeText;private String nextTimeText;
}

5. 创建管理定时任务的工具类

@Component
public class ScheduleQuartzManage {private static final Logger logger = LoggerFactory.getLogger(ScheduleQuartzManage.class);/*** 创建定时任务 定时任务创建之后默认启动状态** @param scheduler:    调度器* @param scheduleLog: 报告订阅对象* @return: void**/public void createScheduleJob(Scheduler scheduler, ScheduleLog scheduleLog) throws SchedulerException {//获取到定时任务的执行类  必须是类的绝对路径名称//定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。
//        Class<? extends Job> jobClass = PushPvImitateDataJob.class;Class<? extends Job> jobClass = null;try {jobClass = (Class<? extends Job>) Class.forName(scheduleLog.getJobClassName());} catch (ClassNotFoundException e) {e.printStackTrace();}// 构建定时任务信息JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(scheduleLog.getId().toString(),"jobGroup").usingJobData("id",scheduleLog.getId()).build();// 设置定时任务执行方式CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleLog.getCronExpression());// 构建触发器trigger// 如果已经有下一次时间,就设置为下一次时间为触发时间CronTrigger trigger;if (!Objects.isNull(scheduleLog.getNextTime())) {Date date = new Date(scheduleLog.getNextTime());trigger = TriggerBuilder.newTrigger().startAt(date).withIdentity(scheduleLog.getId().toString(), "jobGroup").withSchedule(scheduleBuilder).build();} else {trigger = TriggerBuilder.newTrigger().withIdentity(scheduleLog.getId().toString(),"jobGroup").withSchedule(scheduleBuilder).build();}scheduler.scheduleJob(jobDetail, trigger);// 设置下次执行时间//long nextTime = trigger.getNextFireTime().getTime();//LocalDateTime nextTime = DateUtil.dateToLocalDate(trigger.getNextFireTime());//logger.info("下次一执行时间:{}",DateUtil.formatDateTime(new Date(nextTime)));//scheduleLog.setNextTime(nextTime);}/*** 根据任务名称暂停定时任务** @param scheduler 调度器* @param jobName  定时任务名称(这里直接用ReportSubscribePO的Id)* @throws SchedulerException*/public void pauseScheduleJob(Scheduler scheduler, String jobName) throws SchedulerException {JobKey jobKey = JobKey.jobKey(jobName, "jobGroup");scheduler.pauseJob(jobKey);}/*** 根据任务名称恢复定时任务** @param scheduler 调度器* @param scheduleLog  定时任务名称(这里直接用ReportSubscribePO的Id)* @throws SchedulerException*/public void resumeScheduleJob(Scheduler scheduler, ScheduleLog scheduleLog) throws SchedulerException {// 判断当前任务是否在调度中Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.groupEquals("jobGroup"));List<JobKey> thisNameJobs = jobKeys.stream().filter(jobKey -> Objects.equals(scheduleLog.getId().toString(), jobKey.getName())).collect(Collectors.toList());if (thisNameJobs.size() > 0){JobKey jobKey = JobKey.jobKey(scheduleLog.getId().toString(), "jobGroup");scheduler.resumeJob(jobKey);// 下一次执行时间设置回去Trigger trigger = scheduler.getTrigger(TriggerKey.triggerKey(scheduleLog.getId().toString(), "jobGroup"));long nextTime = trigger.getNextFireTime().getTime();scheduleLog.setNextTime(nextTime);}else {createScheduleJob(scheduler, scheduleLog);}}/*** 更新定时任务** @param scheduler    调度器* @param scheduleLog 报告订阅对象* @throws SchedulerException*/public void updateScheduleJob(Scheduler scheduler, ScheduleLog scheduleLog) throws SchedulerException {//获取到对应任务的触发器TriggerKey triggerKey = TriggerKey.triggerKey(scheduleLog.getId().toString(),"jobGroup");//设置定时任务执行方式CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleLog.getCronExpression());//重新构建任务的触发器triggerCronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);if (trigger == null){return;}//  trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();trigger = TriggerBuilder.newTrigger().startNow().withIdentity(scheduleLog.getId().toString(), "jobGroup").withSchedule(scheduleBuilder).build();//重置对应的jobscheduler.rescheduleJob(triggerKey, trigger);scheduleLog.setNextTime(trigger.getNextFireTime().getTime());}/*** 根据定时任务名称从调度器当中删除定时任务** @param scheduler 调度器* @param jobName  定时任务名称 (这里直接用 ScheduleLog 的Id)* @throws SchedulerException*/public void deleteScheduleJob(Scheduler scheduler, String jobName) throws SchedulerException {JobKey jobKey = JobKey.jobKey(jobName,"jobGroup");scheduler.deleteJob(jobKey);}
}

6. 项目启动时做任务初始化

这里我直接让service实现了CommandLineRunner,然后在run()方法中,将初始化逻辑写入进来,让数据库中的持久化的任务全部添加进内存中。

@Service
public class ScheduleLogServiceImpl implements ScheduleLogService, CommandLineRunnerprivate final static Logger logger = LoggerFactory.getLogger(ScheduleLogServiceImpl.class);@Autowiredprivate ScheduleLogDao scheduleLogDao;@Autowiredprivate ScheduleQuartzManage scheduleQuartzManage;@Autowiredprivate Scheduler scheduler; //这里的scheduler来源于配置@Overridepublic void run(String... args) throws Exception {// 初始化所有的已经启用的订阅List<ScheduleLog> enableSubs = getEnableScheduleList();logger.info("需要初始化的任务个数:{}", enableSubs.size());for (ScheduleLog sub : enableSubs) {try {logger.info("开始初始化订阅任务,任务name:{}", sub.getName());scheduleQuartzManage.createScheduleJob(scheduler, sub);} catch (Exception e) {logger.error("启动时初始化订阅任务失败:{}", e.getMessage());}}}@Overridepublic List<ScheduleLog> getEnableScheduleList() {HashMap<String, Object> param = new HashMap<>();param.put("status",1);List<ScheduleLog> list = scheduleLogDao.getList(param);return list;}@Overridepublic boolean add(Map data) {data.put("createTime", DateUtil.currentSeconds());Integer add = scheduleLogDao.add(data);if(add > 0){//创建调度器data.put("id",add);ScheduleLog scheduleLog = BeanUtil.mapToBean(data, ScheduleLog.class,false,null);if(scheduleLog.getStatus() < 1){return true;}try {scheduleQuartzManage.createScheduleJob(scheduler, scheduleLog);} catch (SchedulerException e) {e.printStackTrace();}return true;}return false;}@Overridepublic boolean del(Integer id) {Integer del = scheduleLogDao.del(id);if(del > 0){try {scheduleQuartzManage.deleteScheduleJob(scheduler,String.valueOf(id));} catch (SchedulerException e) {e.printStackTrace();}return true;}return false;}@Overridepublic boolean edit(Map data) {data.put("updateTime",DateUtil.currentSeconds());Integer save = scheduleLogDao.save(data);if(save > 0){try {ScheduleLog scheduleLog = getDetail((Integer) data.get("id"));if(data.get("status").equals(0)){//关闭scheduleQuartzManage.deleteScheduleJob(scheduler,data.get("id").toString());}else{//开启scheduleQuartzManage.deleteScheduleJob(scheduler,data.get("id").toString());scheduleQuartzManage.createScheduleJob(scheduler,scheduleLog);}} catch (SchedulerException e) {e.printStackTrace();}return true;}return false;}
}

至此基本就实现了定时任务的管理了,controller 里的内容包含了对定时任务进行管理的接口,就不写了

总结

  1. 同一个任务是否可以并行执行,可参考第3步设置
  2. 每次项目重新部署后,自动加载数据库中的定时任务
  3. Quartz在发生异常时会重试一次,注意异常处理,可在第3步中处理

参考链接:https://juejin.cn/post/7054762566035193869#heading-7

Cron表达式

不管是Spring自带的定时任务实现,还是SpringBoot整合Quartz的定时任务实现,其触发器都支持用corn表达式来表示。

corn表达式是一个字符串,有6或7个域,域之间是用空格进行间隔。

从左到右每个域表示的含义如下:

第几个域英文释义允许值备注
Seconds0~59
Minutes0~59
Hours0~23
DayOfMonth1-31
Month1-12或月份简写
DayOfWeek1-7或星期简写星期,1表示SUN,在day-of-week字段用”6#3”指这个月第3个周五(6指周五,3指第3个)。如果指定的日期不存在,触发器就不会触发
Year1970~2099

然后,某些域还支持部分特殊字符,特殊字符的含义如下:

特殊字符含义及注意事项
*任意值
?占位符,只能在第四域和第六域中使用,表示未说明的值,即不关心它为何值
-区间,表示区间内有效
/固定间隔,符号前表示开始时间,符号后表示每次递增的值;
,枚举有效值的间隔符,表示附加一个可能值
L表示该区间的最后一个有效值,只能在第四域和第六域中使用, L(“last”) (“last”) “L” 用在day-of-month字段意思是 “这个月最后一天”;用在 day-of-week字段, 它简单意思是 “7” or “SAT”。 如果在day-of-week字段里和数字联合使用,它的意思就是 “这个月的最后一个星期几” – 例如: “6L” means “这个月的最后一个星期五”. 当我们用“L”时,不指明一个列表值或者范围是很重要的,不然的话,我们会得到一些意想不到的结果。
W表示离指定日期的最近的有效工作日,(周一-周五为工作日),W(“weekday”) 只能用在day-of-month字段。用来描叙最接近指定天的工作日(周一到周五)。例如:在day-of-month字段用“15W”指“最接近这个月第15天的工作日”,即如果这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;如果这个月第15天是周日,那么触发器将会在这个月第16天即周一触发;如果这个月第15天是周二,那么就在触发器这天触发,注意一点:这个用法只会在当前月计算值,不会越过当前月。“W”字符仅能在day-of-month指明一天,不能是一个范围或列表。也可以用“LW”来指定这个月的最后一个工作日。

常用corn表达式例子含义说明:

corn表示式表达式含义
*/10 * * * * ? *每隔10秒执行一次
0 30 1 * * ? *每天凌晨1点30分0秒开始执行
0 0 10,14,16 * * ?每天10点、14点、16点执行一次
0 15 10 L * ?每个月最后一天的10点15分执行一次
0 15 10 ? * 6L每月的最后一个星期五上午10:15触发
0 15 10 15 * ?每月15日上午10:15触发
0 15 10 ? * 6#3每月的第三个星期五上午10:15触发
0 15 10 ? * 6L 2018-20202018年到2020年每个月最后一个星期五的10:15执行

校验地址:https://www.bejson.com/othertools/cronvalidate/


文章转载自:
http://airbound.zfqr.cn
http://beige.zfqr.cn
http://zipless.zfqr.cn
http://assort.zfqr.cn
http://surrey.zfqr.cn
http://legalistic.zfqr.cn
http://sonolyze.zfqr.cn
http://inseparability.zfqr.cn
http://salmonid.zfqr.cn
http://genetics.zfqr.cn
http://kheth.zfqr.cn
http://outwith.zfqr.cn
http://demode.zfqr.cn
http://sociopolitical.zfqr.cn
http://pinguid.zfqr.cn
http://bearwood.zfqr.cn
http://victorious.zfqr.cn
http://postoffice.zfqr.cn
http://dll.zfqr.cn
http://steatitic.zfqr.cn
http://berime.zfqr.cn
http://decide.zfqr.cn
http://wendic.zfqr.cn
http://geometricism.zfqr.cn
http://inexplicit.zfqr.cn
http://duckboard.zfqr.cn
http://immusical.zfqr.cn
http://kayah.zfqr.cn
http://suppertime.zfqr.cn
http://mailplane.zfqr.cn
http://episematic.zfqr.cn
http://shlock.zfqr.cn
http://synaesthesia.zfqr.cn
http://irradiancy.zfqr.cn
http://quandang.zfqr.cn
http://mpm.zfqr.cn
http://salwar.zfqr.cn
http://shive.zfqr.cn
http://unmold.zfqr.cn
http://unwalkable.zfqr.cn
http://unfurnish.zfqr.cn
http://galvanometrically.zfqr.cn
http://cursor.zfqr.cn
http://barquisimeto.zfqr.cn
http://recalcitration.zfqr.cn
http://semiconsciousness.zfqr.cn
http://balun.zfqr.cn
http://debride.zfqr.cn
http://rompingly.zfqr.cn
http://doctrinist.zfqr.cn
http://vengeful.zfqr.cn
http://menelaus.zfqr.cn
http://lull.zfqr.cn
http://countermortar.zfqr.cn
http://unchastity.zfqr.cn
http://tucker.zfqr.cn
http://cytotech.zfqr.cn
http://rotochute.zfqr.cn
http://touchy.zfqr.cn
http://collieshangie.zfqr.cn
http://trichomonad.zfqr.cn
http://terrene.zfqr.cn
http://actualite.zfqr.cn
http://behind.zfqr.cn
http://osteochondritis.zfqr.cn
http://cio.zfqr.cn
http://dina.zfqr.cn
http://stylostixis.zfqr.cn
http://actorish.zfqr.cn
http://antisabbatarian.zfqr.cn
http://tropophilous.zfqr.cn
http://eugenics.zfqr.cn
http://trigynous.zfqr.cn
http://technology.zfqr.cn
http://grunt.zfqr.cn
http://uncreate.zfqr.cn
http://photogrammetry.zfqr.cn
http://balletically.zfqr.cn
http://swaddle.zfqr.cn
http://palmitate.zfqr.cn
http://afficionado.zfqr.cn
http://viscose.zfqr.cn
http://hemachrome.zfqr.cn
http://bromate.zfqr.cn
http://tangier.zfqr.cn
http://rating.zfqr.cn
http://convalescent.zfqr.cn
http://stagey.zfqr.cn
http://underwaist.zfqr.cn
http://weatherable.zfqr.cn
http://nooning.zfqr.cn
http://dirl.zfqr.cn
http://anthocyanidin.zfqr.cn
http://ina.zfqr.cn
http://tertius.zfqr.cn
http://fennoscandian.zfqr.cn
http://azotobacter.zfqr.cn
http://betterment.zfqr.cn
http://lurcher.zfqr.cn
http://sagitta.zfqr.cn
http://www.hrbkazy.com/news/84866.html

相关文章:

  • 网站可以做固定资产吗今日热点新闻一览
  • wordpress网站托管今天的新闻头条
  • 手机视频网站开发教程广州网站建设费用
  • 如何做网站迁移站长工具端口
  • 漳州市住房和城乡建设局网站现在做网络推广都有什么方式
  • 苏州建网站的公司哪家公司好中国十大it培训机构排名
  • 南宁美丽南方官方网站建设意见百度指数官网数据
  • discuz网站标题如何优化培训体系
  • python搭建网站网络营销广告策划
  • 高端网页设计培训东莞seo公司
  • 汕尾招聘 网站建设合伙人武汉seo群
  • 爱用建站正规吗店铺推广
  • 小型 网站 源码seo营销网站的设计标准
  • 王烨演的电视剧搜索引擎优化排名技巧
  • 怎么做刷qq会员网站2018关键词排名工具
  • 任县企业做网站宁德市属于哪个省份
  • 资源下载类网站源码青岛网站建设维护
  • inurl 网站建设巩义网络推广外包
  • 视频做动图的网站广州seo公司品牌
  • 如何解决旅游网站建设问题seo网址
  • 网站做seo推广口碑营销例子
  • 2手房产App网站开发郑州网络推广厂家
  • 做网站需要注意什么安徽网站seo
  • 惠州网站网站建设2022年新闻热点事件
  • 06年可以做相册视频的网站sem竞价推广
  • 建站公司联系电话北京网站优化公司哪家好
  • 做百科需要用什么网站做参考嘉兴关键词优化报价
  • 用凡客建站做的网站有哪些培训学校怎么招生
  • 用什么软件做公司网站新媒体运营师证书
  • 微信h5的制作方法谷歌优化排名怎么做