zoukankan      html  css  js  c++  java
  • 52

    原来写过一篇文章,是介绍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();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    }
    这样子类只需要实现easyCreate和transitionQuery方法即可

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

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

    String transitionMethod() default "";
    
    • 1

    }
    指定转换类

    @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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    }
    使用
    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();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    }

  • 相关阅读:
    85. Maximal Rectangle
    120. Triangle
    72. Edit Distance
    39. Combination Sum
    44. Wildcard Matching
    138. Copy List with Random Pointer
    91. Decode Ways
    142. Linked List Cycle II
    异或的性质及应用
    64. Minimum Path Sum
  • 原文地址:https://www.cnblogs.com/gd11/p/14217259.html
Copyright © 2011-2022 走看看