015 springboot自动装配(中台:ElasticJob基础组件封装案例)

        spring在进行扩展的时候,最常用的就是@Autowired 自动装配或Module-wired模块装配(@EnableXXX),Module-wired是将模块整体引入工程中,然后通过几个自定义注解完成应用;

step1. 创建springboot工程rabbit-task引入依赖pom.xml

<properties>
		<java.version>1.8</java.version>
		<elastic-job.version>2.1.4</elastic-job.version>
	</properties>

	<dependencies>
	    <!-- spring boot dependency -->
	    <dependency>
	      	<groupId>org.springframework.boot</groupId>
	      	<artifactId>spring-boot-starter</artifactId>
	    </dependency>
		<!--  elastic-job dependency -->
	    <dependency>
	      <groupId>com.dangdang</groupId>
	      <artifactId>elastic-job-lite-core</artifactId>
	      <version>${elastic-job.version}</version>
	    </dependency>
	    <dependency>
	      <groupId>com.dangdang</groupId>
	      <artifactId>elastic-job-lite-spring</artifactId>
	      <version>${elastic-job.version}</version>
	    </dependency>
	    <dependency>
	    	<groupId>org.springframework.boot</groupId>
	    	<artifactId>spring-boot-configuration-processor</artifactId>
	    	<optional>true</optional>
	    </dependency>
	</dependencies>

step2. 创建JobParserAutoConfigure自动装配类

import org.springframework.context.annotation.Configuration;

@Configuration
public class JobParserAutoConfigure {

}

step3. 创建spring.fatories自动装配加载文件

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.cc.rabbit.task.autoconfigure.JobParserAutoConfigure

        如此rabbit-task构建完成后,引入其他工程时,就会自动找到spring.fatories文件,并将由@Configuration声明的JobParserAutoConfigure做相关的初始化或其他操作,此装配为无条件默认装配。

step4. 通过@Conditional做条件装配:常用@ConditionalOnProperty()进行条件设置,其条件代表需要在application.properties或*.properties文件中配置规定的参数,才启动装配;

通过elastic-job配置来举个例子,elastic-job的使用需要依赖zookeeper配置,将namespace、serverLists作为必须配置参数作为装配条件,同时也是构造条件(官方API设定),其他配置项通过JobZookeeperProperties类进行封装,传入ZookeeperRegistryCenter完成注册中心初始化:

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;


/**
 * @ConditionalOnProperty(prefix = "elastic.job.zk", name = {"namespace","serverLists"},matchIfMissing = false)
 * 引入rabbit-task的工程必须在application.properties中配置elastic.job.zk.namespace和
 * elastic.job.zk.serverLists两个属性,才会装配成功,matchIfMissing = false如果没有配置两个参数
 * 那么rabbit-task就不会加载,此处为强约定;
 * @EnableConfigurationProperties(JobZookeeperProperties.class),当@ConditionalOnProperty验证通过后,将elastic.job.zk
 * 为前缀的配置参数读到JobZookeeperProperties中;然后初始化registryCenter。
 */

