总目录
- 一.任务需求
- 二.定时任务代码
- 代码分析:
- 三.Redis 代码逻辑
- 代码分析:
- 三.远程调用
- 四.熔断代码-hystrix
- 五.远程调用及跨模块调用 想看更详细的 请点击!!
一.任务需求
***需求:***根据固定时间,主动获取本地数据库未推送的数据,然后将这些数据通过远程向某供应商推送。
二.定时任务代码
@Resource
private RedisLock redisLock;
@Resource
private RemoteInitiativeAeService initiativeAeService;
/**
* 主动拉取未读数据 如果数据不为空 主动推送
* 拉取/推送时间 每天凌晨1点执行一次
*/
@Scheduled(cron = "0 0 1 * * ?") //每天凌晨1点执行一次
public void getBatchVaristor() {
//获取当前类名 + 当前方法名
String timerName = this.getClass().getName()
+ Thread.currentThread().getStackTrace()[1].getMethodName();
//如果当前已经持有锁 结束 否则 设置过期时间 为 23小时59分钟
if (redisLock.requireLock(timerName, 86340)) {
return;
}
//查询 未推送过的原材料检验-压敏电阻
List<AeRaiVaristorVO> raiVaristorVo = aeRaiVaristorMapper.selectNoReadVaristor();
//如果存在未读数据 调用远程接口 主动推送
if (StringUtils.isNotEmpty(raiVaristorVo)) {
if (initiativeAeService.addAeVaristor(raiVaristorVo).checkAndGet() == 0) {
throw new CustomException("推送错误! 数据0条!");
}
}
//使用stream流 过滤出刚刚推送的Id
List<Long> varistorIds = raiVaristorVo.stream().
map(AeRaiVaristorVO::getId).collect(Collectors.toList());
//根据Id 将这些数据修改为 已推送 避免下次重复推送
aeRaiVaristorMapper.updateVaristorIsRead(varistorIds);
}
代码分析:
1.获取当前类名 + 当前方法名 作为key
2.判断当前是否已经持有锁 说白了 就是是否存在重复执行 避免集群环境出现多次执行
3.查询 未推送过的原材料检验-压敏电阻
4.判断如果存在 数据 调用远程接口 主动推送
5.使用stream流 过滤出刚刚推送成功的Id
6.根据Id 将这些数据修改为 已推送 避免下次重复推送
三.Redis 代码逻辑
/**
* redis 任务锁key的前缀
*/
public static final String REDIS_LOCK_KEY = "com:guodian:job";
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 判断是否有锁。有 返回true 无 设置一定有效期锁 并 返回 false
* @param lockName key
* @param timeout 锁的有效期时间
* @return 是否持有锁
*/
public boolean requireLock(String lockName, Long timeout) {
String key = REDIS_LOCK_KEY + lockName;
if (StringUtils.isNull(redisTemplate.getExpire(key))){
redisTemplate.expire(key,timeout, TimeUnit.SECONDS); //时间单位为秒 可以设置小时和天
return false;
}
return true;
}
/**
* 判断是否有锁。有 返回true 无 设置有效时间截止点 并 返回 false
* @param lockName key
* @param date 锁的有效时间截止点
* @return 是否持有锁
*/
public boolean requireLock(String lockName, Date date) {
String key = REDIS_LOCK_KEY + lockName;
if (StringUtils.isNull(redisTemplate.getExpire(key))){
redisTemplate.expireAt(key,date);
return false;
}
return true;
}
代码分析:
1.这里有两个方法 第一个方法:判断是否有锁。有 返回true 无 设置一定有效期锁 并 返回 false
第二个方法 :判断是否有锁。有 返回true 无 设置有效时间截止点 并 返回 false
三.远程调用
/**
* @Author wufushan
* @Date 2022/4/20 15:14
* @Version 1.0
*/
@FeignClient(name = "remoteInitiativeAeService", url = "http://localhost:8080",fallbackFactory = RemoteGetUserFactory.class )
public interface RemoteInitiativeAeService {
/**
* 主动推送压敏电阻信息
* @param raiVaristorVo 压敏电阻参数
* @return 推送数量
*/
@PostMapping("/initiative/aeVaristor")
R<Integer> addAeVaristor(@Param("raiVaristorVo") List<AeRaiVaristorVO> raiVaristorVo);
}
四.熔断代码-hystrix
/**
* @Author wfs
* @Date 2022/4/20 15:15
* @Version 1.0
*/
public class RemoteInitiativeAeFactory implements FallbackFactory<RemoteInitiativeAeService> {
private static final Logger log = LoggerFactory.getLogger(RemoteInitiativeAeService.class);
@Override
public RemoteInitiativeAeService create(Throwable throwable) {
log.info("远程WebSocket服务调用失败!{}", throwable.getMessage());
return new RemoteInitiativeAeService() {
@Override
public R<Integer> addAeVaristor(List<AeRaiVaristorVO> raiVaristorVo) {
return R.fail("主动推送压敏电阻数据失败!!");
}
};
}
}
五.远程调用及跨模块调用 想看更详细的 请点击!!
远程调用跨服务+跨模块超详细