diff --git a/doc/db/boot_backend.sql b/doc/db/boot_backend.sql index 2411c553d14359c0709d00762a8cfe5c9e0c0da1..52b5a311076cea3b041e38da5e83d4c79383248c 100644 --- a/doc/db/boot_backend.sql +++ b/doc/db/boot_backend.sql @@ -327,10 +327,14 @@ INSERT INTO `sys_permission` VALUES ('22', '0', '公告管理', 'fa-book', 'page INSERT INTO `sys_permission` VALUES ('23', '22', '查询', '', '', '2', 'articles:query', '100'); INSERT INTO `sys_permission` VALUES ('24', '22', '添加', '', '', '2', 'articles:add', '100'); INSERT INTO `sys_permission` VALUES ('25', '22', '删除', '', '', '2', 'articles:del', '100'); -INSERT INTO `sys_permission` VALUES ('26', '0', '日志查询', 'fa-reorder', 'pages/log/logList.html', '1', 'sys:log:query', '100'); -INSERT INTO `sys_permission` VALUES ('27', '0', '邮件管理', 'fa-envelope', 'pages/mail/mailList.html', '1', '', '100'); +INSERT INTO `sys_permission` VALUES ('26', '0', '日志查询', 'fa-reorder', 'pages/log/logList.html', '1', 'sys:log:query', '13'); +INSERT INTO `sys_permission` VALUES ('27', '0', '邮件管理', 'fa-envelope', 'pages/mail/mailList.html', '1', '', '14'); INSERT INTO `sys_permission` VALUES ('28', '27', '发送邮件', '', '', '2', 'mail:send', '100'); INSERT INTO `sys_permission` VALUES ('29', '27', '查询', '', '', '2', 'mail:all:query', '100'); +INSERT INTO `sys_permission` VALUES ('30', '0', '定时任务管理', 'fa-tasks', 'pages/job/jobList.html', '1', '', '15'); +INSERT INTO `sys_permission` VALUES ('31', '30', '查询', '', '', '2', 'job:query', '100'); +INSERT INTO `sys_permission` VALUES ('32', '30', '新增', '', '', '2', 'job:add', '100'); +INSERT INTO `sys_permission` VALUES ('33', '30', '删除', '', '', '2', 'job:del', '100'); -- ---------------------------- -- Table structure for sys_role @@ -392,6 +396,10 @@ INSERT INTO `sys_role_permission` VALUES ('1', '26'); INSERT INTO `sys_role_permission` VALUES ('1', '27'); INSERT INTO `sys_role_permission` VALUES ('1', '28'); INSERT INTO `sys_role_permission` VALUES ('1', '29'); +INSERT INTO `sys_role_permission` VALUES ('1', '30'); +INSERT INTO `sys_role_permission` VALUES ('1', '31'); +INSERT INTO `sys_role_permission` VALUES ('1', '32'); +INSERT INTO `sys_role_permission` VALUES ('1', '33'); INSERT INTO `sys_role_permission` VALUES ('2', '1'); INSERT INTO `sys_role_permission` VALUES ('2', '2'); INSERT INTO `sys_role_permission` VALUES ('2', '3'); @@ -415,6 +423,8 @@ INSERT INTO `sys_role_permission` VALUES ('2', '22'); INSERT INTO `sys_role_permission` VALUES ('2', '23'); INSERT INTO `sys_role_permission` VALUES ('2', '24'); INSERT INTO `sys_role_permission` VALUES ('2', '25'); +INSERT INTO `sys_role_permission` VALUES ('2', '30'); +INSERT INTO `sys_role_permission` VALUES ('2', '31'); -- ---------------------------- -- Table structure for sys_role_user @@ -479,6 +489,25 @@ CREATE TABLE `t_mail` ( -- Records of t_mail -- ---------------------------- +-- ---------------------------- +-- Table structure for t_job +-- ---------------------------- +DROP TABLE IF EXISTS `t_job`; +CREATE TABLE `t_job` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `jobName` varchar(64) NOT NULL, + `description` varchar(255) DEFAULT NULL, + `cron` varchar(64) NOT NULL, + `springBeanName` varchar(64) NOT NULL COMMENT 'springBean名', + `methodName` varchar(64) NOT NULL COMMENT '方法名', + `isSysJob` tinyint(1) NOT NULL COMMENT '是否是系统job', + `status` tinyint(1) NOT NULL DEFAULT '1', + `createTime` datetime NOT NULL, + `updateTime` datetime NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `jobName` (`jobName`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; + -- ---------------------------- -- Table structure for t_mail_to -- ---------------------------- diff --git a/src/main/java/com/zw/admin/server/config/JobConfig.java b/src/main/java/com/zw/admin/server/config/JobConfig.java index c0933b0a68965bd3db1ad9cda4bf36584cd8481b..f9343069a7dfcbc7333a83c0877cb1c30d3162b2 100644 --- a/src/main/java/com/zw/admin/server/config/JobConfig.java +++ b/src/main/java/com/zw/admin/server/config/JobConfig.java @@ -2,18 +2,18 @@ package com.zw.admin.server.config; import java.io.IOException; +import javax.annotation.PostConstruct; import javax.sql.DataSource; -import org.quartz.Trigger; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.support.PropertiesLoaderUtils; -import org.springframework.scheduling.quartz.CronTriggerFactoryBean; -import org.springframework.scheduling.quartz.JobDetailFactoryBean; import org.springframework.scheduling.quartz.SchedulerFactoryBean; -import com.zw.admin.server.job.DeleteLogJob; +import com.zw.admin.server.model.JobModel; +import com.zw.admin.server.service.JobService; @Configuration public class JobConfig { @@ -34,28 +34,26 @@ public class JobConfig { quartzScheduler.setOverwriteExistingJobs(true); quartzScheduler.setApplicationContextSchedulerContextKey(KEY); - Trigger[] triggers = { deleteLogTrigger().getObject() }; - quartzScheduler.setTriggers(triggers); - return quartzScheduler; } - @Bean - public JobDetailFactoryBean deleteLogJob() { - JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean(); - jobDetailFactory.setJobClass(DeleteLogJob.class); - jobDetailFactory.setDurability(true); - jobDetailFactory.setDescription("定时删除三个月前日志"); - - return jobDetailFactory; - } - - @Bean - public CronTriggerFactoryBean deleteLogTrigger() { - CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean(); - cronTriggerFactoryBean.setJobDetail(deleteLogJob().getObject()); - cronTriggerFactoryBean.setCronExpression("0 0 0 * * ?"); - return cronTriggerFactoryBean; + @Autowired + private JobService jobService; + + /** + * 初始化一个定时删除日志的任务 + */ + @PostConstruct + public void initDeleteLogsJob() { + JobModel jobModel = new JobModel(); + jobModel.setJobName("delete-logs-job"); + jobModel.setCron("0 0 0 * * ?"); + jobModel.setDescription("定时删除三个月前日志"); + jobModel.setSpringBeanName("sysLogServiceImpl"); + jobModel.setMethodName("deleteLogs"); + jobModel.setIsSysJob(true); + + jobService.saveJob(jobModel); } } diff --git a/src/main/java/com/zw/admin/server/config/SwaggerConfig.java b/src/main/java/com/zw/admin/server/config/SwaggerConfig.java index 295ab18f8412c4919668e61a2ed2d4711d57a0d0..c8c5a061345a0c2c39d31d4e9bae81981478f712 100644 --- a/src/main/java/com/zw/admin/server/config/SwaggerConfig.java +++ b/src/main/java/com/zw/admin/server/config/SwaggerConfig.java @@ -60,6 +60,11 @@ public class SwaggerConfig { public Docket mailsDocket() { return docket("邮件", "/mails.*"); } + + @Bean("jobsDocket") + public Docket jobsDocket() { + return docket("定时任务", "/jobs.*"); + } private Docket docket(String title, String path) { Docket docket = new Docket(DocumentationType.SWAGGER_2) diff --git a/src/main/java/com/zw/admin/server/controller/JobController.java b/src/main/java/com/zw/admin/server/controller/JobController.java new file mode 100644 index 0000000000000000000000000000000000000000..26b9d206ee178405b9260106ba6b0805deaf45e7 --- /dev/null +++ b/src/main/java/com/zw/admin/server/controller/JobController.java @@ -0,0 +1,163 @@ +package com.zw.admin.server.controller; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.quartz.CronExpression; +import org.quartz.SchedulerException; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.zw.admin.server.annotation.LogAnnotation; +import com.zw.admin.server.dao.JobDao; +import com.zw.admin.server.model.JobModel; +import com.zw.admin.server.page.table.PageTableHandler; +import com.zw.admin.server.page.table.PageTableHandler.CountHandler; +import com.zw.admin.server.page.table.PageTableHandler.ListHandler; +import com.zw.admin.server.page.table.PageTableRequest; +import com.zw.admin.server.page.table.PageTableResponse; +import com.zw.admin.server.service.JobService; + +import io.swagger.annotations.ApiOperation; + +@RestController +@RequestMapping("/jobs") +public class JobController { + + @Autowired + private JobService jobService; + @Autowired + private JobDao jobDao; + + @LogAnnotation + @ApiOperation("添加定时任务") + @PostMapping + @RequiresPermissions("job:add") + public void add(@RequestBody JobModel jobModel) { + JobModel model = jobDao.getByName(jobModel.getJobName()); + if (model != null) { + throw new IllegalArgumentException(jobModel.getJobName() + "已存在"); + } + + jobModel.setIsSysJob(false); + jobService.saveJob(jobModel); + } + + @LogAnnotation + @ApiOperation("修改定时任务") + @PutMapping + @RequiresPermissions("job:add") + public void update(@RequestBody JobModel jobModel) { + jobModel.setStatus(1); + jobService.saveJob(jobModel); + } + + @LogAnnotation + @ApiOperation("删除定时任务") + @DeleteMapping("/{id}") + @RequiresPermissions("job:del") + public void delete(@PathVariable Long id) throws SchedulerException { + jobService.deleteJob(id); + } + + @ApiOperation("根据id获取定时任务") + @GetMapping("/{id}") + @RequiresPermissions("job:query") + public JobModel getById(@PathVariable Long id) { + return jobDao.getById(id); + } + + @GetMapping + @ApiOperation(value = "定时任务列表") + @RequiresPermissions("job:query") + public PageTableResponse list(PageTableRequest request) { + return PageTableHandler. builder().countHandler(new CountHandler() { + + @Override + public int count(PageTableRequest request) { + return jobDao.count(request.getParams()); + } + }).listHandler(new ListHandler() { + + @Override + public List list(PageTableRequest request) { + List list = jobDao.list(request.getParams(), request.getOffset(), request.getLimit()); + return list; + } + }).build().handle(request); + } + + @ApiOperation(value = "校验cron表达式") + @GetMapping(params = "cron") + public boolean checkCron(String cron) { + return CronExpression.isValidExpression(cron); + } + + @Autowired + private ApplicationContext applicationContext; + + @ApiOperation(value = "springBean名字") + @GetMapping("/beans") + public List listAllBeanName() { + String[] strings = applicationContext.getBeanDefinitionNames(); + List list = new ArrayList<>(); + for (String str : strings) { + if (str.contains(".")) { + continue; + } + + Class clazz = getClass(str); + if (clazz.isAssignableFrom(Controller.class) || clazz.isAnnotationPresent(RestController.class)) { + continue; + } + + list.add(str); + } + list.sort((l1, l2) -> l1.compareTo(l2)); + + return list; + } + + @ApiOperation(value = "springBean的无参方法") + @GetMapping("/beans/{name}") + public Set listMethodName(@PathVariable String name) { + Class clazz = getClass(name); + Method[] methods = clazz.getDeclaredMethods(); + + Set names = new HashSet<>(); + Arrays.asList(methods).parallelStream().forEach(m -> { + Class[] classes = m.getParameterTypes(); + if (classes.length == 0) { + names.add(m.getName()); + } + }); + + return names; + } + + private Class getClass(String name) { + Object object = applicationContext.getBean(name); + Class clazz = object.getClass(); + if (AopUtils.isAopProxy(object)) { + clazz = clazz.getSuperclass(); + } + + return clazz; + } + +} diff --git a/src/main/java/com/zw/admin/server/dao/JobDao.java b/src/main/java/com/zw/admin/server/dao/JobDao.java new file mode 100644 index 0000000000000000000000000000000000000000..a47deeb1e48b04cf47c970fedd9a53e3950cf179 --- /dev/null +++ b/src/main/java/com/zw/admin/server/dao/JobDao.java @@ -0,0 +1,33 @@ +package com.zw.admin.server.dao; + +import java.util.List; +import java.util.Map; + +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import com.zw.admin.server.model.JobModel; + +@Mapper +public interface JobDao { + + @Options(useGeneratedKeys = true, keyProperty = "id") + @Insert("insert into t_job(jobName, description, cron, springBeanName, methodName, isSysJob, status, createTime, updateTime) values(#{jobName}, #{description}, #{cron}, #{springBeanName}, #{methodName}, #{isSysJob}, 1, now(), now())") + int save(JobModel jobModel); + + @Select("select * from t_job t where t.id = #{id}") + JobModel getById(Long id); + + @Select("select * from t_job t where t.jobName = #{jobName}") + JobModel getByName(String jobName); + + int update(JobModel jobModel); + + int count(@Param("params") Map params); + + List list(@Param("params") Map params, @Param("offset") Integer offset, + @Param("limit") Integer limit); +} diff --git a/src/main/java/com/zw/admin/server/job/DeleteLogJob.java b/src/main/java/com/zw/admin/server/job/SpringBeanJob.java similarity index 70% rename from src/main/java/com/zw/admin/server/job/DeleteLogJob.java rename to src/main/java/com/zw/admin/server/job/SpringBeanJob.java index e74be1442dfb4f80d3170f56e14b0285774ea59c..4e227806c8758fbe66c2251b334b6a9a62aa194b 100644 --- a/src/main/java/com/zw/admin/server/job/DeleteLogJob.java +++ b/src/main/java/com/zw/admin/server/job/SpringBeanJob.java @@ -7,21 +7,20 @@ import org.springframework.context.ApplicationContext; import org.springframework.scheduling.quartz.QuartzJobBean; import com.zw.admin.server.config.JobConfig; -import com.zw.admin.server.service.SysLogService; +import com.zw.admin.server.service.JobService; -public class DeleteLogJob extends QuartzJobBean { +public class SpringBeanJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { try { ApplicationContext applicationContext = (ApplicationContext) context.getScheduler().getContext() .get(JobConfig.KEY); - SysLogService service = applicationContext.getBean(SysLogService.class); - service.deleteLogs(); + JobService jobService = applicationContext.getBean(JobService.class); + jobService.doJob(context.getJobDetail().getJobDataMap()); } catch (SchedulerException e) { e.printStackTrace(); } - } } diff --git a/src/main/java/com/zw/admin/server/model/JobModel.java b/src/main/java/com/zw/admin/server/model/JobModel.java new file mode 100644 index 0000000000000000000000000000000000000000..66acee46940c89be9fa89507a0e2536eaec93801 --- /dev/null +++ b/src/main/java/com/zw/admin/server/model/JobModel.java @@ -0,0 +1,26 @@ +package com.zw.admin.server.model; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class JobModel extends BaseEntity { + + private static final long serialVersionUID = -2458935535811207209L; + + private String jobName; + + private String description; + + private String cron; + + private String springBeanName; + + private String methodName; + + private Boolean isSysJob; + + private int status; + +} diff --git a/src/main/java/com/zw/admin/server/page/table/PageTableArgumentResolver.java b/src/main/java/com/zw/admin/server/page/table/PageTableArgumentResolver.java index 269cf434d95d11872a29643fb68e1abb14900e52..830f0a65a31bb73eb9e1b96b998b7f339673d407 100644 --- a/src/main/java/com/zw/admin/server/page/table/PageTableArgumentResolver.java +++ b/src/main/java/com/zw/admin/server/page/table/PageTableArgumentResolver.java @@ -5,6 +5,7 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.StringUtils; import org.springframework.core.MethodParameter; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; @@ -35,13 +36,12 @@ public class PageTableArgumentResolver implements HandlerMethodArgumentResolver PageTableRequest tableRequest = new PageTableRequest(); Map param = request.getParameterMap(); - - if (param.containsKey("limit")) { - tableRequest.setLimit(Integer.parseInt(request.getParameter("limit"))); + if (param.containsKey("start")) { + tableRequest.setOffset(Integer.parseInt(request.getParameter("start"))); } - if (param.containsKey("page")) { - int page = Integer.parseInt(request.getParameter("page")); - tableRequest.setOffset((page - 1) * tableRequest.getLimit()); + + if (param.containsKey("length")) { + tableRequest.setLimit(Integer.parseInt(request.getParameter("length"))); } Map map = Maps.newHashMap(); @@ -55,11 +55,32 @@ public class PageTableArgumentResolver implements HandlerMethodArgumentResolver } }); - if (map.containsKey("orderBy")) { - map.put("orderBy", " order by " + map.get("orderBy")); - } + setOrderBy(tableRequest, map); return tableRequest; } + private void setOrderBy(PageTableRequest tableRequest, Map map) { + StringBuilder orderBy = new StringBuilder(); + int size = map.size(); + for (int i = 0; i < size; i++) { + String index = (String) map.get("order[" + i + "][column]"); + if (StringUtils.isEmpty(index)) { + break; + } + String column = (String) map.get("columns[" + index + "][data]"); + if (StringUtils.isBlank(column)) { + continue; + } + String sort = (String) map.get("order[" + i + "][dir]"); + + orderBy.append(column).append(" ").append(sort).append(", "); + } + + if (orderBy.length() > 0) { + tableRequest.getParams().put("orderBy", + " order by " + StringUtils.substringBeforeLast(orderBy.toString(), ",")); + } + } + } diff --git a/src/main/java/com/zw/admin/server/page/table/PageTableHandler.java b/src/main/java/com/zw/admin/server/page/table/PageTableHandler.java index a462aa696c98ddbed1871cb9c4c4f2783e5bbb2e..0d05e70216d7d2140ca1507e247b62b1f5ca4005 100644 --- a/src/main/java/com/zw/admin/server/page/table/PageTableHandler.java +++ b/src/main/java/com/zw/admin/server/page/table/PageTableHandler.java @@ -13,6 +13,7 @@ import lombok.Builder; */ @Builder public class PageTableHandler { + private CountHandler countHandler; private ListHandler listHandler; @@ -29,7 +30,7 @@ public class PageTableHandler { list = new ArrayList(); } - return PageTableResponse. builder().count(count).code(0).data(list).build(); + return PageTableResponse. builder().recordsTotal(count).recordsFiltered(count).data(list).build(); } public interface ListHandler { diff --git a/src/main/java/com/zw/admin/server/page/table/PageTableResponse.java b/src/main/java/com/zw/admin/server/page/table/PageTableResponse.java index 592241fa4cf0aba103af24b42a54d7817b7b03db..671892db44fec1ce319dbf85c049234d2d7a2387 100644 --- a/src/main/java/com/zw/admin/server/page/table/PageTableResponse.java +++ b/src/main/java/com/zw/admin/server/page/table/PageTableResponse.java @@ -20,8 +20,8 @@ public class PageTableResponse implements Serializable { private static final long serialVersionUID = 620421858510718076L; - private Integer code; - private Integer count; + private Integer recordsTotal; + private Integer recordsFiltered; private List data; } \ No newline at end of file diff --git a/src/main/java/com/zw/admin/server/service/JobService.java b/src/main/java/com/zw/admin/server/service/JobService.java new file mode 100644 index 0000000000000000000000000000000000000000..b3d55bb11643c1ca151d4abeb3659a56fbadbdf6 --- /dev/null +++ b/src/main/java/com/zw/admin/server/service/JobService.java @@ -0,0 +1,15 @@ +package com.zw.admin.server.service; + +import org.quartz.JobDataMap; +import org.quartz.SchedulerException; + +import com.zw.admin.server.model.JobModel; + +public interface JobService { + + void saveJob(JobModel jobModel); + + void doJob(JobDataMap jobDataMap); + + void deleteJob(Long id) throws SchedulerException; +} diff --git a/src/main/java/com/zw/admin/server/service/impl/JobServiceImpl.java b/src/main/java/com/zw/admin/server/service/impl/JobServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..0c586be2772050f0a73aa05b24f12812cced5028 --- /dev/null +++ b/src/main/java/com/zw/admin/server/service/impl/JobServiceImpl.java @@ -0,0 +1,151 @@ +package com.zw.admin.server.service.impl; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.quartz.CronScheduleBuilder; +import org.quartz.CronTrigger; +import org.quartz.JobBuilder; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.TriggerBuilder; +import org.quartz.TriggerKey; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +import com.zw.admin.server.dao.JobDao; +import com.zw.admin.server.job.SpringBeanJob; +import com.zw.admin.server.model.JobModel; +import com.zw.admin.server.service.JobService; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "adminLogger") +@Service +public class JobServiceImpl implements JobService { + + @Autowired + private Scheduler scheduler; + @Autowired + private ApplicationContext applicationContext; + private static final String JOB_DATA_KEY = "JOB_DATA_KEY"; + @Autowired + private JobDao jobDao; + + @Override + public void saveJob(JobModel jobModel) { + checkJobModel(jobModel); + String name = jobModel.getJobName(); + + JobKey jobKey = JobKey.jobKey(name); + JobDetail jobDetail = JobBuilder.newJob(SpringBeanJob.class).storeDurably() + .withDescription(jobModel.getDescription()).withIdentity(jobKey).build(); + + jobDetail.getJobDataMap().put(JOB_DATA_KEY, jobModel); + + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobModel.getCron()); + CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(name).withSchedule(cronScheduleBuilder) + .forJob(jobKey).build(); + + try { + boolean exists = scheduler.checkExists(jobKey); + if (exists) { + scheduler.rescheduleJob(new TriggerKey(name), cronTrigger); + scheduler.addJob(jobDetail, true); + } else { + scheduler.scheduleJob(jobDetail, cronTrigger); + } + + JobModel model = jobDao.getByName(name); + if (model == null) { + jobDao.save(jobModel); + } else { + jobDao.update(jobModel); + } + } catch (SchedulerException e) { + log.error("新增或修改job异常", e); + } + } + + private void checkJobModel(JobModel jobModel) { + String springBeanName = jobModel.getSpringBeanName(); + boolean flag = applicationContext.containsBean(springBeanName); + if (!flag) { + throw new IllegalArgumentException("bean:" + springBeanName + "不存在,bean名如userServiceImpl,首字母小写"); + } + + Object object = applicationContext.getBean(springBeanName); + Class clazz = object.getClass(); + if (AopUtils.isAopProxy(object)) { + clazz = clazz.getSuperclass(); + } + + String methodName = jobModel.getMethodName(); + Method[] methods = clazz.getDeclaredMethods(); + + Set names = new HashSet<>(); + Arrays.asList(methods).parallelStream().forEach(m -> { + Class[] classes = m.getParameterTypes(); + if (classes.length == 0) { + names.add(m.getName()); + } + }); + + if (names.size() == 0) { + throw new IllegalArgumentException("该bean没有无参方法"); + } + + if (!names.contains(methodName)) { + throw new IllegalArgumentException("未找到无参方法" + methodName + ",该bean所有方法名为:" + names); + } + } + + @Override + public void doJob(JobDataMap jobDataMap) { + JobModel jobModel = (JobModel) jobDataMap.get(JOB_DATA_KEY); + + String beanName = jobModel.getSpringBeanName(); + String methodName = jobModel.getMethodName(); + Object object = applicationContext.getBean(beanName); + + try { + log.info("job:bean:{},方法名:{}", beanName, methodName); + Method method = object.getClass().getDeclaredMethod(methodName); + method.invoke(object); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 删除job + * + * @throws SchedulerException + */ + @Override + public void deleteJob(Long id) throws SchedulerException { + JobModel jobModel = jobDao.getById(id); + + if (jobModel.getIsSysJob() != null && jobModel.getIsSysJob()) { + throw new IllegalArgumentException("该job是系统任务,不能删除,因为此job是在代码里初始化的,删除该类job请先确保相关代码已经去除"); + } + + String jobName = jobModel.getJobName(); + JobKey jobKey = JobKey.jobKey(jobName); + + scheduler.pauseJob(jobKey); + scheduler.unscheduleJob(new TriggerKey(jobName)); + scheduler.deleteJob(jobKey); + + jobModel.setStatus(0); + jobDao.update(jobModel); + } + +} diff --git a/src/main/resources/mybatis-mappers/JobMapper.xml b/src/main/resources/mybatis-mappers/JobMapper.xml new file mode 100644 index 0000000000000000000000000000000000000000..345f5b73d0226c066cae2118471ab173934c67d9 --- /dev/null +++ b/src/main/resources/mybatis-mappers/JobMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + and t.description like concat('%', #{params.description}, '%') + + + and t.status = #{params.status} + + + + + + + + + + + update t_job t + + + description = #{description}, + + + cron = #{cron}, + + + springBeanName = #{springBeanName}, + + + methodName = #{methodName}, + + + status = #{status}, + + updateTime = now() + + where t.jobName = #{jobName} + + \ No newline at end of file diff --git a/src/main/resources/public/pages/article/articleList.html b/src/main/resources/public/pages/article/articleList.html index 5688ce20153cde757423cd3209adc99a8b69f8a9..b3ff3ef514fdec041039557e888f011c0aa2e066 100644 --- a/src/main/resources/public/pages/article/articleList.html +++ b/src/main/resources/public/pages/article/articleList.html @@ -3,6 +3,8 @@ Insert title here + + @@ -13,32 +15,23 @@
-
- - - - - - - - -
- - - - - - - - - -
- + +
+ title: + + 时间: + + + 状态: + + +
+
+ + +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+
+ + +
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/public/pages/job/jobList.html b/src/main/resources/public/pages/job/jobList.html new file mode 100644 index 0000000000000000000000000000000000000000..0388f6481561693dc7c5bded0d6578050fc686db --- /dev/null +++ b/src/main/resources/public/pages/job/jobList.html @@ -0,0 +1,172 @@ + + + + +Insert title here + + + + + +
+
+
+
+ + + + + +
+
+
+ 描述: + + + +
+
+
+ +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
idjob名cron表达式bean名方法名描述状态修改时间操作
+
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/public/pages/job/updateJob.html b/src/main/resources/public/pages/job/updateJob.html new file mode 100644 index 0000000000000000000000000000000000000000..e0312448245b9947b54ef9d9a5ee116dd41472bf --- /dev/null +++ b/src/main/resources/public/pages/job/updateJob.html @@ -0,0 +1,120 @@ + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+
+ + +
+
+
+ +
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/public/pages/log/logList.html b/src/main/resources/public/pages/log/logList.html index 367273c133b8a53dc935f41794e95353cb244797..d64804d13d1c43f1c4953e1bc6f6972c40a346d3 100644 --- a/src/main/resources/public/pages/log/logList.html +++ b/src/main/resources/public/pages/log/logList.html @@ -3,6 +3,8 @@ Insert title here + + @@ -14,31 +16,21 @@ @@ -48,10 +40,24 @@
-
-
- - - - - - - - -
- - - - - - - - - -
- + +
+ 昵称: + + 时间: + + + 状态: + + +
- + + + + + + + + + + + + + + + +
id昵称模块状态备注时间
+ - @@ -61,59 +67,11 @@ + + - - \ No newline at end of file diff --git a/src/main/resources/public/pages/mail/mailList.html b/src/main/resources/public/pages/mail/mailList.html index e98b052434266c5f6fe8ed0277e57aa3229aa5bb..cae067ae2b3144c1adf994b41af01136e4946343 100644 --- a/src/main/resources/public/pages/mail/mailList.html +++ b/src/main/resources/public/pages/mail/mailList.html @@ -3,6 +3,8 @@ Insert title here + + @@ -14,22 +16,14 @@
- - - - - - - -
- - - - - - - -
+
+ 标题: + + 时间: + + + +
@@ -44,8 +38,22 @@
-
-
+ + + + + + + + + + + + + + +
id标题内容时间操作
+
@@ -55,45 +63,13 @@ + + - \ No newline at end of file +init(); + \ No newline at end of file diff --git a/src/main/resources/public/pages/role/roleList.html b/src/main/resources/public/pages/role/roleList.html index d26e1617678160430211e7e7b9f0375a5327ab2a..b8944654d6a1765705c7ed89fdf2d3c7fd98a7fd 100644 --- a/src/main/resources/public/pages/role/roleList.html +++ b/src/main/resources/public/pages/role/roleList.html @@ -3,6 +3,8 @@ Insert title here + + @@ -16,10 +18,7 @@
角色: -
- -
- +
@@ -36,65 +35,78 @@
-
-
+ + + + + + + + + + + + + +
角色描述修改时间操作
+
- + + - \ No newline at end of file +init(); + \ No newline at end of file diff --git a/src/main/resources/public/pages/user/userList.html b/src/main/resources/public/pages/user/userList.html index 1fc3d78d3a527be7252bea97c70b7f0219f606d1..5981ac1367161a352c97c81d411d0e9dd2f907c3 100644 --- a/src/main/resources/public/pages/user/userList.html +++ b/src/main/resources/public/pages/user/userList.html @@ -3,6 +3,8 @@ Insert title here + + @@ -13,29 +15,21 @@
-
- - - - - - - -
- - - - - - - -
- + +
+ 用户名: + + 昵称: + + 状态: + + +
@@ -50,8 +44,23 @@
-
-
+ + + + + + + + + + + + + + + +
username昵称手机号邮箱状态操作
+
@@ -60,69 +69,75 @@ - + + - - \ No newline at end of file +init(); + \ No newline at end of file diff --git a/src/main/resources/static/js/my/job.js b/src/main/resources/static/js/my/job.js new file mode 100644 index 0000000000000000000000000000000000000000..4f6e6d79067857ad2bbe67b499133846c6fd4114 --- /dev/null +++ b/src/main/resources/static/js/my/job.js @@ -0,0 +1,72 @@ +function checkCron() { + var cron = $("#cron").val(); + if (cron != "") { + $.ajax({ + type : 'get', + url : '/jobs?cron=' + cron, + success : function(data) { + var msg = "正确"; + if (!data) { + msg = "cron表达式不对"; + } + layer.msg(msg, { + shift : -1, + time : 1000 + }, function() { + }); + } + }); + } else { + layer.msg("cron表达式不能为空", { + shift : -1, + time : 1000 + }, function() { + }); + } +} + +function initBeanNames() { + $.ajax({ + type : 'get', + url : '/jobs/beans', + async : false, + success : function(data) { + var select = $("#springBeanName"); + for (var i = 0; i < data.length; i++) { + var v = data[i]; + select.append("") + } + } + }); +} + +function showMethods() { + var val = $("#springBeanName").val(); + if (val == "") { + return; + } + + $.ajax({ + type : 'get', + url : '/jobs/beans/' + val, + async : false, + success : function(data) { + var select = $("#methodName"); + select.empty(); + if (data.length == 0) { + layer.msg(val + "没有无参方法", { + shift : -1, + time : 1000 + }, function() { + }); + + return; + } + + for (var i = 0; i < data.length; i++) { + var v = data[i]; + select.append("") + } + } + }); +} \ No newline at end of file