1.源起
在做java服务端开发的时候,免不了会接触到定时任务相关模块的开发,什么定时发送邮件,什么定时出报告啦。我这里采用的是quartz开源库,功能强大,还会自动维护数据库,省事,上手比较简单。但是在易用性方面却做的不是很便捷,在项目使用的过程中遇到了一些通点,经过几个版本在迭代,现在的软件界面是你下面看到的效果。我喜欢叫她Task,任务调度小助手。
2.功能
经过几个版本的迭代,目前包含的功能主要有:
- 创新的管理界面设计,直观的展示任务的启用状态、任务的执行状态等信息,将常用功能放在列表,方便使用;
- 在quartz中job是任务执行的最小单元,我们在job的基础上抽象出更加细粒度的task,一个job可以包含多个task;
- 每个task可单独配置对应的参数,task中的配置参数均是通过注解的形式添加;
- task包含两种不同的类型,普通的task会按照配置的顺序,按序执行;另一种特别的task叫flat类型,可以将List中的数据挨个取出,一个接一个发送给后续的任务列表处理;此处命名参与自rxjava,嘿嘿;
- 加入更加完善的任务中断功能,quartz中job中断只给一个bool类型的标记,需要开发者在job中自行处理。Task库中也是基于bool标记,会在任务链执行的过程中对标记进行判断,通过抛异常的方式中断任务。此方法仍然无法做到实时中断任务;
- task具有排序功能,任务执行的顺序即为task列表的顺序;
- 加入了任务日志功能,在任务执行过程中各个task返回的结果会以实时日志的形式通过websocket发送到前端展示,后续加入logger手动打日志的功能;
- Task库中已内置管理界面,只需要在浏览器输入:http://ip:port/task/index.html即可查看任务管理界面。
3.使用
依赖
<dependency>
<groupId>com.basic</groupId>
<artifactId>basic-task</artifactId>
<version>1.1.6</version>
</dependency>
#yml中加入如下配置, task-packages为task存放的包名,可以设置成项目包名
task:
task-packages: com.piesat.project.admin.task
示例
/**
* 任务分为公共组public和自定义组,在选择任务时,会按这两大类分组
* 内置的四种任务均为public
* 在项目实时的过程中如果有一些是封装好的公共任务可定义为public,方便配置时查找
*/
@TaskAnnotation(name = "公共测试", group = Constants.PUBLIC)
public class PublicTask extends BaseTask<String> {
/*
*@TaskParam 注解的变量会显示在task属性配置项,配置后在任务执行时会自动注入
* type/defaultValue/options 三个选项暂时还不能用起来
*/
private final FileFilter filter;
@TaskParam(alias = "待扫描的目录路径", type = DataType.STRING)
private String sourceDirectory;
@TaskParam(alias = "是否扫描子目录", type = DataType.BOOLEAN, defaultValue = "true", options = {"true", "false"})
private boolean needScanChildren;
@TaskParam(alias = "文件过滤器", type = DataType.OBJECT)
private String fileFilter;
public PublicTask(TaskInfo taskInfo) {
super(taskInfo);
filter = new FileFilter();
filter.createFromFilterInfo(new FilterInfo(FilterType.FILE.getType(), fileFilter));
}
/**
* 该方法为任务执行时的实际执行者
* @TaskParam 注解的变量在方法体内均可直接使用
*/
@Override
public TaskResult<?> execute() {
return null;
}
}
/**
* 方法注解的方式在实际的项目过程中用的最多,直接写在service中是一个不错的方式,方便使用spring中的bean
* 一个service中可以注入任一多个task,只要你喜欢
* 你也可以把所有的任务都统一集中到一个service中
* @Parser注解的方法最终会解析成Task对象,如果对这块感兴趣可以查看TaskInstanceCreator类
*/
@Service
public class TestMethodTask {
/**
* name定义任务名称
* group定义任务组,这里的组跟quartz中的group不是同一个东西,需要区分
* params用来定义任务接收的参数,没有数量限制,可通过“:”分隔符来设置参数的别名,方便在前端配置任务时识别
*/
@Parser(name = "task1", group = "test", params = {"path:源地址", "destPath:目标地址"})
public String execute(Map<String, Object> map) {
String path = (String) map.get("path");
String destPath = (String) map.get("destPath");
return "成功了哦";
}
@Parser(name = "flat_task", group = "test", params = {"targetPath", "destPath"})
public String test1(Map<String, Object> map) {
return "成功了哦";
}
}
经过上面两个配置,将会在管理界面显示出如下效果
4.经过
当前的版本应该是第三代
- 初代逻辑都写在job中,任务参数写在yml中,通过spring注入;
- 二代修改为TaskFlow的任务执行形式,将job细化,抽象出task概念;实现将多种task组合成一个job,实现task的复用;
- 三代加入任务参数定制配置,加入任务日志实时显示,重新设计任务展示界面;
- 四代还在酝酿中,完善的日志组件?
- ......
所有这些换代都是被项目推着走的,做着做着发现维护起来已经十分棘手,唯有求变。
也许这也是我们人生活在这个时代的缩影吧,有时候我们在变得更好不是我们主动的选择,是被时代推着走的。致懒惰的自己!
还有其他好想法的,可以在评论区说道,咱们一起完善。
5.终章
项目后续会发到maven中心仓库,没啥经验,有知道的可在评论出说道说道。
服务器已经买好了,后续把使用文件编辑好发到服务器,方便各位看官使用。
项目地址:basic-task