@Configuration
@ConditionalOnProperty(prefix = "elastic.job.zk", name = {"namespace","serverLists"},matchIfMissing = false)
@EnableConfigurationProperties(JobZookeeperProperties.class)
public class JobParserAutoConfigure {
	//初始化RegistryCenter
	@Bean(initMethod = "init")
	public ZookeeperRegistryCenter zookeeperRegistryCenter(JobZookeeperProperties jobZookeeperProperties) {//如果将ZookeeperRegistryCenter注入到spring容器,那么Bean的名字就是方法名字(约定)
		
		ZookeeperConfiguration zkConfig = new ZookeeperConfiguration(jobZookeeperProperties.getServerLists(),
				jobZookeeperProperties.getNamespace());
		zkConfig.setBaseSleepTimeMilliseconds(zkConfig.getBaseSleepTimeMilliseconds());
		zkConfig.setMaxSleepTimeMilliseconds(zkConfig.getMaxSleepTimeMilliseconds());
		zkConfig.setConnectionTimeoutMilliseconds(zkConfig.getConnectionTimeoutMilliseconds());
		zkConfig.setSessionTimeoutMilliseconds(zkConfig.getSessionTimeoutMilliseconds());
		zkConfig.setMaxRetries(zkConfig.getMaxRetries());
		zkConfig.setDigest(zkConfig.getDigest());
		System.out.println("初始化job注册中心配置成功"+zkConfig.getNamespace());
	
		return new ZookeeperRegistryCenter(zkConfig);
	}
}
import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Data;
/**
 * 装载配置参数
 * 装载任何封装组件属性参数时,都要参考官方进行对应,必要配置项扫描加载,
 * 非必要配置项要设定默认值,范围要根据官方给定的有效范围进行设定;
 * 必要配置与非必要配置区分,其一根据业务设定,其二官方在属性说明中
 * 会有是否为构造器注入,是就为必要配置,否即为非必要配置。
 */
@Data
@ConfigurationProperties(prefix = "elastic.job.zk")
public class JobZookeeperProperties {
	
	private String namespace;
	private String serverLists;
	
	private int maxRetries = 3;
	private int connectionTimeoutMilliseconds = 15000;
	private int sessionTimeoutMilliseconds = 60000;
	private int baseSleepTimeMilliseconds = 1000;
	private int maxSleepTimeMilliseconds = 3000;
	private String digest = "";
	
}

step5. 自定义模块装配注解@EnableElasticJob:模块装配注解,除了自定义注解的四个基本属性,还必须要使用@Import注解,将自定义的配置类JobParserAutoConfigure引入;

package com.cc.rabbit.task.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Import;

import com.cc.rabbit.task.autoconfigure.JobParserAutoConfigure;
/**
 * 1 注解四个基本属性设置;
 * 2 模块注入注解:@Import(JobParserAutoConfigure.class)
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(JobParserAutoConfigure.class)
public @interface EnableElasticJob {

}

step6. 自定义@ElasticJobConfig,进行es-job的基础API参数构建,规避每次创建任务都需要构建job类,实现注解式配置,当需要一个job,那么按照此配置项加载一个类,自动解析;

package com.cc.rabbit.task.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 封装elasticjob官方属性,依据官方api给出的属性参数进行声明;
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ElasticJobConfig {

	/*JobCoreConfiguration属性详细说明*/
    String jobName();	//elasticjob的名称
	String cron() default "";
	int shardingTotalCount() default 1;
	String shardingItemParameters() default "";
	String jobParameter() default "";
	boolean failover() default false;
	boolean misfire() default true;
	String description() default "";
	/*DataflowJobConfiguration属性详细说明---是否流式处理数据*/
	boolean streamingProcess() default false;
	/*ScriptJobConfiguration属性详细说明---脚本型作业*/
	String scriptCommandLine() default "";
	/*LiteJobConfiguration属性详细说明---作业运行监控配置*/
	boolean monitorExecution() default false;
	public int monitorPort() default -1;	//must
	public int maxTimeDiffSeconds() default -1;	//must
	public String jobShardingStrategyClass() default "";	//must
	public int reconcileIntervalMinutes() default 10;	//must
	public String eventTraceRdbDataSource() default "";	//must
	/*job:simple命名空间属性详细说明*/
	public boolean disabled() default false;	//must
	boolean overwrite() default false;
	public String distributedListener() default "";
	public long startedTimeoutMilliseconds() default Long.MAX_VALUE;	//must
	public long completedTimeoutMilliseconds() default Long.MAX_VALUE;		//must
	public String jobExceptionHandler() default "com.dangdang.ddframe.job.executor.handler.impl.DefaultJobExceptionHandler";
	public String executorServiceHandler() default "com.dangdang.ddframe.job.executor.handler.impl.DefaultExecutorServiceHandler";
}

step7. 解析自定义@ElasticJobConfig:JobParserAutoConfigure中创建ElasticJobConfParser来解析注解;

