spring boot做定时任务管理模块。
我做的定时器管理界面是下面这样的。
新增页面。
列表页面。
下面来说说做定时任务管理模块的步骤。
1.在pom.xml中配maven库。
<!-- 定时器 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
2.在spring boot中的启动文件(XXApplication )中注入Environment(在使用spring boot 的时候,我们只需要注入Environment类,即可获取到所有的配置资源。)。
@SpringBootApplication(scanBasePackages="com.tky")
@EnableTransactionManagement // 启注解事务管理
@Controller
@RequestMapping(value="")
public class WbybApplication {
@RequestMapping(value="/",method={RequestMethod.GET})
public String index(){
return "/login";
}
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(WbybApplication.class);
springApplication.run(args);
}
@Autowired
private Environment env;
//连接池
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));//用户名
dataSource.setPassword(env.getProperty("spring.datasource.password"));//密码
//生产环境
//dataSource.setInitialSize(50);
//dataSource.setMaxActive(240);
//测试环境
dataSource.setInitialSize(2);
dataSource.setMaxActive(5);
dataSource.setMinIdle(0);
dataSource.setMaxWait(60000);
dataSource.setValidationQuery("SELECT 1 FROM DUAL");
dataSource.setTestOnBorrow(false);
dataSource.setTestWhileIdle(true);
dataSource.setPoolPreparedStatements(false);
return dataSource;
}
@Bean
public StartupRunner startupRunner(){
return new StartupRunner();
}
}
3.在application.yml中加入 定时任务系统标志(最后的一行 dsrwbz: 1 就是加入的定时任务系统标志)。
#路内测试库
spring.datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://10.1.0.207:3306/sidian?useUnicode=true&characterEncoding=UTF-8&useSSL=true
username: root
password: 123456
#配置mongodb参数
spring:
data:
mongodb:
host: 10.1.0.207
port: 27017
database: sidian
spring.http.multipart.maxFileSize: 1000Mb
spring.http.multipart.maxRequestSize: 10000Mb
#定时任务系统标志
dsrwbz: 1
4.在ServletInitializer类的onApplicationEvent方法做一些处理,能服务器启动的时候就能执行 初始化定时任务的方法(this.scheduleJobService.initJobs();这个方法在后面会帖出来)。
/**
*
* @author lwj
* 发布在tomcat时需配置
*
*/
public class ServletInitializer extends SpringBootServletInitializer implements ApplicationListener<ApplicationEvent> {
@Autowired
private ScheduleJobService scheduleJobService;
@Autowired
private Environment env;
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WbybApplication.class);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextClosedEvent || event instanceof ContextStoppedEvent) {
// System.out.println(event.getClass().getSimpleName() + " 事件已发生!");
} else if (event instanceof ContextRefreshedEvent) {
ContextRefreshedEvent evt = (ContextRefreshedEvent) event;
if(evt.getApplicationContext().getParent() == null){
//存一下上下文,反射执行方法要用
//SpringContextUtil.setApplicationContext(evt.getApplicationContext());
//SpringUtil.setApplicationContext(evt.getApplicationContext());
//需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。
//初始化定时任务,读取定时任务标志参数,1表示定时任务系统,0业务系统,业务系统不加载定时任务
if ("1".equals(env.getProperty("dsrwbz"))) {
this.scheduleJobService.initJobs();
}
}
}
}
}
5.声明定时任务工厂bean。
/**
* @ClassName: JavaConfig
* @Description: Java配置
* @author CMB
* @date 2017年5月25日 下午5:23:35
*
*/
@Configuration
public class JavaConfig {
/**
*
* @Title: schedulerFactoryBean
* @Description: 声明定时任务工厂bean
* @param @return 参数
* @return SchedulerFactoryBean 返回类型
* @throws
* @author CMB
* @date 2017年10月17日 下午5:10:48
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(){
return new SchedulerFactoryBean();
}
}
6.写一个SpringUtils工具类获取spring中的bean实体。
/**
* 通类可以通过调用SpringUtils工具类获取spring中的bean实体
*
* @author zhangtianlun
*
*/
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
System.out.println("---------------------------------------------------------------------");
System.out.println("---------------com.tky.common.util.spring.SpringUtil------------------------------------------------------");
System.out.println("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,"
+ "applicationContext="+SpringUtil.applicationContext+"========");
System.out.println("---------------------------------------------------------------------");
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
以上都做定时任务模块 的前期配置。
下面是后台方法(controller,service,dao)。
controller方法。
/**
* @Title: ScheduleJobController.java
* @Package com.tky.sgzz.controller.base
* @Description: 定时任务管理模块控制器
* @author MUJL
* @date 2018年11月25日 上午10:56:38
* @version V1.0
*/
package com.tky.xxjd.controller.scheduler;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.tky.common.data.ResultBean;
import com.tky.common.data.ResultCode;
import com.tky.common.data.RowsWrapper;
import com.tky.common.util.JsonUtil;
import com.tky.core.dto.UserInfo;
import com.tky.xxjd.entity.pingmiantu.ImportXmlRecordData;
import com.tky.xxjd.entity.scheduler.ScheduleJob;
import com.tky.xxjd.service.scheduler.ScheduleJobService;
import io.swagger.annotations.ApiOperation;
/**
* @ClassName: ScheduleJobController
* @Description: 定时任务管理控制器
* @author MUJL
* @date 2018年11月25日 上午10:56:38
*
*/
@Controller
@RequestMapping("/scheduleJobControl")
public class ScheduleJobController {
/**
* 页面文件路径
*/
private static final String SCHEDULE_VIEW_PATH = "/static/xxjd/schedule/";
@Autowired
private ScheduleJobService scheduleJobService;
/**
*
* @Title: toView
* @Description: 打开定时任务管理页面
* @param @param model
* @param @param request
* @param @param session
* @param @param id
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午2:14:15
*/
@RequestMapping("/toView")
public String toView (Model model,ServletRequest request, HttpSession session , Long id ) {
// 查询用户具有的操作权限
return SCHEDULE_VIEW_PATH + "schedulelist";
}
/**
*
* @Title: getScheduleJobList
* @Description: 分页查询定时任务
* @param @param model
* @param @param request
* @param @param session
* @param @param pageNumber
* @param @param pageSize
* @param @param jobname
* @param @param description
* @param @param state
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午2:41:53
*/
@RequestMapping("/getScheduleJobList")
@ResponseBody
public String getScheduleJobList (Model model,ServletRequest request, HttpSession session,
@RequestParam(value = "page", defaultValue = "1") int pageNumber,
@RequestParam(value = "rows", defaultValue = "10") int pageSize,
@RequestParam(value = "jobname", defaultValue = "") String jobname,
@RequestParam(value = "description", defaultValue = "") String description,
@RequestParam(value = "state", defaultValue = "") String state) {
ResultBean<RowsWrapper<ScheduleJob>> rs = scheduleJobService.getScheduleJobList(pageNumber,pageSize,jobname,description,state);
return JsonUtil.toJson(rs);
}
// /**
// *
// * @Title: toAddJob
// * @Description: 跳转新增定时任务页面
// * @param @param model
// * @param @param request
// * @param @param session
// * @param @return 参数
// * @return String 返回类型
// * @throws
// * @author MUJL
// * @date 2018年11月27日 下午5:20:29
// */
// @RequestMapping(value = "/toAddJob", method = { RequestMethod.GET, RequestMethod.POST })
// public String toAddJob(Model model,ServletRequest request, HttpSession session ) {
// return SCHEDULE_VIEW_PATH + "scheduleJobEdit";
// }
/**
*
* @Title: addScheduleJob
* @Description: 添加定时任务
* @param @param model
* @param @param request
* @param @param session
* @param @param job
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午3:18:15
*/
@ResponseBody
@RequestMapping(value = "/addJob", method = {RequestMethod.POST },produces="application/json;charset=utf-8")
@ApiOperation(value="新增修改", notes="保存",response=ScheduleJob.class)
public String addScheduleJob(HttpServletRequest request ,ScheduleJob job) {
ResultBean<ScheduleJob> rs = null;
try {
HttpSession session = request.getSession();
UserInfo userinfo = (UserInfo) session.getAttribute("userInfo");
if (userinfo != null) {
job.setUserid(userinfo.getId());
job.setUsername(userinfo.getName());
}
ScheduleJob job_new = scheduleJobService.saveScheduleJob(job);
rs = new ResultBean<ScheduleJob>(ResultCode.SUCCESS, "保存成功!");
rs.setResult(job_new);
} catch (Exception e) {
e.printStackTrace();
rs = new ResultBean<ScheduleJob>(ResultCode.ERROR_SERVE, "保存失败!");
}
return JsonUtil.toJson(rs);
}
/**
*
* @Title: getAllServices
* @Description: 获取所有Service注解的bean名称
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月26日 下午5:41:14
*/
@RequestMapping("/getAllServices")
@ResponseBody
public String getAllServices(){
ResultBean<List<Map<String, String>>> rb = new ResultBean<>();
rb = this.scheduleJobService.getAllServices();
return JsonUtil.toJson(rb);
}
/**
*
* @Title: getAllMethods
* @Description: 获取bean中定义的方法
* @param @param classname
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月26日 下午5:42:13
*/
@RequestMapping("/getAllMethods")
@ResponseBody
public String getAllMethods(@RequestParam(value = "classname", defaultValue = "") String classname){
ResultBean<List<Map<String, String>>> rb = new ResultBean<>();
rb = this.scheduleJobService.getAllMethods(classname);
return JsonUtil.toJson(rb);
}
/**
*
* @Title: toUpdateJob
* @Description: 打开修改定时任务页面
* @param @param model
* @param @param id
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午5:20:11
*/
@RequestMapping("/toUpdateJob")
public String toUpdateJob(Model model, Long id){
ScheduleJob job = this.scheduleJobService.getScheduleJob(id);
model.addAttribute("job", job);
return SCHEDULE_VIEW_PATH + "scheduleJobEdit";
}
// /**
// *
// * @Title: updateScheduleJob
// * @Description: 修改定时任务
// * @param @param model
// * @param @param request
// * @param @param session
// * @param @param job
// * @param @return 参数
// * @return String 返回类型
// * @throws
// * @author MUJL
// * @date 2018年11月27日 下午5:19:56
// */
// @ResponseBody
// @RequestDescMapping(mappingName="修改定时任务")
// @RequestMapping(value = "/updateJob", method = { RequestMethod.GET, RequestMethod.POST })
// @OperationLog(description="修改定时任务")
// public String updateScheduleJob(Model model,ServletRequest request, HttpSession session ,ScheduleJob job) {
// ResultBean<String> rb = null;
// try {
// scheduleJobService.saveScheduleJob(session, job);
// rb = new ResultBean<>(ResultCode.SUCCESS_CODE, ResultCode.SAVE_SUCCESS_STRING);
// } catch (Exception e) {
// e.printStackTrace();
// rb = new ResultBean<>(ResultCode.ERROR_CODE, ResultCode.SAVE_ERROR_STRING);
// }
// return BaseJSON.toJSONString(rb);
// }
/**
*
* @Title: deleteJobs
* @Description: 删除定时任务
* @param @param jobIds
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午5:19:43
*/
@ResponseBody
@RequestMapping(value = "/deleteJobs", method = { RequestMethod.GET, RequestMethod.POST })
public String deleteJobs(Long id) {
Long[] ids = {id};
ResultBean<List<Map<String, String>>> rb = this.scheduleJobService.deleteJobs(ids);
return JsonUtil.toJson(rb);
}
/**
*
* @Title: checkJobNameExists
* @Description: 检查定时任务名称是否存在
* @param @param jobname
* @param @param id
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午4:45:30
*/
@ResponseBody
@RequestMapping(value = "/checkJobNameExists", method = { RequestMethod.GET, RequestMethod.POST })
public String checkJobNameExists(@RequestParam(value="jobname") String jobname, @RequestParam(value="id", required=false) Long id){
ResultBean<List<Map<String, String>>> rb = this.scheduleJobService.checkJobNameExists(jobname, id);
return JsonUtil.toJson(rb);
}
/**
*
* @Title: startJobs
* @Description: 启用定时任务
* @param @param session
* @param @param jobIds
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月31日 下午5:06:55
*/
@RequestMapping("/startJobs")
@ResponseBody
public String startJobs(Long id) {
Long[] jobIds = {id};
ResultBean<List<Map<String, String>>> rb = this.scheduleJobService.startJobs(jobIds);
return JsonUtil.toJson(rb);
}
/**
*
* @Title: stopJobs
* @Description: 禁用定时任务
* @param @param session
* @param @param jobIds
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月31日 下午5:07:21
*/
@RequestMapping("/stopJobs")
@ResponseBody
public String stopJobs(Long id) {
Long[] jobIds = {id};
ResultBean<List<Map<String, String>>> rb = this.scheduleJobService.stopJobs(jobIds);
return JsonUtil.toJson(rb);
}
/**
*
* @Title: runJob
* @Description: 手动执行定时任务
* @param @param session
* @param @param jobId
* @param @return 参数
* @return String 返回类型
* @throws
* @author MUJL
* @date 2018年11月31日 下午5:07:25
*/
@RequestMapping("/runJob")
@ResponseBody
public String runJob(Long jobId) {
ResultBean<List<Map<String, String>>> rb = this.scheduleJobService.runJob(jobId);
return JsonUtil.toJson(rb);
}
}
service方法。
/**
* @ClassName: ScheduleJobService
* @Description: 定时任务管理接口
* @author MUJL
* @date 2018年11月25日 上午10:57:33
*
*/
public interface ScheduleJobService {
/**
*
* @Title: getScheduleJobList
* @Description: 查询定时任务
* @param @param pageNumber
* @param @param pageSize
* @param @param jobname
* @param @param description
* @param @param state
* @param @return 参数
* @return ResultBean<List<Map<String,Object>>> 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午2:56:01
*/
public ResultBean<RowsWrapper<ScheduleJob>> getScheduleJobList(int pageNumber, int pageSize, String jobname,
String description, String state);
/**
* @Title: getCount
* @Description: 获取定任务总数
* @param @param jobname
* @param @param description
* @param @param state
* @param @return 参数
* @return int 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午2:44:45
*/
// int getCount(String jobname, String description, String state);
/**
* @param session
* @Title: saveScheduleJob
* @Description: 保存定时任务
* @param @param job
* @param @return 参数
* @return void 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午3:18:29
*/
public ScheduleJob saveScheduleJob(ScheduleJob job);
/**
* @Title: initJobs
* @Description: 初始化定时任务
* @param 参数
* @return void 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午5:01:13
*/
public void initJobs();
// /**
// *
// * @Title: hello
// * @Description: 测试用的
// * @param 参数
// * @return void 返回类型
// * @throws
// * @author MUJL
// * @date 2017年10月17日 下午9:28:45
// */
// void hello();
/**
* @Title: getAllServices
* @Description: 获取所有Service注解的bean名称
* @param @return 参数
* @return ResultBean<List<Map<String,String>>> 返回类型
* @throws
* @author MUJL
* @date 2018年11月26日 下午3:26:09
*/
ResultBean<List<Map<String, String>>> getAllServices();
/**
* @param classname
* @Title: getAllMethods
* @Description: 获取bean所有无入参的方法
* @param @return 参数
* @return ResultBean<List<Map<String,String>>> 返回类型
* @throws
* @author MUJL
* @date 2018年11月26日 下午3:31:38
*/
ResultBean<List<Map<String, String>>> getAllMethods(String classname);
/**
* @Title: getScheduleJob
* @Description: 根据id查询定时任务
* @param @param id
* @param @return 参数
* @return ScheduleJob 返回类型
* @throws
* @author MUJL
* @date 2018年11月26日 下午6:12:33
*/
ScheduleJob getScheduleJob(Long id);
/**
* @Title: deleteJobs
* @Description: 删除定时任务
* @param @param jobIds
* @param @return 参数
* @return ResultBean<String> 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午2:55:15
*/
ResultBean<List<Map<String, String>>> deleteJobs(Long[] jobIds);
/**
* @Title: checkJobNameExists
* @Description: 检查定时任务名称是否存在
* @param @param jobname
* @param @param id
* @param @return 参数
* @return ResultBean<Boolean> 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午4:45:40
*/
ResultBean<List<Map<String, String>>> checkJobNameExists(String jobname, Long id);
/**
* @Title: startJobs
* @Description: 启用定时任务
* @param @param session
* @param @param jobIds
* @param @return 参数
* @return ResultBean<String> 返回类型
* @throws
* @author MUJL
* @date 2018年11月31日 上午9:46:11
*/
ResultBean<List<Map<String, String>>> startJobs(Long[] jobIds);
/**
* @Title: stopJobs
* @Description: 禁用定时任务
* @param @param session
* @param @param jobIds
* @param @return 参数
* @return ResultBean<String> 返回类型
* @throws
* @author MUJL
* @date 2018年11月31日 上午9:54:39
*/
ResultBean<List<Map<String, String>>> stopJobs(Long[] jobIds);
/**
* @Title: runJob
* @Description: 执行定时任务
* @param @param jobId
* @param @return 参数
* @return ResultBean<String> 返回类型
* @throws
* @author MUJL
* @date 2018年11月31日 上午10:11:09
*/
ResultBean<List<Map<String, String>>> runJob(Long jobId);
}
serviceimpl方法。
/**
* @ClassName: ScheduleJobServiceImpl
* @Description: 定时任务管理实现类
* @author MUJL
* @date 2018年11月25日 上午10:58:12
*
*/
@Service("scheduleJobService")
public class ScheduleJobServiceImpl implements ScheduleJobService {
/**
* 定时任务数据持久化接口
*/
@Autowired
private ScheduleJobDao scheduleJobDao;
/**
* 定时任务工厂类
*/
@Autowired
private SchedulerFactoryBean schedulerFactoryBean;
@Autowired
private Environment env;
/**
*
* @Title: getScheduleJobList
* @Description: 查询定时任务
* @param @param pageNumber
* @param @param pageSize
* @param @param jobname
* @param @param description
* @param @param state
* @param @return 参数
* @return ResultBean<List<Map<String,Object>>> 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午2:56:01
*/
@Override
public ResultBean<RowsWrapper<ScheduleJob>> getScheduleJobList(int pageNumber, int pageSize, String jobname,
String description, String state) {
ResultBean<RowsWrapper<ScheduleJob>> r = new ResultBean<RowsWrapper<ScheduleJob>>(ResultCode.SUCCESS, ResultCode.SUCCESS_SELECT);
try {
PageRequest pageRequest = new PageRequest(pageNumber - 1 , pageSize, new Sort(Direction.ASC, "id"));
Page<ScheduleJob> page = scheduleJobDao.findAll(new Specification<ScheduleJob>(){
@Override
public Predicate toPredicate(Root<ScheduleJob> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
Path<String> jobnamepath=root.get("jobname");
Path<String> descriptionpath=root.get("description");
Path<String> statepath=root.get("state");
List<Predicate> list = new ArrayList<Predicate>();
//predicates.add(cb.like(root.get(name), "%"+conditions.get(name)+"%"));
if(!StringUtils.isEmpty(jobname)) {
list.add(cb.like(jobnamepath, "%"+jobname+"%"));
}
if(!StringUtils.isEmpty(description)) {
list.add(cb.equal(descriptionpath, "%"+description+"%"));
}
if(!StringUtils.isEmpty(state)) {
list.add(cb.equal(statepath, state));
}
Predicate[] p = new Predicate[list.size()];
return cb.and(list.toArray(p));
}
} , pageRequest);
page.forEach(scheduleJob -> {
if ("1".equals(scheduleJob.getState())) {//state=1启用
// 计算出下次执行时间
CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
try {
cronTriggerImpl.setCronExpression((String) scheduleJob.getCronexpression());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//这里写要准备猜测的cron表达式
List<Date> dateList = TriggerUtils.computeFireTimes(cronTriggerImpl, null, 1);
if (dateList != null && dateList.size() > 0) {
scheduleJob.setNextfiretime(dateList.get(0));
}
}
});
r.setResult(new RowsWrapper<ScheduleJob>(page , pageNumber ,pageSize));
} catch (Exception e) {
// TODO: handle exception
}
return r;
}
/**
* @param session
* @Title: saveScheduleJob
* @Description: 保存定时任务
* @param @param job
* @param @return 参数
* @return void 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午3:18:29
*/
@Override
public ScheduleJob saveScheduleJob(ScheduleJob job) {
ScheduleJob job_new = null;
// 拼接corn表达式,格式 秒 分 时 天 月 年 ,例如0 0 0 ? * *表示每天0点执行
if (job.getRuntime() != null && !"".equals(job.getRuntime())) {
String[] arr = job.getRuntime().split(":");
String corn = "0 " + arr[1] + " " + arr[0] + " ? * *";
job.setCronexpression(corn);
}
// 设置更新时间
job.setUpdatetime(new Date());
// 若没设置启动状态则默认为禁用状态
if (job.getState() == null || "".equals(job.getState())) {
job.setState("0");
}
try {
//保存定时任务
job_new=this.scheduleJobDao.save(job);
if ("1".equals(env.getProperty("dsrwbz"))) {
// 若任务状态为启用,则启动定时任务
if ("1".equals(job.getState())) {
createJob(job);
} else {// 若任务状态为禁用,则停掉定时任务
pauseJob(job);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return job_new;
}
/**
* @Title: initJobs
* @Description: 初始化定时任务
* @param 参数
* @return void 返回类型
* @throws
* @author MUJL
* @date 2018年11月25日 下午5:01:13
*/
@Override
public void initJobs() {
//查询所有定时任务
List<ScheduleJob> jobList = (List<ScheduleJob>) this.scheduleJobDao.findAll();
for (ScheduleJob job : jobList) {
//把设为启用状态的定时任务启动起来
if ("1".equals(job.getState())) {
try {
createJob(job);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
*
* @Title: createJob
* @Description: 创建定时任务,若定时任务已存在则更新
* @param @param job
* @param @throws Exception 参数
* @return void 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午2:20:56
*/
private void createJob(ScheduleJob job) throws Exception{
//获取调度器
Scheduler scheduler = schedulerFactoryBean.getScheduler();
// 获取trigger,即在spring配置文件中定义的 bean id="myTrigger"
TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobname(), job.getJobgroup());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (null == trigger) {
// 不存在,创建一个
MethodInvokingJobDetailFactoryBean methodInvJobDetailFB = new MethodInvokingJobDetailFactoryBean();
methodInvJobDetailFB.setName(job.getJobname());
//methodInvJobDetailFB.setTargetObject(SpringContextUtil.getApplicationContext().getBean(job.getClassname()));SpringUtil.getApplicationContext().getBeansWithAnnotation(Service.class);
methodInvJobDetailFB.setTargetObject(SpringUtil.getApplicationContext().getBean(job.getClassname()));
methodInvJobDetailFB.setTargetMethod(job.getMethod());
methodInvJobDetailFB.afterPropertiesSet();
methodInvJobDetailFB.setConcurrent(false);
JobDetail jobDetail = (JobDetail) methodInvJobDetailFB.getObject();// 动态
jobDetail.getJobDataMap().put("scheduleJob", job);
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronexpression());
// 按新的cronExpression表达式构建一个新的trigger
trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobname(), job.getJobgroup())
.withSchedule(scheduleBuilder).build();
// 加载定时任务
scheduler.scheduleJob(jobDetail, trigger);
} else {
// Trigger已存在,那么更新相应的定时设置
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronexpression());
// 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
}
}
/**
*
* @Title: pauseJob
* @Description: 停止定时任务
* @param @param job
* @param @throws Exception 参数
* @return void 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午2:21:17
*/
private void pauseJob(ScheduleJob job) throws Exception{
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobKey jobKey = JobKey.jobKey(job.getJobname());
scheduler.pauseJob(jobKey);
}
/**
*
* @Title: deleteJob
* @Description: 删除定时任务
* @param @param job
* @param @throws Exception 参数
* @return void 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午2:21:39
*/
private void deleteJob(ScheduleJob job) throws Exception{
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobKey jobKey = JobKey.jobKey(job.getJobname());
scheduler.deleteJob(jobKey);
}
/**
*
* @Title: hello
* @Description: 测试用的
* @param 参数
* @return void 返回类型
* @throws
* @author MUJL
* @date 2017年10月17日 下午9:28:45
*/
// @Override
// @OperationLog(description="定时任务描述,测试用的")
// public void hello() {
// System.out.println("Hello World!");
// }
/**
* @Title: getAllServices
* @Description: 获取所有Service注解的bean名称
* @param @return 参数
* @return ResultBean<List<Map<String,String>>> 返回类型
* @throws
* @author MUJL
* @date 2018年11月26日 下午3:26:09
*/
@Override
public ResultBean<List<Map<String, String>>> getAllServices() {
ResultBean<List<Map<String, String>>> rb = new ResultBean<List<Map<String, String>>>(0, "查询成功!");
List<Map<String, String>> servicesList = new ArrayList<>();
// 通过应用上下文获取所有的org.springframework.stereotype.Service注解类
//Map<String, Object> map = SpringContextUtil.getApplicationContext().getBeansWithAnnotation(Service.class);
Map<String, Object> map = SpringUtil.getApplicationContext().getBeansWithAnnotation(Service.class);
// 将所有Service类名称拼成List,用于前台执行类型下拉菜单
for (String key : map.keySet()) {
Map<String, String> e = new HashMap<>();
e.put("id", key);
e.put("name", key);
servicesList.add(e);
}
rb.setResult(servicesList);
return rb;
}
/**
* @param classname
* @Title: getAllMethods
* @Description: 获取bean所有无入参的方法
* @param @return 参数
* @return ResultBean<List<Map<String,String>>> 返回类型
* @throws
* @author MUJL
* @date 2018年11月26日 下午3:31:38
*/
@Override
public ResultBean<List<Map<String, String>>> getAllMethods(String classname) {
ResultBean<List<Map<String, String>>> rb = new ResultBean<List<Map<String, String>>>(0, "查询成功!");
List<Map<String, String>> methodsList = new ArrayList<>();
// 通过应用上下文获取所有的org.springframework.stereotype.Service注解类
//Map<String, Object> mapb = SpringContextUtil.getApplicationContext().getBeansWithAnnotation(Service.class);
Map<String, Object> mapb = SpringUtil.getApplicationContext().getBeansWithAnnotation(Service.class);
// 根据bean名称取出bean
Object obj = mapb.get(classname);
// 截取出完整类路径+类名
String clazzName = obj.toString();
clazzName = clazzName.substring(0, clazzName.indexOf("@"));
// 获取选择的类的方法
ClassPool pool = ClassPool.getDefault();
ClassClassPath classPath = new ClassClassPath(this.getClass());
pool.insertClassPath(classPath);
CtClass cc;
try {
cc = pool.get(clazzName);
CtMethod[] ms = cc.getDeclaredMethods();
for (CtMethod cm : ms) {
// 取出所有的无入参方法,拼接成List用于前台执行方法下拉框
if (cm.getParameterTypes().length == 0) {
Map<String, String> e = new HashMap<>();
e.put("id", cm.getName());
e.put("name", cm.getName());
methodsList.add(e);
}
}
} catch (NotFoundException e) {
e.printStackTrace();
}
rb.setResult(methodsList);
return rb;
}
/**
* @Title: getScheduleJob
* @Description: 根据id查询定时任务
* @param @param id
* @param @return 参数
* @return ScheduleJob 返回类型
* @throws
* @author MUJL
* @date 2018年11月26日 下午6:12:33
*/
@Override
public ScheduleJob getScheduleJob(Long id) {
return this.scheduleJobDao.findOne(id);
}
/**
* @Title: deleteJobs
* @Description: 删除定时任务
* @param @param jobIds
* @param @return 参数
* @return ResultBean<String> 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午2:55:15
*/
@Override
public ResultBean<List<Map<String, String>>> deleteJobs(Long[] jobIds) {
ResultBean<List<Map<String, String>>> rb = new ResultBean<List<Map<String, String>>>(0, "删除成功!");
try{
//批量删除前,先查出所有要删的定时任务
List<ScheduleJob> jobList = this.scheduleJobDao.getJobs(jobIds);
//停掉定时任务
if ("1".equals(env.getProperty("dsrwbz"))) {
for (ScheduleJob job : jobList) {
deleteJob(job);
}
}
//执行删除
this.scheduleJobDao.delete(jobList);
} catch(Exception e){
e.printStackTrace();
return rb = new ResultBean<List<Map<String, String>>>(-1, "删除失败!");
}
return rb;
}
/**
* @Title: checkJobNameExists
* @Description: 检查定时任务名称是否存在
* @param @param jobname
* @param @param id
* @param @return 参数
* @return ResultBean<Boolean> 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午4:45:40
*/
@Override
public ResultBean<List<Map<String, String>>> checkJobNameExists(String jobname, Long id) {//ResultBean(Integer code, String msg, T result)
try {
int count = 0;
if(id == null) {
count = this.scheduleJobDao.getCountScheduleJobByJobname(jobname);
}
else {
count = this.scheduleJobDao.getCountScheduleJobByJobnameAndId(jobname,id);
}
if (count > 0) {
return new ResultBean<List<Map<String, String>>>(0, "查询成功!", true);
}
} catch (Exception e) {
return new ResultBean<List<Map<String, String>>>(-1, "查询失败!", false);
}
return new ResultBean<List<Map<String, String>>>(0, "查询成功!", false);
}
/**
* @Title: startJobs
* @Description: 启用定时任务
* @param @param session
* @param @param jobIds
* @param @return 参数
* @return ResultBean<String> 返回类型
* @throws
* @author MUJL
* @date 2018年11月31日 上午9:46:11
*/
@Override
public ResultBean<List<Map<String, String>>> startJobs(Long[] jobIds) {
try {
//批量启动定时任务前,查询所有要启动的定时任务
List<ScheduleJob> jobList = this.scheduleJobDao.getJobs(jobIds);
for (int i=jobList.size() - 1; i >= 0; i--) {
ScheduleJob job = jobList.get(i);
//如果已经是启动状态,则不管,也不需要更新状态
if ("1".equals(job.getState())) {
jobList.remove(i);
continue;
} else {
//如果是禁用状态,更新状态,并启动任务
job.setState("1");
if ("1".equals(env.getProperty("dsrwbz"))) {
createJob(job);
}
}
}
//如果有要更新的数据,则执行更新
if (!jobList.isEmpty()) {
this.scheduleJobDao.save(jobList);
}
} catch (Exception e) {
e.printStackTrace();
return new ResultBean<List<Map<String, String>>>(-1, "启动失败!");
}
return new ResultBean<List<Map<String, String>>>(0, "启动成功!");
}
/**
* @Title: stopJobs
* @Description: 禁用定时任务
* @param @param session
* @param @param jobIds
* @param @return 参数
* @return ResultBean<String> 返回类型
* @throws
* @author MUJL
* @date 2018年11月31日 上午9:54:39
*/
@Override
public ResultBean<List<Map<String, String>>> stopJobs(Long[] jobIds) {
try {
//批量禁用定时任务前,查询所有要启动的定时任务
List<ScheduleJob> jobList = this.scheduleJobDao.getJobs(jobIds);
for (int i=jobList.size() - 1; i >= 0; i--) {
ScheduleJob job = jobList.get(i);
//如果已经是禁用状态,则不管,也不需要更新状态
if ("0".equals(job.getState())) {
jobList.remove(i);
continue;
} else {
//如果是启动状态,更新状态,并停掉任务
job.setState("0");
if ("1".equals(env.getProperty("dsrwbz"))) {
pauseJob(job);
}
}
}
//如果有要更新的数据,则执行更新
if (!jobList.isEmpty()) {
this.scheduleJobDao.save(jobList);
}
} catch (Exception e) {
e.printStackTrace();
return new ResultBean<List<Map<String, String>>>(-1, "停止失败!");
}
return new ResultBean<List<Map<String, String>>>(0, "停止成功!");
}
/**
* @Title: runJob
* @Description: 执行定时任务
* @param @param jobId
* @param @return 参数
* @return ResultBean<String> 返回类型
* @see com.tky.sgzz.service.base.ScheduleJobService#runJob(java.lang.Long)
* @throws
* @author MUJL
* @date 2018年11月31日 上午10:11:09
*/
@Override
public ResultBean<List<Map<String, String>>> runJob(Long jobId) {
//立即执行前查询任务
ScheduleJob job = this.scheduleJobDao.findOne(jobId);
//若任务不存在,直接返回
if (job == null) {
return new ResultBean<List<Map<String, String>>>(-1, "您要执行的任务不存在!");
}
try {
//执行任务
runJobInvoke(job);
} catch (Exception e) {
e.printStackTrace();
return new ResultBean<List<Map<String, String>>>(-1, "停止失败!");
}
return new ResultBean<List<Map<String, String>>>(0, "停止成功!");
}
/**
*
* @Title: runJobInvoke
* @Description: 手动执行定时任务
* @param @param job
* @param @throws Exception 参数
* @return void 返回类型
* @throws
* @author MUJL
* @date 2018年11月21日 下午5:23:22
*/
private void runJobInvoke(ScheduleJob job) throws Exception{
// 获取应用上下文
//ApplicationContext ac = SpringContextUtil.getApplicationContext();
ApplicationContext ac = SpringUtil.getApplicationContext();
// 获取要执行的bean
Object bean = ac.getBean(job.getClassname());
// 获取要执行的方法
Method method = ReflectionUtils.findMethod(bean.getClass(), job.getMethod());
if (method != null) {
// 使用Spring反射工具,直接执行方法
ReflectionUtils.invokeMethod(method, bean);
}
}
}
dao方法。
/**
* @ClassName: ScheduleJobDao
* @Description: 定时任务数据持久化接口
* @author MUJL
* @date 2018年11月25日 上午11:00:43
*
*/
@Repository
public interface ScheduleJobDao extends PagingAndSortingRepository<ScheduleJob, Long> ,JpaSpecificationExecutor<ScheduleJob>{
/**
* @Title: findOne
* @Description: 根据定时任务id查询定时任务
* @param @param id
* @param @return 参数
* @return ScheduleJob 返回类型
* @throws
* @author MUJL
* @date 2018年11月26日 下午6:26:29
*/
@Query(value="select a from ScheduleJob a where a.id = ?1 ")
ScheduleJob findOne(Long id);
/**
* @Title: getJobs
* @Description: 根据定时任务id数组查询定时任务
* @param @param jobIds
* @param @return 参数
* @return List<ScheduleJob> 返回类型
* @throws
* @author MUJL
* @date 2018年11月27日 下午3:00:58
*/
@Query("select a from ScheduleJob a where a.id in ?1 ")
List<ScheduleJob> getJobs(Long[] jobIds);
@Query("select count(id) from ScheduleJob a where a.jobname = ?1 ")
Integer getCountScheduleJobByJobname(String jobname);
@Query("select count(id) from ScheduleJob a where a.jobname = ?1 And a.id <> ?2")
Integer getCountScheduleJobByJobnameAndId(String jobname,Long id);
}
实体类。
/**
*
* @ClassName: ScheduleJob
* @Description: TODO(这里用一句话描述这个类的作用)
* @author MUJL
* @date 2018年11月18日 上午8:50:33
*
*/
@Data
@NoArgsConstructor
@Entity
@Table(name = "WBYP_TAB_SCHEDULEJOB")
public class ScheduleJob {
/** 任务id */
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
/** 任务名称 */
private String jobname;
/** 任务分组 */
private String jobgroup;
/** 任务状态 0禁用 1启用 */
private String state;
/** 任务运行时间表达式 */
private String cronexpression;
/** 任务描述 */
private String description;
/** 执行任务类名 */
private String classname;
/** 执行任务方法 */
private String method;
/** 操作员ID */
private Long userid;
/** 操作员名称 */
private String username;
/** 更新时间 */
private Date updatetime;
/** 下次执行时间*/
@Transient
private Date nextfiretime;
@Transient
private String runtime;
}
在这里我先帖一下代码,有时间再补充。