list;
+ try {
+ DbUtil.setCaseInsensitiveGlobal(false);
+ String sql = "select * from usedList where date_add(EndTime, interval " + Constant.MIGRATE_DAY_NUM + " day) < now()";
+ Db testDb1 = Db.use("test_db1");
+ list = testDb1.query(sql);
+ if (null != list && !list.isEmpty()) {
+ list.forEach(entity -> {
+ try {
+ testDb1.del(
+ Entity.create("usedList").set("UsedInCrement", entity.get("UsedInCrement"))
+ );
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ entity.setTableName("usedList_pastDue");
+ });
+ Db.use("test_db2").insert(list);
+ } else {
+ System.out.println("查询数据为空");
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/QuartzManager/src/main/java/com/frost2/quartz/common/util/QuartzUtil.java b/QuartzManager/src/main/java/com/frost2/quartz/common/util/QuartzUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..c916e1b417b529051a4a6351b675339e15b5644f
--- /dev/null
+++ b/QuartzManager/src/main/java/com/frost2/quartz/common/util/QuartzUtil.java
@@ -0,0 +1,236 @@
+package com.frost2.quartz.common.util;
+
+import com.frost2.quartz.common.bean.Code;
+import com.frost2.quartz.common.customException.CustomException;
+import org.quartz.*;
+import org.quartz.impl.StdSchedulerFactory;
+import org.quartz.impl.matchers.GroupMatcher;
+import org.quartz.impl.triggers.CronTriggerImpl;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * @author 陈伟平
+ * @date 2020-9-17 15:38:43
+ */
+public class QuartzUtil {
+
+ private static final SchedulerFactory schedulerFactory = new StdSchedulerFactory();
+ private static final Scheduler scheduler;
+ private final static String groupName = "DEFAULT";
+
+ static {
+ try {
+ scheduler = schedulerFactory.getScheduler();
+ } catch (SchedulerException e) {
+ throw new CustomException(Code.EXECUTION_ERROR);
+ }
+ }
+
+ /**
+ * 传入:任务名称、触发器名称、任务描述、要执行的任务类、cron表达式创建定时任务,
+ * 返回是否创建成功
+ *
+ * 注:
+ * 在创建任务时未设置jobGroup和triggerGroup,Job创建后其均为默认值:DEFAULT,
+ * 因此新创建的任务的jobName和triggerName,均不能与之前任务的重复.
+ *
+ * @param jobName 任务名
+ * @param triggerName 触发器名
+ * @param description 对该任务的描述(非必须)
+ * @param jobClass 要执行的任务
+ * @param cron cron表达式
+ * @return true:创建Job成功,false:创建Job失败
+ */
+ public static boolean addJob(String jobName, String triggerName, String description,
+ Class jobClass, String cron) {
+ try {
+ JobDetail job = JobBuilder.newJob(jobClass)
+ .withIdentity(jobName, groupName)
+ .withDescription(description)
+ .build();
+
+ Trigger trigger = TriggerBuilder.newTrigger()
+ .withIdentity(triggerName, groupName)
+ .startNow()
+ .withSchedule(CronScheduleBuilder.cronSchedule(cron))
+ .build();
+ scheduler.scheduleJob(job, trigger); // 注册到调度器
+ scheduler.start(); // 开启调度器
+ return scheduler.isStarted();
+ } catch (Exception e) {
+ throw new CustomException(Code.EXECUTION_ERROR);
+ }
+ }
+
+ /**
+ * 修改一个任务的触发时间
+ *
+ * @param jobName 任务名称
+ * @param triggerName 触发器名
+ * @param cron cron表达式
+ * @return true:修改Job成功,false:修改Job失败
+ */
+ public static Boolean rescheduleJob(String jobName, String triggerName, String cron) {
+ try {
+ TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);
+ CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
+ if (trigger == null) {
+ return false;
+ }
+
+ checkJobNameAndTriggerName(jobName, trigger);
+
+ Date latestFireTime = new Date();
+ if (!trigger.getCronExpression().equalsIgnoreCase(cron)) {
+ trigger = TriggerBuilder.newTrigger()
+ .withIdentity(triggerName)
+ .startNow()
+ .withSchedule(CronScheduleBuilder.cronSchedule(cron))
+ .build();
+ //rescheduleJob()执行成功返回最近一次执行的时间,如果失败返回null
+ latestFireTime = scheduler.rescheduleJob(triggerKey, trigger);
+ }
+ return null != latestFireTime;
+ } catch (SchedulerException e) {
+ throw new CustomException(Code.EXECUTION_ERROR);
+ }
+ }
+
+ /**
+ * 根据jobName和triggerName删除该JOB
+ *
+ * @param jobName 任务名称
+ * @param triggerName 触发器名
+ * @return true:删除Job成功,false:删除Job失败
+ */
+ public static boolean removeJob(String jobName, String triggerName) {
+ boolean flag;
+ try {
+
+ Trigger trigger = scheduler.getTrigger(new TriggerKey(triggerName));
+ if (null == trigger) {
+ return false;
+ }
+
+ checkJobNameAndTriggerName(jobName, trigger);
+
+ TriggerKey triggerKey = trigger.getKey();
+ scheduler.pauseTrigger(triggerKey);
+ flag = scheduler.unscheduleJob(triggerKey);
+
+ } catch (SchedulerException e) {
+ throw new CustomException(Code.EXECUTION_ERROR);
+ }
+ return flag;
+ }
+
+ /**
+ * 根据jobName和triggerName查询该JOB
+ *
+ * @param jobName 任务名称
+ * @param triggerName 触发器名
+ * @return 该Job相关信息[详见getJobInfo方法]
+ */
+ public static HashMap getJob(String jobName, String triggerName) {
+ try {
+ JobDetail jobDetail = scheduler.getJobDetail(new JobKey(jobName));
+ CronTrigger trigger = (CronTrigger) scheduler.getTrigger(new TriggerKey(triggerName));
+
+ if (null == jobDetail || null == trigger) {
+ return new HashMap<>();
+ }
+
+ checkJobNameAndTriggerName(jobName, trigger);
+
+ return getJobInfo(jobDetail, trigger);
+ } catch (SchedulerException e) {
+ throw new CustomException(Code.EXECUTION_ERROR);
+ }
+ }
+
+ /**
+ * 查询所有正在执行的JOB
+ *
+ * @return 该Job相关信息[详见getJobInfo方法]
+ */
+ public static List> getJobs() {
+ List> list = new ArrayList<>();
+ try {
+ List triggerGroupNames = scheduler.getTriggerGroupNames();
+ for (String groupName : triggerGroupNames) {
+
+ GroupMatcher groupMatcher = GroupMatcher.groupEquals(groupName);
+ //获取所有的triggerKey
+ Set triggerKeySet = scheduler.getTriggerKeys(groupMatcher);
+ for (TriggerKey triggerKey : triggerKeySet) {
+ //获取CronTrigger
+ CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
+ //获取trigger对应的JobDetail
+ JobDetail jobDetail = scheduler.getJobDetail(trigger.getJobKey());
+
+ list.add(getJobInfo(jobDetail, trigger));
+ }
+ }
+ } catch (SchedulerException e) {
+ throw new CustomException(Code.EXECUTION_ERROR);
+ }
+ return list;
+ }
+
+ /**
+ * @param cron cron表达式
+ * @return 最近5次的执行时间
+ */
+ public static List getRecentTriggerTime(String cron) {
+ List list = new ArrayList<>();
+ try {
+ CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
+ cronTriggerImpl.setCronExpression(cron);
+ List dateList = TriggerUtils.computeFireTimes(cronTriggerImpl, null, 5);
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ dateList.forEach(date -> list.add(dateFormat.format(date)));
+ } catch (ParseException e) {
+ throw new CustomException(Code.EXECUTION_ERROR);
+ }
+ return list;
+ }
+
+ /**
+ * 校验cron表达式是否正确
+ *
+ * @param cronExpression cron表达式
+ * @return true:正确,false:不正确
+ */
+ @SuppressWarnings("all")
+ public static boolean checkCronExpression(String cronExpression) {
+ return CronExpression.isValidExpression(cronExpression);
+ }
+
+ /**
+ * 获取该Job对应的相关信息
+ */
+ private static HashMap getJobInfo(JobDetail jobDetail, CronTrigger trigger) {
+ HashMap map = new HashMap<>();
+ map.put("jobName", jobDetail.getKey().getName());
+ map.put("jobGroup", jobDetail.getKey().getGroup());
+ map.put("corn", trigger.getCronExpression());
+ map.put("triggerName", trigger.getKey().getName());
+ map.put("description", jobDetail.getDescription());
+ return map;
+ }
+
+ /**
+ * 校验jobName和triggerName是否匹配
+ * 如不匹配抛出自定义异常
+ */
+ private static void checkJobNameAndTriggerName(String jobName, Trigger trigger) {
+ String name = trigger.getJobKey().getName();
+ if (!name.equals(jobName)) {
+ throw new CustomException(Code.PARAM_FORMAT_ERROR.getCode(), "jobName与triggerName不匹配");
+ }
+ }
+
+}
diff --git a/QuartzManager/src/main/java/com/frost2/quartz/common/util/ResultUtil.java b/QuartzManager/src/main/java/com/frost2/quartz/common/util/ResultUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdf2d41993eff9edd25b56d4f6888f712ded1dac
--- /dev/null
+++ b/QuartzManager/src/main/java/com/frost2/quartz/common/util/ResultUtil.java
@@ -0,0 +1,129 @@
+package com.frost2.quartz.common.util;
+
+import com.frost2.quartz.common.bean.Code;
+import com.frost2.quartz.common.bean.Result;
+import com.frost2.quartz.common.bean.ResultList;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author 陈伟平
+ * @date 2020-03-30-下午 3:21
+ */
+public class ResultUtil {
+
+ /**
+ * 增加行数如果为null或者0则表示删除失败
+ *
+ * @param row 行数
+ */
+ public static ResultList verifyDelete(Integer row) {
+ if (null == row || row == 0) {
+ return new ResultList(Code.DELETE_NULL.getCode(), Code.DELETE_NULL.getMsg(), null);
+ } else {
+ return new ResultList(Code.DELETE_SUCCESS.getCode(), Code.DELETE_SUCCESS.getMsg(), null);
+ }
+ }
+
+ /**
+ * 根据flag判断是否删除成功
+ *
+ * @param flag true:删除成功,false:删除失败
+ */
+ public static ResultList verifyDelete(boolean flag) {
+ if (flag) {
+ return new ResultList(Code.DELETE_SUCCESS.getCode(), Code.DELETE_SUCCESS.getMsg(), null);
+ } else {
+ return new ResultList(Code.DELETE_FAIL.getCode(), Code.DELETE_FAIL.getMsg(), null);
+ }
+ }
+
+ /**
+ * 根据flag判断是否更新成功
+ *
+ * @param flag true:更新成功,false:更新失败
+ */
+ public static ResultList verifyUpdate(boolean flag) {
+ if (flag) {
+ return new ResultList(Code.UPDATE_SUCCESS.getCode(), Code.UPDATE_SUCCESS.getMsg(), null);
+ } else {
+ return new ResultList(Code.UPDATE_NULL.getCode(), Code.UPDATE_NULL.getMsg(), null);
+ }
+ }
+
+ /**
+ * 更新行数如果为null或者0则表示更新失败
+ *
+ * @param row 行数
+ */
+ public static ResultList verifyUpdate(Integer row) {
+ if (null == row || row == 0) {
+ return new ResultList(Code.UPDATE_NULL.getCode(), Code.UPDATE_NULL.getMsg(), null);
+ } else {
+ return new ResultList(Code.UPDATE_SUCCESS.getCode(), Code.UPDATE_SUCCESS.getMsg(), null);
+ }
+ }
+
+ /**
+ * 添加行数如果为null或者0则表示更新失败
+ *
+ * @param row 行数
+ */
+ public static ResultList verifyAdd(Integer row) {
+ if (null == row || row == 0) {
+ return new ResultList(Code.ADD_FAIL.getCode(), Code.ADD_FAIL.getMsg(), null);
+ } else {
+ return new ResultList(Code.ADD_SUCCESS.getCode(), Code.ADD_SUCCESS.getMsg(), null);
+ }
+ }
+
+ /**
+ * 更新行数如果为null或者0则表示更新失败
+ *
+ * @param row 行数
+ */
+ public static ResultList verifyQuery(List> list, Integer row) {
+ if (null == list || list.isEmpty()) {
+ return new ResultList(Code.QUERY_NULL.getCode(), Code.QUERY_NULL.getMsg(), null);
+ } else {
+ if (null == row || row == 0) {
+ return new ResultList(Code.EXECUTION_ERROR.getCode(), Code.EXECUTION_ERROR.getMsg(), null);
+ } else {
+ return new ResultList(Code.QUERY_SUCCESS.getCode(), Code.QUERY_SUCCESS.getMsg(), new Result<>(row, list));
+ }
+ }
+ }
+
+ /**
+ * @param map 返回数据
+ */
+ public static ResultList verifyQuery(Map map) {
+ if (null == map || map.isEmpty()) {
+ return new ResultList(Code.QUERY_NULL.getCode(), Code.QUERY_NULL.getMsg(), null);
+ } else {
+ return new ResultList(Code.QUERY_SUCCESS.getCode(), Code.QUERY_SUCCESS.getMsg(), new Result<>(map.size(), map));
+ }
+ }
+
+ /**
+ * 返回code对应的响应码和响应信息
+ *
+ * @param code 响应码
+ */
+ public static ResultList execute(Code code) {
+ return new ResultList(code.getCode(), code.getMsg(), null);
+ }
+
+ /**
+ * 返回code对应的响应码和传递的响应信息
+ *
+ * @param code 响应码
+ * @param respMsg 对应的响应信息
+ */
+ public static ResultList execute(Code code, String respMsg) {
+ return new ResultList(code.getCode(), respMsg, null);
+ }
+
+
+}
diff --git a/QuartzManager/src/main/java/com/frost2/quartz/controller/TimedTaskController.java b/QuartzManager/src/main/java/com/frost2/quartz/controller/TimedTaskController.java
new file mode 100644
index 0000000000000000000000000000000000000000..de5b840eb65c6e80c13aabbe803eab21996df68e
--- /dev/null
+++ b/QuartzManager/src/main/java/com/frost2/quartz/controller/TimedTaskController.java
@@ -0,0 +1,77 @@
+package com.frost2.quartz.controller;
+
+import com.frost2.quartz.common.bean.ResultList;
+import com.frost2.quartz.service.IHelloService;
+import com.frost2.quartz.service.IMigrateUsedList;
+import com.frost2.quartz.service.ITimedTaskService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * @author 陈伟平
+ * @date 2020-9-19 09:20:32
+ */
+@RestController
+@Api(tags = "定时任务接口")
+@RequestMapping(value = "timed")
+public class TimedTaskController {
+
+ @Resource
+ ITimedTaskService timedTaskServiceImpl;
+
+ @Resource
+ IMigrateUsedList migrateUsedListImpl;
+
+ @Resource
+ IHelloService helloServiceImpl;
+
+ @ApiOperation(value = "迁移历史订单数据定时任务", httpMethod = "POST")
+ @PostMapping(value = "/migrateUsedList")
+ public ResultList migrateUsedList(@RequestParam String jobName,
+ @RequestParam String triggerName,
+ @RequestParam String cron) {
+ return migrateUsedListImpl.migrateUsedList(jobName, triggerName, cron);
+ }
+
+ @ApiOperation(value = "定时任务测试", httpMethod = "POST")
+ @PostMapping(value = "/hello")
+ public ResultList helloTest(@RequestParam String jobName,
+ @RequestParam String triggerName,
+ @RequestParam String cron) {
+ return helloServiceImpl.HelloTest(jobName, triggerName, cron);
+ }
+
+ @ApiOperation(value = "查询所有定时任务", httpMethod = "GET")
+ @GetMapping(value = "/job")
+ public ResultList queryAllTask() {
+ return timedTaskServiceImpl.queryAllTask();
+ }
+
+ @ApiOperation(value = "查询定时任务", httpMethod = "GET")
+ @GetMapping(value = "/job/{jobName}/{triggerName}")
+ public ResultList queryTimedTask(@PathVariable String jobName, @PathVariable String triggerName) {
+ return timedTaskServiceImpl.queryTimedTask(jobName, triggerName);
+ }
+
+ @ApiOperation(value = "查询最近5次执行时间", httpMethod = "GET")
+ @GetMapping(value = "/job/{cron}")
+ public ResultList queryAllTask(@PathVariable String cron) {
+ return timedTaskServiceImpl.getRecentTriggerTime(cron);
+ }
+
+ @ApiOperation(value = "删除定时任务", httpMethod = "DELETE")
+ @DeleteMapping(value = "/job/{jobName}/{triggerName}")
+ public ResultList delTimedTask(@PathVariable String jobName, @PathVariable String triggerName) {
+ return timedTaskServiceImpl.delTimedTask(jobName, triggerName);
+ }
+
+ @ApiOperation(value = "修改定时任务执行时间", httpMethod = "POST")
+ @PostMapping(value = "/job/{jobName}/{triggerName}/{cron}")
+ public ResultList rescheduleJob(@PathVariable String jobName, @PathVariable String triggerName, @PathVariable String cron) {
+ return timedTaskServiceImpl.rescheduleJob(jobName, triggerName, cron);
+ }
+}
diff --git a/QuartzManager/src/main/java/com/frost2/quartz/service/IHelloService.java b/QuartzManager/src/main/java/com/frost2/quartz/service/IHelloService.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b237084863e3a7b9e9a92cfa606b519a52b865a
--- /dev/null
+++ b/QuartzManager/src/main/java/com/frost2/quartz/service/IHelloService.java
@@ -0,0 +1,12 @@
+package com.frost2.quartz.service;
+
+import com.frost2.quartz.common.bean.ResultList;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/15 14:11
+ * @Version 1.0
+ */
+public interface IHelloService {
+ ResultList HelloTest(String jobName, String triggerName, String cron);
+}
diff --git a/QuartzManager/src/main/java/com/frost2/quartz/service/IMigrateUsedList.java b/QuartzManager/src/main/java/com/frost2/quartz/service/IMigrateUsedList.java
new file mode 100644
index 0000000000000000000000000000000000000000..fbec3cd9a3ff6f996fab8c7ef9188de4736eeee4
--- /dev/null
+++ b/QuartzManager/src/main/java/com/frost2/quartz/service/IMigrateUsedList.java
@@ -0,0 +1,13 @@
+package com.frost2.quartz.service;
+
+
+import com.frost2.quartz.common.bean.ResultList;
+
+/**
+ * @author 陈伟平
+ * @date 2020-9-19 15:34:56
+ */
+public interface IMigrateUsedList {
+
+ ResultList migrateUsedList(String jobName, String triggerName, String cron);
+}
diff --git a/QuartzManager/src/main/java/com/frost2/quartz/service/ITimedTaskService.java b/QuartzManager/src/main/java/com/frost2/quartz/service/ITimedTaskService.java
new file mode 100644
index 0000000000000000000000000000000000000000..30474419703049d5f8cd571beb51b1ee991b6661
--- /dev/null
+++ b/QuartzManager/src/main/java/com/frost2/quartz/service/ITimedTaskService.java
@@ -0,0 +1,21 @@
+package com.frost2.quartz.service;
+
+
+import com.frost2.quartz.common.bean.ResultList;
+
+/**
+ * @author 陈伟平
+ * @date 2020-9-19 09:34:54
+ */
+public interface ITimedTaskService {
+
+ ResultList queryTimedTask(String jobName, String triggerName);
+
+ ResultList delTimedTask(String jobName, String triggerName);
+
+ ResultList queryAllTask();
+
+ ResultList getRecentTriggerTime(String cron);
+
+ ResultList rescheduleJob(String jobName, String triggerName, String cron);
+}
diff --git a/QuartzManager/src/main/java/com/frost2/quartz/service/impl/HelloServiceImpl.java b/QuartzManager/src/main/java/com/frost2/quartz/service/impl/HelloServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..acd53f239468cb9b6162756b8a988f56f57b7f5c
--- /dev/null
+++ b/QuartzManager/src/main/java/com/frost2/quartz/service/impl/HelloServiceImpl.java
@@ -0,0 +1,30 @@
+package com.frost2.quartz.service.impl;
+
+import com.frost2.quartz.common.bean.Code;
+import com.frost2.quartz.common.bean.ResultList;
+import com.frost2.quartz.common.job.HelloJob;
+import com.frost2.quartz.common.util.QuartzUtil;
+import com.frost2.quartz.common.util.ResultUtil;
+import com.frost2.quartz.service.IHelloService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/15 14:19
+ * @Version 1.0
+ */
+@Service
+public class HelloServiceImpl implements IHelloService {
+ @Override
+ public ResultList HelloTest(String jobName, String triggerName, String cron) {
+ if (!QuartzUtil.checkCronExpression(cron)) {
+ return ResultUtil.execute(Code.PARAM_FORMAT_ERROR, "cron解析错误");
+ }
+ String description = "HelloWorld测试";
+ boolean isStart = QuartzUtil.addJob(jobName, triggerName, description, HelloJob.class, cron);
+ if (isStart) {
+ return ResultUtil.execute(Code.SUCC);
+ }
+ return ResultUtil.execute(Code.FAIL);
+ }
+}
diff --git a/QuartzManager/src/main/java/com/frost2/quartz/service/impl/MigratedUsedListImpl.java b/QuartzManager/src/main/java/com/frost2/quartz/service/impl/MigratedUsedListImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a84041eac4c1441c50557e652cb4f766d2e261d
--- /dev/null
+++ b/QuartzManager/src/main/java/com/frost2/quartz/service/impl/MigratedUsedListImpl.java
@@ -0,0 +1,38 @@
+package com.frost2.quartz.service.impl;
+
+import com.frost2.quartz.common.bean.Code;
+import com.frost2.quartz.common.bean.ResultList;
+import com.frost2.quartz.common.job.MigrateUsedList;
+import com.frost2.quartz.common.util.QuartzUtil;
+import com.frost2.quartz.common.util.ResultUtil;
+import com.frost2.quartz.service.IMigrateUsedList;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/15 14:18
+ * @Version 1.0
+ */
+@Service
+public class MigratedUsedListImpl implements IMigrateUsedList {
+ /**
+ * 定时将历史订单的数据迁移到备份数据库
+ *
+ * @param jobName 任务名称
+ * @param triggerName 触发器名称
+ * @param cron cron表达式
+ */
+ @Override
+ public ResultList migrateUsedList(String jobName, String triggerName, String cron) {
+ if (!QuartzUtil.checkCronExpression(cron)) {
+ return ResultUtil.execute(Code.PARAM_FORMAT_ERROR, "cron解析错误");
+ }
+ String description = "将90天以前的历史订单迁移到xiaoJi_bak";
+ boolean isStart = QuartzUtil.addJob(jobName, triggerName, description, MigrateUsedList.class, cron);
+ if (isStart) {
+ return ResultUtil.execute(Code.SUCC);
+ }
+ return ResultUtil.execute(Code.FAIL);
+
+ }
+}
diff --git a/QuartzManager/src/main/java/com/frost2/quartz/service/impl/TimedTaskServiceImpl.java b/QuartzManager/src/main/java/com/frost2/quartz/service/impl/TimedTaskServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..604b9ca9b4c5ec4f1d1a11bfb7da274b674c500b
--- /dev/null
+++ b/QuartzManager/src/main/java/com/frost2/quartz/service/impl/TimedTaskServiceImpl.java
@@ -0,0 +1,86 @@
+package com.frost2.quartz.service.impl;
+
+import com.frost2.quartz.common.bean.Code;
+import com.frost2.quartz.common.bean.Result;
+import com.frost2.quartz.common.bean.ResultList;
+import com.frost2.quartz.common.job.HelloJob;
+import com.frost2.quartz.common.job.MigrateUsedList;
+import com.frost2.quartz.common.util.QuartzUtil;
+import com.frost2.quartz.common.util.ResultUtil;
+import com.frost2.quartz.service.IHelloService;
+import com.frost2.quartz.service.IMigrateUsedList;
+import com.frost2.quartz.service.ITimedTaskService;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author 陈伟平
+ * @date 2020-9-19 09:24:07
+ */
+@Service
+public class TimedTaskServiceImpl implements ITimedTaskService {
+
+ /**
+ * 查询正在运行的定时任务
+ *
+ * @param jobName 任务名称
+ * @param triggerName 触发器名
+ * @return JobDetail
+ */
+ @Override
+ public ResultList queryTimedTask(String jobName, String triggerName) {
+ HashMap jobTask = QuartzUtil.getJob(jobName, triggerName);
+ return ResultUtil.verifyQuery(jobTask);
+ }
+
+ /**
+ * @param jobName 任务名称
+ * @param triggerName 触发器名
+ * @return 是否删除成功
+ */
+ @Override
+ public ResultList delTimedTask(String jobName, String triggerName) {
+ boolean isDelJob = QuartzUtil.removeJob(jobName, triggerName);
+ return ResultUtil.verifyDelete(isDelJob);
+ }
+
+ /**
+ * @param jobName 任务名称
+ * @param triggerName 触发器名
+ * @return 是否删除成功
+ */
+ @Override
+ public ResultList rescheduleJob(String jobName, String triggerName,String cron) {
+ if (!QuartzUtil.checkCronExpression(cron)) {
+ return ResultUtil.execute(Code.PARAM_FORMAT_ERROR, "cron解析错误");
+ }
+ boolean isModifyJob = QuartzUtil.rescheduleJob(jobName, triggerName,cron);
+ return ResultUtil.verifyUpdate(isModifyJob);
+ }
+
+ /**
+ * 查询所有正在运行的定时任务
+ *
+ * @return JobDetail
+ */
+ @Override
+ public ResultList queryAllTask() {
+ List> list = QuartzUtil.getJobs();
+ return ResultUtil.verifyQuery(list, list.size());
+ }
+
+ /**
+ * @param cron cron表达式
+ * @return 最近5次的执行时间
+ */
+ @Override
+ public ResultList getRecentTriggerTime(String cron) {
+ if (!QuartzUtil.checkCronExpression(cron)) {
+ return ResultUtil.execute(Code.PARAM_FORMAT_ERROR, "cron解析错误");
+ }
+ List list = QuartzUtil.getRecentTriggerTime(cron);
+ return new ResultList(Code.SUCC.getCode(), Code.SUCC.getMsg(), new Result<>(list.size(), list));
+ }
+}
diff --git a/QuartzManager/src/main/resources/application.properties b/QuartzManager/src/main/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..9192341aeb96244fb2f0803bfac5441a5cc7c5e0
--- /dev/null
+++ b/QuartzManager/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+server.port = 8000
+
diff --git a/QuartzManager/src/main/resources/db.setting b/QuartzManager/src/main/resources/db.setting
new file mode 100644
index 0000000000000000000000000000000000000000..d4b3fdcaf81adb8626368313e95a6c34e2d92d5b
--- /dev/null
+++ b/QuartzManager/src/main/resources/db.setting
@@ -0,0 +1,18 @@
+## db.setting文件
+
+## 这里的test_db1、test_db1、db3是下面对应数据源的标识,不要求与数据库名一样,如db3,个人习惯设置为数据库名。
+
+[test_db1]
+url = jdbc:mysql://localhost:3306/test_db1?allowMultiQueries=true&useUnicode=true&serverTimezone=UTC&characterEncoding=utf8
+user = frost2
+pass = pass
+
+[test_db2]
+url = jdbc:mysql://localhost:3306/test_db2?allowMultiQueries=true&useUnicode=true&serverTimezone=UTC&characterEncoding=utf8
+user = frost2
+pass = pass
+
+[db3]
+url = jdbc:mysql://localhost:3306/test_db3?allowMultiQueries=true&useUnicode=true&serverTimezone=UTC&characterEncoding=utf8
+user = frost2
+pass = pass
diff --git a/QuartzManager/src/main/resources/img/frost2.jpg b/QuartzManager/src/main/resources/img/frost2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..72e2811cc3d51691f4fc081fcaa058d31e2cc3ba
Binary files /dev/null and b/QuartzManager/src/main/resources/img/frost2.jpg differ
diff --git a/QuartzManager/src/main/resources/img/timedTask.png b/QuartzManager/src/main/resources/img/timedTask.png
new file mode 100644
index 0000000000000000000000000000000000000000..759c1726d98c60c64cad4fcd76566c6f2a28054a
Binary files /dev/null and b/QuartzManager/src/main/resources/img/timedTask.png differ
diff --git a/QuartzManager/src/test/java/com/frost2/quartz/QuartzApplicationTests.java b/QuartzManager/src/test/java/com/frost2/quartz/QuartzApplicationTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d9b906003e970511c27b62edfa0992d44c2db7b
--- /dev/null
+++ b/QuartzManager/src/test/java/com/frost2/quartz/QuartzApplicationTests.java
@@ -0,0 +1,13 @@
+package com.frost2.quartz;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class QuartzApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/api-integration/pom.xml b/api-integration/pom.xml
index c4ee0ee48d67b0d41d70bc13b86a01a3a712d45b..0b44b791b59df18c9b2106a3a73be9da6cebd1d4 100644
--- a/api-integration/pom.xml
+++ b/api-integration/pom.xml
@@ -18,6 +18,10 @@
api-integration
api-integration
+
+ org.springframework.boot
+ spring-boot-starter-quartz
+
org.springframework.boot
spring-boot-starter
diff --git a/api-integration/src/main/java/com/hongyi/apiintegration/spring/a01/A01Application.java b/api-integration/src/main/java/com/hongyi/apiintegration/spring/a01/A01Application.java
index 245cd58c81453e4e7e9d35359acf14418c6d7013..126cd7cdd9d01c0d306e01709c378acd3f59a1e5 100644
--- a/api-integration/src/main/java/com/hongyi/apiintegration/spring/a01/A01Application.java
+++ b/api-integration/src/main/java/com/hongyi/apiintegration/spring/a01/A01Application.java
@@ -14,7 +14,6 @@ import java.util.Map;
@SpringBootApplication
-@ComponentScan
public class A01Application {
private static final Logger log = LoggerFactory.getLogger(A01Application.class);
diff --git a/api-integration/src/main/java/com/hongyi/apiintegration/time/HelloJob.java b/api-integration/src/main/java/com/hongyi/apiintegration/time/HelloJob.java
new file mode 100644
index 0000000000000000000000000000000000000000..dfe31caef5e69f2fb80534c64c46b0d1494fdb3a
--- /dev/null
+++ b/api-integration/src/main/java/com/hongyi/apiintegration/time/HelloJob.java
@@ -0,0 +1,28 @@
+package com.hongyi.apiintegration.time;
+
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+import java.util.Date;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/15 11:26
+ * @Version 1.0
+ */
+@Slf4j
+public class HelloJob extends QuartzJobBean {
+
+ @Override
+ protected void executeInternal(JobExecutionContext context) {
+ // get parameters
+ context.getJobDetail().getJobDataMap().forEach(
+ (k, v) -> log.info("param, key:{}, value:{}", k, v)
+ );
+ // your logics
+ log.info("Hello Job执行时间: " + new Date());
+ }
+
+}
diff --git a/api-integration/src/main/java/com/hongyi/apiintegration/time/Main.java b/api-integration/src/main/java/com/hongyi/apiintegration/time/Main.java
index 0749a9ed1a9510929aea6f0b520e35f5e02ff507..f4b84f91cb737e2476b8f1dc70cd0980a0568a9d 100644
--- a/api-integration/src/main/java/com/hongyi/apiintegration/time/Main.java
+++ b/api-integration/src/main/java/com/hongyi/apiintegration/time/Main.java
@@ -1,5 +1,6 @@
package com.hongyi.apiintegration.time;
+import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
@@ -9,5 +10,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
*/
@SpringBootApplication
public class Main {
-
+ public static void main(String[] args) {
+ SpringApplication.run(Main.class, args);
+ }
}
diff --git a/api-integration/src/main/java/com/hongyi/apiintegration/time/QuartzConfig.java b/api-integration/src/main/java/com/hongyi/apiintegration/time/QuartzConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e74ec2643f80f3b36e307c2f0d8e61a9c3f7cc0
--- /dev/null
+++ b/api-integration/src/main/java/com/hongyi/apiintegration/time/QuartzConfig.java
@@ -0,0 +1,50 @@
+package com.hongyi.apiintegration.time;
+
+import org.quartz.*;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/15 11:27
+ * @Version 1.0
+ */
+@Configuration
+public class QuartzConfig {
+
+ /**
+ * JobDetail
+ */
+ @Bean("helloJob")
+ public JobDetail helloJobDetail() {
+ /**
+ * newJob: 设置将要执行的Job,该类需要实现Job接口
+ * withIdentity: JobDetail的id
+ * usingJobData: 可以通过键值对的方式将一些参数传到定时任务中,在定时任务job中使用
+ */
+ return JobBuilder.newJob(HelloJob.class)
+ .withIdentity("DateTimeJob")
+ .usingJobData("msg", "Hello Quartz")
+ .storeDurably() //即使没有Trigger关联时,也不需要删除该JobDetail
+ .build();
+ }
+
+ /**
+ * 触发器
+ */
+ @Bean
+ public Trigger printTimeJobTrigger() {
+ // 每秒执行一次
+ CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
+ /**
+ * forJob: 应用在哪个JobDetail上
+ * withIdentity: Trigger的id
+ * withSchedule: 设置ScheduleBuilder,而ScheduleBuilder在负责真正实例化出一个Trigger
+ */
+ return TriggerBuilder.newTrigger()
+ .forJob(helloJobDetail())
+ .withIdentity("quartzTaskService")
+ .withSchedule(cronScheduleBuilder)
+ .build();
+ }
+}
diff --git a/api-integration/src/main/java/com/hongyi/apiintegration/time/ScheduleTest.java b/api-integration/src/main/java/com/hongyi/apiintegration/time/ScheduleTest.java
deleted file mode 100644
index 407df7511ded653e62ef8f983d1585442910b229..0000000000000000000000000000000000000000
--- a/api-integration/src/main/java/com/hongyi/apiintegration/time/ScheduleTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.hongyi.apiintegration.time;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import java.time.LocalDateTime;
-
-/**
- * @Author Kisugi Takumi
- * @Date 2024/7/15 11:06
- * @Version 1.0
- */
-@Slf4j
-@Component
-@EnableScheduling
-public class ScheduleTest {
- /**
- * 每隔1min执行1次
- */
- @Scheduled(fixedRate = 1000 * 60)
- public void runScheduledFixedRate() {
- log.info("runScheduledFixedRate: current Datetime, {}", LocalDateTime.now());
- }
-}
diff --git a/securitydemo/.idea/.gitignore b/securitydemo/.idea/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/securitydemo/.idea/.name b/securitydemo/.idea/.name
new file mode 100644
index 0000000000000000000000000000000000000000..bec7df056a36f891808e00ed1c4ada1f299a56d0
--- /dev/null
+++ b/securitydemo/.idea/.name
@@ -0,0 +1 @@
+securityDemo
\ No newline at end of file
diff --git a/securitydemo/.idea/compiler.xml b/securitydemo/.idea/compiler.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ed377c4e9cc140661172b2a6ef974805276c15ac
--- /dev/null
+++ b/securitydemo/.idea/compiler.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/securitydemo/.idea/encodings.xml b/securitydemo/.idea/encodings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..aa00ffab7828f4818589659c804ec2cfd99baed3
--- /dev/null
+++ b/securitydemo/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/securitydemo/.idea/jarRepositories.xml b/securitydemo/.idea/jarRepositories.xml
new file mode 100644
index 0000000000000000000000000000000000000000..712ab9d985c20018a0c97b93d2148ac1ffe588a5
--- /dev/null
+++ b/securitydemo/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/securitydemo/.idea/misc.xml b/securitydemo/.idea/misc.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b46ea32a203191e481c567e760305a35b97a7a93
--- /dev/null
+++ b/securitydemo/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/securitydemo/.idea/runConfigurations.xml b/securitydemo/.idea/runConfigurations.xml
new file mode 100644
index 0000000000000000000000000000000000000000..797acea53eb091cf5b30518802c3073f544adeed
--- /dev/null
+++ b/securitydemo/.idea/runConfigurations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/securitydemo/.idea/vcs.xml b/securitydemo/.idea/vcs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6c0b8635858dc7ad44b93df54b762707ce49eefc
--- /dev/null
+++ b/securitydemo/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/securitydemo/.idea/workspace.xml b/securitydemo/.idea/workspace.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7d3ed53e9f47f7cda42107f0ddb8a6b978dee70d
--- /dev/null
+++ b/securitydemo/.idea/workspace.xml
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jr
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1721195419534
+
+
+ 1721195419534
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/securitydemo/pom.xml b/securitydemo/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6533d85f47492fea24f4566021702c4af31af250
--- /dev/null
+++ b/securitydemo/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+ com.hongyi
+ securityDemo
+ 1.0-SNAPSHOT
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.3
+
+
+
+ 15
+ 15
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.4.3
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/securitydemo/src/main/java/com/hongyi/Main.java b/securitydemo/src/main/java/com/hongyi/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..4edc0b8923cfe5e985816f04c0d461e20531317d
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/Main.java
@@ -0,0 +1,18 @@
+package com.hongyi;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 13:56
+ * @Version 1.0
+ */
+@SpringBootApplication
+@MapperScan(basePackages = {"com.hongyi.mapper"})
+public class Main {
+ public static void main(String[] args) {
+ SpringApplication.run(Main.class, args);
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/authentication/SecurityAuthenticationEntryPoint.java b/securitydemo/src/main/java/com/hongyi/authentication/SecurityAuthenticationEntryPoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..261404c2735b6ae440684adf7efbb19281704fa1
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/authentication/SecurityAuthenticationEntryPoint.java
@@ -0,0 +1,26 @@
+package com.hongyi.authentication;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 15:50
+ * @Version 1.0
+ */
+public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
+ response.setContentType("application/json;charset=utf-8");
+ PrintWriter out = response.getWriter();
+ out.write("尚未登录,请先登录");
+ out.flush();
+ out.close();
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/authentication/SecurityAuthenticationFailureHandler.java b/securitydemo/src/main/java/com/hongyi/authentication/SecurityAuthenticationFailureHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7f28377891e3b515f8057083c87fbb3dd64134d
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/authentication/SecurityAuthenticationFailureHandler.java
@@ -0,0 +1,33 @@
+package com.hongyi.authentication;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 15:42
+ * @Version 1.0
+ */
+/**
+ * 处理登录失败时的业务逻辑
+ */
+public class SecurityAuthenticationFailureHandler extends ExceptionMappingAuthenticationFailureHandler {
+ /**
+ * AuthenticationException:异常信息
+ */
+ @Override
+ public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
+ //直接输出json格式的响应信息
+ response.setContentType("application/json;charset=utf-8");
+ PrintWriter out = response.getWriter();
+ out.write(exception.getMessage());
+ out.flush();
+ out.close();
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/authentication/SecurityAuthenticationSuccessHandler.java b/securitydemo/src/main/java/com/hongyi/authentication/SecurityAuthenticationSuccessHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8b6f04c148ec89c97cebcf5c3521d858f1f2204
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/authentication/SecurityAuthenticationSuccessHandler.java
@@ -0,0 +1,28 @@
+package com.hongyi.authentication;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 15:10
+ * @Version 1.0
+ */
+public class SecurityAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
+ @Override
+ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
+ Object principal = authentication.getPrincipal();
+ response.setContentType("application/json;charset=utf-8");
+ PrintWriter out = response.getWriter();
+ out.write(new ObjectMapper().writeValueAsString(principal));
+ out.flush();
+ out.close();
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/authentication/SecurityLogoutSuccessHandler.java b/securitydemo/src/main/java/com/hongyi/authentication/SecurityLogoutSuccessHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..83da404b5c2d700d0e8b8f5c170cc4960d836712
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/authentication/SecurityLogoutSuccessHandler.java
@@ -0,0 +1,26 @@
+package com.hongyi.authentication;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 15:47
+ * @Version 1.0
+ */
+public class SecurityLogoutSuccessHandler implements LogoutSuccessHandler {
+ @Override
+ public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
+ response.setContentType("application/json;charset=utf-8");
+ PrintWriter out = response.getWriter();
+ out.write("注销成功");
+ out.flush();
+ out.close();
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/config/SecurityConfig.java b/securitydemo/src/main/java/com/hongyi/config/SecurityConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b475389a5da83c86b32b90588b9043e7e8814ca
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/config/SecurityConfig.java
@@ -0,0 +1,53 @@
+package com.hongyi.config;
+
+import com.hongyi.authentication.SecurityAuthenticationEntryPoint;
+import com.hongyi.authentication.SecurityAuthenticationFailureHandler;
+import com.hongyi.authentication.SecurityAuthenticationSuccessHandler;
+import com.hongyi.authentication.SecurityLogoutSuccessHandler;
+import com.hongyi.service.MyUserDetailsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+
+import javax.annotation.Resource;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 14:18
+ * @Version 1.0
+ */
+@EnableWebSecurity
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests()
+ .antMatchers("/admin/**")
+ .hasRole("ADMIN")
+ .antMatchers("/user/**")
+ .hasRole("USER")
+ .antMatchers("/visitor/**")
+ .permitAll()
+ .anyRequest()
+ .authenticated()
+ .and()
+ .formLogin()
+ .permitAll();
+ }
+
+ /***************************************在数据库中创建用户和角色****************************************************/
+
+ @Resource
+ private MyUserDetailsService userDetailsService;
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ //关联UserDetailsService对象
+ auth.userDetailsService(userDetailsService)
+ //暂时不对密码进行加密配置
+ .passwordEncoder(NoOpPasswordEncoder.getInstance());
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/controller/AdminController.java b/securitydemo/src/main/java/com/hongyi/controller/AdminController.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fb1b1ebdf373c8bf9ae6977bb7a67b99c596879
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/controller/AdminController.java
@@ -0,0 +1,19 @@
+package com.hongyi.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 16:03
+ * @Version 1.0
+ */
+@RestController
+@RequestMapping("/admin")
+public class AdminController {
+ @GetMapping("/hello")
+ public String hello() {
+ return "hello, admin";
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/controller/HelloController.java b/securitydemo/src/main/java/com/hongyi/controller/HelloController.java
new file mode 100644
index 0000000000000000000000000000000000000000..cbd0cbd1ee5f9c758d11738ab1a7d6b1234284ff
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/controller/HelloController.java
@@ -0,0 +1,19 @@
+package com.hongyi.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 13:56
+ * @Version 1.0
+ */
+@RestController
+public class HelloController {
+
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello, 来跟 学习 Spring Security吧!";
+ }
+
+}
diff --git a/securitydemo/src/main/java/com/hongyi/controller/UserController.java b/securitydemo/src/main/java/com/hongyi/controller/UserController.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa113ca75e3b9501cfe03651140cf12285b9f064
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/controller/UserController.java
@@ -0,0 +1,19 @@
+package com.hongyi.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 16:03
+ * @Version 1.0
+ */
+@RestController
+@RequestMapping("/user")
+public class UserController {
+ @GetMapping("/hello")
+ public String hello() {
+ return "hello, user";
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/controller/VisitorController.java b/securitydemo/src/main/java/com/hongyi/controller/VisitorController.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba2a85c5b34cb3a94be4fe1373aec818edd4aa0d
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/controller/VisitorController.java
@@ -0,0 +1,19 @@
+package com.hongyi.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 16:04
+ * @Version 1.0
+ */
+@RestController
+@RequestMapping("/visitor")
+public class VisitorController {
+ @GetMapping("/hello")
+ public String hello() {
+ return "hello, visitor";
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/entity/User.java b/securitydemo/src/main/java/com/hongyi/entity/User.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f08b6d2c9286cad23ae1aa20b0a56c16d1112d2
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/entity/User.java
@@ -0,0 +1,64 @@
+package com.hongyi.entity;
+
+import lombok.Data;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 16:15
+ * @Version 1.0
+ */
+@Data
+public class User implements UserDetails {
+
+ private Long id;
+
+ private String username;
+
+ private String password;
+
+ private String roles;
+
+ private boolean enable;
+
+ private List authorities;
+
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+ return this.authorities;
+ }
+
+ @Override
+ public String getPassword() {
+ return this.password;
+ }
+
+ @Override
+ public String getUsername() {
+ return this.username;
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/securitydemo/src/main/java/com/hongyi/mapper/UserMapper.java b/securitydemo/src/main/java/com/hongyi/mapper/UserMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..448492bdaedf484a044c3b2a92bfe1289f9129d5
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/mapper/UserMapper.java
@@ -0,0 +1,17 @@
+package com.hongyi.mapper;
+
+import com.hongyi.entity.User;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 16:20
+ * @Version 1.0
+ */
+@Repository
+public interface UserMapper {
+ @Select("SELECT * FROM users WHERE username=#{username}")
+ User findByUserName(@Param("username") String username);
+}
diff --git a/securitydemo/src/main/java/com/hongyi/service/MyUserDetailsService.java b/securitydemo/src/main/java/com/hongyi/service/MyUserDetailsService.java
new file mode 100644
index 0000000000000000000000000000000000000000..89c52ba91793e1acdf9971e3c6e5f615589d35a6
--- /dev/null
+++ b/securitydemo/src/main/java/com/hongyi/service/MyUserDetailsService.java
@@ -0,0 +1,40 @@
+package com.hongyi.service;
+
+import com.hongyi.entity.User;
+import com.hongyi.mapper.UserMapper;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+/**
+ * @Author Kisugi Takumi
+ * @Date 2024/7/17 16:23
+ * @Version 1.0
+ */
+@Service
+public class MyUserDetailsService implements UserDetailsService {
+ @Resource
+ private UserMapper userMapper;
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ // 从数据库尝试读取该用户
+ User user = userMapper.findByUserName(username);
+
+ // 用户不存在,抛出异常
+ if (user == null) {
+ throw new UsernameNotFoundException("用户不存在");
+ }
+
+ // 将数据库形式的roles解析为UserDetails的权限集
+ // AuthorityUtils.commaSeparatedStringToAuthorityList是Spring Security
+ // 提供的用于将逗号隔开的权限集字符串切割成可用权限对象列表的方法
+ // 当然也可以自己实现,如用分号来隔开等,参考generateAuthorities
+ user.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRoles()));
+ return user;
+ }
+}
diff --git a/securitydemo/src/main/resources/application.yml b/securitydemo/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..74a6f5bd63705a2eed6f49b24386ab32492c8983
--- /dev/null
+++ b/securitydemo/src/main/resources/application.yml
@@ -0,0 +1,11 @@
+server:
+ port: 8081
+spring:
+ security:
+ user:
+ name: zym
+ password: zym123
+ datasource:
+ url:
+ username: root
+ password: admin123
\ No newline at end of file
diff --git a/securitydemo/target/classes/application.yml b/securitydemo/target/classes/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f724d69fd447e67a39481930d5cb34ba1f15fc3a
--- /dev/null
+++ b/securitydemo/target/classes/application.yml
@@ -0,0 +1,11 @@
+server:
+ port: 8081
+spring:
+ security:
+ user:
+ name: zym
+ password: zym123
+ datasource:
+ url: jdbc:mysql://81.71.84.137:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
+ username: root
+ password: admin123
\ No newline at end of file
diff --git a/securitydemo/target/classes/com/hongyi/Main.class b/securitydemo/target/classes/com/hongyi/Main.class
new file mode 100644
index 0000000000000000000000000000000000000000..01b8fe32f0b1d3bcea71fc0747eb8ba024aa3e06
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/Main.class differ
diff --git a/securitydemo/target/classes/com/hongyi/authentication/SecurityAuthenticationEntryPoint.class b/securitydemo/target/classes/com/hongyi/authentication/SecurityAuthenticationEntryPoint.class
new file mode 100644
index 0000000000000000000000000000000000000000..437d1fbb2b920b655ce087ac2fa015a16be5e6a9
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/authentication/SecurityAuthenticationEntryPoint.class differ
diff --git a/securitydemo/target/classes/com/hongyi/authentication/SecurityAuthenticationFailureHandler.class b/securitydemo/target/classes/com/hongyi/authentication/SecurityAuthenticationFailureHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7b97d5793ffe7b02391b06e6150b3a83e17a98c
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/authentication/SecurityAuthenticationFailureHandler.class differ
diff --git a/securitydemo/target/classes/com/hongyi/authentication/SecurityAuthenticationSuccessHandler.class b/securitydemo/target/classes/com/hongyi/authentication/SecurityAuthenticationSuccessHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d0b43a5480ee35eb5ea1ecc454a65e7d6844cc4
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/authentication/SecurityAuthenticationSuccessHandler.class differ
diff --git a/securitydemo/target/classes/com/hongyi/authentication/SecurityLogoutSuccessHandler.class b/securitydemo/target/classes/com/hongyi/authentication/SecurityLogoutSuccessHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..595b0d9b7ada9380f4800409b47364dfdc386347
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/authentication/SecurityLogoutSuccessHandler.class differ
diff --git a/securitydemo/target/classes/com/hongyi/config/SecurityConfig.class b/securitydemo/target/classes/com/hongyi/config/SecurityConfig.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d261ed3030c64bce4bfd8807559d5370d963dfc
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/config/SecurityConfig.class differ
diff --git a/securitydemo/target/classes/com/hongyi/controller/AdminController.class b/securitydemo/target/classes/com/hongyi/controller/AdminController.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0c1128c97247c7956c025543688732322951619
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/controller/AdminController.class differ
diff --git a/securitydemo/target/classes/com/hongyi/controller/HelloController.class b/securitydemo/target/classes/com/hongyi/controller/HelloController.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f14d98b10913632b184a68d2c755cbcc3186e06
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/controller/HelloController.class differ
diff --git a/securitydemo/target/classes/com/hongyi/controller/UserController.class b/securitydemo/target/classes/com/hongyi/controller/UserController.class
new file mode 100644
index 0000000000000000000000000000000000000000..f65b72a7bbc03df248e8d92ffa2853d1cb2bc337
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/controller/UserController.class differ
diff --git a/securitydemo/target/classes/com/hongyi/controller/VisitorController.class b/securitydemo/target/classes/com/hongyi/controller/VisitorController.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd8f74c1adf15bb164fc300561ef383ce18f333d
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/controller/VisitorController.class differ
diff --git a/securitydemo/target/classes/com/hongyi/entity/User.class b/securitydemo/target/classes/com/hongyi/entity/User.class
new file mode 100644
index 0000000000000000000000000000000000000000..284b796403eef306642574eb9e4491bc03dded6a
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/entity/User.class differ
diff --git a/securitydemo/target/classes/com/hongyi/mapper/UserMapper.class b/securitydemo/target/classes/com/hongyi/mapper/UserMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..2cbb0c467c37dcaaa25253c56c707f65de400511
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/mapper/UserMapper.class differ
diff --git a/securitydemo/target/classes/com/hongyi/service/MyUserDetailsService.class b/securitydemo/target/classes/com/hongyi/service/MyUserDetailsService.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea072d9a2ad627d79a17267a5cd71569a7d7ebed
Binary files /dev/null and b/securitydemo/target/classes/com/hongyi/service/MyUserDetailsService.class differ