AsyncResultManager.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. package com.shkpr.service.alambizplugin.components;
  2. import com.fasterxml.jackson.core.type.TypeReference;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import com.global.base.log.LogLevelFlag;
  5. import com.global.base.log.LogPrintMgr;
  6. import com.shkpr.service.alambizplugin.commproperties.AsyncTaskProperties;
  7. import com.shkpr.service.alambizplugin.commproperties.TempFileProperties;
  8. import com.shkpr.service.alambizplugin.commtools.CompressorUtils;
  9. import com.shkpr.service.alambizplugin.commtools.ExcelUtils;
  10. import com.shkpr.service.alambizplugin.commtools.ShapeUtils;
  11. import com.shkpr.service.alambizplugin.constants.ExcelEnum;
  12. import com.shkpr.service.alambizplugin.constants.GisSurveyExcelDefine;
  13. import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
  14. import org.apache.commons.compress.archivers.ArchiveException;
  15. import org.apache.commons.io.FileUtils;
  16. import org.opengis.feature.simple.SimpleFeatureType;
  17. import org.springframework.stereotype.Component;
  18. import java.io.File;
  19. import java.io.FileInputStream;
  20. import java.io.FileOutputStream;
  21. import java.io.IOException;
  22. import java.nio.ByteBuffer;
  23. import java.nio.channels.FileChannel;
  24. import java.nio.file.Files;
  25. import java.nio.file.Path;
  26. import java.nio.file.Paths;
  27. import java.util.List;
  28. import java.util.Map;
  29. import java.util.concurrent.ConcurrentHashMap;
  30. /**
  31. * 异步结果管理器
  32. *
  33. * @author 欧阳劲驰
  34. * @since 1.0.0
  35. */
  36. @Component
  37. public class AsyncResultManager {
  38. /**
  39. * 结果文件名
  40. */
  41. public final static String RESULT_FILE_NAME = "result.json";
  42. /**
  43. * 临时文件夹缓存
  44. */
  45. private final static Map<String, Path> TEMP_DIR_CACHE = new ConcurrentHashMap<>();
  46. /**
  47. * 文件分片大小
  48. */
  49. private final static Integer BUFFER_SIZE = 4 * 1024;
  50. /**
  51. * log
  52. */
  53. private final String mStrClassName;
  54. private final String mBizType;
  55. private final AsyncTaskProperties asyncTaskProperties;
  56. private final TempFileProperties tempFileProperties;
  57. private final ObjectMapper objectMapper;
  58. public AsyncResultManager(AsyncTaskProperties asyncTaskProperties, TempFileProperties tempFileProperties, ObjectMapper objectMapper) {
  59. mStrClassName = "AsyncResultManager";
  60. mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
  61. this.asyncTaskProperties = asyncTaskProperties;
  62. this.tempFileProperties = tempFileProperties;
  63. this.objectMapper = objectMapper;
  64. }
  65. /**
  66. * 获取结果
  67. *
  68. * @param flag 结果标识
  69. * @return 检查结果
  70. */
  71. public <T> T getResult(String flag, TypeReference<T> type) {
  72. //创建文件输入流
  73. File file = Paths.get(getResultDirPath(flag).toString(), RESULT_FILE_NAME).toFile();
  74. if (!file.exists()) return null;
  75. try (FileInputStream fileInputStream = new FileInputStream(file)) {
  76. //获取文件通道
  77. FileChannel channel = fileInputStream.getChannel();
  78. //创建缓冲区
  79. ByteBuffer byteBuffer = ByteBuffer.allocate((int) file.length());
  80. //读取通道
  81. int read = channel.read(byteBuffer);
  82. //输入读取信息
  83. if (read > 0) return objectMapper.readValue(byteBuffer.array(), type);
  84. } catch (IOException e) {
  85. //打印报错信息
  86. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
  87. , String.format(
  88. "监测到io异常 结果标识:%s error:%s"
  89. , flag
  90. , e
  91. )
  92. );
  93. return null;
  94. }
  95. return null;
  96. }
  97. /**
  98. * 获取结果文件夹路径
  99. *
  100. * @param flag 结果标识
  101. * @return 结果文件夹路径
  102. */
  103. private Path getResultDirPath(String flag) {
  104. return Paths.get(asyncTaskProperties.getResultPath().toString(), flag);
  105. }
  106. /**
  107. * 创建临时文件夹
  108. *
  109. * @param flag 结果标识
  110. */
  111. public Boolean createTempDirectory(String flag) {
  112. try {
  113. //创建临时文件夹,并缓存路径
  114. Path tempDirectory = Files.createTempDirectory(tempFileProperties.getResourcePath(), flag);
  115. TEMP_DIR_CACHE.put(flag, tempDirectory);
  116. return tempDirectory.toFile().exists();
  117. } catch (IOException e) {
  118. //打印报错信息
  119. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
  120. , String.format(
  121. "监测到io异常 结果标识:%s error:%s"
  122. , flag
  123. , e
  124. )
  125. );
  126. return false;
  127. }
  128. }
  129. /**
  130. * 写入json文件
  131. *
  132. * @param data 数据
  133. * @param flag 结果标识
  134. * @param fileName 文件名
  135. */
  136. public Path writeJson(Object data, String flag, String fileName) {
  137. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  138. , String.format(
  139. "开始执行写入结果文件,结果标识:%s,文件名:%s========>"
  140. , flag
  141. , fileName
  142. )
  143. );
  144. long begin = System.currentTimeMillis();
  145. //写入文件
  146. Path path = Paths.get(TEMP_DIR_CACHE.get(flag).toString(), fileName);
  147. try {
  148. //序列化数据
  149. final byte[] bytes = objectMapper.writeValueAsBytes(data);
  150. //写入文件
  151. int total = writeFile(bytes, path);
  152. if (total > 0) {
  153. long end = System.currentTimeMillis();
  154. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  155. , String.format(
  156. "结束执行写入结果文件,结果标识:%s,文件名:%s,用时(毫秒):%d"
  157. , flag
  158. , fileName
  159. , (end - begin)
  160. )
  161. );
  162. return path;
  163. }
  164. } catch (IOException e) {
  165. //打印报错信息
  166. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
  167. , String.format(
  168. "监测到io异常 结果标识:%s error:%s"
  169. , flag
  170. , e
  171. )
  172. );
  173. }
  174. return null;
  175. }
  176. /**
  177. * 写入excel文件
  178. *
  179. * @param heads 表头
  180. * @param datas 数据
  181. * @param flag 结果标识
  182. * @param fileName 文件名
  183. */
  184. public Path writeExcel(Map<String, Map<String, String>> heads, Map<String, List<Map<String, Object>>> datas, String flag, String fileName) {
  185. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  186. , String.format(
  187. "开始执行写入excel文件,结果标识:%s,文件名:%s========>"
  188. , flag
  189. , fileName
  190. )
  191. );
  192. long begin = System.currentTimeMillis();
  193. //写入文件
  194. Path path = Paths.get(TEMP_DIR_CACHE.get(flag).toString(), fileName);
  195. try {
  196. ExcelUtils.writeFile(heads, datas, Files.newOutputStream(path), ExcelEnum.XLSX
  197. , GisSurveyExcelDefine.FILE_HANDLE.HEADER_ROW_NUM, GisSurveyExcelDefine.FILE_HANDLE.DATA_ROW_NUM);
  198. long end = System.currentTimeMillis();
  199. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  200. , String.format(
  201. "结束执行写入excel文件,结果标识:%s,文件名:%s,用时(毫秒):%d"
  202. , flag
  203. , fileName
  204. , (end - begin)
  205. )
  206. );
  207. return path;
  208. } catch (IOException e) {
  209. //打印报错信息
  210. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
  211. , String.format(
  212. "监测到io异常 结果标识:%s error:%s"
  213. , flag
  214. , e
  215. )
  216. );
  217. return null;
  218. }
  219. }
  220. /**
  221. * 写入shape文件
  222. *
  223. * @param data 数据
  224. * @param flag 结果标识
  225. * @param fileName 文件名
  226. */
  227. public Path writeShape(Map<SimpleFeatureType, List<Map<String, Object>>> data, String flag, String fileName) {
  228. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  229. , String.format(
  230. "开始执行写入shape文件,结果标识:%s,文件名:%s========>"
  231. , flag
  232. , fileName
  233. )
  234. );
  235. long begin = System.currentTimeMillis();
  236. //写入文件
  237. Path path = Paths.get(TEMP_DIR_CACHE.get(flag).toString(), fileName);
  238. try {
  239. //创建临时文件夹
  240. Path tempDirectory = Files.createTempDirectory(tempFileProperties.getResourcePath(), flag);
  241. //导出到shape
  242. ShapeUtils.writeShape(data, tempDirectory);
  243. //压缩文件夹
  244. Path zipPath = CompressorUtils.archivalZip(tempDirectory);
  245. //移动文件
  246. FileUtils.moveFile(zipPath.toFile(), path.toFile());
  247. long end = System.currentTimeMillis();
  248. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  249. , String.format(
  250. "结束执行写入shape文件,结果标识:%s,文件名:%s,用时(毫秒):%d"
  251. , flag
  252. , fileName
  253. , (end - begin)
  254. )
  255. );
  256. return path;
  257. } catch (IOException | ArchiveException e) {
  258. //打印报错信息
  259. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
  260. , String.format(
  261. "监测到io异常 结果标识:%s error:%s"
  262. , flag
  263. , e
  264. )
  265. );
  266. return null;
  267. }
  268. }
  269. /**
  270. * 写文件
  271. *
  272. * @param data 数据
  273. * @param path 文件路径
  274. * @return 写入数量
  275. * @throws IOException io异常
  276. */
  277. private int writeFile(final byte[] data, final Path path) throws IOException {
  278. //创建文件输出流(此处会创建文件)
  279. try (FileOutputStream fileOutputStream = new FileOutputStream(path.toFile())) {
  280. //获取文件通道
  281. FileChannel channel = fileOutputStream.getChannel();
  282. //创建缓冲区
  283. ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
  284. //偏移量
  285. int offset = 0;
  286. //写入总数
  287. int total = 0;
  288. while (offset < data.length) {
  289. //分片大小
  290. int chunkSize = Math.min(BUFFER_SIZE, data.length - offset);
  291. //重置缓冲区,存入缓冲区,翻转
  292. byteBuffer.clear();
  293. byteBuffer.put(data, offset, chunkSize);
  294. byteBuffer.flip();
  295. //写入当前块
  296. total += channel.write(byteBuffer);
  297. offset += chunkSize;
  298. }
  299. //强制写入
  300. channel.force(true);
  301. return total;
  302. }
  303. }
  304. /**
  305. * 替换结果
  306. *
  307. * @param flag 结果标识
  308. * @return 替换状态
  309. */
  310. public boolean replaceResult(String flag) {
  311. //临时文件路径
  312. Path path = TEMP_DIR_CACHE.get(flag);
  313. try {
  314. //替换结果目录
  315. FileUtils.copyDirectory(path.toFile(), getResultDirPath(flag).toFile());
  316. return true;
  317. } catch (IOException e) {
  318. //打印报错信息
  319. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
  320. , String.format(
  321. "监测到io异常 结果标识:%s error:%s"
  322. , flag
  323. , e
  324. )
  325. );
  326. }
  327. return false;
  328. }
  329. }