package com.cc.rabbit.task.autoconfigure;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.cc.rabbit.task.parser.ElasticJobConfParser;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;


/**
 * @ConditionalOnProperty(prefix = "elastic.job.zk", name = {"namespace","serverLists"},matchIfMissing = false)
 * 引入rabbit-task的工程必须在application.properties中配置elastic.job.zk.namespace和
 * elastic.job.zk.serverLists两个属性,才会装配成功,matchIfMissing = false如果没有配置两个参数
 * 那么rabbit-task就不会加载,此处为强约定;
 * @EnableConfigurationProperties(JobZookeeperProperties.class),当@ConditionalOnProperty验证通过后,将elastic.job.zk
 * 为前缀的配置参数读到JobZookeeperProperties中;然后初始化registryCenter。
 */

@Configuration
@ConditionalOnProperty(prefix = "elastic.job.zk", name = {"namespace","serverLists"},matchIfMissing = false)
@EnableConfigurationProperties(JobZookeeperProperties.class)
public class JobParserAutoConfigure {
	//初始化RegistryCenter
	@Bean(initMethod = "init")
	public ZookeeperRegistryCenter zookeeperRegistryCenter(JobZookeeperProperties jobZookeeperProperties) {//如果将ZookeeperRegistryCenter注入到spring容器,那么Bean的名字就是方法名字(约定)
		
		ZookeeperConfiguration zkConfig = new ZookeeperConfiguration(jobZookeeperProperties.getServerLists(),
				jobZookeeperProperties.getNamespace());
		zkConfig.setBaseSleepTimeMilliseconds(zkConfig.getBaseSleepTimeMilliseconds());
		zkConfig.setMaxSleepTimeMilliseconds(zkConfig.getMaxSleepTimeMilliseconds());
		zkConfig.setConnectionTimeoutMilliseconds(zkConfig.getConnectionTimeoutMilliseconds());
		zkConfig.setSessionTimeoutMilliseconds(zkConfig.getSessionTimeoutMilliseconds());
		zkConfig.setMaxRetries(zkConfig.getMaxRetries());
		zkConfig.setDigest(zkConfig.getDigest());
		System.out.println("初始化job注册中心配置成功"+zkConfig.getNamespace());
	
		return new ZookeeperRegistryCenter(zkConfig);
	}
	
	@Bean
	public ElasticJobConfParser elasticJobConfParser(JobZookeeperProperties jobZookeeperProperties,ZookeeperRegistryCenter zookeeperRegistryCenter) {
		
		return new ElasticJobConfParser(jobZookeeperProperties,zookeeperRegistryCenter);
	}
}
package com.cc.rabbit.task.parser;

import com.cc.rabbit.task.autoconfigure.JobZookeeperProperties;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;

public class ElasticJobConfParser {

	private JobZookeeperProperties jobZookeeperProperties;
	private ZookeeperRegistryCenter zookeeperRegistryCenter;
	
	public ElasticJobConfParser(JobZookeeperProperties jobZookeeperProperties,
			ZookeeperRegistryCenter zookeeperRegistryCenter) {
		
		this.jobZookeeperProperties = jobZookeeperProperties;
		this.zookeeperRegistryCenter = zookeeperRegistryCenter;
	}

}

logic:

1. 应用时添加@EnableElasticJob注解;

2.@EnableElasticJob加载JobParserAutoConfigure配置;

3.JobParserAutoConfigure先判断@ConditionalOnProperty条件是否满足,如果满足会将application.properties中配置的参数全部读入JobZookeeperProperties对象;

4.初始化zk(ZookeeperRegistryCenter);

5.初始化es-job(ElasticJobConfParser),ElasticJobConfParser专注解析@ElasticJobConfig注解;

step8. 通过ElasticJobTypeEunm(eunm枚举)来定义es-job的三种作业类型:

package com.cc.rabbit.task.enums;

public enum ElasticJobTypeEunm {
	
