| @@ -14,6 +14,8 @@ import com.ruoyi.common.enums.BusinessType; | |||
| import com.ruoyi.common.utils.pdf.PdfUtils; | |||
| import com.ruoyi.common.utils.poi.ExcelUtil; | |||
| import com.ruoyi.common.utils.translation.TranslateUtils; | |||
| import com.ruoyi.geo.service.GeoExportHandlerService; | |||
| import com.ruoyi.geo.service.GeoImportHandlerService; | |||
| import com.ruoyi.system.service.ISysDeptService; | |||
| import org.apache.commons.compress.utils.Lists; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| @@ -38,7 +40,9 @@ public class TTaskExportController extends BaseController | |||
| private ITTaskExportService tTaskExportService; | |||
| @Autowired | |||
| private ISysDeptService deptService; | |||
| private ISysDeptService deptService; | |||
| @Autowired | |||
| private GeoExportHandlerService exportHandlerService; | |||
| /** | |||
| * 查询导出任务列表 | |||
| @@ -198,4 +202,47 @@ public class TTaskExportController extends BaseController | |||
| PdfUtils.initPdf(response, pdf); | |||
| } | |||
| /** | |||
| * 开始导出任务 | |||
| */ | |||
| @PreAuthorize("@ss.hasPermi('business:export:do')") | |||
| @Log(title = "开始导入任务", businessType = BusinessType.UPDATE) | |||
| @PostMapping("/start/{taskId}") | |||
| public AjaxResult start(@PathVariable Long taskId) | |||
| { | |||
| return AjaxResult.success(exportHandlerService.startTask(taskId)); | |||
| } | |||
| /** | |||
| * 获取导出任务日志 | |||
| */ | |||
| @PreAuthorize("@ss.hasPermi('business:export:do')") | |||
| @GetMapping("/log/{taskId}") | |||
| public AjaxResult log(@PathVariable Long taskId, Integer offset) | |||
| { | |||
| if(null == offset) | |||
| offset = 0; | |||
| return AjaxResult.success(exportHandlerService.loadExportLog(taskId, offset)); | |||
| } | |||
| /** | |||
| * 下载导出任务日志 | |||
| */ | |||
| @PreAuthorize("@ss.hasPermi('business:export:do')") | |||
| @GetMapping("/downloadLog/{taskId}") | |||
| public void downloadLog(@PathVariable Long taskId, HttpServletResponse response) | |||
| { | |||
| exportHandlerService.downloadLog(taskId, response); | |||
| } | |||
| /** | |||
| * 下载导出任务文件 | |||
| */ | |||
| @PreAuthorize("@ss.hasPermi('business:export:down')") | |||
| @GetMapping("/downloadFile/{taskId}") | |||
| public void downloadFile(@PathVariable Long taskId, HttpServletResponse response) | |||
| { | |||
| exportHandlerService.downloadFile(taskId, response); | |||
| } | |||
| } | |||
| @@ -214,7 +214,7 @@ public class TTaskImportController extends BaseController | |||
| @PostMapping("/start/{taskId}") | |||
| public AjaxResult start(@PathVariable Long taskId) | |||
| { | |||
| return AjaxResult.success(importHandlerService.StartTask(taskId)); | |||
| return AjaxResult.success(importHandlerService.startTask(taskId)); | |||
| } | |||
| /** | |||
| @@ -226,7 +226,7 @@ public class TTaskImportController extends BaseController | |||
| { | |||
| if(null == offset) | |||
| offset = 0; | |||
| return AjaxResult.success(importHandlerService.GetImportLog(taskId, offset)); | |||
| return AjaxResult.success(importHandlerService.loadImportLog(taskId, offset)); | |||
| } | |||
| /** | |||
| @@ -236,6 +236,6 @@ public class TTaskImportController extends BaseController | |||
| @GetMapping("/downloadLog/{taskId}") | |||
| public void downloadLog(@PathVariable Long taskId, HttpServletResponse response) | |||
| { | |||
| importHandlerService.DownloadLog(taskId, response); | |||
| importHandlerService.downloadLog(taskId, response); | |||
| } | |||
| } | |||
| @@ -135,6 +135,12 @@ xss: | |||
| urlPatterns: /system/*,/monitor/*,/tool/* | |||
| importTask: | |||
| # 是否启动时执行等待中的任务 | |||
| startOnBoot: false | |||
| # 下次建议读取日志的间隔(毫秒) | |||
| logNextPoll: 2000 | |||
| exportTask: | |||
| # 是否启动时执行等待中的任务 | |||
| startOnBoot: false | |||
| # 下次建议读取日志的间隔(毫秒) | |||
| @@ -1,15 +1,21 @@ | |||
| import cn.hutool.core.io.FileUtil; | |||
| import cn.hutool.core.thread.ThreadUtil; | |||
| import com.alibaba.fastjson2.JSON; | |||
| import com.ruoyi.RuoYiApplication; | |||
| import com.ruoyi.common.geo.GeoParser; | |||
| import com.ruoyi.common.geo.GeoWriter; | |||
| import com.ruoyi.geo.service.GeoExportHandlerService; | |||
| import com.ruoyi.geo.service.GeoImportHandlerService; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.junit.jupiter.api.Test; | |||
| import org.junit.jupiter.api.extension.ExtendWith; | |||
| import org.locationtech.jts.geom.MultiPolygon; | |||
| import org.springframework.boot.test.context.SpringBootTest; | |||
| import org.springframework.test.context.junit.jupiter.SpringExtension; | |||
| import javax.annotation.Resource; | |||
| import java.math.BigDecimal; | |||
| import java.util.LinkedHashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| @@ -19,13 +25,16 @@ import java.util.Map; | |||
| public final class GeoTest | |||
| { | |||
| @Resource | |||
| private GeoImportHandlerService service; | |||
| private GeoImportHandlerService importer; | |||
| @Resource | |||
| private GeoExportHandlerService exporter; | |||
| @Test | |||
| public void test() | |||
| { | |||
| service.StartTask(4L); | |||
| //service.startTask(4L); | |||
| //new Scanner(System.in).next(); | |||
| exporter.startTask(3L); | |||
| ThreadUtil.sleep(5000); | |||
| } | |||
| @@ -36,18 +45,39 @@ public final class GeoTest | |||
| PATH = "D:/m/胜利村_shp_3857/dk.shp"; // dk | |||
| PATH = "D:/m/胜利村_shp_3857/zyhycg.shp"; // zyhycg | |||
| PATH = "D:/m/胜利村_shp_3857/jtzy.shp"; // jtzy | |||
| try(GeoParser geo = new GeoParser()) | |||
| String OUT; | |||
| OUT = "D:/m/output_胜利村_shp_3857/jtzyxx.shp"; | |||
| FileUtil.mkParentDirs(OUT); | |||
| try(GeoParser parser = new GeoParser()) | |||
| { | |||
| geo.Open(PATH, "UTF-8"); | |||
| System.err.println(geo.GetTypeNames()); | |||
| geo.SetSource(0); | |||
| List<Map<String, Object>> cjqies = geo.GetMapList(); | |||
| //List<GeoCJQY> cjqies = geo.GetList(GeoCJQY.class); | |||
| //List<GeoJTZY> cjqies = geo.GetList(GeoJTZY.class); | |||
| //List<GeoZYHYCG> cjqies = geo.GetList(GeoZYHYCG.class); | |||
| //List<GeoDK> cjqies = geo.GetList(GeoDK.class); | |||
| System.err.println(JSON.toJSONString(cjqies)); | |||
| parser.Open(PATH, "UTF-8"); | |||
| System.out.println(parser.GetTypeNames()); | |||
| parser.SetSource(0); | |||
| List<Map<String, Object>> cjqies = parser.GetMapList(); | |||
| //List<GeoCJQY> cjqies = parser.GetList(GeoCJQY.class); | |||
| //List<GeoJTZY> cjqies = parser.GetList(GeoJTZY.class); | |||
| //List<GeoZYHYCG> cjqies = parser.GetList(GeoZYHYCG.class); | |||
| //List<GeoDK> cjqies = parser.GetList(GeoDK.class); | |||
| System.out.println(JSON.toJSONString(cjqies)); | |||
| System.out.println("-------------------------"); | |||
| try(GeoWriter writer = new GeoWriter()) | |||
| { | |||
| writer.Open(OUT, "UTF-8"); | |||
| Map<String, Class<?>> classes = new LinkedHashMap<>(); | |||
| classes.put("QSDWDM", String.class); | |||
| classes.put("QSDWMC", String.class); | |||
| classes.put("Shape_Area", BigDecimal.class); | |||
| classes.put("the_geom", MultiPolygon.class); | |||
| writer.AddSchema("test123", classes); | |||
| System.out.println(writer.GetTypeNames()); | |||
| writer.SetSource(0, false); | |||
| writer.WriteMapList(cjqies); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -2,6 +2,7 @@ package com.ruoyi.business.mapper; | |||
| import java.util.List; | |||
| import com.ruoyi.business.domain.TTaskExport; | |||
| import com.ruoyi.business.domain.TTaskImport; | |||
| /** | |||
| * 导出任务Mapper接口 | |||
| @@ -74,4 +75,7 @@ public interface TTaskExportMapper | |||
| * @return 结果 | |||
| */ | |||
| public int deleteTTaskExportByIds(Long[] ids); | |||
| public int terminateRunningTask(); | |||
| public TTaskExport getForUpdate(Long id); | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| package com.ruoyi.geo.config; | |||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||
| import org.springframework.stereotype.Component; | |||
| @Component | |||
| @ConfigurationProperties(prefix = "export-task") | |||
| public class GeoExportTaskConfig | |||
| { | |||
| public static boolean startOnBoot = false; // 是否启动时执行等待中的任务 | |||
| public static long logNextPoll = 2000; // 下次建议读取日志的间隔(毫秒) | |||
| public void setStartOnBoot(boolean startOnBoot) | |||
| { | |||
| GeoExportTaskConfig.startOnBoot = startOnBoot; | |||
| } | |||
| public void setLogNextPoll(long logNextPoll) | |||
| { | |||
| GeoExportTaskConfig.logNextPoll = logNextPoll; | |||
| } | |||
| } | |||
| @@ -6,9 +6,25 @@ import com.ruoyi.common.utils.StringUtils; | |||
| public final class GeoSysDir | |||
| { | |||
| // 导入日志路径 | |||
| public static final String LOG = "/log"; | |||
| public static final String LOG = "/log"; | |||
| // 导入zip临时解压路径 | |||
| public static final String ZIP_EXTRACT_TEMP = "/unzip"; | |||
| public static final String UNZIP_DECOMPRESS_TEMP = "/unzip"; | |||
| // 导出zip临时生成路径 | |||
| public static final String ZIP_COMPRESS_TEMP = "/zip"; | |||
| // 导出zip临时生成路径 | |||
| public static final String ZIP_FILE_TEMP = "/zip_temp"; | |||
| // 导出zip临时生成路径 | |||
| public static final String ZIP_DOWNLOAD = "/zip"; | |||
| public static String TrimProfile(String path) | |||
| { | |||
| if(StringUtils.isEmpty(path)) | |||
| return ""; | |||
| else if(path.startsWith("/profile")) | |||
| return path.substring("/profile".length()); | |||
| else | |||
| return path; | |||
| } | |||
| public static String GetDir(String path) | |||
| { | |||
| @@ -68,5 +84,17 @@ public final class GeoSysDir | |||
| return "<profile directory>" + fpath.substring(fprofile.length()); | |||
| } | |||
| public static String TrimNormalized(String path) | |||
| { | |||
| if(StringUtils.isEmpty(path)) | |||
| return path; | |||
| String fpath = path.replaceAll("\\\\", "/"); | |||
| String fprofile = RuoYiConfig.getProfile().replaceAll("\\\\", "/"); | |||
| if(!fpath.startsWith(fprofile)) | |||
| return path; | |||
| return fpath.substring(fprofile.length()); | |||
| } | |||
| private GeoSysDir() {} | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| package com.ruoyi.geo.framework; | |||
| import com.ruoyi.business.domain.TGisCjqy; | |||
| import com.ruoyi.common.geo.GeoCreator; | |||
| import com.ruoyi.geo.service.GeoMapperService; | |||
| import com.ruoyi.geo.structs.GeoCJQY; | |||
| import org.locationtech.jts.geom.MultiPolygon; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.stream.Collectors; | |||
| public class GeoCjqyExportTask implements GeoDBExportTaskInterface | |||
| { | |||
| private final static String TYPE_NAME = "村级区域"; | |||
| private final GeoExportTask exportTask; | |||
| private List<TGisCjqy> list; | |||
| public GeoCjqyExportTask(GeoExportTask exportTask) | |||
| { | |||
| this.exportTask = exportTask; | |||
| } | |||
| public int LoadDataList() | |||
| { | |||
| TGisCjqy cond = new TGisCjqy(); | |||
| cond.setImportCode(exportTask.dept.getImportCode()); | |||
| list = GeoMapperService.GisCjqyMapper().selectTGisCjqyList(cond); | |||
| exportTask.logFile.WriteLine(TYPE_NAME + "读取系统数据条数: 区划代码={}, 条数={}", exportTask.dept.getImportCode(), list.size()); | |||
| return list.size(); | |||
| } | |||
| private GeoCJQY ConvertData(TGisCjqy src, GeoCJQY dst) | |||
| { | |||
| if(null == dst) | |||
| dst = new GeoCJQY(); | |||
| dst.the_geom = src.getTheGeom(); | |||
| dst.BSM = src.getBsm().intValue(); | |||
| dst.YSDM = src.getYsdm(); | |||
| dst.CJQYDM = src.getCjqydm(); | |||
| dst.CJQYMC = src.getCjqymc(); | |||
| return dst; | |||
| } | |||
| public void SaveData() | |||
| { | |||
| exportTask.logFile.WriteLine(TYPE_NAME + "开始导出数据: 区划代码={}, 条数={}", exportTask.dept.getDeptName(), list.size()); | |||
| List<GeoCJQY> dataList = list.stream().map((x) -> ConvertData(x, null)).collect(Collectors.toList()); | |||
| exportTask.writer.WriteList(dataList); | |||
| } | |||
| public Map<String, Class<?>> GetTypes() | |||
| { | |||
| Map<String, Class<?>> types = GeoCreator.GetClassTypes(GeoCJQY.class); | |||
| types.put("the_geom", MultiPolygon.class); | |||
| return types; | |||
| } | |||
| } | |||
| @@ -6,7 +6,9 @@ import com.ruoyi.business.mapper.TGisCjqyMapper; | |||
| import com.ruoyi.common.core.domain.entity.SysDept; | |||
| import com.ruoyi.common.utils.StringUtils; | |||
| import com.ruoyi.geo.service.GeoImportHandlerService; | |||
| import com.ruoyi.geo.service.GeoMapperService; | |||
| import com.ruoyi.geo.structs.GeoCJQY; | |||
| import static com.ruoyi.business.constants.TaskEnums.ImportType; | |||
| import java.util.ArrayList; | |||
| @@ -14,14 +16,14 @@ import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.stream.Collectors; | |||
| public class GeoCjqyTask implements GeoDBTaskInterface | |||
| public class GeoCjqyImportTask implements GeoDBImportTaskInterface | |||
| { | |||
| private final static String TYPE_NAME = "村级区域"; | |||
| private final GeoImportTask importTask; | |||
| private List<GeoCJQY> list; | |||
| public GeoCjqyTask(GeoImportTask importTask) | |||
| public GeoCjqyImportTask(GeoImportTask importTask) | |||
| { | |||
| this.importTask = importTask; | |||
| } | |||
| @@ -64,7 +66,7 @@ public class GeoCjqyTask implements GeoDBTaskInterface | |||
| { | |||
| TGisCjqy cond = new TGisCjqy(); | |||
| cond.setCjqydm(qydm); | |||
| List<TGisCjqy> cjqies = GeoImportHandlerService.GisCjqyMapper().selectTGisCjqyList(cond); | |||
| List<TGisCjqy> cjqies = GeoMapperService.GisCjqyMapper().selectTGisCjqyList(cond); | |||
| importTask.logFile.WriteLine(TYPE_NAME + "读取系统已存在的条数: 区划代码={}, 条数={}", qydm, cjqies.size()); | |||
| return cjqies; | |||
| } | |||
| @@ -87,7 +89,7 @@ public class GeoCjqyTask implements GeoDBTaskInterface | |||
| if(ImportType.IT_OVERRIDE.equals(importTask.taskImport.getImportType())) | |||
| { | |||
| importTask.logFile.WriteLine(TYPE_NAME + "覆盖导入, 需清空现有数据, 然后再插入, 区划代码={}", importCode); | |||
| int ret = GeoImportHandlerService.GisCjqyMapper().deleteByCode(importCode); | |||
| int ret = GeoMapperService.GisCjqyMapper().deleteByCode(importCode); | |||
| importTask.logFile.WriteLine(TYPE_NAME + "清空现有数据: {}, 区划代码={}", ret, importCode); | |||
| return ret; | |||
| } | |||
| @@ -100,7 +102,7 @@ public class GeoCjqyTask implements GeoDBTaskInterface | |||
| private int WriteData(List<TGisCjqy> insertList, List<TGisCjqy> updateList, SysDept dept) | |||
| { | |||
| TGisCjqyMapper gisCjqyMapper = GeoImportHandlerService.GisCjqyMapper(); | |||
| TGisCjqyMapper gisCjqyMapper = GeoMapperService.GisCjqyMapper(); | |||
| int i = ListUtil.split(insertList, 50).stream().map(gisCjqyMapper::insertTGisCjqyBatch).reduce(0, Integer::sum); | |||
| importTask.logFile.WriteLine(TYPE_NAME + "新增数据: 区划代码={}, 条数={}", dept.getDeptName(), i); | |||
| int u = ListUtil.split(updateList, 50).stream().map(gisCjqyMapper::updateTGisCjqyBatch).reduce(0, Integer::sum); | |||
| @@ -111,21 +113,29 @@ public class GeoCjqyTask implements GeoDBTaskInterface | |||
| private int SaveDeptData(SysDept dept, List<GeoCJQY> datas) | |||
| { | |||
| importTask.logFile.WriteLine(TYPE_NAME + "开始处理数据: 区划代码={}, 条数={}", dept.getDeptName(), datas.size()); | |||
| List<TGisCjqy> databases = LoadDatabase(dept.getImportCode()); | |||
| Map<String, TGisCjqy> exists = databases.stream().collect(Collectors.toMap(TGisCjqy::getCjqydm, x->x)); | |||
| boolean needCheck = !ImportType.IT_OVERRIDE.equals(importTask.taskImport.getImportType()); | |||
| Map<String, TGisCjqy> exists = null; | |||
| if(needCheck) | |||
| { | |||
| List<TGisCjqy> databases = LoadDatabase(dept.getImportCode()); | |||
| exists = databases.stream().collect(Collectors.toMap(TGisCjqy::getCjqydm, x->x)); | |||
| } | |||
| List<TGisCjqy> insertList = new ArrayList<>(); | |||
| List<TGisCjqy> updateList = new ArrayList<>(); | |||
| for(GeoCJQY data : datas) | |||
| { | |||
| TGisCjqy db = exists.get(data.CJQYDM); | |||
| boolean has = null == db; | |||
| db = ConvertData(data, db, dept); | |||
| if(has) | |||
| insertList.add(db); | |||
| TGisCjqy db = null; | |||
| if(needCheck) | |||
| { | |||
| db = exists.get(data.CJQYDM); | |||
| } | |||
| TGisCjqy item = ConvertData(data, db, dept); | |||
| if(null == db) | |||
| insertList.add(item); | |||
| else | |||
| updateList.add(db); | |||
| updateList.add(item); | |||
| } | |||
| CleanDatabase(dept.getImportCode()); | |||
| @@ -0,0 +1,11 @@ | |||
| package com.ruoyi.geo.framework; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| public interface GeoDBExportTaskInterface | |||
| { | |||
| public Map<String, Class<?>> GetTypes(); | |||
| public int LoadDataList(); | |||
| public void SaveData(); | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| package com.ruoyi.geo.framework; | |||
| public interface GeoDBTaskInterface | |||
| public interface GeoDBImportTaskInterface | |||
| { | |||
| public int LoadDataList(); | |||
| public void CheckData(); | |||
| @@ -0,0 +1,315 @@ | |||
| package com.ruoyi.geo.framework; | |||
| import cn.hutool.core.collection.CollectionUtil; | |||
| import cn.hutool.core.date.DateUtil; | |||
| import cn.hutool.core.io.FileUtil; | |||
| import cn.hutool.core.util.ZipUtil; | |||
| import com.ruoyi.business.domain.TTaskExport; | |||
| import com.ruoyi.common.config.RuoYiConfig; | |||
| import com.ruoyi.common.core.domain.entity.SysDept; | |||
| import com.ruoyi.common.geo.GeoWriter; | |||
| import com.ruoyi.common.utils.ExceptionUtil; | |||
| import com.ruoyi.common.utils.StringUtils; | |||
| import com.ruoyi.common.utils.spring.SpringUtils; | |||
| import com.ruoyi.common.utils.sql.DB; | |||
| import com.ruoyi.geo.constants.GeoShpType; | |||
| import com.ruoyi.geo.constants.GeoSysDir; | |||
| import com.ruoyi.geo.service.GeoExportHandlerService; | |||
| import com.ruoyi.geo.service.GeoMapperService; | |||
| import com.ruoyi.system.mapper.SysDeptMapper; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import java.io.File; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.Date; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.stream.Collectors; | |||
| import static com.ruoyi.business.constants.TaskEnums.TaskStatus; | |||
| @Slf4j | |||
| public class GeoExportTask implements Runnable | |||
| { | |||
| private final Long taskId; | |||
| TTaskExport taskExport; | |||
| GeoTaskLog logFile; | |||
| GeoWriter writer; | |||
| private final List<String> typeNames = Arrays.asList( | |||
| GeoShpType.CJQY, | |||
| GeoShpType.JTZY, | |||
| GeoShpType.ZYHYCG | |||
| ); | |||
| private Map<String, Class<?>> typeClasses; | |||
| private String shpFile; | |||
| private String type; | |||
| String username; | |||
| Date now; | |||
| SysDept dept; | |||
| private GeoDBExportTaskInterface task; | |||
| public GeoExportTask(Long taskId) | |||
| { | |||
| this.taskId = taskId; | |||
| } | |||
| public void Init() | |||
| { | |||
| now = new Date(); | |||
| username = "admin"; //SecurityUtils.getUsername(); | |||
| String path = LogPath(); | |||
| log.info("任务{}日志文件: {}", taskId, path); | |||
| logFile = new GeoTaskLog(path); | |||
| logFile.Open(); | |||
| logFile.WriteLine("任务初始化: {} - {}", taskId, DateUtil.format(now, "yyyy-MM-dd HH:mm:ss.SSS")); | |||
| } | |||
| public void Shutdown() | |||
| { | |||
| //CleanTempFiles(); | |||
| logFile.WriteLine("任务结束: {} - {}", taskId, DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")); | |||
| if(null != logFile) | |||
| { | |||
| logFile.close(); | |||
| } | |||
| log.info("任务{}日志文件: {}", taskId, GeoSysDir.DesensitizedNormalized(LogPath())); | |||
| } | |||
| private String ZipCachePath() | |||
| { | |||
| return GeoSysDir.CacheDir(GeoSysDir.ZIP_COMPRESS_TEMP + "/" + taskId); | |||
| } | |||
| private String ZipTempFilePath() | |||
| { | |||
| return GeoSysDir.CacheDir(GeoSysDir.ZIP_FILE_TEMP + "/" + taskId + ".zip.temp"); | |||
| } | |||
| private String ZipFilePath() | |||
| { | |||
| return GeoSysDir.ExportDir(GeoSysDir.ZIP_DOWNLOAD + "/" + taskId + ".zip"); | |||
| } | |||
| public String LogPath() | |||
| { | |||
| return GeoSysDir.ExportDir(GeoSysDir.LOG) + "/" + taskId + ".log"; | |||
| } | |||
| private void Ready() | |||
| { | |||
| // 先清空源临时解压文件 | |||
| CleanTempFiles(); | |||
| String toDir = ZipCachePath(); | |||
| FileUtil.mkdir(toDir); | |||
| FileUtil.mkParentDirs(ZipFilePath()); | |||
| } | |||
| private void CleanTempFiles() | |||
| { | |||
| String toDir = ZipCachePath(); | |||
| logFile.WriteLine("清理临时文件: " + GeoSysDir.DesensitizedNormalized(toDir)); | |||
| FileUtil.del(toDir); | |||
| } | |||
| private void Compress() | |||
| { | |||
| String cacheDir = ZipCachePath(); | |||
| logFile.WriteLine("开始压缩临时shp文件: " + GeoSysDir.DesensitizedNormalized(cacheDir)); | |||
| String zipTempFile = ZipTempFilePath(); | |||
| FileUtil.mkParentDirs(zipTempFile); | |||
| logFile.WriteLine("生成临时zip文件: " + GeoSysDir.DesensitizedNormalized(zipTempFile)); | |||
| ZipUtil.zip(cacheDir, ZipTempFilePath()); | |||
| String zipFile = ZipFilePath(); | |||
| FileUtil.mkParentDirs(zipFile); | |||
| if(StringUtils.isNotEmpty(taskExport.getFileUrl())) | |||
| { | |||
| File file = new File(RuoYiConfig.getProfile() + "/" + GeoSysDir.TrimProfile(taskExport.getFileUrl())); | |||
| if(file.isFile()) | |||
| { | |||
| logFile.WriteLine("删除之前的zip文件: " + GeoSysDir.DesensitizedNormalized(file.getAbsolutePath())); | |||
| file.delete(); | |||
| } | |||
| } | |||
| logFile.WriteLine("复制zip到下载目录: " + GeoSysDir.DesensitizedNormalized(zipFile)); | |||
| FileUtil.move(new File(zipTempFile), new File(zipFile), true); | |||
| taskExport.setFileUrl("/profile" + GeoSysDir.TrimNormalized(zipFile)); | |||
| } | |||
| private void CreateShp() | |||
| { | |||
| writer = new GeoWriter(); | |||
| if(!writer.Open(shpFile, "UTF-8")) | |||
| { | |||
| logFile.ErrorLine("打开shp文件错误: " + shpFile); | |||
| } | |||
| try | |||
| { | |||
| writer.AddSchema(type, typeClasses); | |||
| System.out.println(writer.GetTypeNames()); | |||
| if(!writer.SetSource(type, false)) | |||
| { | |||
| logFile.ErrorLine("shp文件未找到支持源: " + type); | |||
| return; | |||
| } | |||
| task.SaveData(); | |||
| } | |||
| catch(Exception e) | |||
| { | |||
| e.printStackTrace(); | |||
| } | |||
| finally | |||
| { | |||
| writer.close(); | |||
| writer = null; | |||
| } | |||
| } | |||
| private void LoadDept() | |||
| { | |||
| dept = GeoMapperService.DeptMapper().selectDeptByOrgCode(taskExport.getOrgCode()); | |||
| } | |||
| private void LoadTask() | |||
| { | |||
| TTaskExport task = GeoMapperService.TaskExportMapper().getForUpdate(taskId); | |||
| if(null == task) | |||
| { | |||
| logFile.ErrorLine("任务配置不存在: " + taskId); | |||
| return; | |||
| } | |||
| if(!TaskStatus.ST_WAIT.equals(task.getTaskStatus())) | |||
| { | |||
| logFile.ErrorLine("任务非等待状态: " + taskId); | |||
| return; | |||
| } | |||
| taskExport = task; | |||
| } | |||
| private void SaveTask(String st) | |||
| { | |||
| if(null != taskExport) | |||
| { | |||
| taskExport.setTaskStatus(st); | |||
| GeoMapperService.TaskExportMapper().updateTTaskExport(taskExport); | |||
| } | |||
| } | |||
| private void HandleShpTypes() | |||
| { | |||
| for(String shpType : typeNames) | |||
| { | |||
| type = shpType; | |||
| // 2. 分发任务 | |||
| DispatchTask(); | |||
| } | |||
| } | |||
| private void DispatchTask() | |||
| { | |||
| // 1. 选择任务类型 | |||
| switch(type.toLowerCase()) | |||
| { | |||
| case GeoShpType.CJQY: | |||
| task = new GeoCjqyExportTask(this); | |||
| break; | |||
| case GeoShpType.JTZY: | |||
| task = new GeoJtzyExportTask(this); | |||
| break; | |||
| case GeoShpType.ZYHYCG: | |||
| task = new GeoZyhycgExportTask(this); | |||
| break; | |||
| default: | |||
| logFile.WriteLine("数据类型不支持: " + type); | |||
| return; | |||
| } | |||
| // 2. 处理导入任务 | |||
| DoTask(); | |||
| } | |||
| private void CreateShpFile() | |||
| { | |||
| shpFile = ZipCachePath() + "/"/* + group + "/"*/ + type.toLowerCase() + ".shp"; | |||
| FileUtil.mkParentDirs(shpFile); | |||
| } | |||
| private void DoTask() | |||
| { | |||
| typeClasses = task.GetTypes(); | |||
| int num = task.LoadDataList(); | |||
| if(num == 0) | |||
| { | |||
| logFile.WriteLine("数据库支持源未读取到数据: " + type); | |||
| return; | |||
| } | |||
| CreateShpFile(); | |||
| CreateShp(); | |||
| } | |||
| private void Handle() | |||
| { | |||
| // 0. 初始化任务: 打开日志系统 | |||
| Init(); | |||
| // 1. 加载任务配置, 并检查 | |||
| LoadTask(); | |||
| // 2. 读取文件, 解压文件到工作目录 | |||
| Ready(); | |||
| // 3. 加载部门数据 | |||
| LoadDept(); | |||
| // 4. 依次处理所有shp文件 | |||
| HandleShpTypes(); | |||
| // 5. 压缩 | |||
| Compress(); | |||
| } | |||
| @Override | |||
| public void run() | |||
| { | |||
| Object handle = null; | |||
| try | |||
| { | |||
| handle = DB.BeginTransaction(); | |||
| Handle(); | |||
| // 更改任务状态为已完成 | |||
| SaveTask(TaskStatus.ST_FINISH); | |||
| } | |||
| catch(Exception e) | |||
| { | |||
| e.printStackTrace(); | |||
| logFile.WriteLine(ExceptionUtil.getExceptionMessage(e)); | |||
| SaveTask(TaskStatus.ST_FAIL); | |||
| } | |||
| finally | |||
| { | |||
| DB.EndTransaction(handle); | |||
| // -1: 终止任务, 关闭日志系统 | |||
| Shutdown(); | |||
| } | |||
| } | |||
| public Long GetTaskId() | |||
| { | |||
| return taskId; | |||
| } | |||
| } | |||
| @@ -14,6 +14,7 @@ import com.ruoyi.common.utils.sql.DB; | |||
| import com.ruoyi.geo.constants.GeoShpType; | |||
| import com.ruoyi.geo.constants.GeoSysDir; | |||
| import com.ruoyi.geo.service.GeoImportHandlerService; | |||
| import com.ruoyi.geo.service.GeoMapperService; | |||
| import com.ruoyi.system.mapper.SysDeptMapper; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import static com.ruoyi.business.constants.TaskEnums.TaskStatus; | |||
| @@ -40,7 +41,7 @@ public class GeoImportTask implements Runnable | |||
| String username; | |||
| Date now; | |||
| private GeoDBTaskInterface task; | |||
| private GeoDBImportTaskInterface task; | |||
| public GeoImportTask(Long taskId) | |||
| { | |||
| @@ -72,7 +73,7 @@ public class GeoImportTask implements Runnable | |||
| private String UnzipCachePath() | |||
| { | |||
| return GeoSysDir.CacheDir(GeoSysDir.ZIP_EXTRACT_TEMP + "/" + taskId); | |||
| return GeoSysDir.CacheDir(GeoSysDir.UNZIP_DECOMPRESS_TEMP + "/" + taskId); | |||
| } | |||
| public String LogPath() | |||
| @@ -157,15 +158,14 @@ public class GeoImportTask implements Runnable | |||
| private void LoadDept() | |||
| { | |||
| SysDept cond = new SysDept(); | |||
| SysDeptMapper deptMapper = SpringUtils.getBean(SysDeptMapper.class); | |||
| List<SysDept> sysDepts = deptMapper.selectDeptList(cond); | |||
| List<SysDept> sysDepts = GeoMapperService.DeptMapper().selectDeptList(cond); | |||
| importDeptMap = sysDepts.stream().collect(Collectors.toMap(SysDept::getImportCode, x -> x)); | |||
| sysDeptMap = sysDepts.stream().collect(Collectors.toMap(SysDept::getOrgCode, x -> x)); | |||
| } | |||
| private void LoadTask() | |||
| { | |||
| TTaskImport task = GeoImportHandlerService.TaskImportMapper().getForUpdate(taskId); | |||
| TTaskImport task = GeoMapperService.TaskImportMapper().getForUpdate(taskId); | |||
| if(null == task) | |||
| { | |||
| logFile.ErrorLine("任务配置不存在: " + taskId); | |||
| @@ -184,7 +184,7 @@ public class GeoImportTask implements Runnable | |||
| if(null != taskImport) | |||
| { | |||
| taskImport.setTaskStatus(st); | |||
| GeoImportHandlerService.TaskImportMapper().updateTTaskImport(taskImport); | |||
| GeoMapperService.TaskImportMapper().updateTTaskImport(taskImport); | |||
| } | |||
| } | |||
| @@ -215,13 +215,13 @@ public class GeoImportTask implements Runnable | |||
| switch(type.toLowerCase()) | |||
| { | |||
| case GeoShpType.CJQY: | |||
| task = new GeoCjqyTask(this); | |||
| task = new GeoCjqyImportTask(this); | |||
| break; | |||
| case GeoShpType.JTZY: | |||
| task = new GeoJtzyTask(this); | |||
| task = new GeoJtzyImportTask(this); | |||
| break; | |||
| case GeoShpType.ZYHYCG: | |||
| task = new GeoZyhycgTask(this); | |||
| task = new GeoZyhycgImportTask(this); | |||
| break; | |||
| default: | |||
| logFile.WriteLine("数据类型不支持: " + type); | |||
| @@ -0,0 +1,79 @@ | |||
| package com.ruoyi.geo.framework; | |||
| import com.ruoyi.common.geo.GeoCreator; | |||
| import com.ruoyi.geo.service.GeoExportHandlerService; | |||
| import com.ruoyi.geo.service.GeoMapperService; | |||
| import com.ruoyi.geo.structs.GeoJTZY; | |||
| import com.ruoyi.resource.domain.TResourceLand; | |||
| import org.locationtech.jts.geom.MultiPolygon; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.stream.Collectors; | |||
| public class GeoJtzyExportTask implements GeoDBExportTaskInterface | |||
| { | |||
| private final static String TYPE_NAME = "地块属性"; | |||
| private final GeoExportTask exportTask; | |||
| private List<TResourceLand> list; | |||
| public GeoJtzyExportTask(GeoExportTask exportTask) | |||
| { | |||
| this.exportTask = exportTask; | |||
| } | |||
| public int LoadDataList() | |||
| { | |||
| TResourceLand cond = new TResourceLand(); | |||
| cond.setImportCode(exportTask.dept.getImportCode()); | |||
| list = GeoMapperService.ResourceLandMapper().selectTResourceLandList(cond); | |||
| exportTask.logFile.WriteLine(TYPE_NAME + "读取系统数据条数: 区划代码={}, 条数={}", exportTask.dept.getImportCode(), list.size()); | |||
| return list.size(); | |||
| } | |||
| private GeoJTZY ConvertData(TResourceLand src, GeoJTZY dst) | |||
| { | |||
| if(null == dst) | |||
| dst = new GeoJTZY(); | |||
| dst.the_geom = src.getTheGeom(); | |||
| dst.BSM = src.getBsm(); | |||
| dst.YSDM = src.getYsdm(); | |||
| dst.DKBM = src.getDkbm(); | |||
| dst.DKMC = src.getDkmc(); | |||
| dst.SYQXZ = src.getSyqxz(); | |||
| dst.DKLB = src.getDklb(); | |||
| dst.DLDJ = src.getDldj(); | |||
| dst.TDYT = src.getTdyt(); | |||
| dst.SFJBNT = src.getSfjbnt(); | |||
| dst.DKDZ = src.getDkdz(); | |||
| dst.DKXZ = src.getDkxz(); | |||
| dst.DKNZ = src.getDknz(); | |||
| dst.DKBZ = src.getDkbz(); | |||
| dst.ZJRXM = src.getZjrxm(); | |||
| dst.DKBZXX = src.getDkbzxx(); | |||
| dst.TXMJ = src.getTxmj(); | |||
| dst.QSDWDM = src.getQsdwdm(); | |||
| dst.QSDWMC = src.getQsdwmc(); | |||
| dst.SFZWD = src.getSfzwd(); | |||
| dst.SCMJM = src.getScmjm(); | |||
| return dst; | |||
| } | |||
| public void SaveData() | |||
| { | |||
| exportTask.logFile.WriteLine(TYPE_NAME + "开始导出数据: 区划代码={}, 条数={}", exportTask.dept.getDeptName(), list.size()); | |||
| List<GeoJTZY> dataList = list.stream().map((x) -> ConvertData(x, null)).collect(Collectors.toList()); | |||
| exportTask.writer.WriteList(dataList); | |||
| } | |||
| public Map<String, Class<?>> GetTypes() | |||
| { | |||
| Map<String, Class<?>> types = GeoCreator.GetClassTypes(GeoJTZY.class); | |||
| types.put("the_geom", MultiPolygon.class); | |||
| return types; | |||
| } | |||
| } | |||
| @@ -4,6 +4,7 @@ import cn.hutool.core.collection.ListUtil; | |||
| import com.ruoyi.common.core.domain.entity.SysDept; | |||
| import com.ruoyi.common.utils.StringUtils; | |||
| import com.ruoyi.geo.service.GeoImportHandlerService; | |||
| import com.ruoyi.geo.service.GeoMapperService; | |||
| import com.ruoyi.geo.structs.GeoJTZY; | |||
| import com.ruoyi.resource.domain.TResourceLand; | |||
| import com.ruoyi.resource.mapper.TResourceLandMapper; | |||
| @@ -15,14 +16,14 @@ import java.util.stream.Collectors; | |||
| import static com.ruoyi.business.constants.TaskEnums.ImportType; | |||
| public class GeoJtzyTask implements GeoDBTaskInterface | |||
| public class GeoJtzyImportTask implements GeoDBImportTaskInterface | |||
| { | |||
| private final static String TYPE_NAME = "地块属性"; | |||
| private final GeoImportTask importTask; | |||
| private List<GeoJTZY> list; | |||
| public GeoJtzyTask(GeoImportTask importTask) | |||
| public GeoJtzyImportTask(GeoImportTask importTask) | |||
| { | |||
| this.importTask = importTask; | |||
| } | |||
| @@ -65,7 +66,7 @@ public class GeoJtzyTask implements GeoDBTaskInterface | |||
| { | |||
| TResourceLand cond = new TResourceLand(); | |||
| cond.setImportCode(qydm); | |||
| List<TResourceLand> cjqies = GeoImportHandlerService.ResourceLandMapper().selectTResourceLandList(cond); | |||
| List<TResourceLand> cjqies = GeoMapperService.ResourceLandMapper().selectTResourceLandList(cond); | |||
| importTask.logFile.WriteLine(TYPE_NAME + "读取系统已存在的条数: 区划代码={}, 条数={}", qydm, cjqies.size()); | |||
| return cjqies; | |||
| } | |||
| @@ -117,7 +118,7 @@ public class GeoJtzyTask implements GeoDBTaskInterface | |||
| if(ImportType.IT_OVERRIDE.equals(importTask.taskImport.getImportType())) | |||
| { | |||
| importTask.logFile.WriteLine(TYPE_NAME + "覆盖导入, 需清空现有数据, 然后再插入, 区划代码={}", importCode); | |||
| int ret = GeoImportHandlerService.ResourceLandMapper().deleteByCode(importCode); | |||
| int ret = GeoMapperService.ResourceLandMapper().deleteByCode(importCode); | |||
| importTask.logFile.WriteLine(TYPE_NAME + "清空现有数据: {}, 区划代码={}", ret, importCode); | |||
| return ret; | |||
| } | |||
| @@ -130,7 +131,7 @@ public class GeoJtzyTask implements GeoDBTaskInterface | |||
| private int WriteData(List<TResourceLand> insertList, List<TResourceLand> updateList, SysDept dept) | |||
| { | |||
| TResourceLandMapper gisCjqyMapper = GeoImportHandlerService.ResourceLandMapper(); | |||
| TResourceLandMapper gisCjqyMapper = GeoMapperService.ResourceLandMapper(); | |||
| int i = ListUtil.split(insertList, 30).stream().map(gisCjqyMapper::insertTResourceLandBatch).reduce(0, Integer::sum); | |||
| importTask.logFile.WriteLine(TYPE_NAME + "新增数据: 区划代码={}, 条数={}", dept.getDeptName(), i); | |||
| int u = ListUtil.split(updateList, 1).stream().map(gisCjqyMapper::updateTResourceLandBatch).reduce(0, Integer::sum); | |||
| @@ -141,21 +142,29 @@ public class GeoJtzyTask implements GeoDBTaskInterface | |||
| private int SaveDeptData(SysDept dept, List<GeoJTZY> datas) | |||
| { | |||
| importTask.logFile.WriteLine(TYPE_NAME + "开始处理数据: 区划代码={}, 条数={}", dept.getDeptName(), datas.size()); | |||
| List<TResourceLand> databases = LoadDatabase(dept.getImportCode()); | |||
| Map<String, TResourceLand> exists = databases.stream().collect(Collectors.toMap(TResourceLand::getDkbm, x->x)); | |||
| boolean needCheck = !ImportType.IT_OVERRIDE.equals(importTask.taskImport.getImportType()); | |||
| Map<String, TResourceLand> exists = null; | |||
| if(needCheck) | |||
| { | |||
| List<TResourceLand> databases = LoadDatabase(dept.getImportCode()); | |||
| exists = databases.stream().collect(Collectors.toMap(TResourceLand::getDkbm, x->x)); | |||
| } | |||
| List<TResourceLand> insertList = new ArrayList<>(); | |||
| List<TResourceLand> updateList = new ArrayList<>(); | |||
| for(GeoJTZY data : datas) | |||
| { | |||
| TResourceLand db = exists.get(data.DKBM); | |||
| boolean notExists = null == db; | |||
| db = ConvertData(data, db, dept); | |||
| if(notExists) | |||
| insertList.add(db); | |||
| TResourceLand db = null; | |||
| if(needCheck) | |||
| { | |||
| db = exists.get(data.DKBM); | |||
| } | |||
| TResourceLand item = ConvertData(data, db, dept); | |||
| if(null == db) | |||
| insertList.add(item); | |||
| else | |||
| updateList.add(db); | |||
| updateList.add(item); | |||
| } | |||
| CleanDatabase(dept.getImportCode()); | |||
| @@ -0,0 +1,74 @@ | |||
| package com.ruoyi.geo.framework; | |||
| import cn.hutool.core.util.StrUtil; | |||
| import com.ruoyi.common.geo.GeoCreator; | |||
| import com.ruoyi.common.utils.DecimalUtils; | |||
| import com.ruoyi.geo.service.GeoMapperService; | |||
| import com.ruoyi.geo.structs.GeoZYHYCG; | |||
| import com.ruoyi.resource.domain.TResourceOperation; | |||
| import org.locationtech.jts.geom.MultiPolygon; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.stream.Collectors; | |||
| public class GeoZyhycgExportTask implements GeoDBExportTaskInterface | |||
| { | |||
| private final static String TYPE_NAME = "地块经营"; | |||
| private final GeoExportTask exportTask; | |||
| private List<TResourceOperation> list; | |||
| public GeoZyhycgExportTask(GeoExportTask exportTask) | |||
| { | |||
| this.exportTask = exportTask; | |||
| } | |||
| public int LoadDataList() | |||
| { | |||
| TResourceOperation cond = new TResourceOperation(); | |||
| cond.setImportCode(exportTask.dept.getImportCode()); | |||
| list = GeoMapperService.ResourceOperationMapper().selectTResourceOperationList(cond); | |||
| exportTask.logFile.WriteLine(TYPE_NAME + "读取系统数据条数: 区划代码={}, 条数={}", exportTask.dept.getImportCode(), list.size()); | |||
| return list.size(); | |||
| } | |||
| private GeoZYHYCG ConvertData(TResourceOperation src, GeoZYHYCG dst) | |||
| { | |||
| if(null == dst) | |||
| dst = new GeoZYHYCG(); | |||
| dst.DKBM = src.getDkbm(); | |||
| dst.DKMC = src.getDkmc(); | |||
| dst.SYQXZ = src.getDkdz(); | |||
| dst.JYMJ = src.getJymj(); | |||
| dst.JYDXLX = src.getJydxlx(); | |||
| dst.JYDXMC = src.getJydxmc(); | |||
| dst.JYDXZJLX = src.getJydxzjlx(); | |||
| dst.JYDXZJHM = src.getJydxzjhm(); | |||
| dst.SFQDHT = src.getSfqdht(); | |||
| dst.JYKSSJ = src.getJykssj(); | |||
| dst.JYJSSJ = src.getJyjssj(); | |||
| dst.CBJE = src.getCbje(); | |||
| dst.DXJE = src.getDxje(); | |||
| dst.SQJE = src.getSqje(); | |||
| dst.NSY = src.getNsy(); | |||
| dst.BZXX = src.getBzxx(); | |||
| dst.JYFS = src.getJyfs(); | |||
| return dst; | |||
| } | |||
| public void SaveData() | |||
| { | |||
| exportTask.logFile.WriteLine(TYPE_NAME + "开始导出数据: 区划代码={}, 条数={}", exportTask.dept.getDeptName(), list.size()); | |||
| List<GeoZYHYCG> dataList = list.stream().map((x) -> ConvertData(x, null)).collect(Collectors.toList()); | |||
| exportTask.writer.WriteList(dataList); | |||
| } | |||
| public Map<String, Class<?>> GetTypes() | |||
| { | |||
| return GeoCreator.GetClassTypes(GeoZYHYCG.class); | |||
| } | |||
| } | |||
| @@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil; | |||
| import com.ruoyi.common.core.domain.entity.SysDept; | |||
| import com.ruoyi.common.utils.DecimalUtils; | |||
| import com.ruoyi.common.utils.StringUtils; | |||
| import com.ruoyi.geo.service.GeoImportHandlerService; | |||
| import com.ruoyi.geo.service.GeoMapperService; | |||
| import com.ruoyi.geo.structs.GeoZYHYCG; | |||
| import com.ruoyi.resource.domain.TResourceOperation; | |||
| import com.ruoyi.resource.mapper.TResourceOperationMapper; | |||
| @@ -17,14 +17,14 @@ import java.util.stream.Collectors; | |||
| import static com.ruoyi.business.constants.TaskEnums.ImportType; | |||
| public class GeoZyhycgTask implements GeoDBTaskInterface | |||
| public class GeoZyhycgImportTask implements GeoDBImportTaskInterface | |||
| { | |||
| private final static String TYPE_NAME = "地块经营"; | |||
| private final GeoImportTask importTask; | |||
| private List<GeoZYHYCG> list; | |||
| public GeoZyhycgTask(GeoImportTask importTask) | |||
| public GeoZyhycgImportTask(GeoImportTask importTask) | |||
| { | |||
| this.importTask = importTask; | |||
| } | |||
| @@ -67,7 +67,7 @@ public class GeoZyhycgTask implements GeoDBTaskInterface | |||
| { | |||
| TResourceOperation cond = new TResourceOperation(); | |||
| cond.setImportCode(qydm); | |||
| List<TResourceOperation> cjqies = GeoImportHandlerService.ResourceOperationMapper().selectTResourceOperationList(cond); | |||
| List<TResourceOperation> cjqies = GeoMapperService.ResourceOperationMapper().selectTResourceOperationList(cond); | |||
| importTask.logFile.WriteLine(TYPE_NAME + "读取系统已存在的条数: 区划代码={}, 条数={}", qydm, cjqies.size()); | |||
| return cjqies; | |||
| } | |||
| @@ -115,7 +115,7 @@ public class GeoZyhycgTask implements GeoDBTaskInterface | |||
| if(ImportType.IT_OVERRIDE.equals(importTask.taskImport.getImportType())) | |||
| { | |||
| importTask.logFile.WriteLine(TYPE_NAME + "覆盖导入, 需清空现有数据, 然后再插入, 区划代码={}", importCode); | |||
| int ret = GeoImportHandlerService.ResourceOperationMapper().deleteByCode(importCode); | |||
| int ret = GeoMapperService.ResourceOperationMapper().deleteByCode(importCode); | |||
| importTask.logFile.WriteLine(TYPE_NAME + "清空现有数据: {}, 区划代码={}", ret, importCode); | |||
| return ret; | |||
| } | |||
| @@ -128,7 +128,7 @@ public class GeoZyhycgTask implements GeoDBTaskInterface | |||
| private int WriteData(List<TResourceOperation> insertList, List<TResourceOperation> updateList, SysDept dept) | |||
| { | |||
| TResourceOperationMapper gisCjqyMapper = GeoImportHandlerService.ResourceOperationMapper(); | |||
| TResourceOperationMapper gisCjqyMapper = GeoMapperService.ResourceOperationMapper(); | |||
| int i = ListUtil.split(insertList, 30).stream().map(gisCjqyMapper::insertTResourceOperationBatch).reduce(0, Integer::sum); | |||
| importTask.logFile.WriteLine(TYPE_NAME + "新增数据: 区划代码={}, 条数={}", dept.getDeptName(), i); | |||
| int u = ListUtil.split(updateList, 1).stream().map(gisCjqyMapper::updateTResourceOperationBatch).reduce(0, Integer::sum); | |||
| @@ -139,21 +139,29 @@ public class GeoZyhycgTask implements GeoDBTaskInterface | |||
| private int SaveDeptData(SysDept dept, List<GeoZYHYCG> datas) | |||
| { | |||
| importTask.logFile.WriteLine(TYPE_NAME + "开始处理数据: 区划代码={}, 条数={}", dept.getDeptName(), datas.size()); | |||
| List<TResourceOperation> databases = LoadDatabase(dept.getImportCode()); | |||
| Map<String, TResourceOperation> exists = databases.stream().collect(Collectors.toMap(TResourceOperation::getDkbm, x->x)); | |||
| boolean needCheck = !ImportType.IT_OVERRIDE.equals(importTask.taskImport.getImportType()); | |||
| Map<String, TResourceOperation> exists = null; | |||
| if(needCheck) | |||
| { | |||
| List<TResourceOperation> databases = LoadDatabase(dept.getImportCode()); | |||
| exists = databases.stream().collect(Collectors.toMap(TResourceOperation::getDkbm, x->x)); | |||
| } | |||
| List<TResourceOperation> insertList = new ArrayList<>(); | |||
| List<TResourceOperation> updateList = new ArrayList<>(); | |||
| for(GeoZYHYCG data : datas) | |||
| { | |||
| TResourceOperation db = exists.get(data.DKBM); | |||
| boolean notExists = null == db; | |||
| db = ConvertData(data, db, dept); | |||
| if(notExists) | |||
| insertList.add(db); | |||
| TResourceOperation db = null; | |||
| if(needCheck) | |||
| { | |||
| db = exists.get(data.DKBM); | |||
| } | |||
| TResourceOperation item = ConvertData(data, db, dept); | |||
| if(null == db) | |||
| insertList.add(item); | |||
| else | |||
| updateList.add(db); | |||
| updateList.add(item); | |||
| } | |||
| CleanDatabase(dept.getImportCode()); | |||
| @@ -0,0 +1,268 @@ | |||
| package com.ruoyi.geo.service; | |||
| import cn.hutool.core.io.FileUtil; | |||
| import cn.hutool.core.io.file.FileNameUtil; | |||
| import cn.hutool.core.lang.Assert; | |||
| import cn.hutool.extra.servlet.ServletUtil; | |||
| import com.ruoyi.business.domain.TTaskExport; | |||
| import com.ruoyi.business.mapper.TTaskExportMapper; | |||
| import com.ruoyi.common.constant.HttpStatus; | |||
| import com.ruoyi.common.utils.StringUtils; | |||
| import com.ruoyi.common.utils.sql.DB; | |||
| import com.ruoyi.geo.config.GeoExportTaskConfig; | |||
| import com.ruoyi.geo.constants.GeoSysDir; | |||
| import com.ruoyi.geo.framework.GeoExportTask; | |||
| import com.ruoyi.geo.framework.GeoTaskQueue; | |||
| import com.ruoyi.geo.object.GeoLogInfo; | |||
| import com.ruoyi.system.mapper.SysDeptMapper; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.springframework.stereotype.Service; | |||
| import javax.annotation.PostConstruct; | |||
| import javax.annotation.PreDestroy; | |||
| import javax.annotation.Resource; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.File; | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.net.URLEncoder; | |||
| import java.nio.charset.StandardCharsets; | |||
| import java.util.List; | |||
| import java.util.stream.Collectors; | |||
| import static com.ruoyi.business.constants.TaskEnums.TaskStatus; | |||
| @Service | |||
| @Slf4j | |||
| public class GeoExportHandlerService | |||
| { | |||
| @Resource | |||
| private SysDeptMapper deptMapper; | |||
| @Resource | |||
| private TTaskExportMapper taskExportMapper; | |||
| private GeoTaskQueue taskQueue; | |||
| private synchronized GeoTaskQueue TaskQueue() | |||
| { | |||
| if(null == taskQueue) | |||
| taskQueue = new GeoTaskQueue(true); | |||
| return taskQueue; | |||
| } | |||
| @PostConstruct | |||
| public synchronized void Init() | |||
| { | |||
| SyncTask(); | |||
| LoadTask(); | |||
| } | |||
| @PreDestroy | |||
| public synchronized void Shutdown() | |||
| { | |||
| if(null != taskQueue) | |||
| taskQueue.Quit(); | |||
| } | |||
| private void SyncTask() | |||
| { | |||
| log.info("更改运行中的任务状态为中止......"); | |||
| // 更改运行中的任务状态为中止 | |||
| int i = taskExportMapper.terminateRunningTask(); | |||
| log.info("已设置运行中的任务状态为中止: " + i); | |||
| } | |||
| private void LoadTask() | |||
| { | |||
| if(!GeoExportTaskConfig.startOnBoot) | |||
| return; | |||
| log.info("拉取排队中的任务......"); | |||
| TTaskExport cond = new TTaskExport(); | |||
| cond.setTaskStatus(TaskStatus.ST_WAIT); | |||
| List<TTaskExport> taskExports = taskExportMapper.selectTTaskExportList(cond); | |||
| log.info("拉取到排队中的任务: " + taskExports.size()); | |||
| List<Runnable> tasks = taskExports.stream().map((x) -> new GeoExportTask(x.getId())).collect(Collectors.toList()); | |||
| if(!tasks.isEmpty()) | |||
| TaskQueue().StartTask(tasks); | |||
| } | |||
| public GeoLogInfo loadExportLog(Long taskId, int offset) | |||
| { | |||
| GeoLogInfo info = new GeoLogInfo(); | |||
| info.setNextPollDelay(GeoExportTaskConfig.logNextPoll); | |||
| TTaskExport taskExport = taskExportMapper.selectTTaskExportById(taskId); | |||
| Assert.notNull(taskExport, "导出任务不存在"); | |||
| info.setTaskStatus(taskExport.getTaskStatus()); | |||
| if(TaskStatus.ST_READY.equals(taskExport.getTaskStatus())/* || TaskStatus.ST_WAIT.equals(taskExport.getTaskStatus())*/) | |||
| { | |||
| info.setEof(true); | |||
| info.setLength(-1); | |||
| return info; | |||
| } | |||
| String path = GeoSysDir.ExportDir(GeoSysDir.LOG) + "/" + taskId + ".log"; | |||
| if(!FileUtil.isFile(path)) | |||
| { | |||
| info.setEof(true); | |||
| info.setLength(-1); | |||
| return info; | |||
| } | |||
| info.setEof(!TaskStatus.ST_RUNNING.equals(info.getTaskStatus()) && !TaskStatus.ST_WAIT.equals(info.getTaskStatus())); | |||
| String str = FileUtil.readUtf8String(path); | |||
| info.setLength(str.length()); | |||
| String text; | |||
| if(offset >= str.length() - 1) | |||
| text = ""; | |||
| else if(offset > 0) | |||
| text = str.substring(offset); | |||
| else | |||
| text = str; | |||
| info.setText(text); | |||
| return info; | |||
| } | |||
| public synchronized int startTask(Long id) | |||
| { | |||
| if(null != taskQueue) | |||
| { | |||
| GeoExportTask task = (GeoExportTask)taskQueue.GetCurrentTask(); | |||
| Assert.isFalse(null != task && task.GetTaskId().equals(id), "任务正在执行"); | |||
| boolean exists = null != taskQueue.FindTask((x) -> { | |||
| GeoExportTask t = (GeoExportTask) x; | |||
| return(t.GetTaskId().equals(id)); | |||
| }); | |||
| Assert.isFalse(exists, "任务已在队列中"); | |||
| } | |||
| Object handler = DB.BeginTransaction(); | |||
| try | |||
| { | |||
| TTaskExport taskExport = taskExportMapper.getForUpdate(id); | |||
| Assert.notNull(taskExport, "任务不存在"); | |||
| Assert.isTrue(TaskStatus.ST_READY.equals(taskExport.getTaskStatus()), "任务非准备状态"); | |||
| taskExport.setTaskStatus(TaskStatus.ST_WAIT); | |||
| taskExportMapper.updateTTaskExport(taskExport); | |||
| DB.CommitTransaction(handler); | |||
| } | |||
| catch(Exception e) | |||
| { | |||
| e.printStackTrace(); | |||
| DB.RollbackTransaction(handler); | |||
| return 0; | |||
| } | |||
| int ret = null != taskQueue && taskQueue.HasTask() ? 1 : 2; | |||
| TaskQueue().StartTask(new GeoExportTask(id)); | |||
| return ret; | |||
| } | |||
| public void downloadLog(Long taskId, HttpServletResponse response) | |||
| { | |||
| String path = GeoSysDir.ExportDir(GeoSysDir.LOG) + "/" + taskId + ".log"; | |||
| String dlFileName; | |||
| try | |||
| { | |||
| dlFileName = URLEncoder.encode(FileNameUtil.getName(path), "UTF-8"); | |||
| } | |||
| catch(UnsupportedEncodingException e) | |||
| { | |||
| e.printStackTrace(); | |||
| dlFileName = ""; | |||
| } | |||
| int bytes = 0; | |||
| response.reset(); | |||
| response.addHeader("Access-Control-Allow-Origin", "*"); | |||
| response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); | |||
| response.setHeader("Content-Disposition", "attachment; filename=\"" + dlFileName + "\""); | |||
| response.setContentType("application/octet-stream; charset=UTF-8"); | |||
| TTaskExport taskExport = taskExportMapper.selectTTaskExportById(taskId); | |||
| if(null == taskExport) | |||
| { | |||
| response.setStatus(HttpStatus.NOT_FOUND); | |||
| ServletUtil.write(response, "导出任务不存在", "application/octet-stream; charset=UTF-8"); | |||
| bytes = "导出任务不存在".getBytes(StandardCharsets.UTF_8).length; | |||
| response.addHeader("Content-Length", "" + bytes); | |||
| return; | |||
| } | |||
| File file = new File(path); | |||
| if(!file.isFile()) | |||
| { | |||
| response.setStatus(HttpStatus.NOT_FOUND); | |||
| ServletUtil.write(response, "日志文件不存在", "application/octet-stream; charset=UTF-8"); | |||
| bytes = "日志文件不存在".getBytes(StandardCharsets.UTF_8).length; | |||
| response.addHeader("Content-Length", "" + bytes); | |||
| return; | |||
| } | |||
| ServletUtil.write(response, file); | |||
| response.addHeader("Content-Length", "" + file.length()); | |||
| } | |||
| public void downloadFile(Long taskId, HttpServletResponse response) | |||
| { | |||
| int bytes = 0; | |||
| response.reset(); | |||
| response.addHeader("Access-Control-Allow-Origin", "*"); | |||
| response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); | |||
| response.setHeader("Content-Disposition", "attachment; filename=\"" + taskId + ".zip\""); | |||
| response.setContentType("application/octet-stream; charset=UTF-8"); | |||
| TTaskExport taskExport = taskExportMapper.selectTTaskExportById(taskId); | |||
| if(null == taskExport) | |||
| { | |||
| response.setStatus(HttpStatus.NOT_FOUND); | |||
| ServletUtil.write(response, "导出任务不存在", "application/octet-stream; charset=UTF-8"); | |||
| bytes = "导出任务不存在".getBytes(StandardCharsets.UTF_8).length; | |||
| response.addHeader("Content-Length", "" + bytes); | |||
| return; | |||
| } | |||
| if(!TaskStatus.ST_FINISH.equals(taskExport.getTaskStatus())) | |||
| { | |||
| response.setStatus(HttpStatus.FORBIDDEN); | |||
| ServletUtil.write(response, "导出任务未完成", "application/octet-stream; charset=UTF-8"); | |||
| bytes = "导出任务未完成".getBytes(StandardCharsets.UTF_8).length; | |||
| response.addHeader("Content-Length", "" + bytes); | |||
| return; | |||
| } | |||
| if(StringUtils.isEmpty(taskExport.getFileUrl())) | |||
| { | |||
| response.setStatus(HttpStatus.NOT_FOUND); | |||
| ServletUtil.write(response, "导出文件未生成", "application/octet-stream; charset=UTF-8"); | |||
| bytes = "导出文件未生成".getBytes(StandardCharsets.UTF_8).length; | |||
| response.addHeader("Content-Length", "" + bytes); | |||
| return; | |||
| } | |||
| String path = GeoSysDir.GetDir(GeoSysDir.TrimProfile(taskExport.getFileUrl())); | |||
| String dlFileName; | |||
| try | |||
| { | |||
| dlFileName = URLEncoder.encode(FileNameUtil.getName(path), "UTF-8"); | |||
| } | |||
| catch(UnsupportedEncodingException e) | |||
| { | |||
| e.printStackTrace(); | |||
| dlFileName = ""; | |||
| } | |||
| response.setHeader("Content-Disposition", "attachment; filename=\"" + dlFileName + "\""); | |||
| File file = new File(path); | |||
| if(!file.isFile()) | |||
| { | |||
| ServletUtil.write(response, "导出文件不存在", "application/octet-stream; charset=UTF-8"); | |||
| bytes = "导出文件不存在".getBytes(StandardCharsets.UTF_8).length; | |||
| response.addHeader("Content-Length", "" + bytes); | |||
| return; | |||
| } | |||
| ServletUtil.write(response, file); | |||
| response.addHeader("Content-Length", "" + file.length()); | |||
| } | |||
| } | |||
| @@ -6,7 +6,9 @@ import cn.hutool.core.lang.Assert; | |||
| import cn.hutool.extra.servlet.ServletUtil; | |||
| import com.ruoyi.business.domain.TTaskImport; | |||
| import com.ruoyi.business.mapper.TGisCjqyMapper; | |||
| import com.ruoyi.business.mapper.TTaskExportMapper; | |||
| import com.ruoyi.business.mapper.TTaskImportMapper; | |||
| import com.ruoyi.common.constant.HttpStatus; | |||
| import com.ruoyi.common.utils.sql.DB; | |||
| import com.ruoyi.geo.config.GeoImportTaskConfig; | |||
| import com.ruoyi.geo.constants.GeoSysDir; | |||
| @@ -38,57 +40,11 @@ public class GeoImportHandlerService | |||
| { | |||
| @Resource | |||
| private SysDeptMapper deptMapper; | |||
| private static TTaskImportMapper taskImportMapper; | |||
| private static TGisCjqyMapper gisCjqyMapper; | |||
| private static TResourceLandMapper resourceLandMapper; | |||
| private static TResourceOperationMapper resourceOperationMapper; | |||
| @Resource | |||
| private TTaskImportMapper taskImportMapper; | |||
| private GeoTaskQueue taskQueue; | |||
| @Autowired | |||
| public void setTaskImportMapper(TTaskImportMapper taskImportMapper) | |||
| { | |||
| GeoImportHandlerService.taskImportMapper = taskImportMapper; | |||
| } | |||
| @Autowired | |||
| public void setGisCjqyMapper(TGisCjqyMapper gisCjqyMapper) | |||
| { | |||
| GeoImportHandlerService.gisCjqyMapper = gisCjqyMapper; | |||
| } | |||
| @Autowired | |||
| public void setResourceLandMapper(TResourceLandMapper resourceLandMapper) | |||
| { | |||
| GeoImportHandlerService.resourceLandMapper = resourceLandMapper; | |||
| } | |||
| @Autowired | |||
| public void setResourceOperationMapper(TResourceOperationMapper resourceOperationMapper) | |||
| { | |||
| GeoImportHandlerService.resourceOperationMapper = resourceOperationMapper; | |||
| } | |||
| public static TTaskImportMapper TaskImportMapper() | |||
| { | |||
| return taskImportMapper; | |||
| } | |||
| public static TGisCjqyMapper GisCjqyMapper() | |||
| { | |||
| return gisCjqyMapper; | |||
| } | |||
| public static TResourceLandMapper ResourceLandMapper() | |||
| { | |||
| return resourceLandMapper; | |||
| } | |||
| public static TResourceOperationMapper ResourceOperationMapper() | |||
| { | |||
| return resourceOperationMapper; | |||
| } | |||
| private synchronized GeoTaskQueue TaskQueue() | |||
| { | |||
| if(null == taskQueue) | |||
| @@ -133,7 +89,7 @@ public class GeoImportHandlerService | |||
| TaskQueue().StartTask(tasks); | |||
| } | |||
| public GeoLogInfo GetImportLog(Long taskId, int offset) | |||
| public GeoLogInfo loadImportLog(Long taskId, int offset) | |||
| { | |||
| GeoLogInfo info = new GeoLogInfo(); | |||
| info.setNextPollDelay(GeoImportTaskConfig.logNextPoll); | |||
| @@ -170,7 +126,7 @@ public class GeoImportHandlerService | |||
| return info; | |||
| } | |||
| public synchronized int StartTask(Long id) | |||
| public synchronized int startTask(Long id) | |||
| { | |||
| if(null != taskQueue) | |||
| { | |||
| @@ -205,7 +161,7 @@ public class GeoImportHandlerService | |||
| return ret; | |||
| } | |||
| public void DownloadLog(Long taskId, HttpServletResponse response) | |||
| public void downloadLog(Long taskId, HttpServletResponse response) | |||
| { | |||
| String path = GeoSysDir.ImportDir(GeoSysDir.LOG) + "/" + taskId + ".log"; | |||
| String dlFileName; | |||
| @@ -230,18 +186,24 @@ public class GeoImportHandlerService | |||
| TTaskImport taskImport = taskImportMapper.selectTTaskImportById(taskId); | |||
| if(null == taskImport) | |||
| { | |||
| response.setStatus(HttpStatus.NOT_FOUND); | |||
| ServletUtil.write(response, "导入任务不存在", "application/octet-stream; charset=UTF-8"); | |||
| bytes = "导入任务不存在".getBytes(StandardCharsets.UTF_8).length; | |||
| response.addHeader("Content-Length", "" + bytes); | |||
| return; | |||
| } | |||
| File file = new File(path); | |||
| if(!file.isFile()) | |||
| { | |||
| response.setStatus(HttpStatus.NOT_FOUND); | |||
| ServletUtil.write(response, "日志文件不存在", "application/octet-stream; charset=UTF-8"); | |||
| bytes = "日志文件不存在".getBytes(StandardCharsets.UTF_8).length; | |||
| response.addHeader("Content-Length", "" + bytes); | |||
| return; | |||
| } | |||
| ServletUtil.write(response, file); | |||
| response.addHeader("Content-Length", "" + bytes); | |||
| response.addHeader("Content-Length", "" + file.length()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,92 @@ | |||
| package com.ruoyi.geo.service; | |||
| import com.ruoyi.business.mapper.TGisCjqyMapper; | |||
| import com.ruoyi.business.mapper.TTaskExportMapper; | |||
| import com.ruoyi.business.mapper.TTaskImportMapper; | |||
| import com.ruoyi.resource.mapper.TResourceLandMapper; | |||
| import com.ruoyi.resource.mapper.TResourceOperationMapper; | |||
| import com.ruoyi.system.mapper.SysDeptMapper; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import javax.annotation.Resource; | |||
| @Service | |||
| @Slf4j | |||
| public class GeoMapperService | |||
| { | |||
| private static SysDeptMapper deptMapper; | |||
| private static TTaskImportMapper taskImportMapper; | |||
| private static TTaskExportMapper taskExportMapper; | |||
| private static TGisCjqyMapper gisCjqyMapper; | |||
| private static TResourceLandMapper resourceLandMapper; | |||
| private static TResourceOperationMapper resourceOperationMapper; | |||
| @Autowired | |||
| public void setTaskImportMapper(TTaskImportMapper taskImportMapper) | |||
| { | |||
| GeoMapperService.taskImportMapper = taskImportMapper; | |||
| } | |||
| @Autowired | |||
| public void setTaskExportMapper(TTaskExportMapper taskExportMapper) | |||
| { | |||
| GeoMapperService.taskExportMapper = taskExportMapper; | |||
| } | |||
| @Autowired | |||
| public void setGisCjqyMapper(TGisCjqyMapper gisCjqyMapper) | |||
| { | |||
| GeoMapperService.gisCjqyMapper = gisCjqyMapper; | |||
| } | |||
| @Autowired | |||
| public void setResourceLandMapper(TResourceLandMapper resourceLandMapper) | |||
| { | |||
| GeoMapperService.resourceLandMapper = resourceLandMapper; | |||
| } | |||
| @Autowired | |||
| public void setResourceOperationMapper(TResourceOperationMapper resourceOperationMapper) | |||
| { | |||
| GeoMapperService.resourceOperationMapper = resourceOperationMapper; | |||
| } | |||
| @Autowired | |||
| public void setSysDeptMapper(SysDeptMapper deptMapper) | |||
| { | |||
| GeoMapperService.deptMapper = deptMapper; | |||
| } | |||
| public static TTaskImportMapper TaskImportMapper() | |||
| { | |||
| return taskImportMapper; | |||
| } | |||
| public static TTaskExportMapper TaskExportMapper() | |||
| { | |||
| return taskExportMapper; | |||
| } | |||
| public static TGisCjqyMapper GisCjqyMapper() | |||
| { | |||
| return gisCjqyMapper; | |||
| } | |||
| public static TResourceLandMapper ResourceLandMapper() | |||
| { | |||
| return resourceLandMapper; | |||
| } | |||
| public static TResourceOperationMapper ResourceOperationMapper() | |||
| { | |||
| return resourceOperationMapper; | |||
| } | |||
| public static SysDeptMapper DeptMapper() | |||
| { | |||
| return deptMapper; | |||
| } | |||
| } | |||
| @@ -153,4 +153,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |||
| #{id} | |||
| </foreach> | |||
| </delete> | |||
| <update id="terminateRunningTask"> | |||
| update t_task_export | |||
| set task_status = '5' | |||
| where task_status = '2' | |||
| </update> | |||
| <select id="getForUpdate" parameterType="Long" resultMap="TTaskExportResult"> | |||
| <include refid="selectTTaskExportVo"/> | |||
| where id = #{id} FOR UPDATE | |||
| </select> | |||
| </mapper> | |||
| @@ -2,6 +2,7 @@ package com.ruoyi.common.core.domain.entity; | |||
| import com.ruoyi.common.annotation.Excel; | |||
| import com.ruoyi.common.core.domain.BaseEntity; | |||
| import lombok.Data; | |||
| import org.apache.commons.lang3.builder.ToStringBuilder; | |||
| import org.apache.commons.lang3.builder.ToStringStyle; | |||
| @@ -17,6 +18,7 @@ import java.util.List; | |||
| * | |||
| * @author ruoyi | |||
| */ | |||
| @Data | |||
| public class SysDept extends BaseEntity | |||
| { | |||
| private static final long serialVersionUID = 1L; | |||
| @@ -74,6 +76,10 @@ public class SysDept extends BaseEntity | |||
| private List<SysDept> children = new ArrayList<SysDept>(); | |||
| /** 祖先ID */ | |||
| private Long rootId; | |||
| public Long getDeptId() | |||
| { | |||
| @@ -0,0 +1,160 @@ | |||
| package com.ruoyi.common.geo; | |||
| import cn.hutool.core.util.ClassUtil; | |||
| import org.locationtech.jts.geom.GeometryFactory; | |||
| import org.locationtech.jts.geom.LineString; | |||
| import org.locationtech.jts.geom.LinearRing; | |||
| import org.locationtech.jts.geom.MultiLineString; | |||
| import org.locationtech.jts.geom.MultiPoint; | |||
| import org.locationtech.jts.geom.MultiPolygon; | |||
| import org.locationtech.jts.geom.Point; | |||
| import org.locationtech.jts.geom.Polygon; | |||
| import org.locationtech.jts.io.ParseException; | |||
| import org.locationtech.jts.io.WKTReader; | |||
| import java.lang.reflect.Field; | |||
| import java.lang.reflect.Modifier; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| public final class GeoCreator | |||
| { | |||
| private static GeoCreator geometryCreator = null; | |||
| private static GeometryFactory geometryFactory = new GeometryFactory(); | |||
| private GeoCreator() { | |||
| } | |||
| /** | |||
| * 1.2根据几何对象的WKT描述【String】创建几何对象: 点 【Point】 | |||
| * @return | |||
| * @throws ParseException | |||
| */ | |||
| public static Point PointByWKT(String PointWKT) { | |||
| WKTReader reader = new WKTReader(geometryFactory); | |||
| try | |||
| { | |||
| return (Point) reader.read(PointWKT); | |||
| } | |||
| catch(ParseException e) | |||
| { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| /** | |||
| * 1.3根据几何对象的WKT描述【String】创建几何对象:多点 【MultiPoint】 | |||
| * @return | |||
| * @throws ParseException | |||
| */ | |||
| public static MultiPoint MultiPointByWKT(String MPointWKT) { | |||
| WKTReader reader = new WKTReader( geometryFactory ); | |||
| try | |||
| { | |||
| return (MultiPoint) reader.read(MPointWKT); | |||
| } | |||
| catch(ParseException e) | |||
| { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| public static LineString LineStringByWKT(String LineStringWKT) { | |||
| WKTReader reader = new WKTReader( geometryFactory ); | |||
| try | |||
| { | |||
| return (LineString) reader.read(LineStringWKT); | |||
| } | |||
| catch(ParseException e) | |||
| { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| /** | |||
| * 2.4根据几何对象的WKT描述【String】创建几何对象 : 多线【MultiLineString】 | |||
| * @param MLineStringWKT | |||
| * @return | |||
| * @throws ParseException | |||
| */ | |||
| public static MultiLineString MultiLineByWKT(String MLineStringWKT) { | |||
| WKTReader reader = new WKTReader( geometryFactory ); | |||
| try | |||
| { | |||
| return (MultiLineString) reader.read(MLineStringWKT); | |||
| } | |||
| catch(ParseException e) | |||
| { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| /** | |||
| * 3.1 根据几何对象的WKT描述【String】创建几何对象:多边形 【Polygon】 | |||
| * @param PolygonWKT | |||
| * @return | |||
| * @throws ParseException | |||
| */ | |||
| public static Polygon PolygonByWKT(String PolygonWKT) { | |||
| WKTReader reader = new WKTReader( geometryFactory ); | |||
| try | |||
| { | |||
| return (Polygon) reader.read(PolygonWKT); | |||
| } | |||
| catch(ParseException e) | |||
| { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| /** | |||
| * 3.2 根据几何对象的WKT描述【String】创建几何对象: 多多边形 【MultiPolygon】 | |||
| * @param MPolygonWKT | |||
| * @return | |||
| * @throws ParseException | |||
| */ | |||
| public static MultiPolygon MultiPolygonByWKT(String MPolygonWKT) { | |||
| WKTReader reader = new WKTReader( geometryFactory ); | |||
| try | |||
| { | |||
| return (MultiPolygon) reader.read(MPolygonWKT); | |||
| } | |||
| catch(ParseException e) | |||
| { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| /** | |||
| * 6.1 根据WKT创建环 | |||
| * @param ringWKT | |||
| * @return | |||
| * @throws ParseException | |||
| */ | |||
| public static LinearRing LinearRingByWKT(String ringWKT) { | |||
| WKTReader reader = new WKTReader( geometryFactory ); | |||
| try | |||
| { | |||
| return (LinearRing) reader.read(ringWKT); | |||
| } | |||
| catch(ParseException e) | |||
| { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| public static Map<String, Class<?>> GetClassTypes(Class<?> clazz) | |||
| { | |||
| Field[] fields = clazz.getDeclaredFields(); | |||
| Map<String, Class<?>> ret = new HashMap<>(); | |||
| for(Field field : fields) | |||
| { | |||
| int modifiers = field.getModifiers(); | |||
| if(Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers) || !Modifier.isPublic(modifiers)) | |||
| continue; | |||
| ret.put(field.getName(), field.getType()); | |||
| } | |||
| return ret; | |||
| } | |||
| } | |||
| @@ -0,0 +1,278 @@ | |||
| package com.ruoyi.common.geo; | |||
| import cn.hutool.core.bean.BeanUtil; | |||
| import cn.hutool.core.bean.copier.CopyOptions; | |||
| import cn.hutool.core.io.IoUtil; | |||
| import cn.hutool.core.lang.Assert; | |||
| import org.geotools.data.FeatureWriter; | |||
| import org.geotools.data.Transaction; | |||
| import org.geotools.data.shapefile.ShapefileDataStore; | |||
| import org.geotools.data.shapefile.ShapefileDataStoreFactory; | |||
| import org.geotools.data.simple.SimpleFeatureIterator; | |||
| import org.geotools.data.simple.SimpleFeatureSource; | |||
| import org.geotools.feature.simple.SimpleFeatureTypeBuilder; | |||
| import org.geotools.referencing.crs.DefaultGeographicCRS; | |||
| import org.locationtech.jts.geom.Geometry; | |||
| import org.locationtech.jts.geom.LineString; | |||
| import org.locationtech.jts.geom.LinearRing; | |||
| import org.locationtech.jts.geom.MultiLineString; | |||
| import org.locationtech.jts.geom.MultiPoint; | |||
| import org.locationtech.jts.geom.MultiPolygon; | |||
| import org.locationtech.jts.geom.Point; | |||
| import org.locationtech.jts.geom.Polygon; | |||
| import org.opengis.feature.simple.SimpleFeature; | |||
| import org.opengis.feature.simple.SimpleFeatureType; | |||
| import org.opengis.feature.type.AttributeDescriptor; | |||
| import java.io.Closeable; | |||
| import java.io.File; | |||
| import java.io.Serializable; | |||
| import java.nio.charset.Charset; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.HashMap; | |||
| import java.util.LinkedHashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.Set; | |||
| import java.util.stream.Collectors; | |||
| public final class GeoWriter implements Closeable | |||
| { | |||
| private ShapefileDataStore dataStore; | |||
| private FeatureWriter<SimpleFeatureType, SimpleFeature> writer; | |||
| private SimpleFeatureSource source; | |||
| private Map<String, Class<?>> columnMap; | |||
| public GeoWriter() | |||
| { | |||
| } | |||
| public void Init() | |||
| { | |||
| } | |||
| @Override | |||
| public void close() | |||
| { | |||
| CloseSource(); | |||
| if(null != dataStore) | |||
| { | |||
| dataStore.dispose(); | |||
| dataStore = null; | |||
| } | |||
| } | |||
| public boolean Open(String path, String charsetName) | |||
| { | |||
| return Open(new File(path), charsetName); | |||
| } | |||
| public boolean Open(File file, String charsetName) | |||
| { | |||
| close(); | |||
| try { | |||
| Map<String, Serializable> params = new HashMap<>(); | |||
| // 2、用于捕获参数需求的数据类 URLP:url to the .shp file. | |||
| params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL()); | |||
| dataStore = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params); | |||
| Charset charset = Charset.forName(charsetName); | |||
| dataStore.setCharset(charset); | |||
| return true; | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| private void CheckDataStore() | |||
| { | |||
| Assert.notNull(dataStore, "请先打开"); | |||
| } | |||
| private void CheckWriter() | |||
| { | |||
| Assert.notNull(writer, "请先打开写入"); | |||
| } | |||
| public void AddSchema(String name, Map<String, Class<?>> parms) | |||
| { | |||
| CheckDataStore(); | |||
| try { | |||
| SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder(); | |||
| // 5、设置 -- WGS84:一个二维地理坐标参考系统,使用WGS84数据 | |||
| tBuilder.setCRS(DefaultGeographicCRS.WGS84); | |||
| tBuilder.setName(name); | |||
| parms.forEach(tBuilder::add); | |||
| dataStore.createSchema(tBuilder.buildFeatureType()); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| public boolean SetSource(String typeName, boolean append) | |||
| { | |||
| CloseSource(); | |||
| CheckDataStore(); | |||
| try { | |||
| if(append) | |||
| writer = dataStore.getFeatureWriterAppend(typeName, Transaction.AUTO_COMMIT); | |||
| else | |||
| writer = dataStore.getFeatureWriter(typeName, Transaction.AUTO_COMMIT); | |||
| source = dataStore.getFeatureSource(typeName); | |||
| return InitSource(); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| public List<String> GetTypeNames() | |||
| { | |||
| CheckDataStore(); | |||
| try { | |||
| return Arrays.stream(dataStore.getTypeNames()).collect(Collectors.toList()); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| return null; | |||
| } | |||
| } | |||
| public boolean SetSource(int index, boolean append) | |||
| { | |||
| CloseSource(); | |||
| if(index < 0) | |||
| return true; | |||
| CheckDataStore(); | |||
| return SetSource(GetTypeNames().get(index), append); | |||
| } | |||
| private void CloseSource() | |||
| { | |||
| columnMap = null; | |||
| if(null != writer) | |||
| { | |||
| IoUtil.close(writer); | |||
| writer = null; | |||
| } | |||
| } | |||
| private boolean InitSource() | |||
| { | |||
| if(null == writer) | |||
| return false; | |||
| try { | |||
| if(null == columnMap) | |||
| columnMap = new LinkedHashMap<>(); | |||
| else | |||
| columnMap.clear(); | |||
| SimpleFeatureType schema = source.getSchema(); | |||
| for(int i = 0; i < schema.getAttributeCount(); i++) | |||
| { | |||
| AttributeDescriptor descriptor = schema.getDescriptor(i); | |||
| columnMap.put(descriptor.getLocalName(), descriptor.getType().getBinding()); | |||
| } | |||
| return true; | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| public Object ConvertValue(Class<?> clazz, Object value) | |||
| { | |||
| if(Point.class.isAssignableFrom(clazz)) | |||
| { | |||
| if(value instanceof Point) | |||
| return value; | |||
| else | |||
| return GeoCreator.PointByWKT(value.toString()); | |||
| } | |||
| else if(MultiPoint.class.isAssignableFrom(clazz)) | |||
| { | |||
| if(value instanceof MultiPoint) | |||
| return value; | |||
| else | |||
| return GeoCreator.MultiPointByWKT(value.toString()); | |||
| } | |||
| else if(LineString.class.isAssignableFrom(clazz)) | |||
| { | |||
| if(value instanceof LineString) | |||
| return value; | |||
| else | |||
| return GeoCreator.LineStringByWKT(value.toString()); | |||
| } | |||
| else if(MultiLineString.class.isAssignableFrom(clazz)) | |||
| { | |||
| if(value instanceof MultiLineString) | |||
| return value; | |||
| else | |||
| return GeoCreator.MultiLineByWKT(value.toString()); | |||
| } | |||
| else if(Polygon.class.isAssignableFrom(clazz)) | |||
| { | |||
| if(value instanceof Polygon) | |||
| return value; | |||
| else | |||
| return GeoCreator.PolygonByWKT(value.toString()); | |||
| } | |||
| else if(MultiPolygon.class.isAssignableFrom(clazz)) | |||
| { | |||
| if(value instanceof MultiPolygon) | |||
| return value; | |||
| else | |||
| return GeoCreator.MultiPolygonByWKT(value.toString()); | |||
| } | |||
| else if(LinearRing.class.isAssignableFrom(clazz)) | |||
| { | |||
| if(value instanceof LinearRing) | |||
| return value; | |||
| else | |||
| return GeoCreator.LinearRingByWKT(value.toString()); | |||
| } | |||
| else | |||
| return value; | |||
| } | |||
| public void WriteMapList(List<Map<String, Object>> list) | |||
| { | |||
| CheckWriter(); | |||
| try { | |||
| Set<String> headers = columnMap.keySet(); | |||
| for(Map<String, Object> map : list) | |||
| { | |||
| SimpleFeature feature = writer.next(); | |||
| for(String header : headers) | |||
| { | |||
| Object value = map.get(header); | |||
| if(null == value) | |||
| continue; | |||
| Class<?> clazz = columnMap.get(header); | |||
| feature.setAttribute(header, ConvertValue(clazz, value)); | |||
| } | |||
| } | |||
| writer.write(); | |||
| } catch (Exception e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| public void WriteList(List<?> list) | |||
| { | |||
| List<Map<String, Object>> mapList = list.stream().map((x) -> BeanUtil.beanToMap(x, false, true)).collect(Collectors.toList()); | |||
| WriteMapList(mapList); | |||
| } | |||
| } | |||
| @@ -54,6 +54,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |||
| <if test="status != null and status != ''"> | |||
| AND status = #{status} | |||
| </if> | |||
| <if test="rootId != null ">and (dept_id = #{rootId} OR dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{rootId}, ancestors) ))</if> | |||
| <!-- 数据范围过滤 --> | |||
| ${params.dataScope} | |||
| </select> | |||