feat: 初始化

This commit is contained in:
2024-04-09 11:34:46 +08:00
commit 39f3acc15f
3209 changed files with 253442 additions and 0 deletions
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>febs-server-job</artifactId>
<groupId>com.yida.data.job</groupId>
<version>2.2-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>febs-server-job-biz</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--补充包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!--定时任务-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
</dependency>
<dependency>
<groupId>com.yida.data.school</groupId>
<artifactId>edu-school-api</artifactId>
<version>${febs-cloud.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yida.data.device</groupId>
<artifactId>edu-device-api</artifactId>
<version>${febs-cloud.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yida.data.attendance</groupId>
<artifactId>attendance-api</artifactId>
<version>${febs-cloud.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yida.data.user</groupId>
<artifactId>edu-user-api</artifactId>
<version>${febs-cloud.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yida.data.system</groupId>
<artifactId>febs-server-system-api</artifactId>
<version>${febs-cloud.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yida.data.customForm</groupId>
<artifactId>edu-custom-form-api</artifactId>
<version>2.2-RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yida.data.mall.api</groupId>
<artifactId>edu-mall-api</artifactId>
<version>${febs-cloud.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<outputDirectory>../../../febs-jar</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,26 @@
package com.yida.data.job;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.openfeign.EnableFeignClients;
import cc.mrbird.febs.common.security.starter.annotation.EnableFebsCloudResourceServer;
/**
* @author MrBird
*/
@EnableFeignClients(basePackages = "com.yida.data")
@SpringBootApplication
@EnableFebsCloudResourceServer
@MapperScan("com.yida.data.job.mapper")
public class FebsServerJobApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(FebsServerJobApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
@@ -0,0 +1,27 @@
package com.yida.data.job.annotation;
import com.yida.data.job.validator.CronValidator;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
/**
* @author MrBird
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CronValidator.class)
public @interface IsCron {
String message();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -0,0 +1,90 @@
package com.yida.data.job.configure;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.yida.data.job.constant.JobConstant;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.jdbcjobstore.JobStoreTX;
import org.quartz.simpl.SimpleThreadPool;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.util.Properties;
import java.util.concurrent.ThreadPoolExecutor;
import javax.sql.DataSource;
import lombok.RequiredArgsConstructor;
/**
* 定时任务配置
* http://www.quartz-scheduler.org/documentation/quartz-2.3.0/configuration/
*
* @author MrBird
*/
@Configuration
@RequiredArgsConstructor
public class FebsJobConfigure {
private final DataSource dataSource;
@Bean(JobConstant.JOB_POOL)
public ThreadPoolTaskExecutor scheduleJobExecutorService() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(20);
executor.setKeepAliveSeconds(30);
executor.setThreadNamePrefix("Febs-Job-Thread");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("jobExecutor") ThreadPoolTaskExecutor executor) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
// 设置数据源
DataSource job = ((DynamicRoutingDataSource) dataSource).getDataSource("job");
factory.setDataSource(job);
Properties prop = new Properties();
// 任务调度实例名称,集群时多个实例名称保持一致
prop.put(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME, "FebsCloudScheduler");
// 任务调度实例ID,指定为AUTO时,将自动生成ID
prop.put(StdSchedulerFactory.PROP_SCHED_INSTANCE_ID, StdSchedulerFactory.AUTO_GENERATE_INSTANCE_ID);
// quartz提供的简单线程池,适用于绝大部分场景
prop.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS, SimpleThreadPool.class);
// 并发执行任务的线程数,取决于服务器系统资源
prop.put("org.quartz.threadPool.threadCount", "20");
// 可以是Thread.MIN_PRIORITY1)和Thread.MAX_PRIORITY10)之间的任何int值 。
// 默认值为Thread.NORM_PRIORITY5
prop.put("org.quartz.threadPool.threadPriority", "5");
// 指定任务存储策略,这里使用关系型数据库
prop.put(StdSchedulerFactory.PROP_JOB_STORE_CLASS, JobStoreTX.class);
// 是否开启集群
prop.put("org.quartz.jobStore.isClustered", "true");
// 集群中任务调度实例失效的检查时间间隔,单位为毫秒
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
// 数据表前缀
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
factory.setQuartzProperties(prop);
factory.setSchedulerName("FEBS_Cloud_Scheduler");
// 延时启动
factory.setStartupDelay(1);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
// 启动时更新己存在的 Job
factory.setOverwriteExistingJobs(true);
// 设置自动启动,默认为 true
factory.setAutoStartup(true);
factory.setTaskExecutor(executor);
return factory;
}
}
@@ -0,0 +1,9 @@
package com.yida.data.job.constant;
public interface JobConstant {
/**
* 线程池名称
*/
String JOB_POOL = "jobExecutor";
}
@@ -0,0 +1,35 @@
package com.yida.data.job.controller;
import com.yida.data.common.core.entity.job.Job;
import com.yida.data.job.service.IJobService;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* @author chenbo
*/
@Api(tags = "不鉴权商品上架")
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/in/job")
public class InJobController {
private final IJobService jobService;
@PostMapping("/saveJobNoPermission")
public void saveJobNoPermission(@RequestBody Job job) {
this.jobService.createJob(job);
}
}
@@ -0,0 +1,109 @@
package com.yida.data.job.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.entity.FebsResponse;
import com.yida.data.common.core.entity.QueryRequest;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.job.Job;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.job.service.IJobService;
import org.quartz.CronExpression;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* @author MrBird
*/
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
public class JobController {
private final IJobService jobService;
@GetMapping
@PreAuthorize("hasAuthority('job:view')")
public FebsResponse jobList(QueryRequest request, Job job) {
Map<String, Object> dataTable = FebsUtil.getDataTable(this.jobService.findJobs(request, job));
return new FebsResponse().data(dataTable);
}
@GetMapping("cron/check")
public boolean checkCron(String cron) {
try {
return CronExpression.isValidExpression(cron);
} catch (Exception e) {
return false;
}
}
@PostMapping
public void addJob(@RequestBody @Valid Job job) {
this.jobService.createJob(job);
}
@DeleteMapping("{jobIds}")
@PreAuthorize("hasAuthority('job:delete')")
public void deleteJob(@NotBlank(message = "{required}") @PathVariable String jobIds) {
String[] ids = jobIds.split(StringConstant.COMMA);
this.jobService.deleteJobs(ids);
}
@GetMapping("/delJobByMethod")
public void delJob(String beanName,
String methodName,
String params) {
log.info("param:{},{},{}", beanName, methodName, params);
List<Job> list = jobService.list(Wrappers.lambdaQuery(new Job())
.eq(Job::getBeanName, beanName)
.eq(Job::getMethodName, methodName)
.eq(Job::getParams, params));
log.info("data:{}", list);
if (CollUtil.isNotEmpty(list)) {
this.jobService.deleteJobs(list.stream().map(x -> x.getJobId().toString()).toArray(String[]::new));
}
}
@GetMapping("run/{jobIds}")
@PreAuthorize("hasAuthority('job:run')")
public void runJob(@NotBlank(message = "{required}") @PathVariable String jobIds) {
this.jobService.run(jobIds);
}
@GetMapping("pause/{jobIds}")
@PreAuthorize("hasAuthority('job:pause')")
public void pauseJob(@NotBlank(message = "{required}") @PathVariable String jobIds) {
this.jobService.pause(jobIds);
}
@GetMapping("resume/{jobIds}")
@PreAuthorize("hasAuthority('job:resume')")
public void resumeJob(@NotBlank(message = "{required}") @PathVariable String jobIds) {
this.jobService.resume(jobIds);
}
@PostMapping("excel")
@PreAuthorize("hasAuthority('job:export')")
public void export(QueryRequest request, Job job, HttpServletResponse response) {
List<Job> jobs = this.jobService.findJobs(request, job).getRecords();
}
}
@@ -0,0 +1,59 @@
package com.yida.data.job.controller;
import com.yida.data.common.core.entity.FebsResponse;
import com.yida.data.common.core.entity.QueryRequest;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.job.JobLog;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.job.service.IJobLogService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* @author MrBird
*/
@Slf4j
@Validated
@RestController
@RequestMapping("log")
@RequiredArgsConstructor
public class JobLogController {
private final IJobLogService jobLogService;
@GetMapping
@PreAuthorize("hasAuthority('job:log:view')")
public FebsResponse jobLogList(QueryRequest request, JobLog log) {
Map<String, Object> dataTable = FebsUtil.getDataTable(this.jobLogService.findJobLogs(request, log));
return new FebsResponse().data(dataTable);
}
@DeleteMapping("{jobIds}")
@PreAuthorize("hasAuthority('job:log:delete')")
public void deleteJobLog(@NotBlank(message = "{required}") @PathVariable String jobIds) {
String[] ids = jobIds.split(StringConstant.COMMA);
this.jobLogService.deleteJobLogs(ids);
}
@GetMapping("excel")
@PreAuthorize("hasAuthority('job:log:export')")
public void export(QueryRequest request, JobLog jobLog, HttpServletResponse response) {
List<JobLog> jobLogs = this.jobLogService.findJobLogs(request, jobLog).getRecords();
//ExcelKit.$Export(JobLog.class, response).downXlsx(jobLogs, false);
}
}
@@ -0,0 +1,55 @@
package com.yida.data.job.helper;
import com.yida.data.common.core.entity.job.Job;
import com.yida.data.common.core.entity.job.JobLog;
import com.yida.data.job.service.IJobLogService;
import com.yida.data.job.utils.SpringContextUtil;
import java.util.concurrent.Future;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* 定时任务
*
* @author MrBird
*/
@Slf4j
public class ScheduleJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) {
ThreadPoolTaskExecutor scheduleJobExecutorService = SpringContextUtil.getBean(ThreadPoolTaskExecutor.class);
Job scheduleJob = (Job) context.getMergedJobDataMap().get(Job.JOB_PARAM_KEY);
IJobLogService scheduleJobLogService = SpringContextUtil.getBean(IJobLogService.class);
JobLog jobLog = new JobLog();
jobLog.setJobId(scheduleJob.getJobId());
jobLog.setBeanName(scheduleJob.getBeanName());
jobLog.setMethodName(scheduleJob.getMethodName());
jobLog.setParams(scheduleJob.getParams());
long startTime = System.currentTimeMillis();
try {
// 执行任务
ScheduleRunnable task = new ScheduleRunnable(scheduleJob.getBeanName(), scheduleJob.getMethodName(),
scheduleJob.getParams());
Future<?> future = scheduleJobExecutorService.submit(task);
future.get();
long times = System.currentTimeMillis() - startTime;
jobLog.setTimes(times);
jobLog.setStatus(JobLog.JOB_SUCCESS);
} catch (Exception e) {
log.error("任务执行失败,任务ID:{},任务方法名称:{}" + scheduleJob.getJobId(), scheduleJob.getMethodName(), e);
long times = System.currentTimeMillis() - startTime;
jobLog.setTimes(times);
jobLog.setStatus(JobLog.JOB_FAIL);
jobLog.setError(StringUtils.substring(e.toString(), 0, 2000));
} finally {
scheduleJobLogService.saveJobLog(jobLog);
}
}
}
@@ -0,0 +1,49 @@
package com.yida.data.job.helper;
import com.yida.data.job.utils.SpringContextUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import lombok.extern.slf4j.Slf4j;
/**
* 执行定时任务
*
* @author MrBird
*/
@Slf4j
public class ScheduleRunnable implements Runnable {
private final Object target;
private final Method method;
private final String params;
ScheduleRunnable(String beanName, String methodName, String params) throws NoSuchMethodException, SecurityException {
this.target = SpringContextUtil.getBean(beanName);
this.params = params;
if (StringUtils.isNotBlank(params)) {
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
} else {
this.method = target.getClass().getDeclaredMethod(methodName);
}
}
@Override
public void run() {
try {
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotBlank(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
} catch (Exception e) {
log.error("执行定时任务失败", e);
}
}
}
@@ -0,0 +1,176 @@
package com.yida.data.job.helper;
import com.yida.data.common.core.entity.job.Job;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import java.util.Date;
import lombok.extern.slf4j.Slf4j;
/**
* 定时任务工具类
*
* @author MrBird
*/
@Slf4j
public class ScheduleUtils {
private static final String JOB_NAME_PREFIX = "TASK_";
/**
* 获取触发器 key
*/
private static TriggerKey getTriggerKey(Long jobId) {
return TriggerKey.triggerKey(JOB_NAME_PREFIX + jobId);
}
/**
* 获取jobKey
*/
private static JobKey getJobKey(Long jobId) {
return JobKey.jobKey(JOB_NAME_PREFIX + jobId);
}
/**
* 获取表达式触发器
*/
public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
try {
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
} catch (SchedulerException e) {
log.error("获取Cron表达式失败", e);
}
return null;
}
/**
* 创建定时任务
*/
public static void createScheduleJob(Scheduler scheduler, Job scheduleJob) {
try {
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class)
.withIdentity(getJobKey(scheduleJob.getJobId()))
.build();
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
// 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(getTriggerKey(scheduleJob.getJobId()))
.withSchedule(scheduleBuilder).build();
Date nextFireTime = trigger.getFireTimeAfter(trigger.getStartTime());
if (nextFireTime == null || nextFireTime.before(new Date())) {
return;
}
// 放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(Job.JOB_PARAM_KEY, scheduleJob);
scheduler.scheduleJob(jobDetail, trigger);
// 暂停任务
if (scheduleJob.getStatus().equals(Job.ScheduleStatus.PAUSE.getValue())) {
pauseJob(scheduler, scheduleJob.getJobId());
}
log.info("添加定时任务,[{}]", scheduleJob);
} catch (SchedulerException e) {
log.error("创建定时任务失败", e);
}
}
/**
* 更新定时任务
*/
public static void updateScheduleJob(Scheduler scheduler, Job scheduleJob) {
try {
TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());
if (trigger == null) {
throw new SchedulerException("获取Cron表达式失败");
} else {
// 按新的 cronExpression表达式重新构建 trigger
trigger = trigger.getTriggerBuilder()
.withIdentity(triggerKey)
.withSchedule(scheduleBuilder)
.build();
// 参数
trigger.getJobDataMap().put(Job.JOB_PARAM_KEY, scheduleJob);
}
Date nextFireTime = trigger.getNextFireTime();
if (nextFireTime == null || nextFireTime.before(new Date())) {
return;
}
scheduler.rescheduleJob(triggerKey, trigger);
// 暂停任务
if (scheduleJob.getStatus().equals(Job.ScheduleStatus.PAUSE.getValue())) {
pauseJob(scheduler, scheduleJob.getJobId());
}
} catch (SchedulerException e) {
log.error("更新定时任务失败", e);
}
}
/**
* 立即执行任务
*/
public static void run(Scheduler scheduler, Job scheduleJob) {
try {
// 参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(Job.JOB_PARAM_KEY, scheduleJob);
scheduler.triggerJob(getJobKey(scheduleJob.getJobId()), dataMap);
} catch (SchedulerException e) {
log.error("执行定时任务失败", e);
}
}
/**
* 暂停任务
*/
public static void pauseJob(Scheduler scheduler, Long jobId) {
try {
scheduler.pauseJob(getJobKey(jobId));
} catch (SchedulerException e) {
log.error("暂停定时任务失败", e);
}
}
/**
* 恢复任务
*/
public static void resumeJob(Scheduler scheduler, Long jobId) {
try {
scheduler.resumeJob(getJobKey(jobId));
} catch (SchedulerException e) {
log.error("恢复定时任务失败", e);
}
}
/**
* 删除定时任务
*/
public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
try {
scheduler.deleteJob(getJobKey(jobId));
} catch (SchedulerException e) {
log.error("删除定时任务失败", e);
}
}
}
@@ -0,0 +1,10 @@
package com.yida.data.job.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.job.JobLog;
/**
* @author MrBird
*/
public interface JobLogMapper extends BaseMapper<JobLog> {
}
@@ -0,0 +1,20 @@
package com.yida.data.job.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.job.Job;
import java.util.List;
/**
* @author MrBird
*/
public interface JobMapper extends BaseMapper<Job> {
/**
* 获取定时任务列表
*
* @return 定时任务列表
*/
List<Job> queryList();
}
@@ -0,0 +1,39 @@
package com.yida.data.job.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.QueryRequest;
import com.yida.data.common.core.entity.job.JobLog;
import com.yida.data.job.constant.JobConstant;
import org.springframework.scheduling.annotation.Async;
/**
* @author MrBird
*/
public interface IJobLogService extends IService<JobLog> {
/**
* 获取定时任务日志分页数据
*
* @param request request
* @param jobLog jobLog
* @return 定时任务日志分页数据
*/
IPage<JobLog> findJobLogs(QueryRequest request, JobLog jobLog);
/**
* 保存定时任务日志
*
* @param log 定时任务日志
*/
@Async(JobConstant.JOB_POOL)
void saveJobLog(JobLog log);
/**
* 删除定时任务日志
*
* @param jobLogIds 定时任务日志id数组
*/
void deleteJobLogs(String[] jobLogIds);
}
@@ -0,0 +1,73 @@
package com.yida.data.job.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.QueryRequest;
import com.yida.data.common.core.entity.job.Job;
/**
* @author MrBird
*/
public interface IJobService extends IService<Job> {
/**
* 获取定时任务
*
* @param jobId 任务id
* @return 定时任务
*/
Job findJob(Long jobId);
/**
* 获取定时任务分页数据
*
* @param request request
* @param job job
* @return 定时任务分页数据
*/
IPage<Job> findJobs(QueryRequest request, Job job);
/**
* 创建定时任务
*
* @param job job
*/
void createJob(Job job);
/**
* 删除定时任务
*
* @param jobIds 定时任务id数组
*/
void deleteJobs(String[] jobIds);
/**
* 批量更新定时任务状态
*
* @param jobIds 定时任务id
* @param status 待更新状态
*/
void updateBatch(String jobIds, String status);
/**
* 运行定时任务
*
* @param jobIds 定时任务id
*/
void run(String jobIds);
/**
* 暂停定时任务
*
* @param jobIds 定时任务id
*/
void pause(String jobIds);
/**
* 恢复定时任务
*
* @param jobIds 定时任务id
*/
void resume(String jobIds);
}
@@ -0,0 +1,58 @@
package com.yida.data.job.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.QueryRequest;
import com.yida.data.common.core.entity.constant.FebsConstant;
import com.yida.data.common.core.entity.job.JobLog;
import com.yida.data.common.core.utils.SortUtil;
import com.yida.data.job.mapper.JobLogMapper;
import com.yida.data.job.service.IJobLogService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
/**
* @author MrBird
*/
@Slf4j
@Service("JobLogService")
public class JobLogServiceImpl extends ServiceImpl<JobLogMapper, JobLog> implements IJobLogService {
@Override
public IPage<JobLog> findJobLogs(QueryRequest request, JobLog jobLog) {
LambdaQueryWrapper<JobLog> queryWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(jobLog.getBeanName())) {
queryWrapper.eq(JobLog::getBeanName, jobLog.getBeanName());
}
if (StringUtils.isNotBlank(jobLog.getMethodName())) {
queryWrapper.eq(JobLog::getMethodName, jobLog.getMethodName());
}
if (StringUtils.isNotBlank(jobLog.getStatus())) {
queryWrapper.eq(JobLog::getStatus, jobLog.getStatus());
}
Page<JobLog> page = new Page<>(request.getPageNum(), request.getPageSize());
SortUtil.handlePageSort(request, page, "createTime", FebsConstant.ORDER_DESC, true);
return this.page(page, queryWrapper);
}
@Override
public void saveJobLog(JobLog log) {
this.save(log);
}
@Override
public void deleteJobLogs(String[] jobLogIds) {
List<String> list = Arrays.asList(jobLogIds);
this.baseMapper.deleteBatchIds(list);
}
}
@@ -0,0 +1,154 @@
package com.yida.data.job.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.QueryRequest;
import com.yida.data.common.core.entity.constant.FebsConstant;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.job.Job;
import com.yida.data.common.core.utils.SortUtil;
import com.yida.data.job.helper.ScheduleUtils;
import com.yida.data.job.mapper.JobMapper;
import com.yida.data.job.service.IJobService;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* @author MrBird
*/
@Slf4j
@Service("JobService")
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class JobServiceImpl extends ServiceImpl<JobMapper, Job> implements IJobService {
private final Scheduler scheduler;
/**
* 项目启动时,初始化定时器
*/
@PostConstruct
public void init() {
List<Job> scheduleJobList = this.baseMapper.queryList();
// 如果不存在,则创建
scheduleJobList.forEach(scheduleJob -> {
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobId());
if (cronTrigger == null) {
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
} else {
ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
}
});
}
@Override
public Job findJob(Long jobId) {
return this.getById(jobId);
}
@Override
public IPage<Job> findJobs(QueryRequest request, Job job) {
LambdaQueryWrapper<Job> queryWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(job.getBeanName())) {
queryWrapper.eq(Job::getBeanName, job.getBeanName());
}
if (StringUtils.isNotBlank(job.getMethodName())) {
queryWrapper.eq(Job::getMethodName, job.getMethodName());
}
if (StringUtils.isNotBlank(job.getParams())) {
queryWrapper.like(Job::getParams, job.getParams());
}
if (StringUtils.isNotBlank(job.getRemark())) {
queryWrapper.like(Job::getRemark, job.getRemark());
}
if (StringUtils.isNotBlank(job.getStatus())) {
queryWrapper.eq(Job::getStatus, job.getStatus());
}
if (job.getType() != null) {
queryWrapper.eq(Job::getType, job.getType());
}
if (StringUtils.isNotBlank(job.getCreateTimeFrom()) && StringUtils.isNotBlank(job.getCreateTimeTo())) {
queryWrapper
.ge(Job::getCreateDate, job.getCreateTimeFrom())
.le(Job::getCreateDate, job.getCreateTimeTo());
}
Page<Job> page = new Page<>(request.getPageNum(), request.getPageSize());
SortUtil.handlePageSort(request, page, "createTime", FebsConstant.ORDER_DESC, true);
IPage<Job> page1 = this.page(page, queryWrapper);
return page1;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void createJob(Job job) {
if (job.getJobId() == null) {
if (StrUtil.isBlank(job.getStatus())) {
job.setStatus(Job.ScheduleStatus.PAUSE.getValue());
}
save(job);
ScheduleUtils.createScheduleJob(scheduler, job);
} else {
ScheduleUtils.updateScheduleJob(scheduler, job);
updateById(job);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteJobs(String[] jobIds) {
List<String> list = Arrays.asList(jobIds);
log.info("ids:{}", jobIds);
list.forEach(jobId -> ScheduleUtils.deleteScheduleJob(scheduler, Long.valueOf(jobId)));
this.baseMapper.deleteBatchIds(list);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateBatch(String jobIds, String status) {
List<String> list = Arrays.asList(jobIds.split(StringConstant.COMMA));
Job job = new Job();
job.setStatus(status);
this.baseMapper.update(job, new LambdaQueryWrapper<Job>().in(Job::getJobId, list));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void run(String jobIds) {
String[] list = jobIds.split(StringConstant.COMMA);
Arrays.stream(list).forEach(jobId -> ScheduleUtils.run(scheduler, this.findJob(Long.valueOf(jobId))));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void pause(String jobIds) {
String[] list = jobIds.split(StringConstant.COMMA);
Arrays.stream(list).forEach(jobId -> ScheduleUtils.pauseJob(scheduler, Long.valueOf(jobId)));
this.updateBatch(jobIds, Job.ScheduleStatus.PAUSE.getValue());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void resume(String jobIds) {
String[] list = jobIds.split(StringConstant.COMMA);
Arrays.stream(list).forEach(jobId -> ScheduleUtils.resumeJob(scheduler, Long.valueOf(jobId)));
this.updateBatch(jobIds, Job.ScheduleStatus.NORMAL.getValue());
}
}
@@ -0,0 +1,28 @@
package com.yida.data.job.task;
import com.yida.data.school.feign.transaction.RemoteProductOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@RequiredArgsConstructor
public class ApplyProductService {
private final RemoteProductOrderService remoteProductOrderService;
/**
* 更新订单状态
*/
public void updateOrderStatus() {
remoteProductOrderService.updateOrderStatus();
}
/**
* 更新退款订单状态
*/
public void updateRefundStatus() {
remoteProductOrderService.updateRefundStatus();
}
}
@@ -0,0 +1,60 @@
package com.yida.data.job.task;
import com.yida.data.attendance.feign.RemoteAttendanceDeviceService;
import com.yida.data.attendance.feign.RemoteAttendanceResultService;
import com.yida.data.attendance.feign.RemoteUserStrategyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 考勤相关定时任务
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class AttendanceTask {
private final RemoteUserStrategyService remoteUserStrategyService;
private final RemoteAttendanceResultService remoteAttendanceResultService;
private final RemoteAttendanceDeviceService remoteAttendanceDeviceService;
/**
* 更新设备在线状态
*/
public void updateDeviceStatus() {
remoteAttendanceDeviceService.updateDeviceStatus();
}
/**
* 校时所有设备
*/
public void timingAllDevice() {
remoteAttendanceDeviceService.timingAllDevice();
}
/**
* 初始化考勤结果
*/
public void initAttendanceData() {
remoteAttendanceResultService.initAttendanceResult();
}
/**
* 考勤报告推送
*/
public void attendanceNotice() {
remoteAttendanceResultService.attendanceNotice();
}
/**
* 处理超时用户策略
*/
public void checkOverTimeUserStrategy() {
remoteUserStrategyService.checkOverTimeUserStrategy();
}
}
@@ -0,0 +1,48 @@
package com.yida.data.job.task;
import com.yida.data.mall.feign.RemoteBillOrderService;
import com.yida.data.mall.feign.RemoteBillStatisticsService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 账单模块相关定时任务
*
* @author ZYJ
* @date 2022/4/14
*/
@Component
@AllArgsConstructor
public class BillTask {
private final RemoteBillOrderService remoteBillOrderService;
private final RemoteBillStatisticsService remoteBillStatisticsService;
/**
* 更新超时账单订单状态
*/
public void updateBillOrderStatus() {
remoteBillOrderService.updateBillOrderStatus();
}
/**
* 更新退款订单状态
*/
public void updateRefundStatus() {
remoteBillOrderService.updateRefundStatus();
}
/**
* 更新缴费统计数据
*/
public void updateBillStatistics() {
remoteBillStatisticsService.updateBillStatistics();
}
/**
* 更新缴费账单明细数据
*/
public void updateBillPayDetail() {
remoteBillStatisticsService.updateBillPayDetail();
}
}
@@ -0,0 +1,32 @@
package com.yida.data.job.task;
import com.yida.data.device.feign.consume.RemoteConsumeOrderService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 消费订单模块相关定时任务
*
* @author ZYJ
* @date 2023/4/13
*/
@Component
@AllArgsConstructor
public class ConsumeTask {
private final RemoteConsumeOrderService remoteConsumeOrderService;
/**
* 更新超时订单状态
*/
public void updateOrderStatus() {
remoteConsumeOrderService.updateOrderStatus();
}
/**
* 更新退款订单状态
*/
public void updateRefundStatus() {
remoteConsumeOrderService.updateRefundStatus();
}
}
@@ -0,0 +1,29 @@
package com.yida.data.job.task;
import com.yida.data.customForm.feign.RemoteFormService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author ccl
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class FormUpdateTask {
@Resource
private RemoteFormService remoteFormService;
public void formUpdate(String id) {
log.info("执行表单发布定时任务,id:[{}]", id);
remoteFormService.updateById(Long.valueOf(id));
}
public void formRemind(String id) {
log.info("执行表单定时提醒任务,id:[{}]", id);
remoteFormService.remindLast(Long.valueOf(id));
}
}
@@ -0,0 +1,27 @@
package com.yida.data.job.task;
import com.yida.data.mall.feign.RemoteBillOrderService;
import com.yida.data.mall.feign.RemoteBillStatisticsService;
import com.yida.data.school.feign.smart.RemoteSmartWelcomeService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 迎新指南模块相关定时任务
*
* @author ZYJ
* @date 2023/6/21
*/
@Component
@AllArgsConstructor
public class GuideTask {
private final RemoteSmartWelcomeService remoteSmartWelcomeService;
/**
* 更新超时迎新订单状态
*/
public void updateGuideRosterOrderStatus() {
remoteSmartWelcomeService.updateGuideRosterOrderStatus();
}
}
@@ -0,0 +1,43 @@
package com.yida.data.job.task;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.entity.job.Job;
import com.yida.data.job.service.IJobService;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.cron.pattern.CronPattern;
import cn.hutool.cron.pattern.CronPatternUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
@RequiredArgsConstructor
public class JobTask {
private final IJobService jobService;
/**
* 清理过期的用户定时任务
*/
public void cleanExpiredUserJob() {
List<Job> list = jobService.list(Wrappers.<Job>lambdaQuery()
.eq(Job::getType, 1));
List<String> delJobs = new ArrayList<>();
for (Job job : list) {
Date date = CronPatternUtil.nextDateAfter(new CronPattern(job.getCronExpression()), new Date(), true);
log.info("clean job,date:{}", date);
if (date == null) {
delJobs.add(job.getJobId().toString());
}
}
if (CollUtil.isNotEmpty(delJobs)) {
jobService.deleteJobs(delJobs.toArray(new String[0]));
}
}
}
@@ -0,0 +1,16 @@
package com.yida.data.job.task;
import com.yida.data.system.feign.RemoteCommonService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class MsgTask {
private final RemoteCommonService remoteCommonService;
public void saveReceiveMsg() {
remoteCommonService.saveReceiveMsg();
}
}
@@ -0,0 +1,24 @@
package com.yida.data.job.task;
import com.yida.data.school.feign.news.RemoteNoticeUpdateService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author ccl
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class NoticeUpdateTask {
private final RemoteNoticeUpdateService remoteNoticeUpdateService;
public void noticeUpdate(String id) {
log.info("执行更新商品定时任务,id:[{}]", id);
remoteNoticeUpdateService.updateBuyNoticeById(Long.valueOf(id));
}
}
@@ -0,0 +1,40 @@
package com.yida.data.job.task;
import com.yida.data.school.feign.transaction.RemoteProductService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author ccl
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class ProductUpdateTask {
private final RemoteProductService remoteProductService;
public void productUpdate(String id) {
log.info("执行更新商品定时任务,id:[{}]", id);
remoteProductService.upDateProductById(Long.valueOf(id));
}
public void productSendNotice(String id) {
log.info("执行商品催缴定时任务,id:[{}]", id);
remoteProductService.productSendNotice(Long.valueOf(id));
}
/**
* 监测商品是否失效任务
*
* @param
*/
public void productMonitor() {
log.info("执行更新商品定时任务,id:[{}]");
remoteProductService.productMonitor();
}
}
@@ -0,0 +1,17 @@
package com.yida.data.job.task;
import com.yida.data.school.feign.news.RemoteManuscriptService;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
@Component
@RequiredArgsConstructor
public class SchoolManuscriptTask {
private final RemoteManuscriptService remoteManuscriptService;
public void publishManuscript(String manuscriptId) {
remoteManuscriptService.publishManuscript(Long.valueOf(manuscriptId));
}
}
@@ -0,0 +1,20 @@
package com.yida.data.job.task;
import com.yida.data.school.feign.news.RemoteNoticeSchoolService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
@Slf4j
public class SchoolNoticeTask {
private final RemoteNoticeSchoolService remoteNoticeSchoolService;
public void sendSchoolNotice(String noticeId) {
log.info("发送学校通知任务执行,id:[{}]", noticeId);
remoteNoticeSchoolService.sendNotice(Long.valueOf(noticeId));
}
}
@@ -0,0 +1,28 @@
package com.yida.data.job.task;
import com.yida.data.device.feign.studentCard.RemoteStudentCardService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
@Slf4j
public class StudentCardTask {
private final RemoteStudentCardService remoteStudentCardService;
/**
* 更新设备定位
*/
public void updateCardPos() {
remoteStudentCardService.updateCardPos();
}
/**
* 更新设备在线状态
*/
public void updateCardStatus() {
remoteStudentCardService.updateCardStatus();
}
}
@@ -0,0 +1,27 @@
package com.yida.data.job.task;
import com.yida.data.system.feign.RemoteDeptService;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
@Component
@RequiredArgsConstructor
public class SysTask {
private final RemoteDeptService remoteDeptService;
/**
* 同步企业微信部门
*/
public void syncQywxDept() {
remoteDeptService.syncQywxDept();
}
/**
* 处理挂在学校下的部门
*/
public void dealNoParentDept() {
remoteDeptService.dealNoParentDept();
}
}
@@ -0,0 +1,22 @@
package com.yida.data.job.task;
import com.yida.data.device.feign.telephone.RemoteTelephoneService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
@Slf4j
public class TelephoneTask {
private final RemoteTelephoneService remoteTelephoneService;
/**
* 更新话机在线状态
*/
public void updateTelephoneStatus() {
remoteTelephoneService.updateTelephoneStatus();
}
}
@@ -0,0 +1,67 @@
package com.yida.data.job.task;
import com.yida.data.user.feign.RemoteStaffService;
import com.yida.data.user.feign.RemoteStudentService;
import com.yida.data.user.feign.RemoteUserDeptService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 用户模块相关定时任务
*
* @author ZYJ
* @date 2021/11/30
*/
@Component
@AllArgsConstructor
public class UserTask {
private final RemoteStudentService remoteStudentService;
private final RemoteStaffService remoteStaffService;
private final RemoteUserDeptService remoteUserDeptService;
/**
* 同步企业微信学生信息
*/
public void syncQywxStudent() {
remoteStudentService.syncQywxStudent();
}
/**
* 同步企业微信职工信息
*/
public void syncQywxStaff() {
remoteStaffService.syncQywxStaff();
}
/**
* 同步企业微信家校部门
*/
public void syncUserDept() {
remoteUserDeptService.syncUserDept();
}
/**
* 处理挂在学校下的家校部门
*/
public void dealNoParentUserDept() {
remoteUserDeptService.dealNoParentUserDept();
}
/**
* 定时更新学生数据缓存
*/
public void updateStudentCache() {
remoteStudentService.updateStudentCache();
}
/**
* 定时更新教职工数据缓存
*/
public void updateStaffCache() {
remoteStaffService.updateStaffCache();
}
}
@@ -0,0 +1,19 @@
package com.yida.data.job.task;
import com.yida.data.school.feign.visitor.RemoteVisitorService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class VisitorTask {
private final RemoteVisitorService remoteVisitorService;
/**
* 过期请求
*/
public void dealRequestDdl() {
remoteVisitorService.dealRequestDdl();
}
}
@@ -0,0 +1,46 @@
package com.yida.data.job.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* 用于从 IOC容器中获取 Bean
*
* @author MrBird
*/
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
public static boolean isSingleton(String name) {
return applicationContext.isSingleton(name);
}
public static Class<?> getType(String name) {
return applicationContext.getType(name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
}
@@ -0,0 +1,29 @@
package com.yida.data.job.validator;
import com.yida.data.job.annotation.IsCron;
import org.quartz.CronExpression;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* 校验是否为合法的 Cron表达式
*
* @author MrBird
*/
public class CronValidator implements ConstraintValidator<IsCron, String> {
@Override
public void initialize(IsCron isCron) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
try {
return CronExpression.isValidExpression(value);
} catch (Exception e) {
return false;
}
}
}
@@ -0,0 +1,6 @@
required=\u4E0D\u80FD\u4E3A\u7A7A
range=\u6709\u6548\u957f\u5ea6{min}\u5230{max}\u4e2a\u5b57\u7b26
email=\u90ae\u7bb1\u683c\u5f0f\u4e0d\u5408\u6cd5
mobile=\u624b\u673a\u53f7\u4e0d\u5408\u6cd5
noMoreThan=\u957f\u5ea6\u4e0d\u80fd\u8d85\u8fc7{max}\u4e2a\u5b57\u7b26
invalid=\u503c\u4e0d\u5408\u6cd5
@@ -0,0 +1,9 @@
████████ ██████ ████████ ████████ ███████ ██ ██
░░░░░░██ ░█░░░░██ ░░░░░░██ ░██░░░░░ ░██░░░░██ ░██ ░██
██ ░█ ░██ ██ ░██ ░██ ░██░██ ░██
██ ░██████ ██ █████░███████ ░██ ░██░██ ░██
██ ░█░░░░ ██ ██ ░░░░░ ░██░░░░ ░██ ░██░██ ░██
██ ░█ ░██ ██ ░██ ░██ ██ ░██ ░██
████████░███████ ████████ ░████████░███████ ░░███████
░░░░░░░░ ░░░░░░░ ░░░░░░░░ ░░░░░░░░ ░░░░░░░ ░░░░░░░
${spring.application.name}
@@ -0,0 +1,29 @@
spring:
profiles:
active: "@env-name@"
application:
name: FEBS-Server-Job
cloud:
nacos:
config:
server-addr: ${nacos.url}
group: DEFAULT_GROUP
prefix: febs-server-job
file-extension: yaml
discovery:
server-addr: ${nacos.url}
logging:
level:
org:
springframework:
boot:
actuate:
endpoint:
EndpointId: error
com:
alibaba:
cloud:
nacos:
client:
NacosPropertySourceBuilder: error
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.job.mapper.JobMapper">
<select id="queryList" resultType="com.yida.data.common.core.entity.job.Job">
select job_id jobId,
bean_name beanName,
method_name methodName,
params,
cron_expression cronExpression,
status,
remark,
create_time createTime
from t_job
where STATUS = 0
order by job_id
</select>
</mapper>