zoukankan      html  css  js  c++  java
  • Excel优雅导出

    流程

    原来写过一篇文章,是介绍EasyExcel的,但是现在有些业务需要解决,流程如下
    1.需要把导出条件转换成中文并存入数据库
    2.需要分页导出
    3.需要上传FTP或者以后上传OSS

    解决方案

    大体的流程采用摸板方法模式,这样简化条件转换以及上传FTP操作

    public abstract class EasyExcelUtil {
    
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        private final CloudOrderManagementDao cloudOrderManagementDao;
    
        //上下文对象
        private final ExportDTO dto;
    
        //ftp信息
        private final FileClient fileClient;
    
        protected final RedisUtil redisUtil;
    
    
        private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 30,
                60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));;
        /**
         * 构造方法子类必须实现
         *
         * @param cloudOrderManagementDao dao
         * @param dto                     上下文对象
         * @param fileClient              文件上传对象
         * @param redisUtil               redis
         */
        public EasyExcelUtil(CloudOrderManagementDao cloudOrderManagementDao, ExportDTO dto, FileClient fileClient, RedisUtil redisUtil) {
            this.cloudOrderManagementDao = cloudOrderManagementDao;
            this.dto = dto;
            this.fileClient = fileClient;
            this.redisUtil = redisUtil;
        }
    
        /**
         * 主方法
         */
        public final void createExcel() {
            try {
                File file = this.createFile();
                CloudExportInfo exportInfo = this.createExportInfo(file.getName());
                threadPoolExecutor.execute(() -> {
                    this.easyCreate(file);
                    this.uploadFile(file);
                    updateExportInfo(exportInfo);
                });
            } catch (Exception e) {
                logger.error("ExcelUtil error{}", e);
            }
        }
    
        /**
         * 创建文件
         *
         * @return 文件对象
         * @throws IOException
         */
        private File createFile() throws IOException {
            File temp = File.createTempFile("temp", ".xlsx");
            logger.info("ExcelUtil创建文件成功{}", temp.getAbsolutePath());
            return temp;
        }
    
    
        /**
         * 创建导出对象,并存数据库
         *
         * @param fileName 文件名
         * @return 导出对象
         */
        private CloudExportInfo createExportInfo(String fileName) {
            CloudExportInfo exportInfo = new CloudExportInfo();
            exportInfo.setId(dto.getUuid());
            exportInfo.setUserId(dto.getUserId());
            exportInfo.setCreateBy(dto.getUserName());
            exportInfo.setExportStatus(com.blgroup.vision.common.utils.R.CloudConstant.TWO);
            exportInfo.setExportType(dto.getExportType());
            exportInfo.setQueryParam(this.transitionQuery());
            exportInfo.setExportCount(dto.getTotal());
            exportInfo.setFileName(fileName);
            exportInfo.setExportDir(dto.getBasisDir() + File.separator + fileName);
            cloudOrderManagementDao.saveExportInfo(exportInfo);// 初始化导出信息
            redisUtil.set(R.CloudConstant.CLOUD_DOWNLOAD_PROGRESS + "_" + dto.getUuid(), "5", 60 * 5);
            logger.info("ExcelUtil创建导出信息成功{}", JSON.toJSONString(exportInfo));
            return exportInfo;
        }
    
        /**
         * 上传文件
         *
         * @param file 文件,策略模式 未来可能支持OSS
         */
        private void uploadFile(File file) {
            redisUtil.set(R.CloudConstant.CLOUD_DOWNLOAD_PROGRESS + "_" + dto.getUuid(), "95", 60 * 5);
            fileClient.uploadFile(file, dto.getBasisDir());
            redisUtil.set(R.CloudConstant.CLOUD_DOWNLOAD_PROGRESS + "_" + dto.getUuid(), "100", 60 * 5);
        }
    
        /**
         * 上传完成,更新导出对象
         *
         * @param exportInfo
         * @return
         */
        private CloudExportInfo updateExportInfo(CloudExportInfo exportInfo) {
            exportInfo.setExportStatus(com.blgroup.vision.common.utils.R.CloudConstant.ONE);
            cloudOrderManagementDao.saveExportInfo(exportInfo);// 初始化导出信息
            logger.info("ExcelUtil上完成");
            return exportInfo;
        }
    
        /**
         * 导出方法,可以实现分批导出,也可以一次性导出
         *
         * @param file 文件
         */
        public abstract void easyCreate(File file);
    
        /**
         * 对查询字段进行转换
         * @return
         */
        public abstract String transitionQuery();
    }
    

    这样子类只需要实现easyCreatetransitionQuery方法即可

    查询条件转换

    针对查询条件转换,例如QO字段为'merchantId' 需要转换为商户值需要转换为ID对应的商户名称
    如果是每个导出方法写一段转换类太麻烦这里使用注解的方式
    在属性上使用表明中文意思和转换方法

    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface FieldNameTransition {
        /**
         * 中文名称
         * @return
         */
        String value();
    
    
        String transitionMethod() default "";
    
    
    }
    

    指定转换类

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    /**
     * 指定转换类
     */
    public @interface TransitionClass {
        Class<?> value();
    }
    

    通过反射进行转换

    public class ExcelTransitionFieldUtil {
        public static Logger logger = LoggerFactory.getLogger(ExcelTransitionFieldUtil.class);
    
        private final ApplicationContext applicationContext;
    
        public ExcelTransitionFieldUtil(ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }
    
        public String transition(Object object) {
            List<Map<String, String>> resultList = new ArrayList<>();
            Object transitionBean = null;
            //获取传过来的对象
            Class<?> dtoClass = object.getClass();
            if (dtoClass.isAnnotationPresent(TransitionClass.class)) {
                //获取类上的注解,得到转换类 获取spring ioc中转换类的对象
                transitionBean = applicationContext.getBean(dtoClass.getAnnotation(TransitionClass.class).value());
            }
            //获取对象的全部字段
            Field[] fields = dtoClass.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(FieldNameTransition.class)) {
                    field.setAccessible(true);
                    //获取字段中需要转换的注解
                    try {
                        if (field.get(object) != null && StringUtils.isNotBlank(field.get(object).toString())) {
                            FieldNameTransition fieldAnnotation = field.getAnnotation(FieldNameTransition.class);
                            Map<String, String> tempMap = new HashMap<>();
                            tempMap.put("name", fieldAnnotation.value());
                            //如果定义了转换方法
                            if (StringUtils.isNotBlank(fieldAnnotation.transitionMethod()) && transitionBean != null) {
                                Method method = transitionBean.getClass().getMethod(fieldAnnotation.transitionMethod(), dtoClass);
                                Object invoke = method.invoke(transitionBean, object);
                                tempMap.put("value", invoke.toString());
                            } else {
                                tempMap.put("value", field.get(object).toString());
                            }
                            resultList.add(tempMap);
                        }
                    }catch (Exception e){
                        logger.error("反射转换发生异常 {}", e);
                    }
                }
            }
            return JSON.toJSONString(resultList);
        }
    }
    

    使用

    QueryMerchantExportQO queryDTO = QueryMerchantExportQO.builder()
          .isNeedAudit(request.getParameter("isNeedAudit"))
          .keyword(request.getParameter("keyword"))
          .merchantType(request.getParameter("merchantType"))
          .shopId(request.getParameter("shopId"))
          .storeCode(request.getParameter("storeCode"))
          .storeType(request.getParameter("storeType"))
          .hideFlag(request.getParameter("hideFlag")).build();
    ExportDTO exportDTO = ExportDTO.builder().userId(UserUtils.getUser().getId())
          .userName(UserUtils.getUser().getName())
          .exportType("9")
          .uuid(UUID.randomUUID().toString())
          .basisDir("/cloudDownFile" + File.separator + LocalDate.now().getYear() + File.separator + LocalDate.now().getMonth().getValue())
          .total(Integer.valueOf(request.getParameter("total")))
          .build();
    FtpInfo ftpInfo = new FtpInfo(server, uname, pwd, port);
    new EasyExcelUtil(cloudOrderManagementDao, exportDTO, new FtpFileClient(ftpInfo), redisUtil) {
          @Override
          public void easyCreate(File file) {
                //do something
          }
    
          @Override
          public String transitionQuery() {
    			//转换
          return new ExcelTransitionFieldUtil(applicationContext).transition(queryDTO);
          }
          }.createExcel();
    }
    

    结尾

    现在问题是转换类型只能是String类型,以后可能改进

  • 相关阅读:
    详解EBS接口开发之采购申请导入
    EBS HRMS数据表
    会计期间
    帐套和会计科目的理解
    oracle中动态SQL详解
    不同币种汇率转换
    API创建/更新员工联系电话
    API创建/更新员工薪水
    Android 圆形、圆角图片ImageView
    Knowledge Generation Model for Visual Analytics
  • 原文地址:https://www.cnblogs.com/ingxx/p/14137367.html
Copyright © 2011-2022 走看看