springboot2.0+mybatis+postgresql9.6+quartz(修正版)

Posted 正面打爆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot2.0+mybatis+postgresql9.6+quartz(修正版)相关的知识,希望对你有一定的参考价值。

做了一个简单的定时任务。

一、依赖

<dependencies>
		<!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> 
			</dependency> -->
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<version>42.2.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>1.1.10</version>
		</dependency>

		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.2.3</version>
		</dependency>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz-jobs</artifactId>
			<version>2.2.3</version>
		</dependency>

		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>

		<!-- spring-boot-devtools依赖包 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
			<scope>true</scope>
		</dependency>

		<!-- servlet 依赖. 
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<scope>provided</scope>
		</dependency>
		-->
		<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

  以上依赖的版本和顺序不要随意变动,否则会出现问题

二、application.yml

spring:
  quartz:
    #相关属性配置
    properties:
      org:
        quartz:
          scheduler:
            instanceName: clusteredScheduler
            instanceId: AUTO
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
            tablePrefix: QRTZ_
            isClustered: true
            clusterCheckinInterval: 10000
            useProperties: false
            dataSource: quartz
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
          plugin:
            jobInitializer:
              class: org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
              fileNames: quartz_jobs.xml
              failOnFileNotFound: true
              scanInterval: 1000
              wrapInUserTransaction: false
    #数据库方式
    job-store-type: jdbc
    #初始化表结构
    #jdbc:
      #initialize-schema: never

  datasource:
    druid:
      driver-class-name: org.postgresql.Driver
      url: jdbc:postgresql://127.0.0.1:5432/quartz
      username: admin
      password: 123456
  jpa:
    properties:
      hibernate:
        temp: 
          use_jdbc_metadata_defaults: false
        ddl-auto: create #ddl-auto:设为update表示每次都不会重新建表
      show-sql: true
  mvc:
    view:
      prefix: /WEB-INF/jsp/
      suffix: .jsp
  http:
    encoding:
      charset: UTF-8
      enabled: true
      force: true 
      

mybatis: 
  mapperLocations: classpath:mapper/*.xml
  typeAliasesPackage: tk.mapper.model 
      

#      
#  application:
#    name: quartz-cluster-node-second
server:
  port: 8083
  servlet:
    context-path: /test
#####################################################################################################
# 打印日志
logging:
  level:
    root: INFO
    org.hibernate: INFO
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
    com.springms: DEBUG
    com.lyw.timers.mapper: DEBUG
#####################################################################################################
###JSP
########################################################

  自己根据情况修改下数据库的信息

三、一个初始化的任务

<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data
	xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_2_0.xsd"
	version="2.0">
	   <pre-processing-commands>
                <!-- <delete-jobs-in-group>*</delete-jobs-in-group> -->  
                <delete-triggers-in-group>*</delete-triggers-in-group>
        </pre-processing-commands>

        <processing-directives>
                <overwrite-existing-data>true</overwrite-existing-data>
                <ignore-duplicates>false</ignore-duplicates>
        </processing-directives>
	
	<schedule>		 		
		<job>
			<name>PrvdDataJob</name>
			<group>DayEnd</group>
			<description>timer</description>
			<job-class>com.lyw.timers.PrvdDataJob</job-class>
		</job>
		<trigger>
			<cron>
				<name>PrvdDataJobTrigger</name>
				<group>Trigger_DayEnd</group>
				<job-name>PrvdDataJob</job-name>
				<job-group>DayEnd</job-group>
				<cron-expression>*/3 * * * * ?</cron-expression>
			</cron>
		</trigger>
	
	</schedule>
</job-scheduling-data>

  同放于application.yml。

四、定义一个任务类

@Component("PrvdDataJob")
public class PrvdDataJob implements Job{
	static Logger logger = LoggerFactory.getLogger(PrvdDataJob.class);

	public PrvdDataJob() {
		
	}
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		try {
			System.out.println(((CronTrigger)context.getTrigger()).getCronExpression());
//			System.out.println("我的3秒一次");
		} catch (Exception e) {
			throw new JobExecutionException("执行PrvdDataJob任务异常",e);
		}
		
	}

}

五、一个Service类

@Service
public class TimersService {
	
	@Autowired
	private Scheduler scheduler;
	
	@Autowired
	private TimerMapper timerMapper;
	

	public String setTimer(TimerVo tvo) throws Exception{
		
		return buildTimer(tvo);
	}

	/**
	 * 该方法用于获取到相应的任务,并进行设置
	 */
	public String buildTimer(TimerVo tvo) throws Exception{
		Timer timer = new Timer();
		BeanUtils.copyProperties(tvo, timer);
	    //查询名为triggerName的任务
	    timer = timerMapper.getCronTrigger(timer);
	    //记录上一次的expression
	    timer.setBeforeExpression(timer.getExpression());
	    
	    String expression = "";
	    
	    if(tvo.getMonth().length()>0) {
	    	expression = tvo.getSecord()+" "+tvo.getMinute()+" "+tvo.getHour()+" "+tvo.getDay()+" "+tvo.getMonth()+" ?";
	    }
	    if(tvo.getMonth().length()<=0 && tvo.getDay().length()>0) {
	    	expression = tvo.getSecord()+" "+tvo.getMinute()+" "+tvo.getHour()+" "+tvo.getDay()+" * ?";
	    }
	    
	    if(tvo.getWeek().length()>0) {
	    	expression = tvo.getSecord()+" "+tvo.getMinute()+" "+tvo.getHour()+" ? * "+tvo.getWeek();
	    }
	    
	    timer.setExpression(expression);
	    //设置开始时间为time秒调一次
	   
	    
	    //数据有任务触发器
	    if(timer.getName() != null) {
	    	//设置TriggerKey
	    	TriggerKey triggerKey = TriggerKey.triggerKey(timer.getName(), timer.getGroup());
	    	
			//设置JobKey
			JobKey jobKey = JobKey.jobKey(timer.getJobName(), timer.getJobGroup());
		    
		    //判断当前任务存在
		    boolean isExists = scheduler.checkExists(triggerKey);
		    
		    if(isExists) {
		    	//停止任务
//		    	scheduler.pauseTrigger(triggerKey);
//		    	scheduler.pauseJob(jobKey);
		    	//更新任务时间设置
		    	timerMapper.updateByNameAndGroup(timer);
		    	//启动任务
		    	scheduler.resumeJob(jobKey);
		    	scheduler.resumeTrigger(triggerKey);
		    	scheduler.start();
		    	
		    }
	    }
	    
	    return toString(timer);
	}
	
