diff --git a/pom.xml b/pom.xml index f4937ac288fd1bf9b15008947c09d0b4e02fda73..4a8faa14ccf808b6a8c2efc03c8e75472ba7ea2d 100644 --- a/pom.xml +++ b/pom.xml @@ -207,7 +207,15 @@ 1.8 system ${basedir}/lib/ueditor-1.1.2.jar - + + + + + + org.quartz-scheduler + quartz + 2.2.1 + diff --git a/src/main/java/com/fc/test/common/listener/ConfigListener.java b/src/main/java/com/fc/test/common/listener/ConfigListener.java new file mode 100644 index 0000000000000000000000000000000000000000..4cc8e7ad5bce32fa0a385ede78dd8929447e86f0 --- /dev/null +++ b/src/main/java/com/fc/test/common/listener/ConfigListener.java @@ -0,0 +1,49 @@ +package com.fc.test.common.listener; + +import com.fc.test.quartz.QuartzScheduler; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; +import java.util.HashMap; +import java.util.Map; + +/** + * @Auther: Jan 橙寂 + * @Date: 2019-7-1 11:06 + * @Description: + * @Version: 1.0 + */ +@WebListener +public class ConfigListener implements ServletContextListener { + + @Autowired + private QuartzScheduler scheduler; + private static Map conf = new HashMap<>(); + + public static Map getConf() { + return conf; + } + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + conf.clear(); + } + + @Override + public void contextInitialized(ServletContextEvent evt) { + ServletContext sc = evt.getServletContext(); + + //项目发布,当前运行环境的绝对路径 + conf.put("realPath", sc.getRealPath("/").replaceFirst("/", "")); + + //servletContextPath,默认"" + conf.put("contextPath", sc.getContextPath()); + + //开启定时调度 + // scheduler.startJob(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/fc/test/controller/admin/QuartzController.java b/src/main/java/com/fc/test/controller/admin/QuartzController.java new file mode 100644 index 0000000000000000000000000000000000000000..9e6980a54b393b6656c5fe62ae64856cd0821f48 --- /dev/null +++ b/src/main/java/com/fc/test/controller/admin/QuartzController.java @@ -0,0 +1,91 @@ +package com.fc.test.controller.admin; + +import com.fc.test.common.base.BaseController; +import com.fc.test.model.custom.TitleVo; +import com.fc.test.quartz.QuartzScheduler; +import io.swagger.annotations.Api; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@Api(value = "任务调度类") +@RequestMapping("quartz") +/** + * @Auther: Jan 橙寂 + * @Date: 2019-7-1 11:06 + * @Description: + * @Version: 1.0 + */ +public class QuartzController extends BaseController{ + + + @Autowired + private QuartzScheduler scheduler; + + + /** + * 调用这个方法开启任务调度 + * @param model + * @return + */ + @GetMapping("start") + @ResponseBody + public String start(Model model) + { + scheduler.startJob(); + return "success"; + } + + + /** + * 调用这个方法停止任务调度 + * @param model + * @return + */ + @GetMapping("stop") + @ResponseBody + public Object stop(Model model,String taskName,String groupName) + { + return scheduler.pauseJob(taskName,groupName); + + } + + + /** + * 调用这个方法继续任务调度 + * @param model + * @return + */ + @GetMapping("resume") + @ResponseBody + public Object resume(Model model,String taskName,String groupName) + { + return scheduler.resumeJob(taskName,groupName); + + } + + + /** + * 修改定时器 + * @param model + * @return + */ + @GetMapping("update") + @ResponseBody + public String update(Model model,String taskName,String groupName,String cron) + { + try { + scheduler.modifyJob(taskName,groupName,cron); + } catch (SchedulerException e) { + e.printStackTrace(); + return "fail"; + } + return "success"; + } + +} diff --git a/src/main/java/com/fc/test/quartz/QuartzConfig.java b/src/main/java/com/fc/test/quartz/QuartzConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..02ed832cafcd8ecb9fcc27b30f64e1230f4c05a9 --- /dev/null +++ b/src/main/java/com/fc/test/quartz/QuartzConfig.java @@ -0,0 +1,29 @@ +package com.fc.test.quartz; + +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SchedulerFactory; +import org.quartz.impl.StdSchedulerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @CLASSNAME QuartzConfig + * @Description Quartz配置类 + * @Auther Jan 橙寂 + * @DATE 2019/9/2 0002 15:21 + */ +@Configuration +public class QuartzConfig { + + /** + * 初始注入scheduler + * @return + * @throws SchedulerException + */ + @Bean + public Scheduler scheduler() throws SchedulerException{ + SchedulerFactory schedulerFactoryBean = new StdSchedulerFactory(); + return schedulerFactoryBean.getScheduler(); + } +} diff --git a/src/main/java/com/fc/test/quartz/QuartzDefault.java b/src/main/java/com/fc/test/quartz/QuartzDefault.java new file mode 100644 index 0000000000000000000000000000000000000000..bcc2419c20888ecc323451b9dd2705939390690a --- /dev/null +++ b/src/main/java/com/fc/test/quartz/QuartzDefault.java @@ -0,0 +1,81 @@ +package com.fc.test.quartz; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Scheduled; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * @CLASSNAME QuartzDefault + * @Description springboot 默认的定时调度配置(不需要任何包)但是不能动态的开启(关闭)或者添加 任务 + * @Auther Jan 橙寂 + * @DATE 2019/9/2 0002 14:46 + */ +@Configuration +//@EnableScheduling //开启定时调度的开关 +public class QuartzDefault { + + + //配置表达式 现在这个是每一分钟执行一次 + @Scheduled(cron = "0 0/1 * * * *") + public void timer(){ + //获取当前时间 + LocalDateTime localDateTime = LocalDateTime.now(); + System.out.println("当前时间为:" + localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + } + + + /*按顺序依次为 + 1 秒(0~59) + 2 分钟(0~59) + 3 小时(0~23) + 4 天(0~31) + 5 月(0~11) + 6 星期(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT) + 7.年份(1970-2099) + 其中每个元素可以是一个值(如6),一个连续区间(9-12),一个间隔时间(8-18/4)(/表示每隔4小时),一个列表(1,3,5),通配符。由于"月份中的日期"和"星期中的日期"这两个元素互斥的,必须要对其中一个设置?. + 0 0 10,14,16 * * ? 每天上午10点,下午2点,4点 + 0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时 + 0 0 12 ? * WED 表示每个星期三中午12点 + "0 0 12 * * ?" 每天中午12点触发 + "0 15 10 ? * *" 每天上午10:15触发 + "0 15 10 * * ?" 每天上午10:15触发 + "0 15 10 * * ? *" 每天上午10:15触发 + "0 15 10 * * ? 2005" 2005年的每天上午10:15触发 + "0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发 + "0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发 + "0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 + "0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发 + "0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发 + "0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发 + "0 15 10 15 * ?" 每月15日上午10:15触发 + "0 15 10 L * ?" 每月最后一日的上午10:15触发 + "0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发 + "0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发 + "0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发 + 有些子表达式能包含一些范围或列表 + 例如:子表达式(天(星期))可以为 “MON-FRI”,“MON,WED,FRI”,“MON-WED,SAT” + “*”字符代表所有可能的值 + “/”字符用来指定数值的增量 + 例如:在子表达式(分钟)里的“0/15”表示从第0分钟开始,每15分钟 + 在子表达式(分钟)里的“3/20”表示从第3分钟开始,每20分钟(它和“3,23,43”)的含义一样 + “?”字符仅被用于天(月)和天(星期)两个子表达式,表示不指定值 + 当2个子表达式其中之一被指定了值以后,为了避免冲突,需要将另一个子表达式的值设为“?” + “L” 字符仅被用于天(月)和天(星期)两个子表达式,它是单词“last”的缩写 + 如果在“L”前有具体的内容,它就具有其他的含义了。例如:“6L”表示这个月的倒数第6天 + 注意:在使用“L”参数时,不要指定列表或范围,因为这会导致问题 + W 字符代表着平日(Mon-Fri),并且仅能用于日域中。它用来指定离指定日的最近的一个平日。大部分的商业处理都是基于工作周的,所以 W 字符可能是非常重要的。 + 例如,日域中的 15W 意味着 "离该月15号的最近一个平日。" 假如15号是星期六,那么 trigger 会在14号(星期五)触发,因为星期四比星期一离15号更近。 + C:代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。 + 字段 允许值 允许的特殊字符 + 秒 0-59 , - * / + 分 0-59 , - * / + 小时 0-23 , - * / + 日期 1-31 , - * ? / L W C + 月份 1-12 或者 JAN-DEC , - * / + 星期 1-7 或者 SUN-SAT , - * ? / L C # + 年(可选) 留空, 1970-2099 , - * /*/ + + +} diff --git a/src/main/java/com/fc/test/quartz/QuartzScheduler.java b/src/main/java/com/fc/test/quartz/QuartzScheduler.java new file mode 100644 index 0000000000000000000000000000000000000000..4261b14c632cf85293fd4d33a85e7db748e268f0 --- /dev/null +++ b/src/main/java/com/fc/test/quartz/QuartzScheduler.java @@ -0,0 +1,150 @@ +package com.fc.test.quartz; + +import com.fc.test.quartz.job.TestQuartzJob; +import org.quartz.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +import java.util.Date; + +/** + * @CLASSNAME QuartzConfig + * @Description Quartz配置类 + * @Auther Jan 橙寂 + * @DATE 2019/9/2 0002 15:21 + */ +@Configuration +public class QuartzScheduler { + + @Autowired + private Scheduler scheduler; + + //这个东西可以放在配置文件中 + //cron表达式 一分钟执行一次 + private final String TEST_CRON="0 0/1 * * * ?"; + + /** + * 开始工作 + */ + public void startJob() + { + try { + initTestJob("test","test"); + scheduler.start(); + + } catch (SchedulerException e) { + e.printStackTrace(); + System.out.println("任务掉度开启失败"); + } + + } + + /** + * 初始化一个任务 + * @param taskName + * @param groupName + * @throws SchedulerException + */ + private void initTestJob(String taskName,String groupName) throws SchedulerException { + if (!checkJobExists(taskName,groupName)) { + // 通过JobBuilder构建JobDetail实例,JobDetail规定只能是实现Job接口的实例 + // JobDetail 是具体Job实例 + JobDetail jobDetail = JobBuilder.newJob(TestQuartzJob.class).withIdentity(taskName, groupName).build(); + // 基于表达式构建触发器 + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(TEST_CRON); + // CronTrigger表达式触发器 继承于Trigger + // TriggerBuilder 用于构建触发器实例 + CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(taskName, groupName) + .withSchedule(cronScheduleBuilder.withMisfireHandlingInstructionDoNothing()).build(); + scheduler.scheduleJob(jobDetail, cronTrigger); + } + } + + + + /** + * 修改某个任务的执行时间 + * + * @param name + * @param group + * @param cron 表达式 + * @return + * @throws SchedulerException + */ + public boolean modifyJob(String name, String group, String cron) throws SchedulerException { + Date date = null; + TriggerKey triggerKey = new TriggerKey(name, group); + CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey); + if (cronTrigger != null) { + String oldTime = cronTrigger.getCronExpression(); + if (!oldTime.equalsIgnoreCase(cron)) { + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cron); + CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group) + .withSchedule(cronScheduleBuilder).build(); + date = scheduler.rescheduleJob(triggerKey, trigger); + } + } + return date==null?false:true; + } + + + /** + * 继续执行定时任务 + * @param taskName + * @param groupName + * @return + */ + public boolean resumeJob(String taskName, String groupName) { + boolean bl = false; + try { + //JobKey定义了job的名称和组别 + JobKey jobKey = JobKey.jobKey(taskName, groupName); + if (jobKey != null) { + //继续任务 + scheduler.resumeJob(jobKey); + bl = true; + } + } catch (SchedulerException e) { + System.out.println("继续调度任务异常:" + e); + } catch (Exception e) { + System.out.println("继续调度任务异常:" + e); + } + return bl; + } + + /** + * 暂停任务 + * @param taskName + * @param groupName + * @return + */ + public boolean pauseJob(String taskName, String groupName) { + boolean bl = false; + try { + //JobKey定义了job的名称和组别 + JobKey jobKey = JobKey.jobKey(taskName, groupName); + //暂停任务 + if (jobKey != null) { + scheduler.pauseJob(jobKey); + bl = true; + } + } catch (SchedulerException e) { + // getLog().info("暂停调度任务异常:" + e); + } catch (Exception e) { + // getLog().info("暂停调度任务异常:"+ e); + } + return bl; + } + + /** + * 判断定时任务是否已经存在 + * @param taskName + * @param groupName + * @return + * @throws SchedulerException + */ + public boolean checkJobExists(String taskName, String groupName) throws SchedulerException { + TriggerKey triggerKey = TriggerKey.triggerKey(taskName, groupName); + return scheduler.checkExists(triggerKey); + } +} diff --git a/src/main/java/com/fc/test/quartz/job/TestQuartzJob.java b/src/main/java/com/fc/test/quartz/job/TestQuartzJob.java new file mode 100644 index 0000000000000000000000000000000000000000..4e84246c2c8481b707d7b470f6bb7f58b19d5013 --- /dev/null +++ b/src/main/java/com/fc/test/quartz/job/TestQuartzJob.java @@ -0,0 +1,22 @@ +package com.fc.test.quartz.job; + +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * @CLASSNAME TestQuartzJob + * @Description 定时调度具体工作类 + * @Auther Jan 橙寂 + * @DATE 2019/9/2 0002 15:33 + */ +@Component +public class TestQuartzJob implements Job { + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + System.out.println(new Date()+"测试定时调度正在执行"); + } +} diff --git a/src/main/java/com/fc/test/shiro/config/ShiroFilterMapFactory.java b/src/main/java/com/fc/test/shiro/config/ShiroFilterMapFactory.java index c6148318a2d7c9242ec4deea8ad7b4550d5cf1b5..c7f8cc1a04d7810382960535b18a8cefc7958a2c 100644 --- a/src/main/java/com/fc/test/shiro/config/ShiroFilterMapFactory.java +++ b/src/main/java/com/fc/test/shiro/config/ShiroFilterMapFactory.java @@ -48,6 +48,9 @@ user:例如/admins/user/**=user没有参数表示必须存在用户,当登入 filterChainDefinitionMap.put("/druid/**", "anon"); //释放websocket请求 filterChainDefinitionMap.put("/websocket", "anon"); + + //任务调度暂时放开 + filterChainDefinitionMap.put("/quartz/**", "anon"); // //对所有页面进行认证 diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 495f0f10351a058a2a2244495e4fee101ae252b8..f3a99e1730de936482edf72f2f9e90dbd402a001 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -2,7 +2,7 @@ spring : datasource : driverClassName : com.mysql.jdbc.Driver - url : jdbc:mysql://192.168.1.28:13306/springbootv2?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false + url : jdbc:mysql://localhost:3306/springbootv2?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false username : root password : root hikari: