ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 一、快速开发 ### **背景** 新版JobServer(基于RayFramework平台的一套独立运行容器,与主程序完全分开独立运行,支持通过协议通讯),我们只需基于业务,分析业务,写出符合业务需要的job,就完成了调度开发工作,至于容器自身的细节,我们不必去理会,由JobServer平台自身管理; ### **开发步骤** 1、新建一个job类,继承自RayPeriodScheduleJobInJobServer(如果您希望不独立部署,而是合并到appServer中,那么继承自RayPeriodScheduleJobInAppServer); 2、在void doInRayPeriodJob(SysJobExecution sysjobexecution)方法中实现自己的业务逻辑; 3、为了把业务与技术分离,平台建议新建一个专用的service类(事务控制在这里),跟在主程序一样,这里可以使用开发平台的任何基础设施;**如果业务比较复杂,比如是循环业务,那么,建议新建一个专业的action类(那么事务从service层就转移控制在这里),供service调用**; >[info] 注意: > 1、job类中,必须加入注解@Component; > 2、doInRayPeriodJob业务中,可以使用开发平台的各种基础设施,跟平台主程序一样强大; > 3、到这里,开发就完成了,非常简单,对不对? ### **参考代码** Job: ``` @Component public class ScanCardCandidateJob extends RayPeriodScheduleJobInJobServer { @Autowired private ScanCardCandidateService scanCardCandidateService; @Override protected void doInRayPeriodJob(SysJobExecution sysjobexecution, StringBuilder errorMessage) { scanCardCandidateService.scanCandidate(); } @Override protected String allowedIps() { return all; } @Override protected boolean enabled() { return true; } @Override protected long initialDelayInSeconds() { return 1 * minute; } @Override protected String jobDesc() { return "候选卡片处理"; } @Override protected long periodInSeconds() { return 1 * minute; } } ``` Service: ``` @Service public class ScanCardCandidateService extends RayScheduleJobService { @Autowired private CardInfoDao cardInfoDao; @Autowired private CardInfoCandidateDao cardInfoCandidateDao; @Autowired private CardSourceDao cardSourceDao; @Autowired private ScanCardCandidateAction action; public void scanCandidate() { List<CardInfoCandidate> candidates = cardInfoCandidateDao.findAll(); for (CardInfoCandidate candidate : candidates) { action.doAction(candidate); } } } ``` Action: ``` @Component public class ScanCardCandidateAction extends RayScheduleJobAction { @Autowired private CardInfoDao cardInfoDao; @Autowired private CardInfoCandidateDao cardInfoCandidateDao; @Autowired private CardSourceDao cardSourceDao; @Transactional public void doAction(CardInfoCandidate candidate) { try { CardSource cardsource = cardSourceDao.findBySourceName(candidate.getCardSource()); if (cardsource == null) { } CardInfo cardinfo = new CardInfo(); cardinfo.setAccessCode(candidate.getAccessCode()); cardinfo.setCardSource(cardsource.getSourceId()); cardinfo.setCardStatus(CardStatus.initialized); cardinfo.setRealNameStatus(CardRealNameStatus.not_real_named); cardinfo.setCardUserStaff(0L); cardinfo.setIccidCode(candidate.getIccidCode()); cardinfo.setTerminalAgentStaff(0L); cardinfo.setTopAgentStaff(0L); cardinfo.setCardUserStaff(0L); cardinfo.setApiAgentStaff(0L); cardinfo.setUserCode(candidate.getUserCode()); boolean flag = ApiFacade.initOperation(cardinfo); cardInfoDao.save(cardinfo); cardInfoCandidateDao.delete(candidate); } catch (Exception ex) { } } } ``` ## 二、打包部署 这里打包也非常简单,只需要选择运行模式为jobserver的打包任务即可; ![](https://img.kancloud.cn/7a/6b/7a6b1ccf3ba3158e1fc9bd1eb1476fa7_1366x736.png) 如何定义呢?可以参考:[后端开发](../../%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91.md)中,打包模式的内容 >[info] 这里的调试,也非常简单,跟主工程一样,只要确保run-mode=jobserver,即可; ## 三、支持cron表达式的版本 将继承的基础类由*RayPeriodScheduleJobInJobServer*调整为*RayCronScheduleJobInJobServer*,业务方法由doInRayPeriodJob()改为doInRayCronJob(),并额外的增加了一个方法cron(),用途是提供cron表达式; ### **如何定义cron表达式** 字符串以6个空格隔开,分为7个域(其中第7个域是年份,可以留空),每一个域代表一个含义; | 域序号(从左往右)| 域意义 | 取值范围 |特殊字符 | | --- | --- | --- |--- | | 1 | 秒 | 0-59 | ,-*/ | | 2 | 分 | 0-59 | ,-*/ | | 3 | 小时 | 0-23 | ,-*/ | | 4 | 日期 | 1-31 | ,-*?/LW | | 5 | 月份 | 1-12 或者 JAN-DEC | ,-*/ | | 6 | 星期 | 1-7 或者 SUN-SAT | ,-*?/L# | | 7 | 年份(可选,留空)| 1970~2099 | ,-*/ | 关于特殊字符的含义,如下表所示: | 字符 | 说明 | | --- | --- | | , |表示列出枚举值,例如:在分域使用5,20,则意味着在5和20分每分钟触发一次| | - | 表示范围,例如在分域使用5-20,表示从5分到20分钟每分钟触发一次 | | * | 表示匹配该域的任意值。假如在分域使用, 即表示每分钟都会触发事件 | | / | 表示递增触发,然后每隔固定时间触发一次。例如在分域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次 | | ? | 表示不指定值,使用的场景为不需要关心当前设置这个字段的值,它只能用在日期和星期两个域;例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为”?” 具体设置为 0 0 0 10 \* ? | | # | 序号,用于确定每个月第几个星期几,只能出现在日期域。例如在周字段上设置”6#3”表示在每月的第三个周六 | | L | 表示最后,只能出现在星期和日期域。如果在星期域使用5L,意味着在最后的一个星期四触发 | | W | 表示有效工作日(周一到周五),只能出现在日期域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 日期使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 | | LW | 这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五 | ### **参考代码** ``` @Component public class TestCronJob extends RayCronScheduleJobInJobServer { @Override protected void doInRayCronJob(SysJobExecution sysjobexecution, StringBuilder errorMessage) throws Exception { //business } @Override protected String allowedIps() { return all; } @Override protected boolean enabled() { return true; } @Override protected String jobDesc() { return "cron的job测试"; } // 每个月1日的23点 @Override protected String cron() { return "* * 23 1 * ? "; } @Override protected long initialDelayInSeconds() { return 0; } @Override protected long periodInSeconds() { return 0; } @Override protected String allowedInstanceIds() { return null; } } ```