一、结构速览

首先我们了解的是他的接口:
和之前的接口一样,例如

  1. serviceId: opexport.ServicePackOrderExcelService
  2. methodId: writeExcel

image.png
以上是一个写出Excel的接口(以下举例)


@RpcService
    public void writeExcel(Condition condition, String fileName, Integer exportId) {
        String ossId = "";
        long fileSize = 0L;
        Integer status = 0;
        try {
            UserRoleToken urt = (UserRoleToken) ContextUtils.get("exportUser"); //urt
            String password = (String) ContextUtils.get("password"); //密码
            String manageUnit = urt.getManageUnit(); //管理单位
            condition.setStart(0);
            condition.setLimit(0);//病人的状况

            Date startTime = DateConversion.firstSecondsOfDay(condition.getStartTime());
            Date endTime = DateConversion.lastSecondsOfDay(condition.getEndTime());
            condition.setStartTime(startTime);
            condition.setEndTime(endTime);
            //存放的多条excel信息
            List<ServicePackOrderExcelBean> list = this.getServicePackOrderExcelBean(condition, manageUnit);
            //文件路径
            String filePath = FileUtil.getPath() + fileName;
            //excel写入器
            ExcelWriter excelWriter = EasyExcel.write(filePath, ServicePackOrderExcelBean.class)
                    .password(password)
                    .build();

            WriteSheet writeSheet = EasyExcel.writerSheet("健康管理订单").build();
            writeSheet.setAutoTrim(Boolean.TRUE); //是否自动换行
            //正式写
            excelWriter.write(list, writeSheet);
            //
            excelWriter.finish();
            list.clear();
            ossId = (new UploadService()).uploadFile(fileName, urt);
            status = 1;
            //获取文件大小
            fileSize = FileUtil.getFileSize(fileName);
        } catch (Exception e) {
            status = -1;
            LOGGER.error("导出文件失败", e);
        } finally {
            String  json = JSONUtils.toString(condition);
            //输入备份(记录)
            exportRecordService.updateFileIdById(exportId, ossId, fileSize, status, json);
            FileUtil.deleteFile(fileName);
        }
    }

1、参数

  • condition参数:暂存输出数据4的信息
  • fileName:文件名
  • exportId:输出Id,在记录输出备份是充当id

2、猜测流程:

1.条件准备阶段:

先去获取用户token,excel写入器的密码,管理单位(根据token获取),开始和结束时间、文件路径filePath等信息

2.数据获取阶段:

存放的多条excel信息,通过getServicePackOrderExcelBean()封装数据 (默认选择)

 List<ServicePackOrderExcelBean> list = this.getServicePackOrderExcelBean(condition, manageUnit);

FileUtil工具实现文件地址的获取

String filePath = FileUtil.getPath() + fileName; //暂存服务器的文件地址

3.excel写入器构建:

EasyExcel的write()方法获取ExcelWriter写入器,通过WriteSheet添加输出数据的条件,

ExcelWriter excelWriter = EasyExcel.write(filePath, ServicePackOrderExcelBean.class)
                    .password(password)
                    .build();
WriteSheet writeSheet = EasyExcel.writerSheet("健康管理订单").build();
            writeSheet.setAutoTrim(Boolean.TRUE);

正式写入:excelWriter.write(list, writeSheet); 记得关闭流finish()

excelWriter.write(list, writeSheet);
excelWriter.finish();

4.备份记录

先把文件存入oss阿里,获取oss的id

ossId = (new UploadService()).uploadFile(fileName, urt);

所有记录备份都会以ExportRecord
image.png
输入备份(记录),其实就是根据输出id修改改变的信息字段,最后把文件删除(FileUtil工具我们后面讲)

String  json = JSONUtils.toString(condition);
//输入备份(记录)
exportRecordService.updateFileIdById(exportId, ossId, fileSize, status, json);
FileUtil.deleteFile(fileName);

这样就完成了一个基本的输出流程

二、数据封装

之前出现过的getServicePackOrderExcelBean()方法,其实就是一个数据集,存放excelBean的集合。

