如果使用 springboot 内置的 TaskScheduler 定时任务实现动态任务,请阅读
最近项目用到Quartz,所以花了几天时间折腾下,记录一下,送给刚接触且迷茫的小伙伴,分别介绍2种方式
Quartz的表不用多说,要么去官网下载,要么去包里找 D:\web\apache-maven-repository\org\quartz-scheduler\quartz\2.3.2\quartz-2.3.2.jar!\org\quartz\impl\jdbcjobstore\tables_mysql_innodb.sql
,然后执行一下脚本即可。
我在项目里是做成了一个自定义的 task-spring-boot-starter,方便其他地方使用,引入依赖
io.github.chichengyu
task-spring-boot-starter
1.3.3.RELEASE
即可使用。下面进入正题
一:jpa
导包:
org.springframework.boot
spring-boot-starter-quartz
mysql
mysql-connector-java
5.1.41
再看配置 application.yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/quartz?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT
username: root
password: 123456
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: never
ok了,没错就是这么简单的配置,然后写一个定时任务执行一下就可以持久化到数据库
重点说下第二种,
二:jdbc
导包:
org.springframework.boot
spring-boot-starter-data-jdbc
org.springframework.boot
spring-boot-starter-quartz
mysql
mysql-connector-java
5.1.41
配置 application.yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/quartz?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT
username: root
password: 123456
首先创建一个工具类 SpringContextUtils.java
package com.example.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring Context 工具类
*/
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static Object getBean(String name){
return applicationContext.getBean(name);
}
public static T getBean(Class clazz){
return applicationContext.getBean(clazz);
}
public static T getBean(String name,Class 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 extends Object> getType(String name){
return applicationContext.getType(name);
}
}
接着创建 Quartz
配置类 QuartzConfig.java
,内容中的方式一、方式二差效果都一样,本人比较喜欢第一种,不多说,爽,哈哈
package com.example.job;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
/**
* Quartz配置
*/
@Configuration
@EnableScheduling
public class QuartzConfig {
/*********************************** 方式一 start **************************************/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
//quartz参数
Properties prop = new Properties();
prop.put("org.quartz.scheduler.instanceName", "TaskScheduler");
prop.put("org.quartz.scheduler.instanceId", "AUTO");
//线程池配置
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "20");
prop.put("org.quartz.threadPool.threadPriority", "5");
//JobStore配置
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
//集群配置
prop.put("org.quartz.jobStore.isClustered", "false");// 集群时一定要设置为 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_");
prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
//PostgreSQL数据库,需要打开此注释
//prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
/* 使用动态注入数据源
prop.put("org.quartz.jobStore.dataSource","qzDS");
prop.put("org.quartz.dataSource.qzDS.driver","com.mysql.jdbc.Driver");
prop.put("org.quartz.dataSource.qzDS.URL","jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=UTF-8&useSSL=false");
prop.put("org.quartz.dataSource.qzDS.user","root");
prop.put("org.quartz.dataSource.qzDS.password","123456");
prop.put("org.quartz.dataSource.qzDS.maxConnections","60");*/
factory.setQuartzProperties(prop);
factory.setSchedulerName("TaskScheduler");
//延时启动
factory.setStartupDelay(30);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
//可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
factory.setOverwriteExistingJobs(true);
//设置自动启动,默认为true
factory.setAutoStartup(true);
return factory;
}
/*********************************** 方式一 end **************************************/
//-------------------------------------------------------------------------------------
/*********************************** 方式二 start **************************************/
/*@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setQuartzProperties(quartzProperties());
return factory;
}
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
//在quartz.properties中的属性被读取并注入后再初始化对象
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}*/
/**
* quartz初始化监听器
*/
/*@Bean
public QuartzInitializerListener executorListener() {
return new QuartzInitializerListener();
}*/
/**
* 通过SchedulerFactoryBean获取Scheduler的实例
*/
/*@Bean(name = "Scheduler")
public Scheduler scheduler() throws IOException {
return schedulerFactoryBean().getScheduler();
}*/
/*********************************** 方式二 end **************************************/
}
继续创建定时任务执行Bean QuartzJob.java
继承 Quartz 的 QuartzJobBean
package com.example.job;
import com.example.job.pojo.TaskJobEntity;
import com.example.job.pojo.TaskJobLogEntity;
import com.example.service.TaskJobLogService;
import com.example.util.R;
import com.example.util.SpringContextUtils;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.lang.reflect.Method;
import java.util.Date;
/**
* 定时任务
*/
@DisallowConcurrentExecution//上次任务没有执行完,下次任务推迟执行
public class QuartzJob extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
TaskJobEntity taskJobEntity = (TaskJobEntity) jobExecutionContext.getMergedJobDataMap().get(TaskJobEntity.JOB_PARAM_KEY);
logger.info("定时器参数,{}",taskJobEntity);
// 获取日志服务对象Bean
TaskJobLogService logService = SpringContextUtils.getBean(TaskJobLogService.class);
//数据库保存执行记录
TaskJobLogEntity logEntity = new TaskJobLogEntity();
logEntity.setJobId(taskJobEntity.getJobId());
logEntity.setBeanName(taskJobEntity.getBeanName());
logEntity.setParams(taskJobEntity.getParams());
logEntity.setCreateTime(new Date());
// 任务开始执行时间
long startTime = System.currentTimeMillis();
try {
//执行任务
logger.debug("任务准备执行,任务ID:" + taskJobEntity.getJobId());
Object target = SpringContextUtils.getBean(taskJobEntity.getBeanName());
Method method = target.getClass().getDeclaredMethod("run", String.class);
R> result = (R>)method.invoke(target,taskJobEntity.getParams());
// 任务执行时长
long times = System.currentTimeMillis() - startTime;
//任务状态 0:成功 1:失败
logEntity.setTimes((int) times);
logEntity.setStatus(0);
if (null != result) {
logEntity.setStatus(result.getCode());
logEntity.setMessage(result.getMsg());
}
logger.debug("任务执行完毕,任务ID:" + taskJobEntity.getJobId() + " 总共耗时:" + times + "毫秒");
} catch (Exception e) {
logger.error("任务执行失败,任务ID:" + taskJobEntity.getJobId(), e);
// 任务执行时长
long times = System.currentTimeMillis() - startTime;
// 任务状态 0:成功 1:失败 记录数据库
logEntity.setTimes((int)times);
logEntity.setStatus(1);
logEntity.setError(e.toString());
}finally {
// 最终记录到数据库
logService.save(logEntity);
}
}
}
继续创建一个工具-定时任务管理 QuartzJobManager.java
,包含任务的添加
、更新
、删除
、暂停
、执行
方法
package com.example.job;
import com.example.job.pojo.TaskJobEntity;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* 定时任务管理
*/
@Component
public class QuartzJobManager {
// 前缀
private final String JOB_NAME = "TASK_";
@Autowired
private SchedulerFactoryBean schedulerFactoryBean;
//@Autowired
//private Scheduler scheduler;
/**
* 获取调度器
* @return
*/
public Scheduler getScheduler(){
return schedulerFactoryBean.getScheduler();
}
/**
* 获取 jobkey
* @param jobId
* @return
*/
public JobKey getJobKey(Long jobId){
return JobKey.jobKey(JOB_NAME + jobId);
}
/**
* 获取 triggerKey
* @param jobId
* @return
*/
public TriggerKey getTriggerKey(Long jobId){
return TriggerKey.triggerKey(JOB_NAME + jobId);
}
/**
* 获取表达式触发器
* @param scheduler
* @param jobId
* @return
*/
public CronTrigger getCronTrigger(Scheduler scheduler,Long jobId){
try {
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
} catch (SchedulerException e) {
throw new RuntimeException("获取定时任务CronTrigger出现异常", e);
}
}
/**
* 创建任务
* @param taskJobEntity 任务实体类(对应自定义的数据库任务表)
* @return Date 返回创建任务成功后执行时间
*/
public Date createScheduleJob(TaskJobEntity taskJobEntity){
try {
// 1.获取调度器 Scheduler
Scheduler scheduler = getScheduler();
// 2.定义 jobDetail(构建job信息)
JobDetail jobDetail = JobBuilder.newJob(QuartzJob.class).withIdentity(getJobKey(taskJobEntity.getJobId())).build();
// 3.定义trigger(按新的cronExpression表达式构建一个新的trigger)
// 不触发立即执行,等待下次Cron触发频率到达时刻开始按照Cron频率依次执行 withMisfireHandlingInstructionDoNothing
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(taskJobEntity.getCronExpression()).withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(taskJobEntity.getJobId())).withSchedule(cronScheduleBuilder).build();
// 放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(TaskJobEntity.JOB_PARAM_KEY,taskJobEntity);
// 4.执行
Date startTime = scheduler.scheduleJob(jobDetail,trigger);
// 暂停任务
if (taskJobEntity.getStatus() == 1){// 0表示继续,1表示暂停
pauseJob(taskJobEntity.getJobId());
}
return startTime;
} catch (SchedulerException e) {
throw new RuntimeException("创建定时任务失败",e);
}
}
/**
* 更新定时任务
* @param taskJobEntity 任务实体类(对应自定义的数据库任务表)
* @return Date 返回更新任务成功后执行时间
*/
public Date updateScheduleJob(TaskJobEntity taskJobEntity){
try {
TriggerKey triggerKey = getTriggerKey(taskJobEntity.getJobId());
// 1.获取调度器 Scheduler
Scheduler scheduler = getScheduler();
// 2.获取 cron 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(taskJobEntity.getCronExpression()).withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = getCronTrigger(scheduler, taskJobEntity.getJobId());
// 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
// 放入参数,运行时的方法可以获取
trigger.getJobDataMap().put(TaskJobEntity.JOB_PARAM_KEY,taskJobEntity);
// 3.执行
Date updateTime = scheduler.rescheduleJob(triggerKey,trigger);
// 暂停任务
if (taskJobEntity.getStatus() == 1){// 0表示继续,1表示暂停
pauseJob(taskJobEntity.getJobId());
}
return updateTime;
} catch (SchedulerException e) {
throw new RuntimeException("更新定时任务失败",e);
}
}
/**
* 立即执行(让定时任务立即执行,**注意:暂停状态下的定时任务,如果立即执行,只会执行一次,相当于一次性执行)
* @param taskJobEntity 任务实体类(对应自定义的数据库任务表)
*/
public void run(TaskJobEntity taskJobEntity){
try {
// 参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(TaskJobEntity.JOB_PARAM_KEY,taskJobEntity);
getScheduler().triggerJob(getJobKey(taskJobEntity.getJobId()),dataMap);
} catch (SchedulerException e) {
throw new RuntimeException("立即执行定时任务失败",e);
}
}
/**
* 暂停任务
* @param jobId 任务jobId
*/
public void pauseJob(Long jobId){
try {
getScheduler().pauseJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RuntimeException("暂停定时任务失败",e);
}
}
/**
* 恢复任务
* @param jobId 任务jobId
*/
public void resumeJob(Long jobId){
try {
getScheduler().resumeJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RuntimeException("恢复定时任务失败",e);
}
}
/**
* 验证定时任务是否存在
* @param jobId 任务id
* @return
*/
public boolean check(Long jobId){
try {
return getScheduler().checkExists(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RuntimeException("验证定时任务是否存在失败",e);
}
}
/**
* 删除定时任务
* @param jobId 定时任务id
*/
public void deleteScheduleJob(Long jobId){
// 1.获取调度器 Scheduler
Scheduler scheduler = getScheduler();
try {
// 2.暂停触发器
scheduler.pauseTrigger(getTriggerKey(jobId));
// 3.删除触发器
scheduler.unscheduleJob(getTriggerKey(jobId));
// 4.删除任务
scheduler.deleteJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RuntimeException("删除定时任务失败",e);
}
}
}
别急,还没完,继续创建接口 ITask.java
,这个接口的作用就是,需要添加定时器时只需要实现该接口即可(如:需要多个定时器,只需要创建多个类来实现该接口
)
package com.example.job.task;
import com.example.util.R;
/**
* 定时任务接口,所有定时任务都要实现该接口
*/
public interface ITask {
/**
* 执行定时任务接口
* @param params 参数,多参数使用JSON数据
* @return R
*/
R run(String params);
}
接口内容很简单吧,就一个待实现方法,好了,到此基本完成了,接下来创建一个测试定时器 TestTask
,注意了,这个测试定时器只需要实现定时器接口 ITask.java
,并实现 run
方法,注意:该名称必须与我们自定义的定时器表中的 Bean 名称一致
package com.example.job.task;
import com.example.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 测试定时器
*/
@Slf4j
@Component("testTask") // 该名称必须与我们自定义的定时器表中的 Bean 名称一致
public class TestTask implements ITask{
/**
* 执行定时任务接口
* @param params 参数,多参数使用JSON数据
* @return R
*/
@Override
public R run(String params) {
log.info("测试定时器任务执行了,{}",params);
return R.success("ok");
}
}
ok了到此,大功告成。现在只需要创建一个测试控制器来添加一个测试定时控制器TestController.java
来 添加
、删除
、暂停
我们的定时任务就可以了
package com.example.job;
import com.example.job.pojo.TaskJobEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* 测试定时器
*/
@RestController
public class TestController {
@Autowired
private QuartzJobManager quartzJobManager;
@GetMapping("/check")
public String testQuartzCheck(){
boolean res1 = quartzJobManager.check(100L);
boolean res2 = quartzJobManager.check(200L);
boolean res3 = quartzJobManager.check(300L);
return "ok:验证任务是否存在," + res1 + "," + res2 + "," + res3;
}
@GetMapping("/addjob")
public String testQuartzAdd() {
TaskJobEntity taskJobEntity = new TaskJobEntity();
taskJobEntity.setBeanName("testTask");
taskJobEntity.setJobId(100L);
taskJobEntity.setStatus(0);
taskJobEntity.setParams("我是测试定时器");
taskJobEntity.setCronExpression("*/2 * * * * ?");
taskJobEntity.setRemark("测试");
taskJobEntity.setCreateTime(new Date());
Date startTime = quartzJobManager.createScheduleJob(taskJobEntity);
return "ok:开始时间," + startTime;
}
@GetMapping("/updatejob")
public String testQuartzUpdate(){
TaskJobEntity taskJobEntity = new TaskJobEntity();
taskJobEntity.setBeanName("testTask");
taskJobEntity.setJobId(100L);
taskJobEntity.setStatus(0);
taskJobEntity.setParams("修改-我是测试定时器");
taskJobEntity.setCronExpression("*/10 * * * * ?");
taskJobEntity.setRemark("修改-测试");
taskJobEntity.setCreateTime(new Date());
Date updateTime = quartzJobManager.updateScheduleJob(taskJobEntity);
return "ok:修改成功,时间," + updateTime;
}
@GetMapping("/runjob")
public String testQuartzRunJob(){
TaskJobEntity taskJobEntity = new TaskJobEntity();
taskJobEntity.setBeanName("testTask");
taskJobEntity.setJobId(100L);
taskJobEntity.setStatus(0);
taskJobEntity.setParams("立即执行-我是测试定时器");
taskJobEntity.setCronExpression("*/2 * * * * ?");
taskJobEntity.setRemark("立即执行-测试");
taskJobEntity.setCreateTime(new Date());
quartzJobManager.run(taskJobEntity);
return "ok:立即执行成功";
}
@GetMapping("/pausejob")
public String testQuartzPauseJob(){
quartzJobManager.pauseJob(100L);
return "ok:暂停成功";
}
@GetMapping("/resumejob")
public String testQuartzResumeJob(){
quartzJobManager.resumeJob(100L);
return "ok:恢复成功";
}
@GetMapping("/delete")
public String testQuartzDelete(){
quartzJobManager.deleteScheduleJob(100L);
return "ok:删除成功";
}
}
到此彻底完成了,好了,启动springBoot,访问接口,查看是不是定时器是不是成功了,再看数据库是不是已经有记录了,恭喜你。
提供一下Quartz实现中用到的自定义的两张表
、实体类
、R类
自定义的两张表 定时器表 task_job
与 定时器日志表 task_job_log
CREATE TABLE `task_job` (
`job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务id',
`bean_name` varchar(200) DEFAULT NULL COMMENT 'spring bean名称',
`params` text COMMENT '参数',
`cron_expression` varchar(100) DEFAULT NULL COMMENT 'cron表达式',
`status` tinyint(4) DEFAULT NULL COMMENT '任务状态 0:正常 1:暂停',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`job_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='定时任务';
CREATE TABLE `task_job_log` (
`log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务日志id',
`job_id` bigint(20) NOT NULL COMMENT '任务id',
`bean_name` varchar(200) DEFAULT NULL COMMENT 'spring bean名称',
`params` text COMMENT '参数',
`status` tinyint(4) NOT NULL COMMENT '任务状态 0:成功 1:失败',
`message` text COMMENT '正常信息',
`error` text COMMENT '失败信息',
`times` int(11) NOT NULL COMMENT '耗时(单位:毫秒)',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`log_id`),
KEY `job_id` (`job_id`),
KEY `create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='定时任务日志';
对应的实体类
package com.example.job.pojo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 定时任务
*/
@Data
public class TaskJobEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 任务调度参数key
*/
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
/**
* 任务id
*/
private Long jobId;
/**
* spring bean名称
*/
private String beanName;
/**
* 参数
*/
private String params;
/**
* cron表达式
*/
private String cronExpression;
/**
* 任务状态
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
}
日志实体类
package com.example.job.pojo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 定时任务日志
*/
@Data
public class TaskJobLogEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 日志id
*/
private Long logId;
/**
* 任务id
*/
private Long jobId;
/**
* spring bean名称
*/
private String beanName;
/**
* 参数
*/
private String params;
/**
* 任务状态 0:成功 1:失败
*/
private Integer status;
/**
* 正常信息
*/
private String message;
/**
* 失败信息
*/
private String error;
/**
* 耗时(单位:毫秒)
*/
private Integer times;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
}
用到的 R.java
类
package com.example.util;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.io.Serializable;
/**
* 返回数据类
* @param
*/
//保证序列化json的时候,如果是null的对象,key也会消失
//@JsonInclude(Include.NON_NULL)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class R implements Serializable {
// 成功值
private static final int SUCCESS_CODE = 0;
// 失败值
private static final int ERROR_CODE = 1;
//状态码
private int code;
//消息
private String msg;
//返回数据
private T data;
private R(int code){
this.code = code;
}
private R(int code, T data){
this.code = code;
this.data = data;
}
private R(int code, String msg){
this.code = code;
this.msg = msg;
}
private R(int code, String msg, T data){
this.code = code;
this.msg = msg;
this.data = data;
}
public static R success(){
return new R(SUCCESS_CODE,"success");
}
public static R success(String msg){
return new R(SUCCESS_CODE,msg);
}
public static R success(T data){
return new R(SUCCESS_CODE,data);
}
public static R success(String msg, T data){
return new R(SUCCESS_CODE,msg,data);
}
public static R error(){
return new R(ERROR_CODE,"error");
}
public static R error(String msg){
return new R(ERROR_CODE,msg);
}
public static R error(int code, String msg){
return new R(code,msg);
}
public int getCode(){
return code;
}
public String getMsg(){
return msg;
}
public T getData(){
return data;
}
}