	SIMPLE("SimpleJob","简单类型job"),
	DATAFLOW("DataflowJob","流式类型job"),
	SCRIPT("ScriptJob","脚本类型job");
	
	private String type;
	private String desc;
	
	private ElasticJobTypeEunm(String type,String desc) {
		this.type = type;
		this.desc = desc;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}
	
	
}

step9. ElasticJobConfParser解析es-job的时机,ElasticJobConfParser与spring直接存在某种依赖关系,那么对于ElasticJobConfParser解析es-job的恰当时机就要在spring提供的一些机制中根据业务场景进行确定,此处举例为分布式定时任务的基础封装,在诸多场景中最为合理的是当应用服务都启动以后,即所有的springBean加载完成后,做es-job的解析,定时任务场景本身就是对于应用服务进行定时作业的一种机制,所有必须保证规划的应用已经存在,才能生效;初始化过程为,先初始化es-job相关的JobCoreConfiguration、SimpleJobConfiguration及LiteJobConfiguration,然后在构建SpringJobScheduler;对比前期代码实现的集成方式,逻辑为相反;

package com.cc.rabbit.task.parser;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.util.StringUtils;

import com.cc.rabbit.task.annotation.ElasticJobConfig;
import com.cc.rabbit.task.autoconfigure.JobZookeeperProperties;
import com.cc.rabbit.task.enums.ElasticJobTypeEunm;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.JobTypeConfiguration;
import com.dangdang.ddframe.job.config.dataflow.DataflowJobConfiguration;
import com.dangdang.ddframe.job.config.script.ScriptJobConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.event.rdb.JobEventRdbConfiguration;
import com.dangdang.ddframe.job.executor.handler.JobProperties;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.lite.spring.api.SpringJobScheduler;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;

public class ElasticJobConfParser implements ApplicationListener<ApplicationReadyEvent>{

	private JobZookeeperProperties jobZookeeperProperties;
	private ZookeeperRegistryCenter zookeeperRegistryCenter;
	
	public ElasticJobConfParser(JobZookeeperProperties jobZookeeperProperties,
			ZookeeperRegistryCenter zookeeperRegistryCenter) {
		
		this.jobZookeeperProperties = jobZookeeperProperties;
		this.zookeeperRegistryCenter = zookeeperRegistryCenter;
	}

