Java注解实现异步导入与导出(一)
上一篇写完了用注解实现异步导入,这一篇实现用注解异步导出。
1.配景:
导出最容易碰到的题目就是超时了,随着我们DB数据越来越多,导出时特殊容易超时,这时间通常的办理办法就是优化SQL,大概直接限定导出条数,但是这两种方法都只能办理暂时的题目,过一段时间大概就又会冒出来。以是还是使用异步导出,先存到nas中,然后让用户再去下载。
2. 流程操持:
2.1 天生一条导出记录2.2 异步查询并写入execl2.3 把execl上传到nfsc,并更新导出记录2.4 下载,从nfsc下载文件3. 代码实现:
从上面的流程中可以看出,体系中只有第二步的差异的,别的都是一样的,全部我们还是可以用注解来实现通过流程。
3.1 创建自界说注解
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** */@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface Export { //业务模块名称 String moduleName() default ""; //文件逾期时间 int expireTime() default 24; //excel剖析类 Class clazz();}3.2 编写切面:
import com.alibaba.excel.EasyExcel;import com.alibaba.fastjson.JSON;import com.google.common.util.concurrent.ThreadFactoryBuilder;import com.demo.cemp.framework.common.base.ResultUtil;import com.demo.cemp.goods.common.utils.DateUtil;import com.demo.cemp.goods.common.utils.FileUploadUtil;import com.demo.cemp.goods.mallgoods.service.impl.ImportExportRecords;import com.demo.framework.domain.Result;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang.time.DateUtils;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.stereotype.Component;import java.util.Date;import java.util.concurrent.*;/** */@Component@Aspect@Slf4jpublic class ExportAspect { public static ThreadFactory commonThreadFactory = new ThreadFactoryBuilder().setNameFormat("upload-pool-%d") .setPriority(Thread.NORM_PRIORITY).build(); public static ExecutorService uploadExecuteService = new ThreadPoolExecutor(1, 20, 300L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1024), commonThreadFactory, new ThreadPoolExecutor.AbortPolicy()); @Pointcut("@annotation(com.demo.cemp.goods.mallgoods.service.Export)") public void exportPoint() {} @Around(value = "exportPoint()") public Object uploadControl(ProceedingJoinPoint joinPoint) throws Throwable { // 获取方法上的注解,进而获取uploadType MethodSignature signature = (MethodSignature)joinPoint.getSignature(); Export annotation = signature.getMethod().getAnnotation(Export.class); // 线程池启动异步线程,开始实行上传的逻辑,joinPoint.proceed()就是你实现的业务功能 uploadExecuteService.submit(() -> { ImportExportRecords records = new ImportExportRecords(); try { // 1、初始化导出日记,记录开始时间 records.setModuleName(annotation.moduleName()); records.setExpireTime(DateUtil.format(DateUtils.addHours(new Date(),annotation.expireTime()), DateUtil.DATE_TIME_PATTERN)); records.setType(2); records.setStartTime(new Date()); // records= writeRecordsToDB(records); System.out.println("writeInitToDB"); //2 实行业务方法 查询导出数据 Object result = joinPoint.proceed(); Result errorResult = JSON.parseObject(JSON.toJSONString(result), Result.class); if (errorResult!=null && errorResult.isSuccess()) { // 3 文件上传 String filePath = FileUploadUtil.getDefaultSavePath("businessCoupon", "demo.xlsx","test"); EasyExcel.write(filePath, annotation.clazz()).sheet("sheet").doWrite(JSON.parseArray(errorResult.getObj().toString(),annotation.clazz())); records.setState(1); records.setNfsPath(filePath); } else { // 失败, records.setState(2); records.setErrorReason(errorResult.getErrorMessage()); } } catch (Throwable e) { // 非常,须要记录 log.error("error",e); records.setState(2); records.setErrorReason(e.getMessage()); } //4 更新导入日记效果// updateByRecordsId(records); System.out.println("updateByRecordsId"); }); return ResultUtil.success(); }}3.3 使用:
@Export(moduleName="test",clazz = MallOrderExcelVO.class) public Result<List<MallOrderExcelVO>> exportOrderList(PointMallOrderDTO orderDTO) { try { List<MallOrderExcelVO> excelList = Lists.newArrayList(); int curPageNo = 1; int pageSize = 500; orderDTO.setPageSize(pageSize); while (orderCount > 0) { orderDTO.setPageNo(curPageNo++); List<MallOrderPO> orderList2 = pointMallOrderService.getMallOrderList2(orderDTO); if (orderList2 == null ) { log.info("[商城订单管理]===哀求失败 params={} curPageNo={}", JSON.toJSONString(orderDTO), curPageNo); continue; } if (CollectionUtils.isEmpty(orderList2)) { break; } excelList.addAll(orderList2.stream().map(this::getOrderExcelVO).collect(Collectors.toList())); orderCount = Math.max(0, orderCount - pageSize); } return SFResultUtil.success(excelList); } catch (Exception e) { log.error("[商城订单管理]===导出订单非常", e); } return SFResultUtil.error(""); } |