private List<ServicePackOrderExcelBean> getServicePackOrderExcelBean(Condition condition, String manageUnit) {
        QueryResult<ServicePackOrderDTO> result = orderService.queryServicePackOrderWithServiceAndPayStatusManageUnit(condition, manageUnit);
        List<ServicePackOrderExcelBean> list = Lists.newArrayList();
        if (result != null && !CollectionUtils.isEmpty(result.getItems())) {
            for (ServicePackOrderDTO servicePackOrderDTO : result.getItems()) {
                String patientId = servicePackOrderDTO.getPatientId();
                PatientDTO patientDTO = new PatientDTO();
                if (ValidateUtil.blankString(patientId)) {
                    patientDTO.setPatientName(servicePackOrderDTO.getPatientName());
                    patientDTO.setCertificate(servicePackOrderDTO.getCertificate());
                } else {
                    patientDTO = patientService.getPatientByMpiId(patientId);
                }
                String purchaserId = servicePackOrderDTO.getPurchaserId();
                Map<String, Object> param = new HashMap<>();
                BeanUtils.map(servicePackOrderDTO, param);

                ServicePackOrderExcelBean excelBean = new ServicePackOrderExcelBean();
                excelBean.setOrderId(servicePackOrderDTO.getOrderId());
                if (ValidateUtil.notBlankString(purchaserId)) {
                    User user = remoteUserService.getByKey(purchaserId);
                    excelBean.setUserName(user.getName());
                    excelBean.setUserMobile(user.getMobile());
                } else {
                    excelBean.setUserName("");
                    excelBean.setUserMobile("");
                }
                excelBean.setServicepackName(servicePackOrderDTO.getServicepackName());
                excelBean.setServicepackDoctor((String) param.get("doctorIdText"));
                excelBean.setServicepackOrgan((String) param.get("organIdText"));
                excelBean.setOrderStatus((String) param.get("orderStatusText"));
                excelBean.setTotalPrice(servicePackOrderDTO.getTotalPrice());
                excelBean.setServicepackPrice(servicePackOrderDTO.getServicepackPrice());
                excelBean.setPayStatus((String) param.get("payOrderStatusText"));
                if (null != patientDTO) {
                    excelBean.setPatientName(patientDTO.getPatientName());
                }
                excelBean.setCreateTime(servicePackOrderDTO.getCreateTime());
                excelBean.setFromFlag((String) param.get("fromFlagText"));
                excelBean.setEndTime(servicePackOrderDTO.getEndTime());
                excelBean.setTradeNo(servicePackOrderDTO.getOutTradeNo());
                //需要新增退款相关字段 2020-12-3
                excelBean.setRefundAmount(servicePackOrderDTO.getRefundAmount());
                excelBean.setRefundOperator(servicePackOrderDTO.getRefundOperator());
                excelBean.setRefundReason(servicePackOrderDTO.getRefundReason());
                excelBean.setRefundTime(servicePackOrderDTO.getRefundTime());
                // 新增健康管理营销页推广相关字段
                if (ValidateUtil.notNullAndZeroInteger(servicePackOrderDTO.getMarketingChannelId())){
                    MarketingChannelDTO channel = marketingChannelService.getByChannelId(servicePackOrderDTO.getMarketingChannelId());
                    excelBean.setMarketingChannelCode(channel.getChannelCode());
                    excelBean.setMarketingChannelName(channel.getChannelName());
                    excelBean.setMarketingPageName(marketingPageService.getMarketingPageNameById(servicePackOrderDTO.getMarketingPageId()));
                }
                list.add(excelBean);
            }
        }
        return list;
    }

其实就是一个数据整合的过程 ,其中常用的数据工具有以下几种。

主体:

需要先创建一个实体类(ServicePackOrderExcelBean),来充当excel内容的容器。

常用的数据工具:

1、数据转换:

ObjectCopyUtils.convert(对象类,转换类.class) ,此方法类可以实现类型转换

 List<ServicePackOrderDTO> servicePackOrderDTOs = (ObjectCopyUtils.convert(servicePackOrders, ServicePackOrderDTO.class))

**

2、文件工具

可以实现文件在本地的删除、创建

    public static File createNewFile(String pathName) {
        File file = new File(getPath() + pathName);
        if (file.exists()) {
            file.delete();
        } else {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
        }
        return file;
    }            
    public static void deleteFile(String fileName){
        String filePath = FileUtil.getPath() + fileName;
        File file=new File(filePath);
        file.delete();
    }