	public String toString(Timer timer) {
		String beforeExpression = timer.getBeforeExpression().replace("*", "").replace("/", "").replace("?", "").trim();
		String expression = timer.getExpression().replace("*", "").replace("/", "").replace("?", "").trim();
		StringBuffer sb = new StringBuffer("任务名: "+timer.getJobName());
		sb.append("
<br/>");
		sb.append("任务所属组: "+timer.getJobGroup());
		sb.append("
<br/>");
		sb.append("上一次时间设置:每 "+beforeExpression+" 秒执行一次");
		sb.append("
<br/>");
		sb.append("当前的时间设置:每 "+expression+" 秒执行一次");
		return sb.toString();
	}
}

六、最后给下Timer和TimerVo类

public class TimerVo extends Timer{
	private String month;
	private String day;
	private String week;
	private String hour;
	private String minute;
	private String secord;
	public String getMonth() {
		return month;
	}
	public void setMonth(String month) {
		this.month = month;
	}
	public String getDay() {
		return day;
	}
	public void setDay(String day) {
		this.day = day;
	}
	public String getWeek() {
		return week;
	}
	public void setWeek(String week) {
		this.week = week;
	}
	public String getHour() {
		return hour;
	}
	public void setHour(String hour) {
		this.hour = hour;
	}
	public String getMinute() {
		return minute;
	}
	public void setMinute(String minute) {
		this.minute = minute;
	}
	public String getSecord() {
		return secord;
	}
	public void setSecord(String secord) {
		this.secord = secord;
	}
	@Override
	public String toString() {
		return "TimerVo [month=" + month + ", day=" + day + ", week=" + week + ", hour=" + hour + ", minute=" + minute
				+ ", secord=" + secord + "]";
	}
	
	
}

  

public class Timer {
	private String name;
	private String group;
	private String expression;
	private String jobName;
	private String jobGroup;
	private String beforeExpression;
	
	public String getBeforeExpression() {
		return beforeExpression;
	}
	public void setBeforeExpression(String beforeExpression) {
		this.beforeExpression = beforeExpression;
	}
	public String getJobName() {
		return jobName;
	}
	public void setJobName(String jobName) {
		this.jobName = jobName;
	}
	public String getJobGroup() {
		return jobGroup;
	}
	public void setJobGroup(String jobGroup) {
		this.jobGroup = jobGroup;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getGroup() {
		return group;
	}
	public void setGroup(String group) {
		this.group = group;
	}
	public String getExpression() {
		return expression;
	}
	public void setExpression(String expression) {
		this.expression = expression;
	}
	
	@Override
	public String toString() {
		return "Timer [name=" + name + ", group=" + group + ", expression=" + expression + "]";
	}
	
	
}

  

七、mapper层这样写

@Repository
public interface TimerMapper {
	
	@Select("select t.trigger_name,t.trigger_group,t.job_name,t.job_group,q.cron_expression from qrtz_cron_triggers q,qrtz_triggers t where 1=1 and t.trigger_name=q.trigger_name and  t.trigger_name=#{name}")
	@Results({
		@Result(property = "name",  column = "trigger_name"),
		@Result(property = "group",  column = "trigger_group"),
		@Result(property = "jobName",  column = "job_name"),
		@Result(property = "jobGroup",  column = "job_group"),
		@Result(property = "expression", column = "cron_expression")
		
	})
	Timer getCronTrigger(Timer timer);
	
	@Update("update qrtz_cron_triggers set cron_expression = #{expression} where trigger_name = #{name} and trigger_group = #{group}")
	void updateByNameAndGroup(Timer timer);
}

  Controller就不再上代码了,这个就是方法调用了,相信大家都没问题。

 

总结:

1、问题最大的是数据库的建立,下载的quartz包中有SQL脚本,很坑的是在postgresql中不能一口气去执行。

2、版本间的依赖总算是摸索出了一套可用的,踩了不少坑。

3、cron表达式的按周,其实一般来说是带上星期几的,例如:每周一,每周三..

4、网上很多写法都是重新new了一个job,我是在数据库先查到那个任务,然后直接更新表达式,再启动一次任务,写法有些不同。

暂时就想到这么多了。

 

以上是关于springboot2.0+mybatis+postgresql9.6+quartz(修正版)的主要内容,如果未能解决你的问题,请参考以下文章

学习整合springboot2.0 和 mybatis,实现基本的CRUD

springboot2.0整合mybatis

SpringBoot2.0 基础案例(10):整合Mybatis框架,集成分页助手插件

SpringBoot2.0之四 简单整合MyBatis

Spring Boot 鉴权之—— springboot2.0.4+mybatis 整合的完整用例

springboot2.0入门-- springboot使用mybatis-generator自动代码生成