增加导出功能
This commit is contained in:
+157
@@ -0,0 +1,157 @@
|
||||
package com.bms.price.task;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.bms.common.config.BmsConfig;
|
||||
import com.bms.common.core.redis.RedisCache;
|
||||
import com.bms.common.utils.StringUtils;
|
||||
import com.bms.common.utils.poi.ExcelUtil;
|
||||
import com.bms.price.domain.PrcOrderBill;
|
||||
import com.bms.price.domain.PrcOrderBillExportTask;
|
||||
import com.bms.price.domain.vo.PrcBillingBillListExportRow;
|
||||
import com.bms.price.domain.vo.PrcOrderBillListExportRow;
|
||||
import com.bms.price.service.IPrcOrderBillService;
|
||||
import com.bms.price.service.support.OrderBillExportSupport;
|
||||
|
||||
/**
|
||||
* Async Excel export for order list / billing list.
|
||||
* Writes under download path; poll task then download by taskId.
|
||||
*/
|
||||
@Component
|
||||
public class PrcOrderBillExportAsyncRunner
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(PrcOrderBillExportAsyncRunner.class);
|
||||
|
||||
public static final String CACHE_KEY_PREFIX = "price:billing:export:task:";
|
||||
public static final int TTL_MINUTES = 60;
|
||||
public static final String REL_DIR = "orderBillExport";
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private IPrcOrderBillService orderBillService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
/**
|
||||
* @param authentication login from request thread; required because {@code selectBillList} uses {@code @DataScope}
|
||||
*/
|
||||
@Async("threadPoolTaskExecutor")
|
||||
public void run(String taskId, String exportType, PrcOrderBill query, String fileName,
|
||||
Authentication authentication)
|
||||
{
|
||||
Path file = null;
|
||||
SecurityContext previous = SecurityContextHolder.getContext();
|
||||
try
|
||||
{
|
||||
// Async pool threads have no JWT filter; restore caller login for DataScope.
|
||||
if (authentication != null)
|
||||
{
|
||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||
context.setAuthentication(authentication);
|
||||
SecurityContextHolder.setContext(context);
|
||||
}
|
||||
put(taskId, PrcOrderBillExportTask.STATUS_RUNNING, 5, "querying", null,
|
||||
exportType, fileName, null, 0);
|
||||
List<PrcOrderBill> list = orderBillService.selectBillList(query == null ? new PrcOrderBill() : query);
|
||||
int rows = list == null ? 0 : list.size();
|
||||
put(taskId, PrcOrderBillExportTask.STATUS_RUNNING, 40, "building excel", null,
|
||||
exportType, fileName, null, rows);
|
||||
|
||||
Path dir = Paths.get(BmsConfig.getDownloadPath(), REL_DIR).toAbsolutePath().normalize();
|
||||
Files.createDirectories(dir);
|
||||
file = dir.resolve(taskId + ".xlsx").normalize();
|
||||
if (!file.startsWith(dir))
|
||||
{
|
||||
throw new IllegalStateException("invalid export path");
|
||||
}
|
||||
try (OutputStream out = Files.newOutputStream(file))
|
||||
{
|
||||
if (PrcOrderBillExportTask.TYPE_BILLING.equals(exportType))
|
||||
{
|
||||
List<PrcBillingBillListExportRow> exportRows = OrderBillExportSupport.toBillingListRows(list);
|
||||
new ExcelUtil<PrcBillingBillListExportRow>(PrcBillingBillListExportRow.class)
|
||||
.exportExcelToStream(exportRows, "\u8ba1\u8d39\u5217\u8868", out);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<PrcOrderBillListExportRow> exportRows = OrderBillExportSupport.toOrderListRows(list);
|
||||
new ExcelUtil<PrcOrderBillListExportRow>(PrcOrderBillListExportRow.class)
|
||||
.exportExcelToStream(exportRows, "\u8ba2\u5355\u5217\u8868", out);
|
||||
}
|
||||
}
|
||||
String storageKey = REL_DIR + "/" + taskId + ".xlsx";
|
||||
put(taskId, PrcOrderBillExportTask.STATUS_SUCCESS, 100, "done", null,
|
||||
exportType, fileName, storageKey, rows);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("order bill export failed taskId={}", taskId, e);
|
||||
if (file != null)
|
||||
{
|
||||
try { Files.deleteIfExists(file); } catch (Exception ignore) { }
|
||||
}
|
||||
put(taskId, PrcOrderBillExportTask.STATUS_FAIL, 100, "failed", errorMessage(e),
|
||||
exportType, fileName, null, 0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (previous == null)
|
||||
{
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
SecurityContextHolder.setContext(previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void put(String taskId, String status, int percent, String message, String error,
|
||||
String exportType, String fileName, String storageKey, int rowCount)
|
||||
{
|
||||
PrcOrderBillExportTask task = new PrcOrderBillExportTask();
|
||||
task.setTaskId(taskId);
|
||||
task.setStatus(status);
|
||||
task.setPercent(percent);
|
||||
task.setMessage(message);
|
||||
task.setError(error);
|
||||
task.setExportType(exportType);
|
||||
task.setFileName(fileName);
|
||||
task.setStorageKey(storageKey);
|
||||
task.setRowCount(rowCount);
|
||||
redisCache.setCacheObject(CACHE_KEY_PREFIX + taskId, task, TTL_MINUTES, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
public PrcOrderBillExportTask get(String taskId)
|
||||
{
|
||||
return redisCache.getCacheObject(CACHE_KEY_PREFIX + taskId);
|
||||
}
|
||||
|
||||
private static String errorMessage(Exception e)
|
||||
{
|
||||
String msg = e.getMessage();
|
||||
if (StringUtils.isEmpty(msg))
|
||||
{
|
||||
msg = e.getClass().getSimpleName();
|
||||
}
|
||||
if (msg.length() > 500)
|
||||
{
|
||||
msg = msg.substring(0, 500);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user