当然常用的是获取文件信息(参数为文件地址),以及Excel文件名获取

      public static String getPath() {
        return FileUtil.class.getResource("/").getPath();
    }

    public static String getExcelFileName(Integer exportType){
        String date = DateConversion.getDateFormatter(new Date(),DateConversion.YYYYMMDDHHMMSS);
        String fileName = ExportFileEnum.getFileNameByExportType(exportType) + "-" + date +".xlsx";
        return fileName;
    }

3、集合工具

CollectionUtils常用与List集合的判空,也可用于map映射判空

CollectionUtils.isEmpty(list)

当然还有数据到集合的转换,以及合并数组

    public static List arrayToList(Object source) {
        return Arrays.asList(ObjectUtils.toObjectArray(source));
    }

    public static <E> void mergeArrayIntoCollection(Object array, Collection<E> collection) ;

4、验证工具

ValidateUtil工具用于数据的验证,包含大量的类型
字符串,数字类型,布尔的各种数值判断

    public static boolean nullOrZeroDouble(Double value) {
        return value == null || value == 0.0D;
    }

    public static boolean notNullDouble(Double value) {
        return value != null && value != 0.0D;
    }

    public static boolean notNullAndZeroInteger(Integer value) {
        return value != null && value != 0;
    }

    public static boolean nullOrZeroInteger(Integer value) {
        return value == null || value == 0;
    }

    public static boolean notNullAndZeroLong(Long value) {
        return value != null && value != 0L;
    }

    public static boolean nullOrZeroLong(Long value) {
        return value == null || value == 0L;
    }

    public static boolean notBlankString(String value) {
        return value != null && !"".equals(value.trim());
    }

    public static boolean blankString(String value) {
        return value == null || "".equals(value.trim());
    }

    public static boolean blankList(List list) {
        return list == null || list.size() == 0;
    }

    public static boolean notBlankList(List list) {
        return list != null && list.size() != 0;
    }
    public static boolean isTrue(Boolean arg) {
        return arg == null ? false : arg;
    }
    public static boolean isNotTrue(Boolean arg) {
        return arg == null || !arg;
    }

    public static boolean isNum(String value) {
        return !blankString(value) && isStrictNumeric(value.trim());
    }

5、BeanUtils

将一个对象分装成一个map映射

 BeanUtils.map(servicePackOrderDTO, param);

添加对象的属性,以及获取对象属性

oldObj = BeanUtils.getProperty(hisServiceConfig, key);
BeanUtils.setProperty(hisServiceConfig, key, value);
newObj = BeanUtils.getProperty(hisServiceConfig, key);

6、密码工具

可以获取密码, 以及验证密码

   public static String getPassWord(){
        String verificationCode = null;
        if (canPassWord())
            verificationCode = String.valueOf((int)((Math.random()*9+1)*1000));
        return verificationCode;
    }

    public static Boolean canPassWord(){
        String op_export_password =  ParamUtils.getParam("OP_EXPORT_PASSWORD","false");
        return Boolean.valueOf(op_export_password);
    }

三、业务实现

运营平台的导出excel

以下就是实现excel文件的封装
image.png

    /**
     * 健康管理订单列表导出
     */
    @RpcService
    public void exportServicePackOrderExcel(Condition condition) {
        UserRoleToken urt = UserRoleToken.getCurrent();
        Integer exportType = ExportFileEnum.ServicePackOrderExcel.getExportType();
        String fileName = FileUtil.getExcelFileName(exportType);
        String password = PassWordUtil.getPassWord();
        //记录下载
        Integer exportId = recordExport(exportType, fileName, password);
        threadPoolTaskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                ContextUtils.put("exportUser", urt);
                ContextUtils.put("password", password);
                servicePackOrderExcelService.writeExcel(condition, fileName, exportId);
            }
        });
    }

传入json参数

endTime: "2020-12-09"
fromFlag: ""
limit: 10
orderStatus: ""
start: 0
startTime: "2020-12-02"
  1. 接口先进行了输出类型、文件名、密码等获取
  2. 然后调用_ExportRecordService的saveExportRecord()方法来保存导出记录_
  3. 通过一个线程池执行excel的写入

为什么要用一个线程池来写入呢?
为了更快的读取、写入excel文档

小提示

当然导出也有另外的方式:
image.png
以上方法没有调用opexport模块,直接给前端传送一个集合List
猜测 可能是前端封装了数据