目录
一、SpringTask简介及使用方法
1.简介
SpringTask 是 Spring 框架提供的任务调度工具,它允许按照预定的时间自动执行特定的代码逻辑。
因此我们在一个spring项目中使用SpringTask时,无须引入新的依赖。
2.使用方法
1)在启动类上加上@EnableScheduling注解
java
@SpringBootApplication
@EnableScheduling
public class LANApplication {
public static void main(String[] args) {
SpringApplication.run(LANApplication.class,args);
}
}
2)编写定时任务类Task
java
@Component
@Slf4j
public class DataInputPerDayTask {
@Scheduled(cron = "0 0 1 1/2 * ?") // 每隔一天的凌晨1点执行
public void inputData(){
log.info("开始向数据库加入打印机模拟数据...");
// 生成模拟数据并调用service方法保存数据
}
}
3.注意事项
在编写定时任务类Task时,有两个重要的地方需要注意:
1.需要在类前加上@Component注解,将这个类注入到spring容器当中交给容器管理
2.在需要定时执行的方法前加上@Scheduled注解并加上cron表达式来说明定时执行的周期
3.其中cron表达式可在在线生成网站上生成,网址如下:在线Cron表达式生成器
二、实现模拟打印机定时向数据库传入数据
1.用到的DTO类
java
import lombok.Data;
import java.util.Date;
@Data
public class JobTaskDTO {
private Integer id;
private String sn;
private String currentJobId;
private String currentJobName;
private Double currentJobLayerHeight;
private Integer currentJobStartLayer;
private Integer currentJobCurrentLayer;
private Date currentJobStartTime;
private Date currentJobEndTime;
private Date currentJobEstimateTime;
private Integer currentJobMaxLayerNo;
private Date updTime;
private Integer isFinish;
private Integer isOld;
private Double currentJobPowderUsage;
}
java
import lombok.Data;
import java.util.Date;
@Data
public class PrinterStatisticsDTO {
private Integer id;
private String sn;
private String workTimeLong;
private String idleTimeLong;
private Double powderUsage;
private Double printWeight;
private Date date;
}
2.用到的Mapper
java
@Mapper
public interface TaskMapper {
/**
* 插入作业状态数据
* @param jobTaskDTO 作业状态数据对象
* @return 插入结果
*/
@Insert("INSERT INTO printer_job_status (sn, current_job_id, current_job_name, current_job_layer_height, " +
"current_job_start_layer, current_job_current_layer, current_job_start_time, current_job_end_time, " +
"current_job_estimate_time, current_job_max_layer_no, upd_time, is_finish, is_old, " +
"current_job_powder_usage) " +
"VALUES (#{sn}, #{currentJobId}, #{currentJobName}, #{currentJobLayerHeight}, " +
"#{currentJobStartLayer}, #{currentJobCurrentLayer}, #{currentJobStartTime}, #{currentJobEndTime}, " +
"#{currentJobEstimateTime}, #{currentJobMaxLayerNo}, #{updTime}, #{isFinish}, #{isOld}, " +
"#{currentJobPowderUsage})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insertJobStatus(JobTaskDTO jobTaskDTO);
@Insert("INSERT INTO printer_statistics (sn, work_time_long, idle_time_long, powder_usage, print_weight, date) " +
"VALUES (#{sn}, #{workTimeLong}, #{idleTimeLong}, #{powderUsage}, #{printWeight}, #{date})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertPrinterStatistics(PrinterStatisticsDTO printerStatisticsDTO);
}
这里简单解释一下为什么要用mapper,而不是从controller和service开始往下传:
因为打印机从controller传过来的数据时字节流数据,从controller传过来在service中经过解析成对应的对象再传入数据库,如果用Task从controller中传过来,那就要模拟字节流数据和模拟http请求,特别繁琐且复杂,这里直接采用最直接的方式直接在task中封装好对象用mapper传进数据库即可。
3.Task类
java
@Component
@Slf4j
public class DataInputPerDayTask {
@Autowired
private StreamServiceImpl streamServiceImpl;
@Autowired
private TaskMapper taskMapper;
/**
* 每隔一天的凌晨1点执行该方法向数据库传入打印机模拟数据(增加一条打印机)
*/
@Scheduled(cron = "0 0 1 1/2 * ?") // 每隔一天的凌晨1点执行
// @Scheduled(cron = "0/5 * * * * ? ") // 每隔五秒测试
public void inputData(){
// log.info("开始向数据库加入打印机模拟数据...");
// 生成模拟数据并调用service方法保存数据
//PrinterFormat printerFormat = generateMockData();
//treamServiceImpl.savePrinterInfo(printerFormat);
}
/**
* 生成打印机事件数据
*/
@Scheduled(cron = "0 0 1 1/2 * ?") // 每隔一天的凌晨1点执行
// @Scheduled(cron = "0/5 * * * * ? ") // 每隔五秒测试
public void insertJobData() {
log.info("开始向数据库加入打印机事件模拟数据...");
JobTaskDTO jobTaskDTO = generateJobDataTask();
taskMapper.insertJobStatus(jobTaskDTO);
}
@Scheduled(cron = "0 0 1 1/2 * ?") // 每隔一天的凌晨1点执行
// @Scheduled(cron = "0/5 * * * * ? ") // 每隔五秒测试
public void insertPrinterStatisticsData() {
log.info("开始向数据库加入粉料模拟数据...");
PrinterStatisticsDTO printerStatisticsDTO = generatePrinterStatisticsData();
taskMapper.insertPrinterStatistics(printerStatisticsDTO);
}
//-----------------------------以下为生成模拟数据的逻辑----------------------------------------------------
/**
* 生成打印机模拟数据
* @return
*/
private PrinterFormat generateMockData() {
PrinterFormat printerFormat = new PrinterFormat();
// 常规属性
General general = new General();
general.setAirDir("Y+");
general.setDog("SN" + new Random().nextInt(10000));
general.setId("ID" + new Random().nextInt(10000));
general.setManufacturer("广州晋原铭科技有限公司");
general.setManufacturerId("JYM99999T2107GD-CN");
general.setScannerNum(new Random().nextInt(5));
printerFormat.setGeneral(general);
// 振镜卡对象scanner列表
PrinterScannerInfo[] scanners = new PrinterScannerInfo[2]; // 假设有两个scanner
for (int i = 0; i < scanners.length; i++) {
PrinterScannerInfo scanner = new PrinterScannerInfo();
scanner.setColId(new Random().nextInt(10));
scanner.setRowId(new Random().nextInt(10));
scanner.setX0(new Random().nextDouble() * 100);
scanner.setY0(new Random().nextDouble() * 100);
scanners[i] = scanner;
}
printerFormat.setScanners(scanners);
// 工作区属性
Workplate workplate = new Workplate();
workplate.setDepth((int) (new Random().nextDouble() * 100));
workplate.setType("square");
workplate.setWidth((int) (new Random().nextDouble() * 100));
workplate.setZoneCols(new Random().nextInt(5));
workplate.setZoneOverlap(new Random().nextInt(5));
workplate.setZoneRows(new Random().nextInt(5));
PrinterZoneInfo[] zones = new PrinterZoneInfo[2]; // 假设有两个zone
for (int i = 0; i < zones.length; i++) {
PrinterZoneInfo zone = new PrinterZoneInfo();
zone.setColId(new Random().nextInt(10));
zone.setRowId(new Random().nextInt(10));
zone.setDepth(new Random().nextDouble() * 100);
zone.setWidth(new Random().nextDouble() * 100);
zone.setX0(new Random().nextDouble() * 100);
zone.setY0(new Random().nextDouble() * 100);
zones[i] = zone;
}
workplate.setZones(zones);
printerFormat.setWorkplate(workplate);
return printerFormat;
}
/**
* 生成打印机事件数据
* @return
*/
private JobTaskDTO generateJobDataTask() {
JobTaskDTO jobTaskDTO = new JobTaskDTO();
jobTaskDTO.setSn("SN20241111");
jobTaskDTO.setCurrentJobId("_240904_114708");
jobTaskDTO.setCurrentJobName("auto_240904_1147");
jobTaskDTO.setCurrentJobLayerHeight(0.029999999329447746);
jobTaskDTO.setCurrentJobStartLayer(new Random().nextInt(769) + 1); // 假设起始层数是1到769之间的随机数
jobTaskDTO.setCurrentJobCurrentLayer(new Random().nextInt(769) + 1); // 假设当前层数是1到769之间的随机数
jobTaskDTO.setCurrentJobStartTime(new Date()); // 当前时间
jobTaskDTO.setCurrentJobEndTime(addHours(jobTaskDTO.getCurrentJobStartTime(), 2)); // 两小时后的时间
jobTaskDTO.setCurrentJobEstimateTime(addHours(jobTaskDTO.getCurrentJobStartTime(), 4)); // 四小时后的时间
jobTaskDTO.setCurrentJobMaxLayerNo(769);
jobTaskDTO.setUpdTime(new Date());
jobTaskDTO.setIsFinish(new Random().nextInt(2)); // 0或1
jobTaskDTO.setIsOld(new Random().nextInt(2)); // 0或1
jobTaskDTO.setCurrentJobPowderUsage(Math.random() * 100); // 假设粉末使用量是0到100之间的随机数
return jobTaskDTO;
}
/**
* 生成打印机事件模拟数据所用的方法,用于给时间往后推x小时
* @param date
* @param hours
* @return
*/
private Date addHours(Date date, int hours) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.HOUR_OF_DAY, hours);
return cal.getTime();
}
private PrinterStatisticsDTO generatePrinterStatisticsData() {
PrinterStatisticsDTO dto = new PrinterStatisticsDTO();
dto.setSn("SN20241111");
Random random = new Random();
dto.setWorkTimeLong(String.valueOf(random.nextInt(900) + 100));
dto.setIdleTimeLong(String.valueOf(random.nextInt(900) + 100));
DecimalFormat decimalFormat = new DecimalFormat("0.00000000");
dto.setPowderUsage(Double.valueOf(decimalFormat.format(Math.random())));
dto.setPrintWeight(0.0);
dto.setDate(new Date());
return dto;
}
}