美文网首页
Java注解实现异步导入与导出(二)

Java注解实现异步导入与导出(二)

作者: 雪飘千里 | 来源:发表于2022-07-19 21:03 被阅读0次

    Java注解实现异步导入与导出(一)

    上一篇写完了用注解实现异步导入,这一篇实现用注解异步导出。

    1.背景:

    导出最容易遇到的问题就是超时了,随着我们DB数据越来越多,导出时特别容易超时,这时候通常的解决办法就是优化SQL,或者直接限制导出条数,但是这两种方法都只能解决暂时的问题,过一段时间可能就又会冒出来。所以还是使用异步导出,先存到nas中,然后让用户再去下载。

    2. 流程设计:

    2.1  生成一条导出记录
    2.2  异步查询并写入execl
    2.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
    @Slf4j
    public 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("");
        }
    
    

    相关文章

      网友评论

          本文标题:Java注解实现异步导入与导出(二)

          本文链接:https://www.haomeiwen.com/subject/kcusirtx.html