From 930509dc370d3ae69bd1140f3e4bdd685263b9a0 Mon Sep 17 00:00:00 2001 From: DengMin <16679070171@qq.com> Date: Tue, 15 Feb 2022 15:58:55 +0800 Subject: [PATCH] 定时任务 --- pom.xml | 4 ++++ src/main/java/com/subsidy/common/configure/JobFactory.java | 31 +++++++++++++++++++++++++++++++ src/main/java/com/subsidy/common/configure/QuartzConfig.java | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/subsidy/common/constant/CourseNotification.java | 14 ++++++++++++++ src/main/java/com/subsidy/controller/ClassNoticeController.java | 16 ++++++++++------ src/main/java/com/subsidy/dto/classNotice/SendNotificationDTO.java | 11 +++++++++++ src/main/java/com/subsidy/jobs/CourseNotificationJob.java | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/subsidy/jobs/Scheduler.java | 154 ---------------------------------------------------------------------------------------------------------------------------------------------------------- src/main/java/com/subsidy/jobs/SchedulerJob.java | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/subsidy/mapper/MemberMapper.java | 5 +++++ src/main/java/com/subsidy/service/ClassNoticeService.java | 3 +++ src/main/java/com/subsidy/service/impl/ClassNoticeServiceImpl.java | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/main/java/com/subsidy/util/QuartzUtil.java | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/resources/application-quartz.properties | 7 +++++++ src/main/resources/code.properties | 4 ++++ src/main/resources/mapper/MemberMapper.xml | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 596 insertions(+), 161 deletions(-) create mode 100644 src/main/java/com/subsidy/common/configure/JobFactory.java create mode 100644 src/main/java/com/subsidy/common/configure/QuartzConfig.java create mode 100644 src/main/java/com/subsidy/common/constant/CourseNotification.java create mode 100644 src/main/java/com/subsidy/dto/classNotice/SendNotificationDTO.java create mode 100644 src/main/java/com/subsidy/jobs/CourseNotificationJob.java delete mode 100644 src/main/java/com/subsidy/jobs/Scheduler.java create mode 100644 src/main/java/com/subsidy/jobs/SchedulerJob.java create mode 100644 src/main/java/com/subsidy/util/QuartzUtil.java create mode 100755 src/main/resources/application-quartz.properties diff --git a/pom.xml b/pom.xml index 4365dae..7f3882c 100644 --- a/pom.xml +++ b/pom.xml @@ -197,6 +197,10 @@ spring-boot-starter-data-redis + + org.springframework.boot + spring-boot-starter-quartz + redis.clients diff --git a/src/main/java/com/subsidy/common/configure/JobFactory.java b/src/main/java/com/subsidy/common/configure/JobFactory.java new file mode 100644 index 0000000..9a0bdcb --- /dev/null +++ b/src/main/java/com/subsidy/common/configure/JobFactory.java @@ -0,0 +1,31 @@ +package com.subsidy.common.configure; + +import org.quartz.spi.TriggerFiredBundle; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.scheduling.quartz.AdaptableJobFactory; +import org.springframework.stereotype.Component; + +/** + *

+ * JobFactory实例 + *

+ * + * @author DengMin + * @since 2020/12/9 + */ +@Component +public class JobFactory extends AdaptableJobFactory { + + private AutowireCapableBeanFactory factory; + + public JobFactory(AutowireCapableBeanFactory factory) { + this.factory = factory; + } + + @Override + protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { + Object job = super.createJobInstance(bundle); + factory.autowireBean(job); + return job; + } +} diff --git a/src/main/java/com/subsidy/common/configure/QuartzConfig.java b/src/main/java/com/subsidy/common/configure/QuartzConfig.java new file mode 100644 index 0000000..cdb7008 --- /dev/null +++ b/src/main/java/com/subsidy/common/configure/QuartzConfig.java @@ -0,0 +1,45 @@ +package com.subsidy.common.configure; + +import org.quartz.Scheduler; +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.scheduling.quartz.SchedulerFactoryBean; +import javax.sql.DataSource; + +/** + *

+ * Quartz配置 + *

+ * + * @author DengMin + * @since 2020/12/8 + */ +@Configuration +public class QuartzConfig { + + @Autowired + private JobFactory jobFactory; + + @Autowired + private DataSource dataSource; + + @Bean + public SchedulerFactoryBean schedulerFactoryBean() { + SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); + schedulerFactoryBean.setOverwriteExistingJobs(true); + schedulerFactoryBean.setStartupDelay(60); + schedulerFactoryBean.setJobFactory(jobFactory); + schedulerFactoryBean.setOverwriteExistingJobs(true); + schedulerFactoryBean.setStartupDelay(1); + schedulerFactoryBean.setDataSource(dataSource); + schedulerFactoryBean.setConfigLocation(new ClassPathResource("/application-quartz.properties")); + return schedulerFactoryBean; + } + + @Bean + public Scheduler scheduler() { + return schedulerFactoryBean().getScheduler(); + } +} diff --git a/src/main/java/com/subsidy/common/constant/CourseNotification.java b/src/main/java/com/subsidy/common/constant/CourseNotification.java new file mode 100644 index 0000000..449a57a --- /dev/null +++ b/src/main/java/com/subsidy/common/constant/CourseNotification.java @@ -0,0 +1,14 @@ +package com.subsidy.common.constant; + +public class CourseNotification { + + public static final String UNSENT = "待发送"; + + public static final String SENT = "已发送"; + + public static final String ALL = "全部成员"; + + public static final String NOT_SIGNED_IN = "未签到成员"; + + public static final String UNFINISHED = "未完课成员"; +} diff --git a/src/main/java/com/subsidy/controller/ClassNoticeController.java b/src/main/java/com/subsidy/controller/ClassNoticeController.java index bbe911f..8097ff0 100644 --- a/src/main/java/com/subsidy/controller/ClassNoticeController.java +++ b/src/main/java/com/subsidy/controller/ClassNoticeController.java @@ -3,6 +3,7 @@ package com.subsidy.controller; import com.subsidy.common.ResponseData; import com.subsidy.common.ResponseVO; +import com.subsidy.dto.classNotice.SendNotificationDTO; import com.subsidy.model.ClassNoticeDO; import com.subsidy.service.ClassNoticeService; import io.swagger.annotations.ApiOperation; @@ -23,7 +24,7 @@ import io.swagger.annotations.Api; * @since 2022-01-21 */ @RestController -@Api(tags = "") +@Api(tags = "课程通知") @RequestMapping("/classNotice") public class ClassNoticeController { @@ -31,7 +32,7 @@ public class ClassNoticeController { private ClassNoticeService classNoticeService; @PostMapping("addNotice") - @ApiOperation("新增一个通知 classId noticeType isAuto noticeTime") + @ApiOperation("新增一个通知 classId noticeType isAuto noticeTime") public ResponseVO addNotice(@RequestBody ClassNoticeDO classNoticeDO){ return ResponseData.generateCreatedResponse(0,classNoticeService.addNotice(classNoticeDO)); } @@ -49,12 +50,15 @@ public class ClassNoticeController { } @PostMapping("queryClassNotices") - @ApiOperation("查看某个课程的通知提醒 classId 课程id") + @ApiOperation("查看某个课程的通知提醒 classId 课程id status 状态(待发送/已发送)") public ResponseVO queryClassNotices(ClassNoticeDO classNoticeDO){ return ResponseData.generateCreatedResponse(0,classNoticeService.queryClassNotices(classNoticeDO)); } - - - + @PostMapping("sendClassNotices") + @ApiOperation("发送通知:classId/课程Id sendType/发送类型(全部成员/未签到成员/未完课成员)") + public ResponseVO sendClassNotices(@RequestBody SendNotificationDTO sendNotificationDTO) { + classNoticeService.sendNotification(sendNotificationDTO); + return ResponseData.generateCreatedResponse(0); + } } diff --git a/src/main/java/com/subsidy/dto/classNotice/SendNotificationDTO.java b/src/main/java/com/subsidy/dto/classNotice/SendNotificationDTO.java new file mode 100644 index 0000000..bfa506d --- /dev/null +++ b/src/main/java/com/subsidy/dto/classNotice/SendNotificationDTO.java @@ -0,0 +1,11 @@ +package com.subsidy.dto.classNotice; + +import lombok.Data; + +@Data +public class SendNotificationDTO { + + private Long classId; + + private String sendType; +} diff --git a/src/main/java/com/subsidy/jobs/CourseNotificationJob.java b/src/main/java/com/subsidy/jobs/CourseNotificationJob.java new file mode 100644 index 0000000..3388b6b --- /dev/null +++ b/src/main/java/com/subsidy/jobs/CourseNotificationJob.java @@ -0,0 +1,58 @@ +package com.subsidy.jobs; + +import com.subsidy.common.constant.CourseNotification; +import com.subsidy.mapper.ClassNoticeMapper; +import com.subsidy.mapper.MemberMapper; +import com.subsidy.model.ClassNoticeDO; +import com.subsidy.model.MemberDO; +import com.subsidy.util.SMSUtils; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 课程通知 + *

+ * + * @author DengMin + * @since 2022/2/14 + */ +@Component +public class CourseNotificationJob implements Job { + + @Autowired + private MemberMapper memberMapper; + + @Autowired + private ClassNoticeMapper classNoticeMapper; + + @Autowired + private SMSUtils smsUtils; + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + Map map = jobExecutionContext.getJobDetail().getJobDataMap(); + Map params = (Map) map.get("params"); + if(params != null) { + List list = memberMapper.getMemberList((Long) params.get("classId")); + if(list != null && list.size() > 0) { + for (MemberDO memberDO : list) { + if(memberDO != null) { + // smsUtils.send(memberDO.getTelephone(), ""); + } + } + + ClassNoticeDO classNoticeDO = new ClassNoticeDO(); + classNoticeDO.setId((Long) params.get("id")); + classNoticeDO.setStatus(CourseNotification.SENT); + classNoticeMapper.updateById(classNoticeDO); + } + } + } +} diff --git a/src/main/java/com/subsidy/jobs/Scheduler.java b/src/main/java/com/subsidy/jobs/Scheduler.java deleted file mode 100644 index a685f28..0000000 --- a/src/main/java/com/subsidy/jobs/Scheduler.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.subsidy.jobs; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.subsidy.common.RedisPrefixConstant; -import com.subsidy.mapper.OprAdmDictMapper; -import com.subsidy.mapper.OprMemDictMapper; -import com.subsidy.mapper.SignInRecordMapper; -import com.subsidy.mapper.VodPlayHistoryMapper; -import com.subsidy.model.OprAdmDictDO; -import com.subsidy.model.SignInRecordDO; -import com.subsidy.util.DateFormatUtil; -import com.subsidy.util.RedisUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Set; - -/** - *

- * 定时器 - *

- * - * @author DengMin - * @since 2021/12/21 - */ - -@Component -public class Scheduler { - - @Autowired - private OprAdmDictMapper oprAdmDictMapper; - - @Autowired - private OprMemDictMapper oprMemDictMapper; - - @Autowired - private VodPlayHistoryMapper vodPlayHistoryMapper; - - @Autowired - private SignInRecordMapper signInRecordMapper; - - @Autowired - private RedisUtil redisUtil; - - @Autowired - private MongoTemplate mongoTemplate; - /** - 删除十天前登录记录(管理端) - */ - //@Scheduled(cron = "0 42 18 * * ?") - public void delOprAdmRecord() { - List list = oprAdmDictMapper.getRecordByDate(); - if(list != null) { - for (OprAdmDictDO oprAdmDictDO : list) { - //oprAdmDictMapper.deleteById(oprAdmDictDO.getId()); - } - } - } - - ///** - // * 删除十天前登录记录(学员) - // */ - ////@Scheduled(cron = "0 42 18 * * ?") - //public void delOprMemRecord() { - // List list = oprMemDictMapper.getRecordByDate(); - // if(list != null) { - // for (OprMemDictDO oprMemDictDO : list) { - // oprMemDictMapper.deleteById(oprMemDictDO.getId()); - // } - // } - //} - - ///** - // * 用户数据审计记录添加(学员) - // */ - ////@Scheduled(cron = "0 39 18 * * ?") - //public void getOprMemRecord() { - // Set set = redisUtil.scan("*memberLogin*"); - // if(set != null) { - // for (String str : set) { - // int result = (Integer) redisUtil.get(str); - // OprMemDictDO oprMemDictDO = new OprMemDictDO(); - // String [] opr = str.split("_"); - // LocalDateTime createDate = DateFormatUtil.secondToLocalDateTime(Long.valueOf(opr[3])); - // oprMemDictDO.setResult(result); - // oprMemDictDO.setOprType("登录"); - // oprMemDictDO.setUserId(Long.valueOf(opr[2])); - // oprMemDictDO.setCreateDate(createDate); - // oprMemDictMapper.insert(oprMemDictDO); - // redisUtil.del(str); - // } - // } - //} - - /** - * 视频播放记录缩量 - */ -// @Scheduled(cron = "0 48 14 * * ?") -// @Transactional(rollbackFor = Exception.class) -// public void condenseVodPlayHistory() { -// List list = vodPlayHistoryMapper.getVodPlayHistory(); -// vodPlayHistoryMapper.delete(null); -// //List vodPlayHistoryList = vodPlayHistoryMapper.selectList(null); -// //for (VodPlayHistoryDO vodPlayHistoryDO : vodPlayHistoryList) { -// vodPlayHistoryMapper.deleteById(null); -// //} -// -// for (VodPlayHistoryDO vodPlayHistoryDO : list) { -// vodPlayHistoryMapper.insert(vodPlayHistoryDO); -// } -// } - - /** - * 定时同步Redis签到数据 - * 1天前的 - * 增量版 - */ - @Transactional(rollbackFor = Exception.class) - public void synchronizeSignInRecord() { - List list = signInRecordMapper.getSignInRecord(); - if(list != null && list.size() > 0) { - for (SignInRecordDO signInRecordDO : list) { - Set set = redisUtil.scan(RedisPrefixConstant.SUBSIDY_SIGN_INFO_PREFIX + signInRecordDO.getMemberId() + ":classId:" + signInRecordDO.getClassId() + ":" + DateFormatUtil.format(signInRecordDO.getSignInDate(), "yyyy-MM-dd")+":*"); - if(set != null && set.size() > 0) { - redisUtil.del(set); - } - redisUtil.set(RedisPrefixConstant.SUBSIDY_SIGN_INFO_PREFIX + signInRecordDO.getMemberId() + ":classId:" + signInRecordDO.getClassId() + ":" + DateFormatUtil.format(signInRecordDO.getSignInDate(), "yyyy-MM-dd") + ":" + DateFormatUtil.LocalDateTimeToSecond(signInRecordDO.getSignInDate()), null); - } - } - } - - /** - * 全部同步Redis签到数据 - */ - @Transactional(rollbackFor = Exception.class) - public void synchronizeSignInRecordAll() { - Set set = redisUtil.scan(RedisPrefixConstant.SUBSIDY_SIGN_INFO_PREFIX+"*"); - if(set != null && set.size() > 0) { - redisUtil.del(set); - } - - List list = signInRecordMapper.selectList(new QueryWrapper<>()); - for (SignInRecordDO signInRecordDO : list) { - redisUtil.set(RedisPrefixConstant.SUBSIDY_SIGN_INFO_PREFIX + signInRecordDO.getMemberId() + ":classId:" + signInRecordDO.getClassId() + ":" + DateFormatUtil.format(signInRecordDO.getSignInDate(), "yyyy-MM-dd") + ":" + DateFormatUtil.LocalDateTimeToSecond(signInRecordDO.getSignInDate()), null); - } - - } -} diff --git a/src/main/java/com/subsidy/jobs/SchedulerJob.java b/src/main/java/com/subsidy/jobs/SchedulerJob.java new file mode 100644 index 0000000..157379e --- /dev/null +++ b/src/main/java/com/subsidy/jobs/SchedulerJob.java @@ -0,0 +1,154 @@ +package com.subsidy.jobs; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.subsidy.common.RedisPrefixConstant; +import com.subsidy.mapper.OprAdmDictMapper; +import com.subsidy.mapper.OprMemDictMapper; +import com.subsidy.mapper.SignInRecordMapper; +import com.subsidy.mapper.VodPlayHistoryMapper; +import com.subsidy.model.OprAdmDictDO; +import com.subsidy.model.SignInRecordDO; +import com.subsidy.util.DateFormatUtil; +import com.subsidy.util.RedisUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + *

+ * 定时器 + *

+ * + * @author DengMin + * @since 2021/12/21 + */ + +@Component +public class SchedulerJob { + + @Autowired + private OprAdmDictMapper oprAdmDictMapper; + + @Autowired + private OprMemDictMapper oprMemDictMapper; + + @Autowired + private VodPlayHistoryMapper vodPlayHistoryMapper; + + @Autowired + private SignInRecordMapper signInRecordMapper; + + @Autowired + private RedisUtil redisUtil; + + @Autowired + private MongoTemplate mongoTemplate; + /** + 删除十天前登录记录(管理端) + */ + //@Scheduled(cron = "0 42 18 * * ?") + public void delOprAdmRecord() { + List list = oprAdmDictMapper.getRecordByDate(); + if(list != null) { + for (OprAdmDictDO oprAdmDictDO : list) { + //oprAdmDictMapper.deleteById(oprAdmDictDO.getId()); + } + } + } + + ///** + // * 删除十天前登录记录(学员) + // */ + ////@Scheduled(cron = "0 42 18 * * ?") + //public void delOprMemRecord() { + // List list = oprMemDictMapper.getRecordByDate(); + // if(list != null) { + // for (OprMemDictDO oprMemDictDO : list) { + // oprMemDictMapper.deleteById(oprMemDictDO.getId()); + // } + // } + //} + + ///** + // * 用户数据审计记录添加(学员) + // */ + ////@Scheduled(cron = "0 39 18 * * ?") + //public void getOprMemRecord() { + // Set set = redisUtil.scan("*memberLogin*"); + // if(set != null) { + // for (String str : set) { + // int result = (Integer) redisUtil.get(str); + // OprMemDictDO oprMemDictDO = new OprMemDictDO(); + // String [] opr = str.split("_"); + // LocalDateTime createDate = DateFormatUtil.secondToLocalDateTime(Long.valueOf(opr[3])); + // oprMemDictDO.setResult(result); + // oprMemDictDO.setOprType("登录"); + // oprMemDictDO.setUserId(Long.valueOf(opr[2])); + // oprMemDictDO.setCreateDate(createDate); + // oprMemDictMapper.insert(oprMemDictDO); + // redisUtil.del(str); + // } + // } + //} + + /** + * 视频播放记录缩量 + */ +// @Scheduled(cron = "0 48 14 * * ?") +// @Transactional(rollbackFor = Exception.class) +// public void condenseVodPlayHistory() { +// List list = vodPlayHistoryMapper.getVodPlayHistory(); +// vodPlayHistoryMapper.delete(null); +// //List vodPlayHistoryList = vodPlayHistoryMapper.selectList(null); +// //for (VodPlayHistoryDO vodPlayHistoryDO : vodPlayHistoryList) { +// vodPlayHistoryMapper.deleteById(null); +// //} +// +// for (VodPlayHistoryDO vodPlayHistoryDO : list) { +// vodPlayHistoryMapper.insert(vodPlayHistoryDO); +// } +// } + + /** + * 定时同步Redis签到数据 + * 1天前的 + * 增量版 + */ + @Transactional(rollbackFor = Exception.class) + public void synchronizeSignInRecord() { + List list = signInRecordMapper.getSignInRecord(); + if(list != null && list.size() > 0) { + for (SignInRecordDO signInRecordDO : list) { + Set set = redisUtil.scan(RedisPrefixConstant.SUBSIDY_SIGN_INFO_PREFIX + signInRecordDO.getMemberId() + ":classId:" + signInRecordDO.getClassId() + ":" + DateFormatUtil.format(signInRecordDO.getSignInDate(), "yyyy-MM-dd")+":*"); + if(set != null && set.size() > 0) { + redisUtil.del(set); + } + redisUtil.set(RedisPrefixConstant.SUBSIDY_SIGN_INFO_PREFIX + signInRecordDO.getMemberId() + ":classId:" + signInRecordDO.getClassId() + ":" + DateFormatUtil.format(signInRecordDO.getSignInDate(), "yyyy-MM-dd") + ":" + DateFormatUtil.LocalDateTimeToSecond(signInRecordDO.getSignInDate()), null); + } + } + } + + /** + * 全部同步Redis签到数据 + */ + @Transactional(rollbackFor = Exception.class) + public void synchronizeSignInRecordAll() { + Set set = redisUtil.scan(RedisPrefixConstant.SUBSIDY_SIGN_INFO_PREFIX+"*"); + if(set != null && set.size() > 0) { + redisUtil.del(set); + } + + List list = signInRecordMapper.selectList(new QueryWrapper<>()); + for (SignInRecordDO signInRecordDO : list) { + redisUtil.set(RedisPrefixConstant.SUBSIDY_SIGN_INFO_PREFIX + signInRecordDO.getMemberId() + ":classId:" + signInRecordDO.getClassId() + ":" + DateFormatUtil.format(signInRecordDO.getSignInDate(), "yyyy-MM-dd") + ":" + DateFormatUtil.LocalDateTimeToSecond(signInRecordDO.getSignInDate()), null); + } + + } +} diff --git a/src/main/java/com/subsidy/mapper/MemberMapper.java b/src/main/java/com/subsidy/mapper/MemberMapper.java index 33f39d1..8e229dc 100644 --- a/src/main/java/com/subsidy/mapper/MemberMapper.java +++ b/src/main/java/com/subsidy/mapper/MemberMapper.java @@ -55,4 +55,9 @@ public interface MemberMapper extends BaseMapper { */ IPage manageMember(IPage iPage,Long companyId,String userName); + List getMemberList(Long classId); + + List getMemberListBySignInRecord(Long classId); + + List getUnfinishedMemberList(Long classId); } diff --git a/src/main/java/com/subsidy/service/ClassNoticeService.java b/src/main/java/com/subsidy/service/ClassNoticeService.java index 98d24cf..58f800c 100644 --- a/src/main/java/com/subsidy/service/ClassNoticeService.java +++ b/src/main/java/com/subsidy/service/ClassNoticeService.java @@ -1,5 +1,6 @@ package com.subsidy.service; +import com.subsidy.dto.classNotice.SendNotificationDTO; import com.subsidy.model.ClassNoticeDO; import com.baomidou.mybatisplus.extension.service.IService; @@ -22,4 +23,6 @@ public interface ClassNoticeService extends IService { String deleteNotice(ClassNoticeDO classNoticeDO); List queryClassNotices(ClassNoticeDO classNoticeDO); + + void sendNotification(SendNotificationDTO sendNotificationDTO); } diff --git a/src/main/java/com/subsidy/service/impl/ClassNoticeServiceImpl.java b/src/main/java/com/subsidy/service/impl/ClassNoticeServiceImpl.java index 9391ae3..c8631e4 100644 --- a/src/main/java/com/subsidy/service/impl/ClassNoticeServiceImpl.java +++ b/src/main/java/com/subsidy/service/impl/ClassNoticeServiceImpl.java @@ -1,14 +1,29 @@ package com.subsidy.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.subsidy.common.constant.CourseNotification; +import com.subsidy.common.exception.HttpException; +import com.subsidy.dto.classNotice.SendNotificationDTO; +import com.subsidy.jobs.CourseNotificationJob; +import com.subsidy.mapper.MemberMapper; +import com.subsidy.model.ClassDictDO; import com.subsidy.model.ClassNoticeDO; import com.subsidy.mapper.ClassNoticeMapper; +import com.subsidy.model.MemberDO; +import com.subsidy.service.ClassDictService; import com.subsidy.service.ClassNoticeService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.subsidy.util.ConstantUtils; +import com.subsidy.util.DateFormatUtil; +import com.subsidy.util.QuartzUtil; +import com.subsidy.util.SMSUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; - +import org.springframework.transaction.annotation.Transactional; +import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** *

@@ -21,8 +36,34 @@ import java.util.List; @Service public class ClassNoticeServiceImpl extends ServiceImpl implements ClassNoticeService { + @Autowired + private QuartzUtil quartzUtil; + + @Autowired + private ClassDictService classDictService; + + @Autowired + private MemberMapper memberMapper; + + @Autowired + private SMSUtils smsUtils; + + @Transactional(rollbackFor = Exception.class) + @Override public String addNotice(ClassNoticeDO classNoticeDO) { + if(DateFormatUtil.parse(classNoticeDO.getNoticeTime(),"yyyy-MM-dd").before(new Date())) { + throw new HttpException(70001); + } + + classNoticeDO.setStatus(CourseNotification.UNSENT); this.baseMapper.insert(classNoticeDO); + + ClassDictDO classDictDO = classDictService.getById(classNoticeDO.getClassId()); + Map params = new HashMap<>(); + params.put("classId", classNoticeDO.getClassId()); + params.put("id", classNoticeDO.getId()); + String name = classDictDO.getClassName()+"-"+classNoticeDO.getNoticeType()+"-"+classNoticeDO.getNoticeTime(); + quartzUtil.addSimpleJob(CourseNotificationJob.class,DateFormatUtil.parse(classNoticeDO.getNoticeTime(), "yyyy-MM-dd") , params, name, "CourseNotificationJob"); return ConstantUtils.ADD_SUCCESS; } @@ -31,15 +72,48 @@ public class ClassNoticeServiceImpl extends ServiceImpl queryClassNotices(ClassNoticeDO classNoticeDO){ return this.baseMapper.selectList(new QueryWrapper() .lambda() + .eq(ClassNoticeDO::getStatus, classNoticeDO.getStatus()) .eq(ClassNoticeDO::getClassId,classNoticeDO.getClassId())); } + @Override + public void sendNotification(SendNotificationDTO sendNotificationDTO) { + if(sendNotificationDTO.getSendType().equals(CourseNotification.ALL)) { + List list = memberMapper.getMemberList(sendNotificationDTO.getClassId()); + if(list != null) { + for (MemberDO memberDO : list) { + smsUtils.send(memberDO.getTelephone(), ""); + } + } + } else if(sendNotificationDTO.getSendType().equals(CourseNotification.NOT_SIGNED_IN)) { + List list = memberMapper.getMemberListBySignInRecord(sendNotificationDTO.getClassId()); + if(list != null) { + for (MemberDO memberDO : list) { + smsUtils.send(memberDO.getTelephone(), ""); + } + } + } else if(sendNotificationDTO.getSendType().equals(CourseNotification.UNFINISHED)) { + List list = memberMapper.getUnfinishedMemberList(sendNotificationDTO.getClassId()); + if(list != null) { + for (MemberDO memberDO : list) { + smsUtils.send(memberDO.getTelephone(), ""); + } + } + } + } } diff --git a/src/main/java/com/subsidy/util/QuartzUtil.java b/src/main/java/com/subsidy/util/QuartzUtil.java new file mode 100644 index 0000000..d60aeca --- /dev/null +++ b/src/main/java/com/subsidy/util/QuartzUtil.java @@ -0,0 +1,119 @@ +package com.subsidy.util; + +import com.subsidy.common.exception.HttpException; +import org.quartz.CronScheduleBuilder; +import org.quartz.CronTrigger; +import org.quartz.DateBuilder; +import org.quartz.JobBuilder; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SimpleTrigger; +import org.quartz.Trigger; +import org.quartz.TriggerBuilder; +import org.quartz.TriggerKey; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import static org.quartz.DateBuilder.futureDate; + +@Component +public class QuartzUtil { + + @Autowired + private Scheduler scheduler; + + /** + * 添加定时任务,只执行一次的定时任务 + * + * @param cls 执行类 + * @param date 时间 + * @param params 参数 + * @param name 定时器名称 + * @param group 定时器组名 + */ + public void addSimpleJob(Class cls, Date date, Map params, String name, String group) { + try { + JobKey key = new JobKey(name, group); + List triggers = (List) scheduler.getTriggersOfJob(key); + if (triggers.size() == 0) { + int time = (int) (date.getTime() - System.currentTimeMillis()) / 1000; + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("params", params); + JobDetail jobDetail = JobBuilder.newJob(cls) + .withIdentity(name, group) + .usingJobData(jobDataMap) + .build(); + SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() + .withIdentity(name, group) + .startAt(futureDate(time, DateBuilder.IntervalUnit.SECOND)) + .build(); + scheduler.scheduleJob(jobDetail, trigger); + if (!scheduler.isShutdown()) { + scheduler.start(); + } + } + } catch (Exception e) { + throw new HttpException(70002); + } + } + + /** + * 添加定时任务,循环不断执行的定时任务 + * + * @param cls 执行类 + * @param cron cron 表达式 + * @param params 参数 + * @param name 定时器名称 + * @param group 定时器组名 + */ + public void addCronJob(Class cls, String cron, Map params, String name, String group) { + try { + JobKey key = new JobKey(name, group); + List triggers = (List) scheduler.getTriggersOfJob(key); + if (triggers.size() == 0) { + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("params", params); + JobDetail jobDetail = JobBuilder.newJob(cls) + .withIdentity(name, group) + .usingJobData(jobDataMap) + .build(); + CronTrigger trigger = TriggerBuilder.newTrigger() + .withIdentity(name, group) + .withSchedule(CronScheduleBuilder.cronSchedule(cron)) + .build(); + scheduler.scheduleJob(jobDetail, trigger); + if (!scheduler.isShutdown()) { + scheduler.start(); + } + } + } catch (Exception e) { + throw new HttpException(70002); + } + } + + /** + * 删除定时器 + * + * @param name 定时器名称 + * @param group 定时器组名 + */ + public void deleteJob(String name, String group) { + try { + JobKey key = new JobKey(name, group); + List triggers = (List) scheduler.getTriggersOfJob(key); + if (triggers.size() > 0) { + TriggerKey triggerKey = TriggerKey.triggerKey(name, group); + scheduler.pauseTrigger(triggerKey); + scheduler.unscheduleJob(triggerKey); + scheduler.deleteJob(JobKey.jobKey(name, group)); + } + } catch (Exception e) { + throw new HttpException(70003); + } + } +} \ No newline at end of file diff --git a/src/main/resources/application-quartz.properties b/src/main/resources/application-quartz.properties new file mode 100755 index 0000000..0d1f6b6 --- /dev/null +++ b/src/main/resources/application-quartz.properties @@ -0,0 +1,7 @@ +spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX +spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate +spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_ +spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool +spring.quartz.properties.org.quartz.threadPool.threadCount=15 +spring.quartz.properties.org.quartz.threadPool.threadPriority=5 +spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true \ No newline at end of file diff --git a/src/main/resources/code.properties b/src/main/resources/code.properties index 6e59202..abbb579 100644 --- a/src/main/resources/code.properties +++ b/src/main/resources/code.properties @@ -44,4 +44,8 @@ meishu.code-message[10001]=导入失败 meishu.code-message[11001]=该行业已存在 +meishu.code-message[70001]=添加通知失败,通知时间不能小于今天时间 +meishu.code-message[70002]=定时任务创建失败 +meishu.code-message[70003]=定时任务删除失败 + meishu.code-message[12001]=该职级已存在 diff --git a/src/main/resources/mapper/MemberMapper.xml b/src/main/resources/mapper/MemberMapper.xml index 1a7fcc0..754148c 100644 --- a/src/main/resources/mapper/MemberMapper.xml +++ b/src/main/resources/mapper/MemberMapper.xml @@ -206,4 +206,60 @@ + + + + + -- libgit2 0.25.0