SpringCloud还有很多的功能,请大家参照《史上最简单的SpringCloud教程》http://blog.csdn.net/forezp/article/details/69939114 方志朋的博客。
本章开始,将陆续介绍集成quartz、Mybatis、多数据源、动态数据源、redis等功能,供大家参考。
为了尽量简化系统规模,我们重新来建立一个项目,即一个eurkea,一个springboot项目。
1、首先建立maven 的pom项目springcloud-parent进行统一的配置文件管理(配置文件分为开发、测试、UAT、PRD四个文件夹,默认用的dev的文件夹)
pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hotkidceo.parent</groupId>
<artifactId>ceo-springcloud-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>ceo-springcloud-parent</name>
<description>parent</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<profiles>
<profile>
<!-- 本地开发环境 -->
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 测试环境 -->
<id>test</id>
<properties>
<profiles.active>test</profiles.active>
</properties>
</profile>
<profile>
<!-- uat环境 -->
<id>uat</id>
<properties>
<profiles.active>uat</profiles.active>
</properties>
</profile>
<profile>
<!-- 生产环境 -->
<id>prd</id>
<properties>
<profiles.active>prd</profiles.active>
</properties>
</profile>
</profiles>
<build>
<finalName>${project.artifactId}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<!-- 资源根目录排除各环境的配置,防止在生成目录中多余其它目录 -->
<excludes>
<exclude>**/*.*</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources/${profiles.active}</directory>
</resource>
<!-- 加入公用配置 -->
<resource>
<directory>src/main/resources/common</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、建立eureka-server,pom文件如下
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wantceo.eurekaserver</groupId>
<artifactId>ceo-eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>com.hotkidceo.parent</groupId>
<artifactId>ceo-springcloud-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<!--eureka server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- spring boot test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
配置文件如下bootstrap.yml:
spring:
application:
name: ceo-eureka-server
server:
port: 8601
eureka:
instance:
hostname: localhost
server:
enableSelfPreservation: true
renewalPercentThreshold: 0.1
client:
#通过eureka.client.registerWithEureka:false和fetchRegistry:false来表明自己是一个eureka server.
registerWithEureka: false
fetchRegistry: false
编写一个启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaServer {
public static void main(String[] args) {
SpringApplication.run(EurekaServer.class, args);
}
}
3、建立一个springboot的maven项目 cureka-client-test-quartz
pom文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wantceo.eurekaclienttest2</groupId>
<artifactId>ceo-eureka-client-test2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ceo-eureka-client-test2</name>
<parent>
<groupId>com.hotkidceo.parent</groupId>
<artifactId>ceo-springcloud-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<!--eureka server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</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>
<!-- MYSQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 与数据库操作相关的依赖 -->
<!-- Jdbc 模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!-- druid 线程池模块 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.3</version>
</dependency>
<!-- quartz模块 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- spring boot test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
配置文件:
spring:
application:
name: ceo-eureka-client-test-quartz
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1/bpm?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
username: root
password: 123
server:
port: 8641
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8601/eureka/
在resources目录下建立common文件夹,并建立一个applicationContext.xml备用
配置文件目录如下
建立包domain、service、task、util,目录结构如下
在task包里面建立TestTask,增加两个方法 run() 和 run2()
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestTask {
/** 日志对象 */
private static final Logger LOG = LoggerFactory.getLogger(TestTask.class);
public void run() {
if (LOG.isInfoEnabled()) {
LOG.info("测试任务线程开始执行");
//new ScheduleJobService().getScheduleJob();
}
}
public void run2() {
if (LOG.isInfoEnabled()) {
LOG.info("测试任务线程开始执行22222");
//new ScheduleJobService().getScheduleJob();
}
}
在domain里面建立job的实体类ScheduleJob
public class ScheduleJob {
private String jobName;
private String jobGroup;
private String desc;
private String jobStatus;
private String cronExpression;
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 getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getJobStatus() {
return jobStatus;
}
public void setJobStatus(String jobStatus) {
this.jobStatus = jobStatus;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
}
在service包内新增QuartzJobFactory 继承 Job,用于
@DisallowConcurrentExecution
public class QuartzJobFactory implements Job{
private static final Logger LOG = Logger.getLogger(QuartzJobFactory.class.getName());
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LOG.log(Level.INFO, "QuartzJobFactory execute start");
ScheduleJob scheduleJob = (ScheduleJob)context.getMergedJobDataMap().get("scheduleJob");
LOG.log(Level.INFO, "QuartzJobFactory execute end job name :" + scheduleJob.getJobName());
}
}
@DisallowConcurrentExecution 禁止并发执行多个相同定义的JobDetail, 这个注解是加在Job类上的, 但意思并不是不能同时执行多个Job, 而是不能并发执行同一个Job Definition(由JobDetail定义), 但是可以同时执行多个不同的JobDetail, 举例说明,我们有一个Job类,叫做SayHelloJob, 并在这个Job上加了这个注解, 然后在这个Job上定义了很多个JobDetail, 如sayHelloToJoeJobDetail, sayHelloToMikeJobDetail, 那么当scheduler启动时, 不会并发执行多个sayHelloToJoeJobDetail或者sayHelloToMikeJobDetail, 但可以同时执行sayHelloToJoeJobDetail跟sayHelloToMikeJobDetail
创建ScheduleJobService 定时计划服务
public class ScheduleJobService {
private static final Logger Logger = LoggerFactory.getLogger(ScheduleJobService.class);
public void getScheduleJob(){
try {
SchedulerFactoryBean schedulerFactoryBean = SpringApplicationContextUtil.getBean("scheduler");
Scheduler scheduler = schedulerFactoryBean.getScheduler();
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
ScheduleJob job = new ScheduleJob();
job.setJobName(jobKey.getName());
job.setJobGroup(jobKey.getGroup());
job.setDesc("触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
job.setJobStatus(triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
job.setCronExpression(cronExpression);
}
jobList.add(job);
}
}
for (ScheduleJob job : jobList) {
Logger.info("计划列表,name:{},group:{},desc:{},status:{}",job.getJobName(),job.getJobGroup(),job.getDesc(),job.getJobStatus());
}
} catch (SchedulerException e) {
Logger.error("SchedulerException", e);
}
}
}
applicationContext.xml的配置如下:
<!-- 使用MethodInvokingJobDetailFactoryBean,任务类可以不实现Job接口,通过targetMethod指定调用方法-->
<bean id="taskJob" class="com.hotkidceo.springcloud.task.TestTask"/>
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="group" value="job_work"/>
<property name="name" value="job_work_name"/>
<!--false表示等上一个任务执行完后再开启新的任务-->
<property name="concurrent" value="false"/>
<property name="targetObject">
<ref bean="taskJob"/>
</property>
<property name="targetMethod">
<value>run</value>
</property>
</bean>
<bean id="jobDetail2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="group" value="job_work"/>
<property name="name" value="job_work_name2"/>
<!--false表示等上一个任务执行完后再开启新的任务-->
<property name="concurrent" value="false"/>
<property name="targetObject">
<ref bean="taskJob"/>
</property>
<property name="targetMethod">
<value>run2</value>
</property>
</bean>
<!-- 调度触发器 -->
<bean id="myTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="name" value="work_default_name"/>
<property name="group" value="work_default"/>
<property name="jobDetail">
<ref bean="jobDetail" />
</property>
<property name="cronExpression">
<value>0/15 * * * * ?</value>
</property>
</bean>
<bean id="myTrigger2"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="name" value="work_default_name2"/>
<property name="group" value="work_default"/>
<property name="jobDetail">
<ref bean="jobDetail2" />
</property>
<property name="cronExpression">
<value>0/10 * * * * ?</value>
</property>
</bean>
<!-- 调度工厂 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="myTrigger"/>
<ref bean="myTrigger2"/>
</list>
</property>
</bean>
最后建立一个启动类:
@EnableEurekaClient
@SpringBootApplication
@RestController
@ImportResource("applicationContext.xml")
public class EurekaserverClientOneApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaserverClientOneApplication.class, args);
}
}
启动eureka-server 再启动client,输出如下:
2018-07-26 11:04:40.003 INFO 39156 --- [eduler_Worker-3] com.hotkidceo.springcloud.task.TestTask : 测试任务线程开始执行22222
2018-07-26 11:04:45.003 INFO 39156 --- [eduler_Worker-4] com.hotkidceo.springcloud.task.TestTask : 测试任务线程开始执行
2018-07-26 11:04:50.003 INFO 39156 --- [eduler_Worker-5] com.hotkidceo.springcloud.task.TestTask : 测试任务线程开始执行22222
2018-07-26 11:05:00.004 INFO 39156 --- [eduler_Worker-6] com.hotkidceo.springcloud.task.TestTask : 测试任务线程开始执行
2018-07-26 11:05:00.005 INFO 39156 --- [eduler_Worker-7] com.hotkidceo.springcloud.task.TestTask : 测试任务线程开始执行22222
小编的这个方法,基本是从网上找的,用的是配置文件的方法,目的是为了一个job类里面可以写多个任务方法。大家还可以参考下面这个文章
https://blog.csdn.net/zahngjialiang/article/details/78690932 Springboot实现quartz定时
源码地址:
parent
https://gitee.com/EricLoveMia/eric-springcloud-parent.git
server
https://gitee.com/EricLoveMia/eureka-server.git
client
https://gitee.com/EricLoveMia/eureka-client-test-quzrtz.git
sql在quzrtz项目中