我们知道在springboot项目执行定时任务和异步任务还是比较简单的,因为springboot框架为我们做的太多了,封装好了太多的东西
如执行定时任务,只需要在项目启动类上,加上@EnableScheduling,表示启用调度任务
然后再创建一个类,用于声明需要执行的任务job即可
例如创建一个定时任务类,在类上加上@Component注解,声明为被spring管理的bean,可以被spring容器扫描到
在需要执行的具体方法上加上@Scheduled注解,注解里边可以设置固定执行,延迟执行等方法,不过平时用的最多的还是使用cron表达式方式灵活设置执行频率,cron表达式在线生成可以参考这个网站:在线Cron表达式生成器
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dcboot.module.apiservice.apiserviceininterface.service.ApiserviceInInterfaceService;
import com.dcboot.module.apiservice.apiserviceininterface.vo.AccInterfaceResponse;
import com.dcboot.module.common.enums.CollectDataTypeEnum;
import com.dcboot.module.common.enums.BaiXinTaxInterfaceCodeEnum;
import com.dcboot.module.common.enums.HuiFaLawInterfaceCodeEnum;
import com.dcboot.module.common.enums.LawDataInfoTypeEnum;
import com.dcboot.module.ifserv.client.dto.request.HuiFaLawRequestDTO;
import com.dcboot.module.ifserv.client.service.BaiXinTaxService;
import com.dcboot.module.taxdata.entity.DataGetRecord;
import com.dcboot.module.customer.register.entity.Customer;
import com.dcboot.module.customer.register.service.CustomerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.Future;
/**
* @author xiaomifeng1010
* @version 1.0
* @date: 2022/3/10 18:49
* @Description
*/
@Component
@Slf4j
public class GetAndSaveTaxAndLawDataTask {
@Autowired
private CustomerService customerService;
@Autowired
private BaiXinTaxService baiXinTaxService;
@Autowired
private HuiFaLawRequestDTO huiFaLawRequestDTO;
@Autowired
private ApiserviceInInterfaceService apiserviceInInterfaceService;
/**
* cron表达式需要为6位
* @param
* @description: 每月10号6:30开始执行,获取百信财税数据
* @author: xiaomifeng1010
* @date: 2022/3/14
* @return: void
**/
@Scheduled(cron = "0 30 6 10 * ?")
public void getBaiXinTaxData() {
List<Customer> customerList = customerService.list(Wrappers.<Customer>lambdaQuery()
.select(Customer::getEntName));
customerList.forEach(customer -> {
String enterpriseName = customer.getEntName();
String uscc = customer.getUscc();
BaiXinTaxInterfaceCodeEnum[] baiXinTaxInterfaceCodeEnums = BaiXinTaxInterfaceCodeEnum.values();
long snowId = IdUtil.getSnowflake().nextId();
for (BaiXinTaxInterfaceCodeEnum baiXinTaxInterfaceCodeEnum : baiXinTaxInterfaceCodeEnums) {
String interfaceCode = baiXinTaxInterfaceCodeEnum.getInterfaceCode();
JSONObject jsonObject = baiXinTaxService.obtainData(interfaceCode, enterpriseName, uscc);
DataGetRecord dataGetRecord = new DataGetRecord();
Integer auto = CollectDataTypeEnum.AUTO.getCode();
dataGetRecord.setGetType(auto);
dataGetRecord.setGetTypeDescription(CollectDataTypeEnum.getName(auto));
dataGetRecord.setBatchId(snowId);
Future<Boolean> booleanFuture = baiXinTaxService.explainBaiXinTaxData(dataGetRecord, jsonObject, interfaceCode, enterpriseName, uscc);
if (booleanFuture.isDone()) {
try {
Boolean batchSaveSuccess = booleanFuture.get();
if (BooleanUtils.isFalse(batchSaveSuccess)) {
dataGetRecord.setIsSuccess(0);
dataGetRecord.insert();
}
} catch (Exception e) {
dataGetRecord.setIsSuccess(0);
dataGetRecord.setExceptionMessage(e.getMessage());
dataGetRecord.insert();
log.error("出错了", e);
}
}
log.info("添加财税信息数据成功");
}
});
}
/**
* cron表达式需要为6位
* @param
* @description: 每月10号5:30开始执行,获取百信财税数据
* @author: xiaomifeng1010
* @date: 2022/3/16
* @return: void
**/
@Scheduled(cron = "0 30 5 10 * ?")
public void getHuiFaLawData() {
List<Customer> customerList = customerService.list(Wrappers.<Customer>lambdaQuery()
.select(Customer::getEntName));
customerList.forEach(customer -> {
String enterpriseName = customer.getEntName();
String uscc = customer.getUscc();
LawDataInfoTypeEnum[] lawDataInfoTypeEnums = LawDataInfoTypeEnum.values();
long snowId = IdUtil.getSnowflake().nextId();
huiFaLawRequestDTO.setN(enterpriseName);
huiFaLawRequestDTO.setId(uscc);
for (LawDataInfoTypeEnum lawDataInfoTypeEnum : lawDataInfoTypeEnums) {
String pageType = lawDataInfoTypeEnum.getLawDataInfoType();
huiFaLawRequestDTO.setPageType(pageType);
String requestJsonStr = JSONObject.toJSONString(huiFaLawRequestDTO);
String interfaceCode = HuiFaLawInterfaceCodeEnum.HF.getInterfaceCode();
AccInterfaceResponse accInterfaceResponse = apiserviceInInterfaceService.obtainAccData(interfaceCode, requestJsonStr);
DataGetRecord dataGetRecord = new DataGetRecord();
dataGetRecord.setEnterpriseName(enterpriseName);
dataGetRecord.setUscc(uscc);
Integer auto = CollectDataTypeEnum.AUTO.getCode();
dataGetRecord.setGetType(auto);
dataGetRecord.setGetTypeDescription(CollectDataTypeEnum.getName(auto));
dataGetRecord.setBatchId(snowId);
dataGetRecord.setInterfaceCode(interfaceCode+":"+pageType);
dataGetRecord.setInterfaceCodeDescription(HuiFaLawInterfaceCodeEnum.getDescription(interfaceCode)+":"+lawDataInfoTypeEnum.getDescription());
String datas = accInterfaceResponse.getDatas();
String hit = accInterfaceResponse.getHit();
String cost = accInterfaceResponse.getCost();
log.info("获取数据:{}", datas);
if (StringUtils.equals(hit, "0") || StringUtils.equals(cost, "0")) {
dataGetRecord.setIsSuccess(0);
// 出现异常的时候,datas存的是异常信息 @see ApiserviceInInterfaceServiceImpl (157行)
dataGetRecord.setExceptionMessage(datas);
dataGetRecord.insert();
}
dataGetRecord.setIsSuccess(1);
dataGetRecord.insert();
}
});
}
}
我这里写了两个需要执行的定时任务,如果需要异步执行这两个定时任务,就需要自定义设置一下执行定时任务的线程池
如下:
创建一个配置类,用于配置执行定时任务和异步任务的线程池
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.Task;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @author xiaomifeng1010
* @version 1.0
* @date: 2022/3/13 20:33
* @Description 线程池配置
*/
@Configuration
@Slf4j
public class ThreadPoolConfig implements AsyncConfigurer,SchedulingConfigurer {
/**
* 异步任务执行线程池参数
*/
private static final Integer CORE_POOL_SIZE = 5;
private static final Integer MAX_POOL_SIZE = 200;
private static final Integer QUEUE_CAPACITY = 2000;
private static final String THREAD_NAME_PREFIX = "async-thread-";
private static final Integer KEEP_ALIVE_SECONDS = 60;
/**
* 定时任务线程池线程名前缀
*/
private static final String SCHEDULER_THEREAD_NAME_PREFIX = "task-";
/**
* @description: 创建执行spring task定时任务的线程池,调用@scheduled注解的定时任务
* @author: pengshaoshuan
* @date: 2022/3/13
* @param
* @return: TaskScheduler
**/
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(10);
threadPoolTaskScheduler.setThreadNamePrefix(SCHEDULER_THEREAD_NAME_PREFIX);
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
return threadPoolTaskScheduler;
}
/**
* @description: 创建执行异步任务的线程池,用于调用 @async注解的方法
* @author: xiaomifeng1010
* @date: 2022/3/13
* @param
* @return: ThreadPoolTaskExecutor
**/
@Bean("asyncThreadPoolTaskExecutor")
public ThreadPoolTaskExecutor asyncThreadPoolTaskExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
// 核心线程数量
threadPoolTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);
// 最大线程数量
threadPoolTaskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
// 队列中最大任务数
threadPoolTaskExecutor.setQueueCapacity(QUEUE_CAPACITY);
// 线程名称前缀
threadPoolTaskExecutor.setThreadNamePrefix(THREAD_NAME_PREFIX);
// 当达到最大线程数时如何处理新任务(拒绝策略)
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 线程空闲后最大存活时间
threadPoolTaskExecutor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);
// 初始化线程池
threadPoolTaskExecutor.initialize();
// 关闭线程池
threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
return threadPoolTaskExecutor;
}
/**
* Callback allowing a {@link TaskScheduler
* TaskScheduler} and specific {@link Task Task}
* instances to be registered against the given the {@link ScheduledTaskRegistrar}.
*
* @param taskRegistrar the registrar to be configured.
*/
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler());
}
/**
* The {@link Executor} instance to be used when processing async
* method invocations.
*/
@Override
public Executor getAsyncExecutor() {
return asyncThreadPoolTaskExecutor();
}
/**
* The {@link AsyncUncaughtExceptionHandler} instance to be used
* when an exception is thrown during an asynchronous method execution
* with {@code void} return type.
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> {
log.error("异步任务执行出现异常, message {}, method {}, params {}", throwable, method, objects);
};
}
}
虽然在执行@Async注解的异步方法时,异步不用自定义线程池,因为springboot会创建一个默认的执行异步任务的线程池,不过一般推荐最好在执行异步任务的时候自定义一下线程池,同时可以声明线程的名称前缀,最好与业务相关,在日志排查的时候是有用的
由于最近的项目中需要执行的异步任务是需要调用第三方服务商的服务接口,所以有可能调用失败,所以还添加了重试机制,而重试机制,spring框架也提供了解决方案,只需要在项目中引入spring-retry
pom文件中加入:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
需要异步执行的方法以及需要重试的方法 代码如下:
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dcboot.module.apiservice.apiserviceininterface.entity.ApiserviceInInterface;
import com.dcboot.module.apiservice.apiserviceininterface.service.ApiserviceInInterfaceService;
import com.dcboot.module.common.enums.BaiXinTaxInterfaceCodeEnum;
import com.dcboot.module.ifserv.client.dto.request.BaiXinTaxRequestDTO;
import com.dcboot.module.ifserv.client.service.BaiXinTaxService;
import com.dcboot.module.taxdata.entity.*;
import com.dcboot.module.taxdata.service.CsxxlrService;
import com.dcboot.module.taxdata.service.CsxxqsService;
import com.dcboot.module.taxdata.service.CsxxsjService;
import com.dcboot.module.taxdata.service.CsxxyjService;
import com.dcboot.module.common.util.SignUtil;
import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* @author xiaomifeng1010
* @version 1.0
* @date: 2022/3/9 13:53
* @Description
*/
@Service
@Slf4j
public class BaiXinTaxServiceImpl implements BaiXinTaxService {
@Value("${baixin.tax.signKey:39e5853d04ecc4ea4982561a1ddac5ae034c5b33a6d73af4ab56887dff695f88}")
private String signKey;
@Value("${baixin.tax.clientId:dxxtest}")
private String clientId;
@Value("${baixin.tax.host:http://demo.gdxinrong.cn:8886}")
private String host;
private static final String LIST = "list";
private static final String DATA = "data";
private static final String CODE = "code";
private static final String SUCCESS = "success";
@Autowired
CsxxyjService csxxyjService;
@Autowired
CsxxqsService csxxqsService;
@Autowired
CsxxsjService csxxsjService;
@Autowired
CsxxlrService csxxlrService;
@Autowired
@Qualifier("apiserviceInInterfaceService")
private ApiserviceInInterfaceService accInterfaceService;
/**
* @param interfaceCode 该参数配置在dcb_apiservice_in_interface表中INTERFACECODE字段
* @param enterpriseName 纳税人名称
* @param uscc 统一社会信用代码
* @description: 调用百信财税接口,获取财税数据
* @author: xiaomifeng1010
* @date: 2022/3/9
* @return: AccInterfaceResponse
**/
@Override
// 默认重试3次,时间间隔2秒
@Retryable(value = Exception.class, backoff = @Backoff(delay = 2000))
public JSONObject obtainData(String interfaceCode, String enterpriseName, String uscc) {
try {
String description = BaiXinTaxInterfaceCodeEnum.getDescription(interfaceCode);
log.info("开始调用百信财税获取{}数据接口", description);
Stopwatch stopwatch = Stopwatch.createStarted();
ApiserviceInInterface accInterfaceDO = accInterfaceService.getInterfacebycode(interfaceCode);
BaiXinTaxRequestDTO baiXinTaxRequestDTO = new BaiXinTaxRequestDTO();
baiXinTaxRequestDTO.setClientId(clientId);
// 纳税人名称(企业名称)或者统一社会信信用代码传入任一,即可
if (StringUtils.isNotBlank(enterpriseName)) {
baiXinTaxRequestDTO.setNsrmc(enterpriseName);
}
if (StringUtils.isNotBlank(uscc)) {
baiXinTaxRequestDTO.setShxydm(uscc);
}
String params = JSONObject.toJSONString(baiXinTaxRequestDTO, true);
baiXinTaxRequestDTO.setSign(SignUtil.sign(JSON.parseObject(params), signKey));
String finalParams = JSONObject.toJSONString(baiXinTaxRequestDTO, true);
log.info("请求参数:{}", finalParams);
String resultdata = HttpUtil.post(host + "/" + accInterfaceDO.getUrl(), finalParams);
JSONObject jsonObject = JSON.parseObject(resultdata);
long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
log.info("调用百信财税获取{}数据结束,耗时{}毫秒", description, elapsed);
return jsonObject;
} catch (Exception e) {
log.error("出错了,开始重试", e);
throw new RuntimeException(e.getMessage());
}
}
/**
* @param resultData 百信财税响应的数据
* @param interfaceCode 该参数配置在dcb_apiservice_in_interface表中INTERFACECODE字段
* @param enterpriseName
* @param uscc 统一社会信用代码
* @description: 解析百信财税返回的数据, 存入沉淀库(不处理企业工商信息 )
* @author: xiaomifeng1010
* @date: 2022/3/10
* @return: Boolean
**/
@Override
@Async("asyncThreadPoolTaskExecutor")
public Future<Boolean> explainBaiXinTaxData(DataGetRecord dataGetRecord, JSONObject resultData, String interfaceCode, String enterpriseName, String uscc) {
Integer code = resultData.getInteger(CODE);
Boolean isSuccess = resultData.getBoolean(SUCCESS);
// 不处理企业基本工商信息及变更信息接口数据
if (StringUtils.equalsIgnoreCase(interfaceCode, BaiXinTaxInterfaceCodeEnum.BXBASE.getInterfaceCode()) ||
StringUtils.equalsIgnoreCase(interfaceCode, BaiXinTaxInterfaceCodeEnum.BGXX.getInterfaceCode())) {
return new AsyncResult<>(Boolean.TRUE);
}
// 状态码code为1,并且success参数为true时,才是响应正常,返回有财税数据
if (BooleanUtils.isFalse(isSuccess) || !Objects.equals(NumberUtils.INTEGER_ONE, code)) {
return new AsyncResult<>(Boolean.FALSE);
}
JSONObject dataJSONObject = resultData.getJSONObject(DATA);
// 财税信息中欠税数据信息有可能返回的数据是空的,表示没有欠税信息
if (Objects.isNull(dataJSONObject)) {
return new AsyncResult<>(Boolean.TRUE);
}
// 更新之前先清理旧数据
deleteOldTaxData(interfaceCode,enterpriseName,uscc);
if (dataJSONObject.containsKey(LIST)) {
JSONArray dataArray = dataJSONObject.getJSONArray(LIST);
if (dataArray.size() > 0) {
StopWatch stopWatch = new StopWatch();
String interfaceDescription = BaiXinTaxInterfaceCodeEnum.getDescription(interfaceCode);
// 处理数据进行记录
dataGetRecord.setInterfaceCode(interfaceCode);
dataGetRecord.setInterfaceCodeDescription(interfaceDescription);
// 记录耗时
stopWatch.start("处理" + interfaceDescription + "数据,并保存");
if (StringUtils.equalsIgnoreCase(BaiXinTaxInterfaceCodeEnum.QYSBXX.getInterfaceCode(), interfaceCode)) {
List<Csxxyj> csxxyjList = dataArray.toJavaList(Csxxyj.class);
csxxyjList.stream().forEach(o -> {
o.setZtmc(enterpriseName);
o.setTyshxydm(uscc);
});
//应交税额(近一年)
csxxyjService.saveBatch(csxxyjList);
String tableName = Csxxyj.class.getAnnotation(TableName.class).value();
log.info("数据批量保存成功到表:" + tableName);
dataGetRecord.setTableName(tableName);
dataGetRecord.setCount(csxxyjList.size());
} else if (StringUtils.equalsIgnoreCase(BaiXinTaxInterfaceCodeEnum.QYZSXX.getInterfaceCode(), interfaceCode)) {
List<Csxxsj> csxxsjList = dataArray.toJavaList(Csxxsj.class);
csxxsjList.stream().forEach(o -> {
// Long id = csxxsjService.getObj(Wrappers.<Csxxsj>lambdaQuery()
// .select(Csxxsj::getEntId)
// .eq(Csxxsj::getZsxmsz, o.getZsxmsz())
// .eq(Csxxsj::getJkrq, o.getJkrq())
// .eq(Csxxsj::getTyshxydm, uscc), a -> Long.valueOf(String.valueOf(a)));
o.setZtmc(enterpriseName);
o.setTyshxydm(uscc);
});
//企业实缴(近一年)
csxxsjService.saveBatch(csxxsjList);
String tableName = Csxxsj.class.getAnnotation(TableName.class).value();
log.info("数据批量保存成功到表:" +tableName);
dataGetRecord.setTableName(tableName);
dataGetRecord.setCount(csxxsjList.size());
} else if (StringUtils.equalsIgnoreCase(BaiXinTaxInterfaceCodeEnum.QYQSXX.getInterfaceCode(), interfaceCode)) {
List<Csxxqs> csxxqsList = dataArray.toJavaList(Csxxqs.class);
csxxqsList.stream().forEach(o -> {
o.setZtmc(enterpriseName);
o.setTyshxydm(uscc);
});
//欠税信息(近12个月)
csxxqsService.saveBatch(csxxqsList);
String tableName = Csxxqs.class.getAnnotation(TableName.class).value();
log.info("数据批量保存成功到表:" +tableName );
dataGetRecord.setTableName(tableName);
dataGetRecord.setCount(csxxqsList.size());
} else if (StringUtils.equalsIgnoreCase(BaiXinTaxInterfaceCodeEnum.LRB.getInterfaceCode(), interfaceCode)) {
List<Csxxlr> csxxlrList = dataArray.toJavaList(Csxxlr.class);
csxxlrList.stream().forEach(o -> {
o.setId(IdUtil.getSnowflake().nextId());
o.setZtmc(enterpriseName);
o.setTyshxydm(uscc);
});
//企业利润(近三年)
csxxlrService.saveBatch(csxxlrList);
String tableName = Csxxlr.class.getAnnotation(TableName.class).value();
log.info("数据批量保存成功到表:" + tableName);
dataGetRecord.setTableName(tableName);
dataGetRecord.setCount(csxxlrList.size());
}
stopWatch.stop();
log.info(stopWatch.prettyPrint());
log.info("执行完[{}]任务,耗时{}毫秒,执行了{}项任务", stopWatch.getLastTaskName(), stopWatch.getTotalTimeMillis(), stopWatch.getTaskCount());
dataGetRecord.setIsSuccess(1);
dataGetRecord.setEnterpriseName(enterpriseName);
dataGetRecord.setUscc(uscc);
dataGetRecord.insert();
return new AsyncResult<>(Boolean.TRUE);
}
return new AsyncResult<>(Boolean.FALSE);
}
return new AsyncResult<>(Boolean.FALSE);
}
/**
* @description: 批量更新新税务数据时,先删除旧数据
* @author: xiaomifeng1010
* @date: 2022/3/14
* @param interfaceCode
* @param enterpriseName
* @param uscc
* @return: void
**/
public void deleteOldTaxData(String interfaceCode,String enterpriseName,String uscc){
if (StringUtils.equalsIgnoreCase(BaiXinTaxInterfaceCodeEnum.QYSBXX.getInterfaceCode(), interfaceCode)){
List<Long> csxxyjIdList = csxxyjService.listObjs(Wrappers.<Csxxyj>lambdaQuery()
.select(Csxxyj::getId).eq(Csxxyj::getTyshxydm, uscc).eq(Csxxyj::getZtmc, enterpriseName), a -> Long.valueOf(String.valueOf(a)));
if (CollectionUtils.isNotEmpty(csxxyjIdList)){
csxxyjService.deleteBatch(csxxyjIdList);
}
}else if (StringUtils.equalsIgnoreCase(BaiXinTaxInterfaceCodeEnum.QYZSXX.getInterfaceCode(), interfaceCode)) {
List<Long> csxxsjIdList = csxxsjService.listObjs(Wrappers.<Csxxsj>lambdaQuery()
.select(Csxxsj::getId).eq(Csxxsj::getTyshxydm, uscc).eq(Csxxsj::getZtmc, enterpriseName), a -> Long.valueOf(String.valueOf(a)));
if (CollectionUtils.isNotEmpty(csxxsjIdList)){
csxxsjService.deleteBatch(csxxsjIdList);
}
}else if (StringUtils.equalsIgnoreCase(BaiXinTaxInterfaceCodeEnum.QYQSXX.getInterfaceCode(), interfaceCode)) {
List<Long> csxxqsIdList = csxxqsService.listObjs(Wrappers.<Csxxqs>lambdaQuery()
.select(Csxxqs::getId).eq(Csxxqs::getTyshxydm, uscc).eq(Csxxqs::getZtmc, enterpriseName), a -> Long.valueOf(String.valueOf(a)));
if (CollectionUtils.isNotEmpty(csxxqsIdList)){
csxxqsService.deleteBatch(csxxqsIdList);
}
}else if (StringUtils.equalsIgnoreCase(BaiXinTaxInterfaceCodeEnum.LRB.getInterfaceCode(), interfaceCode)) {
List<Long> csxxlrIdList = csxxlrService.listObjs(Wrappers.<Csxxlr>lambdaQuery()
.select(Csxxlr::getId).eq(Csxxlr::getTyshxydm, uscc).eq(Csxxlr::getZtmc, enterpriseName), a -> Long.valueOf(String.valueOf(a)));
if (CollectionUtils.isNotEmpty(csxxlrIdList)) {
csxxlrService.deleteBatch(csxxlrIdList);
}
}
}
/**
* 重试3次后仍然失败后,执行的方法
* @param e
* @return
*/
@Recover
public JSONObject recover(Exception e){
log.error("重试3次,依然无法获取财税信息,出错信息:{}",e.getMessage());
return new JSONObject();
}
}
在需要重试的方法上加上 @Retryable(value = Exception.class, backoff = @Backoff(delay = 2000))
那么该方法在执行出现exception的时候,会再次执行,执行了执行的重试次数后,依然失败,则会调用被@Recover注解的方法,注意重试的方法中捕获到了异常后,需要重新抛出,这样才能被
@Recover注解的方法捕获到,进行后续处理
最后别忘了在启动类上加上需要@EnableAsync 和@EnableRetry注解,表示启用异步执行与重试机制