一、结构速览
首先我们了解的是他的接口:
和之前的接口一样,例如
serviceId: opexport.ServicePackOrderExcelService
methodId: writeExcel
以上是一个写出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
输入备份(记录),其实就是根据输出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文件的封装
/**
* 健康管理订单列表导出
*/
@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"
- 接口先进行了输出类型、文件名、密码等获取
- 然后调用_ExportRecordService的saveExportRecord()方法来保存导出记录_
- 通过一个线程池执行excel的写入
为什么要用一个线程池来写入呢?
为了更快的读取、写入excel文档
小提示
当然导出也有另外的方式:
以上方法没有调用opexport模块,直接给前端传送一个集合List猜测 可能是前端封装了数据