手工调用使用场景:想同时支持redis和jdbc场景,想更灵活调用
使用方法
//锁任务时长
private static final int SECOND= 1000;
/**
* 定时更新任务状态
*/
@Scheduled(cron="50 * * * * ?")
public void updateUserTaskAckStatus(){
try{
JdbcLockService.startCrontabTask("suncloud-log-updateUserTaskAckStatus",20*SECOND,10*SECOND,()->unicastTaskService.updateUserTaskAckStatus());
}catch (Exception e){
log.error("updateUserTaskAckStatus",e);
}
}
配置:
@Bean("jdbcTemplateLockProvider")
public JdbcTemplateLockProvider scheduledMysqlLockConfiguration(DataSource mysqlDataSource) {
return new JdbcTemplateLockProvider(mysqlDataSource);
}
核心类JdbcLockService
import com.bin.common.CrontabFunction;
import com.bin.common.utils.DateUtils;
import com.bin.common.utils.SpringBeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.core.LockConfiguration;
import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.core.SimpleLock;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import java.time.Instant;
import java.util.Date;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import static java.time.temporal.ChronoUnit.MILLIS;
/**jdbc分布式锁调度
* @Desc
* @Author zzb
* @CreateTime 2019/12/9 10:36
*/
@Slf4j
public class JdbcLockService {
/**提供参数,没有返回值
* @param name
* @param lockAtMostLen
* @param lockAtLeastLen
* @param supplier
* @param param
* @param <T>
* @throws Exception
*/
public static <T> void startSupplierTask(String name, long lockAtMostLen, long lockAtLeastLen, Supplier<T> supplier,T param) throws Exception{
startTask(name,lockAtMostLen,lockAtLeastLen,null,param,null,supplier,null);
}
/**没有参数,没有返回结果
* @param name
* @param lockAtMostLen
* @param lockAtLeastLen
* @param crontabFunction
* @throws Exception
*/
public static void startCrontabTask(String name, long lockAtMostLen, long lockAtLeastLen, CrontabFunction crontabFunction) throws Exception{
startTask(name,lockAtMostLen,lockAtLeastLen,crontabFunction,null,null,null,null);
}
/**有参数,没返回结果
* @param name
* @param lockAtMostLen
* @param lockAtLeastLen
* @param consumer
* @param param
* @param <T>
* @throws Exception
*/
public static <T> void startConsumerTask(String name, long lockAtMostLen, long lockAtLeastLen, Consumer<T> consumer,T param) throws Exception{
startTask(name,lockAtMostLen,lockAtLeastLen,null,param,consumer,null,null);
}
/**有参数,有返回
* @param name
* @param lockAtMostLen
* @param lockAtLeastLen
* @param function
* @param param
* @param <T>
* @param <R>
* @return
* @throws Exception
*/
public static <T,R> R startFunctionTask(String name, long lockAtMostLen, long lockAtLeastLen, Function<T,R> function,T param) throws Exception{
return startTask(name,lockAtMostLen,lockAtLeastLen,null,param,null,null,function);
}
/**统一任务
* @param name
* @param lockAtMostLen
* @param lockAtLeastLen
* @param crontabFunction
* @param param
* @param consumer
* @param supplier
* @param function
* @param <T>
* @param <R>
* @return
* @throws Exception
*/
public static <T,R> R startTask(String name, long lockAtMostLen, long lockAtLeastLen, CrontabFunction crontabFunction, T param, Consumer<T> consumer, Supplier<R> supplier, Function<T, R> function) throws Exception{
Instant now = Instant.now();
long st = now.getEpochSecond()*1000;
String lockAtMostUntilString = DateUtils.format(new Date(st+lockAtMostLen),DateUtils.DATE_TIME_PATTERN);
String lockAtLeastUntilString = DateUtils.format(new Date(st+lockAtLeastLen),DateUtils.DATE_TIME_PATTERN);
log.info("start task name={} lockAtMostUntil={} lockAtLeastUntil={}",name, lockAtMostUntilString,lockAtLeastUntilString);
LockProvider lockProvider = SpringBeanUtils.getBean(JdbcTemplateLockProvider.class);
if(lockProvider == null){
throw new NullPointerException("JdbcTemplateLockProvider is null");
}
LockConfiguration configuration = new LockConfiguration(name,now.plus(lockAtMostLen, MILLIS),now.plus(lockAtLeastLen, MILLIS));
Optional<SimpleLock> optional = lockProvider.lock(configuration);
if(optional.isPresent()){
log.info("get task lock success, task name={}",name);
try{
if(supplier != null){
return supplier.get();
}else if(function != null){
return function.apply(param);
}else if(consumer != null){
consumer.accept(param);
return null;
}else if(crontabFunction != null){
crontabFunction.runTask();
return null;
}
}finally {
optional.get().unlock();
long et = System.currentTimeMillis();
log.info("task unlock, timeLen ={},task name={}",(et-st),name);
}
}else{
log.info("get task lock failure,task name={}",name);
}
return null;
}
}
辅助类:CrontabFunction,SpringBeanUtils
@FunctionalInterface
public interface CrontabFunction {
void runTask();
}
辅助类:SpringBeanUtils
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
@Component
public class SpringBeanUtils implements BeanFactoryAware {
private static WebApplicationContext context;
private static BeanFactory beanFactory;
/**
* 注入BeanFactory实例
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
SpringBeanUtils.beanFactory = beanFactory;
}
@Autowired
public void setApplicationContext(WebApplicationContext context) {
SpringBeanUtils.context = context;
}
/**
* 根据bean的名称获取相应类型的对象
*/
public static Object getBean(String beanName) {
return beanFactory.getBean(beanName);
}
/**
* 根据bean的名称获取相应类型的对象,使用泛型,获得结果后,不需要强制转换为相应的类型
*/
public static <T> T getBean(Class<T> clazz) {
return context.getBean(clazz);
}
/**
* 根据bean的名称获取相应类型的对象,使用泛型,获得结果后,不需要强制转换为相应的类型
*/
public static <T> T getBean2(Class<T> clazz) {
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
T bean = wac.getBean(clazz);
return bean;
}
public static WebApplicationContext getApplicationContext() {
return SpringBeanUtils.context;
}
}
版权声明:本文为u012621115原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。