	@Override
	public void onApplicationEvent(ApplicationReadyEvent event) {
		try {
			//获取应用上下文
			ApplicationContext applicationContext = event.getApplicationContext();
			//获取所有添加@ElasticJobConfig注解的bean
			Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(ElasticJobConfig.class);
			//循环所有Bean,独立配置,初始化相关内容
			for(Iterator<?> it = beanMap.values().iterator();it.hasNext();) {
				Object confBean = it.next();
				Class<?> clazz = confBean.getClass();
				//如果是一个子类,匿名或带有“$”符号,将真正的名字取出复制给clazz
				if(clazz.getName().indexOf("$") > 0) {
					String className = clazz.getName();
					//从0截取到$前为真正的类名
					clazz = Class.forName(className.substring(0,className.indexOf("$")));
				}
				/* 获取接口类型,用于判断任务类型(简单类型、流式、脚本)
				 * 此处简写,取第一个interface;
				 * 正常生产中类可能实现多个interface,要遍历判断;
				 */
				String jobTypeName = clazz.getInterfaces()[0].getSimpleName();
				//获取ElasticJobConfig的配置项
				ElasticJobConfig conf = clazz.getAnnotation(ElasticJobConfig.class);
				
				String jobClass = clazz.getName();
				//防止重复:使用Namespace加jobname组合
				//String jobName = conf.jobName();
				String jobName = this.jobZookeeperProperties.getNamespace() +"."+ conf.jobName();
				String cron = conf.cron();
				String shardingItemParameters = conf.shardingItemParameters();
				String description = conf.description();
				String jobParameter = conf.jobParameter();
				String jobExceptionHandler = conf.jobExceptionHandler();
				String executorServiceHandler = conf.executorServiceHandler();

				String jobShardingStrategyClass = conf.jobShardingStrategyClass();
				String eventTraceRdbDataSource = conf.eventTraceRdbDataSource();
				String scriptCommandLine = conf.scriptCommandLine();

				boolean failover = conf.failover();
				boolean misfire = conf.misfire();
				boolean overwrite = conf.overwrite();
				boolean disabled = conf.disabled();
				boolean monitorExecution = conf.monitorExecution();
				boolean streamingProcess = conf.streamingProcess();

				int shardingTotalCount = conf.shardingTotalCount();
				int monitorPort = conf.monitorPort();
				int maxTimeDiffSeconds = conf.maxTimeDiffSeconds();
				int reconcileIntervalMinutes = conf.reconcileIntervalMinutes();	
				
				// 1 先将当当网的esjob相关configuration实例化(然后在与spring做集成)
				JobCoreConfiguration coreConfig = JobCoreConfiguration
						.newBuilder(jobName, cron, shardingTotalCount)
						.shardingItemParameters(shardingItemParameters)
						.description(description)
						.failover(failover)
						.jobParameter(jobParameter)
						.misfire(misfire)
						.jobProperties(JobProperties.JobPropertiesEnum.JOB_EXCEPTION_HANDLER.getKey(), jobExceptionHandler)
						.jobProperties(JobProperties.JobPropertiesEnum.EXECUTOR_SERVICE_HANDLER.getKey(), executorServiceHandler)
						.build();
				
				/* 2 确定创建任务的类型
				 * 通过判断继承接口的名字与ElasticJobTypeEunm枚举中定义的属性值是否一致来判断任务类型;
				 */
				JobTypeConfiguration typeConfig = null;
				if(ElasticJobTypeEunm.SIMPLE.getType().equals(jobTypeName)) {
					typeConfig = new SimpleJobConfiguration(coreConfig, jobClass);
				}
				if(ElasticJobTypeEunm.DATAFLOW.getType().equals(jobTypeName)) {
					typeConfig = new DataflowJobConfiguration(coreConfig, jobClass, streamingProcess);
				}
				if(ElasticJobTypeEunm.SCRIPT.getType().equals(jobTypeName)) {
					typeConfig = new ScriptJobConfiguration(coreConfig, scriptCommandLine);
				}
				
				// 3 初始化LiteJobConfiguration
				LiteJobConfiguration jobConfig = LiteJobConfiguration
						.newBuilder(typeConfig)
						.overwrite(overwrite)
						.disabled(disabled)
						.monitorPort(monitorPort)
						.monitorExecution(monitorExecution)
						.maxTimeDiffSeconds(maxTimeDiffSeconds)
						.jobShardingStrategyClass(jobShardingStrategyClass)
						.reconcileIntervalMinutes(reconcileIntervalMinutes)
						.build();
				
				// 4 创建一个spring的beanDefiniton
				BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(SpringJobScheduler.class);
				factory.setInitMethodName("init");
				factory.setScope("prototype");  //多例(非单例)
				
//				//  -1.添加bean构造参数,相当于添加自己的真实的任务实现类
				if (!ElasticJobTypeEunm.SCRIPT.getType().equals(jobTypeName)) {
					factory.addConstructorArgValue(confBean);
				}
				//	-2.添加注册中心
				factory.addConstructorArgValue(this.zookeeperRegistryCenter);
				//	-3.添加LiteJobConfiguration
				factory.addConstructorArgValue(jobConfig);

				//	-4.如果有eventTraceRdbDataSource 则也进行添加
				if (StringUtils.hasText(eventTraceRdbDataSource)) {
					BeanDefinitionBuilder rdbFactory = BeanDefinitionBuilder.rootBeanDefinition(JobEventRdbConfiguration.class);
					rdbFactory.addConstructorArgReference(eventTraceRdbDataSource);
					factory.addConstructorArgValue(rdbFactory.getBeanDefinition());
				}
				
				//  5.添加监听
				List<?> elasticJobListeners = getTargetElasticJobListeners(conf);
				factory.addConstructorArgValue(elasticJobListeners);
				
				// 6.把factory也就是 SpringJobScheduler注入到Spring容器中
				DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();

				String registerBeanName = conf.jobName() + "SpringJobScheduler";
				defaultListableBeanFactory.registerBeanDefinition(registerBeanName, factory.getBeanDefinition());
				SpringJobScheduler scheduler = (SpringJobScheduler)applicationContext.getBean(registerBeanName);
				scheduler.init();
				System.out.println("启动elastic-job作业: " + jobName);
				
			}
			System.out.println("共计启动elastic-job作业数量为:"+beanMap.values().size()+"个");
			
		} catch (Exception e) {
			System.out.println("elasticjob 启动异常, 系统强制退出");
			System.exit(1);
		}
		
		
	}
	private List<BeanDefinition> getTargetElasticJobListeners(ElasticJobConfig conf) {
		List<BeanDefinition> result = new ManagedList<BeanDefinition>(2);
		String listeners = conf.listener();
		if (StringUtils.hasText(listeners)) {
			BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(listeners);
			factory.setScope("prototype");
			result.add(factory.getBeanDefinition());
		}

		String distributedListeners = conf.distributedListener();
		long startedTimeoutMilliseconds = conf.startedTimeoutMilliseconds();
		long completedTimeoutMilliseconds = conf.completedTimeoutMilliseconds();

		if (StringUtils.hasText(distributedListeners)) {
			BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(distributedListeners);
			factory.setScope("prototype");
			factory.addConstructorArgValue(Long.valueOf(startedTimeoutMilliseconds));
			factory.addConstructorArgValue(Long.valueOf(completedTimeoutMilliseconds));
			result.add(factory.getBeanDefinition());
		}
		return result;
	}

}

