更新时间:2021年03月18日 08时58分22秒 来源:黑马程序员论坛
原因 最近在公司写一些job,公司使用的是spring boot提供的注解形式实现的。 解决方案这样在自测的时候很麻烦,而且测试提测的时候需要修改cron表达式->提交git->jenkins打包重启 查阅资料后决定选用任务调度平台,有很多优秀的任务调度平台,选择xxl-job是因为文档清晰、使用简单、基于远程RPC调用、官方提供spring boot例子。 部署首先需要执行官网提供的sql docker pull xuxueli/xxl-job-admin:2.0.2使用docker下载镜像 这里最新版本是2.0.2 然后运行docker镜像 注意修改参数 docker run -e PARAMS="--spring.datasource.url=jdbc:mysql://数据库地址:3306/xxl-job?Unicode=true&characterEncoding=UTF-8 --spring.datasource.password=数据库密码 --spring.mail.host=smtp.163.com --spring.mail.username=邮箱名 --spring.mail.password=邮箱密码 --xxl.job.login.password=登录密码" -p 8080:8080 -v /tmp:/data/applogs --name xxl-job-admin --privileged=true -d xuxueli/xxl-job-admin:2.0.2注意一些参数如邮箱可以省略 在项目中配置这里配置使用官网示例中的spring boot配置 @Configurationpublic class XxlJobConfig { private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class); @Value("${xxl.job.admin.addresses}") private String adminAddresses; @Value("${xxl.job.executor.appname}") private String appName; @Value("${xxl.job.executor.ip}") private String ip; @Value("${xxl.job.executor.port}") private int port; @Value("${xxl.job.accessToken}") private String accessToken; @Value("${xxl.job.executor.logpath}") private String logPath; @Value("${xxl.job.executor.logretentiondays}") private int logRetentionDays; @Bean(initMethod = "start", destroyMethod = "destroy") public XxlJobSpringExecutor xxlJobExecutor() { logger.info(">>>>>>>>>>> xxl-job config init."); XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); xxlJobSpringExecutor.setAdminAddresses(adminAddresses); xxlJobSpringExecutor.setAppName(appName); xxlJobSpringExecutor.setIp(ip); xxlJobSpringExecutor.setPort(port); xxlJobSpringExecutor.setAccessToken(accessToken); xxlJobSpringExecutor.setLogPath(logPath); xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); return xxlJobSpringExecutor; }}官网给出的执行器配置说明 ### 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册xxl.job.executor.appname=xxl-job-executor-sample### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";xxl.job.executor.ip=### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;xxl.job.executor.port=9999### 执行器通讯TOKEN [选填]:非空时启用;xxl.job.accessToken=### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler### 执行器日志保存天数 [选填] :值大于3时生效,启用执行器Log文件定期清理功能,否则不生效;xxl.job.executor.logretentiondays=-1执行器官方给出了不少执行器,但是要在原有项目上改造需要自己写执行器,当然可以使用一个任务写一个执行器,这样执行器就会很多,很难以维护。所以这里采用反射的方式 @Component@JobHandler(value = "BeanByClassHandler")public class BeanByClassHandler extends IJobHandler { @Autowired private ApplicationContext applicationContext; //根据完整类名 通过反射执行指定方法 @Override public ReturnT<String> execute(String param) throws Exception { XxlJobLogger.log(param); if (param == null || param.equals("")) { return new ReturnT<>(ReturnT.FAIL_CODE, "参数不能为空!"); } String[] split = param.split(","); if (split == null || split.length < 2) { return new ReturnT<>(ReturnT.FAIL_CODE, "参数格式错误,应为 完整类名,方法名"); } Class taskBeanClass = null; try { taskBeanClass = Class.forName(split[0]); } catch (Exception e) { return new ReturnT<>(ReturnT.FAIL_CODE, "类" + split[0] + "不存在"); } Method method = null; try { method = taskBeanClass.getMethod(split[1]); } catch (Exception e) { return new ReturnT<>(ReturnT.FAIL_CODE, "方法" + split[1] + "不存在"); } Object o = applicationContext.getBean(taskBeanClass); if (o == null) { return new ReturnT<>(ReturnT.FAIL_CODE, "在Application中类不存在"); } try { method.invoke(o); } catch (Exception e) { return new ReturnT<>(ReturnT.FAIL_CODE, "方法执行失败"); } return new ReturnT<>(ReturnT.SUCCESS_CODE, "执行成功"); }}首先是全类名执行器使用反射的方式 这样全类名很长所以可以使用spring管理beanName获得实例进行反射 @Component@JobHandler(value = "BeanByNameHandler")public class BeanByNameHandler extends IJobHandler { @Autowired private ApplicationContext applicationContext; //根据spring管理的bean name获取指定类 @Override public ReturnT<String> execute(String param) throws Exception { XxlJobLogger.log(param); if (param == null || param.equals("")) { return new ReturnT<>(ReturnT.FAIL_CODE, "参数不能为空!"); } String[] split = param.split(","); if (split == null || split.length < 2) { return new ReturnT<>(ReturnT.FAIL_CODE, "参数格式错误,应为bean名称,方法名"); } Object o = applicationContext.getBean(split[0]); if(o == null){ return new ReturnT<>(ReturnT.FAIL_CODE,"类在applicationContext中不存在"); } Method method; try { method = o.getClass().getMethod(split[1]); }catch (Exception e){ return new ReturnT<>(ReturnT.FAIL_CODE,"方法"+split[1]+"不存在"); } try { method.invoke(o); }catch (Exception e){ return new ReturnT<>(ReturnT.FAIL_CODE,"调用方法失败"); } return new ReturnT<>(ReturnT.SUCCESS_CODE,"调用job成功"); }}调用在web界面新建任务 参数为 全类名,方法名即可。如下图所示 缺点当然也可以执行shell脚本
|
推荐了解热门学科
java培训 | Python人工智能 | Web前端培训 | PHP培训 |
区块链培训 | 影视制作培训 | C++培训 | 产品经理培训 |
UI设计培训 | 新媒体培训 | 产品经理培训 | Linux运维 |
大数据培训 | 智能机器人软件开发 |
传智播客是一家致力于培养高素质软件开发人才的科技公司,“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。
传智播客从未停止思考
传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”
中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。
何为中高级程序员课程?
传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展。“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。
黑马程序员热门视频教程【点击播放】
Python入门教程完整版(懂中文就能学会) | 零起点打开Java世界的大门 |
C++| 匠心之作 从0到1入门学编程 | PHP|零基础入门开发者编程核心技术 |
Web前端入门教程_Web前端html+css+JavaScript | 软件测试入门到精通 |