定时任务管理系统(spring boot + quartz + angular)

时间:2022-04-23 08:00:30

由于公司的项目越来越多,定时任务越来越多,像以前只是使用spring的@Scheduled注解来实现一个个定时任务已经不能满足需要了。需要一个独立系统专门来完成所有定时任务,既然这样,那么我们必须要可视化,对所有任务进行管理(新增或者删除),关联任务(A任务执行完,B任务执行)等。以下是我搭建项目时的思路:

  1. 首先,项目应该前后端分离,所以项目结构上应该是parent下面一个service项目和一个web项目。
  2. 后端框架:spring boot(1.4.3) 和 quartz-scheduler(2.2.1)
  3. 前端:Angular 2.4 (node 7.7.3)
  4. web项目部署时,打成webjars供service项目依赖。为了直接使用spring mvc的默认配置,所以maven打包资源文件时指定到META-INF/resources/webjars/目录下

使用maven搭建项目(项目命名 Knight 包含knight-service和knight-web ),依次引入spring boot相关依赖, quartz-scheduler依赖以及配置(持久化,创建表的语句官网有提供,我也把sql脚本加入到了项目中)。
knight-service项目依赖

    <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>com.4past</groupId>
<artifactId>knight-web</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
</dependencies>

application.properties 只需要配置spring.datasource相关(先执行创建表的sql脚本)

quartz.properties配置如下:

org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.useProperties = true
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_

接下来就要配置SchedulerFactoryBean

    @Bean
public SchedulerFactoryBean schedulerFactory(@Qualifier("dataSource") DataSource dataSource) throws ParseException {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setDataSource(dataSource);
schedulerFactoryBean.setTriggers(assembleTriggers());
schedulerFactoryBean.setGlobalJobListeners(assembleJobListeners());
return schedulerFactoryBean;
}

因为我们要创建很多的任务Job和Trigger,所以不需要用spring bean管理了,直接用工具类创建。
比如创建JobDetail的方法:

    /**
* JobDetail工厂对象生成JobDetail
*
* @param jobClass job类
* @param description 任务描述
* @param groupName 分组名
* @return JobDetail
*/

private JobDetail makeJobDetail(Class<? extends Job> jobClass, String description, String groupName) {
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
jobDetailFactoryBean.setJobClass(jobClass);
jobDetailFactoryBean.setDurability(true);
jobDetailFactoryBean.setName(jobClass.getName());
jobDetailFactoryBean.setGroup(groupName);
jobDetailFactoryBean.setDescription(description);
jobDetailFactoryBean.afterPropertiesSet();
return jobDetailFactoryBean.getObject();
}

其他的如trigger等,都使用工具类的创建方法来创建。
这样我们需每次服务启动就运行的任务,就通过这些方法来创建,最后丢到SchedulerFactoryBean中即可。

因为我们创建了SchedulerFactoryBean,所以我们也在service层中利用Scheduler来对所有任务进行管理。

前端部分可以直接打开终端进入对应目录,用 ng new KnightWeb(需要先安装node,angular-cli)来创建项目
用maven配置项目的打包:

 <build>
<resources>
<resource>
<directory>dist</directory>
<includes>
<include>**/**.**</include>
</includes>
<!-- 注意这个目录必须如此(knight自己定义),迎合spring默认 /webjars/** 的路径-->
<targetPath>META-INF/resources/webjars/knight</targetPath>
</resource>
</resources>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v7.7.3</nodeVersion>
<npmVersion>4.1.2</npmVersion>
</configuration>
</execution>

<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>

<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

这样就完成了项目的搭建。在开发中不用每次都打包,ng server运行前端来访问http://localhost:4200即可。IDE一般都要npm插件。配置运行命令:npm start即可。
需要注意的时候,这样运行,访问service项目是要跨域的,所以在启动类中需要配置运行跨域,继承WebMvcConfigurerAdapter
实现:

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*")
.allowedOrigins("*");
}

部署的时候,利用maven打包,就只需要部署service项目一个jar运行即可。
我已经把这个项目精简后传到了github:https://github.com/pujiaolin/Knight