step10. 测试es-job组件封装:

1.创建测试项目rabbit-es-job并将rabbit-task依赖引入:

2.配置application.properties,配置必要的两个参数属性namespace和serverLists

server.port=8881

elastic.job.zk.namespace=elastic-job
elastic.job.zk.serverLists=192.168.85.140:2182,192.168.85.142:2182,192.168.85.141:2182


#mysql数据源
spring.datasource.url=jdbc:mysql://localhost:3306/elasticjob?useUnicode=true&characterEncoding=utf-8&verifyServerCertificate=false&useSSL=false&requireSSL=false
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root


3.将自定义注解@EnableElasticJob添加到Application

package com.cc.es;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.cc.rabbit.task.annotation.EnableElasticJob;

@EnableElasticJob
@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}

4.创建定时任务TestJob与DemoJob做为测试:必须添加@Component注解将测试类注入spring容器;通过@ElasticJobConfig自定义注解配置定时任务参数;<必须开启虚拟机的zookeeper作为测试>

package com.cc.es.task.test;

import org.springframework.stereotype.Component;

import com.cc.rabbit.task.annotation.ElasticJobConfig;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;

@Component
@ElasticJobConfig(
		jobName = "com.cc.es.task.test.TestJob",
		cron = "0/5 * * * * ?",
		description = "测试定时任务",
		overwrite = true,
		shardingTotalCount = 5
		)
public class TestJob implements SimpleJob{

	@Override
	public void execute(ShardingContext shardingContext) {
		System.out.println("-----执行Test job!");
		
	}

}
package com.cc.es.task.test;

import org.springframework.stereotype.Component;

import com.cc.rabbit.task.annotation.ElasticJobConfig;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;

@Component
@ElasticJobConfig(
		jobName = "com.cc.es.task.test.DemoJob",
		cron = "0/10 * * * * ?",
		description = "样例测试定时任务",
		overwrite = true,
		shardingTotalCount = 5
		)
public class DemoJob implements SimpleJob{

	@Override
	public void execute(ShardingContext shardingContext) {
		System.out.println("-----执行Demo Job!");
		
	}

}

5.运行Application测试输出:

ElasticJob基础组件封装完成,测试通过。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值