From 5a77756c336a89452ed30419ec7720e2fd0b4d33 Mon Sep 17 00:00:00 2001 From: ZZX9599 <536509593@qq.com> Date: Wed, 19 Nov 2025 16:10:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=A8=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/yj/earth/ServerApp.java | 16 +- .../java/com/yj/earth/auth/AuthGenerator.java | 2 +- .../controller/BusinessConfigController.java | 2 +- .../controller/FileInfoController.java | 2 +- .../business/controller/GdalController.java | 5 +- .../controller/GraphHopperController.java | 29 +++- .../controller/IconLibraryController.java | 2 +- .../business/controller/MatterController.java | 11 +- .../controller/MilitaryLibraryController.java | 2 +- .../controller/ModelLibraryController.java | 5 +- .../business/controller/PoiController.java | 37 +++- .../business/controller/RoleController.java | 2 +- .../controller/RoleSourceController.java | 2 +- .../business/controller/SourceController.java | 2 +- .../business/controller/SystemController.java | 2 +- .../com/yj/earth/business/domain/Matter.java | 2 + .../com/yj/earth/business/domain/PoiInfo.java | 4 + .../service/impl/FileInfoServiceImpl.java | 5 +- .../common/config/GlobalExceptionHandler.java | 17 +- .../com/yj/earth/common/util/PoiExporter.java | 4 +- .../yj/earth/datasource/DatabaseManager.java | 163 +++++++++++++----- src/main/java/com/yj/earth/design/Matter.java | 2 + .../com/yj/earth/dto/matter/AddMatterDto.java | 2 + .../yj/earth/dto/matter/UpdateMatterDto.java | 2 + src/main/resources/application.yml | 6 + 25 files changed, 238 insertions(+), 90 deletions(-) diff --git a/src/main/java/com/yj/earth/ServerApp.java b/src/main/java/com/yj/earth/ServerApp.java index 5a83fb4..09a86dd 100644 --- a/src/main/java/com/yj/earth/ServerApp.java +++ b/src/main/java/com/yj/earth/ServerApp.java @@ -15,6 +15,8 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy; import javax.annotation.Resource; import java.io.IOException; +import static com.yj.earth.datasource.DatabaseManager.initializeDatabasePath; + @Slf4j @EnableAspectJAutoProxy @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) @@ -27,14 +29,10 @@ public class ServerApp implements CommandLineRunner { private ServerInitService serverInitService; public static void main(String[] args) throws IOException { + // 提前初始化数据库路径 + initializeDatabasePath(); // 启动项目SDK服务 SdkUtil.startSdkIfConfigured(); - // 初始化数据库相关操作 - String activeDataSource = DatabaseManager.getActiveDataSource(); - // 获取数据库类型 - DatabaseManager.DatabaseType dbType = DatabaseManager.DatabaseType.valueOf(activeDataSource.toUpperCase()); - // 初始化数据库 - DatabaseManager.initDatabase(dbType); // 启动应用服务 SpringApplication application = new SpringApplication(ServerApp.class); // 允许循环引用 @@ -45,6 +43,12 @@ public class ServerApp implements CommandLineRunner { @Override public void run(String... args) throws Exception { + // 初始化数据库相关操作 + String activeDataSource = DatabaseManager.getActiveDataSource(); + // 获取数据库类型 + DatabaseManager.DatabaseType dbType = DatabaseManager.DatabaseType.valueOf(activeDataSource.toUpperCase()); + // 初始化数据库 + DatabaseManager.initDatabase(dbType); // 初始化资源 serverInitService.init(); // 检查默认数据 diff --git a/src/main/java/com/yj/earth/auth/AuthGenerator.java b/src/main/java/com/yj/earth/auth/AuthGenerator.java index 98da629..2164f05 100644 --- a/src/main/java/com/yj/earth/auth/AuthGenerator.java +++ b/src/main/java/com/yj/earth/auth/AuthGenerator.java @@ -77,7 +77,7 @@ public class AuthGenerator { public static void main(String[] args) { try { // 生成加密的授权字符串 - String authContent = generateAuth("标准版", 1000, 7, "25F429FDA965007B72BB7A6B2C03535A"); + String authContent = generateAuth("标准版", 1000, 365, "196CB2226A5D5334B9C065ECFC77F4B9"); // 定义授权文件路径(当前目录下的 yjearth.lic) Path licPath = Paths.get("yjearth.lic"); diff --git a/src/main/java/com/yj/earth/business/controller/BusinessConfigController.java b/src/main/java/com/yj/earth/business/controller/BusinessConfigController.java index a840f56..a67d3b6 100644 --- a/src/main/java/com/yj/earth/business/controller/BusinessConfigController.java +++ b/src/main/java/com/yj/earth/business/controller/BusinessConfigController.java @@ -14,7 +14,7 @@ import javax.annotation.Resource; @Tag(name = "业务配置管理") -@CheckAuth + @RestController @RequestMapping("/businessConfig") public class BusinessConfigController { diff --git a/src/main/java/com/yj/earth/business/controller/FileInfoController.java b/src/main/java/com/yj/earth/business/controller/FileInfoController.java index e906428..4cd8315 100644 --- a/src/main/java/com/yj/earth/business/controller/FileInfoController.java +++ b/src/main/java/com/yj/earth/business/controller/FileInfoController.java @@ -45,7 +45,7 @@ import java.util.HashMap; import java.util.Map; @Tag(name = "文件数据管理") -@CheckAuth + @RestController @RequestMapping("/fileInfo") public class FileInfoController { diff --git a/src/main/java/com/yj/earth/business/controller/GdalController.java b/src/main/java/com/yj/earth/business/controller/GdalController.java index 5f344c4..abd6c88 100644 --- a/src/main/java/com/yj/earth/business/controller/GdalController.java +++ b/src/main/java/com/yj/earth/business/controller/GdalController.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -27,7 +28,6 @@ public class GdalController { @Operation(summary = "导入矢量数据") @PostMapping("/import") public void importDataStreamGzip(@Parameter(description = "矢量文件路径", required = true) @RequestParam("path") String path, HttpServletResponse response) throws IOException { - // 解析矢量文件、得到JSON数据 String jsonData = GdalJsonConverter.convertToJson(path); @@ -38,8 +38,7 @@ public class GdalController { response.setCharacterEncoding("UTF-8"); // 使用GZIP压缩并输出 - try (OutputStream outputStream = response.getOutputStream(); - GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream)) { + try (OutputStream outputStream = response.getOutputStream(); GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream)) { gzipOutputStream.write(jsonData.getBytes(StandardCharsets.UTF_8)); gzipOutputStream.finish(); } diff --git a/src/main/java/com/yj/earth/business/controller/GraphHopperController.java b/src/main/java/com/yj/earth/business/controller/GraphHopperController.java index 8598c8e..698b978 100644 --- a/src/main/java/com/yj/earth/business/controller/GraphHopperController.java +++ b/src/main/java/com/yj/earth/business/controller/GraphHopperController.java @@ -38,7 +38,7 @@ import java.util.concurrent.atomic.AtomicBoolean; @Data @Slf4j @Tag(name = "路径规划管理") -@CheckAuth + @RestController @RequestMapping("/graphhopper") public class GraphHopperController { @@ -58,7 +58,7 @@ public class GraphHopperController { @Operation(summary = "加载地图数据") @PostMapping("/loadMap") - @CheckAuth + public ApiResponse loadMap(@Parameter(description = "文件路径") @RequestParam String path) { File osmFile = new File(path); if (!osmFile.exists()) { @@ -108,7 +108,7 @@ public class GraphHopperController { @Operation(summary = "清除地图服务") @PostMapping("/clearMap") - @CheckAuth + public ApiResponse clearMap() { // 防止并发操作(与加载操作互斥) if (isLoading.get()) { @@ -146,11 +146,14 @@ public class GraphHopperController { @Operation(summary = "路径规划") @PostMapping("/route") - @CheckAuth + public ApiResponse calculateRoute(@RequestBody RouteRequest request) { - // 校验地图是否加载完成 + 实例是否可用 + // 区分未加载地图和加载中两种状态 + if (isLoading.get()) { + return ApiResponse.failure("地图正在加载中,请稍后再试"); + } if (!isLoaded.get() || currentHopper == null) { - return ApiResponse.failure("地图未加载完成"); + return ApiResponse.failure("地图未加载,请先加载地图"); } try { // 构建路径点列表 @@ -203,8 +206,20 @@ public class GraphHopperController { } } + @Operation(summary = "获取地图加载状态") + @GetMapping("/status") + public ApiResponse getMapStatus() { + if (isLoading.get()) { + return ApiResponse.success("地图正在加载中"); + } else if (isLoaded.get() && currentHopper != null) { + return ApiResponse.success("地图已加载完成"); + } else { + return ApiResponse.success("地图未加载"); + } + } + @Operation(summary = "获取交通方式") - @CheckAuth + @PostMapping("/profiles") public ApiResponse profiles() { return ApiResponse.success(graphHopperProperties.getProfiles()); diff --git a/src/main/java/com/yj/earth/business/controller/IconLibraryController.java b/src/main/java/com/yj/earth/business/controller/IconLibraryController.java index c055ad1..c09fafa 100644 --- a/src/main/java/com/yj/earth/business/controller/IconLibraryController.java +++ b/src/main/java/com/yj/earth/business/controller/IconLibraryController.java @@ -42,7 +42,7 @@ import java.util.Map; import java.util.stream.Collectors; @Tag(name = "图标数据管理") -@CheckAuth + @RestController @RequestMapping("/iconLibrary") public class IconLibraryController { diff --git a/src/main/java/com/yj/earth/business/controller/MatterController.java b/src/main/java/com/yj/earth/business/controller/MatterController.java index c9ad89c..ea5f133 100644 --- a/src/main/java/com/yj/earth/business/controller/MatterController.java +++ b/src/main/java/com/yj/earth/business/controller/MatterController.java @@ -28,8 +28,17 @@ public class MatterController { @PostMapping("/add") @Operation(summary = "添加物资") public ApiResponse add(@RequestBody AddMatterDto addMatterDto) { + // 获取名称 + String name = addMatterDto.getName(); + // 判断名称是否存在 + if (matterService.exists(new LambdaQueryWrapper().eq(Matter::getName, name))) { + return ApiResponse.failure("物资已存在"); + } Matter matter = new Matter(); BeanUtils.copyProperties(addMatterDto, matter); + if (matter.getNum() == null) { + matter.setNum(0); + } matterService.save(matter); return ApiResponse.success(null); } @@ -61,7 +70,7 @@ public class MatterController { @PostMapping("/list") public ApiResponse list(@Parameter(description = "分页数量") @RequestParam(value = "pageNum") Integer pageNum, @Parameter(description = "分页大小") @RequestParam(value = "pageSize") Integer pageSize, - @Parameter(description = "物资名称") @RequestParam(value = "name") String name) { + @Parameter(description = "物资名称") @RequestParam(value = "name", required = false) String name) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); if (StringUtils.isNotBlank(name)) { queryWrapper.like(Matter::getName, name); diff --git a/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java b/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java index fc78d6b..7afc6b4 100644 --- a/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java +++ b/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java @@ -42,7 +42,7 @@ import java.util.Map; import java.util.stream.Collectors; @Tag(name = "军标数据管理") -@CheckAuth + @RestController @RequestMapping("/militaryLibrary") public class MilitaryLibraryController { diff --git a/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java b/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java index e83a282..f06a497 100644 --- a/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java +++ b/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java @@ -42,7 +42,7 @@ import java.util.*; import java.util.stream.Collectors; @Tag(name = "模型数据管理") -@CheckAuth + @RestController @RequestMapping("/modelLibrary") public class ModelLibraryController { @@ -543,7 +543,7 @@ public class ModelLibraryController { // 先将当前分类ID加入结果列表(确保包含自身) resultList.add(currentTypeId); - // 查询当前分类的「直接子分类」(按 tree_index 排序、保持树形结构原有顺序) + // 查询当前分类的「直接子分类」 String childSql = "SELECT id FROM model_type WHERE parent_id = ? ORDER BY tree_index ASC"; List childParams = new ArrayList<>(); childParams.add(currentTypeId); @@ -578,5 +578,4 @@ public class ModelLibraryController { } return str.startsWith(".") ? str.substring(1) : str; } - } diff --git a/src/main/java/com/yj/earth/business/controller/PoiController.java b/src/main/java/com/yj/earth/business/controller/PoiController.java index 1fbb75c..282f154 100644 --- a/src/main/java/com/yj/earth/business/controller/PoiController.java +++ b/src/main/java/com/yj/earth/business/controller/PoiController.java @@ -5,15 +5,15 @@ import com.yj.earth.vo.PoiVo; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.Data; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.sql.*; import java.io.File; +import java.sql.*; import java.util.ArrayList; import java.util.List; @@ -21,15 +21,20 @@ import java.util.List; @RestController @RequestMapping("/poi") public class PoiController { - private static Connection connection; + private static final Logger logger = LoggerFactory.getLogger(PoiController.class); - static { - try { + @Value("${poi.global.enabled:false}") + private boolean poiEnabled; + + private Connection connection; + + // 初始化数据库连接的方法 + private void initConnection() throws SQLException, ClassNotFoundException { + if (connection == null || connection.isClosed()) { Class.forName("org.sqlite.JDBC"); String dbPath = System.getProperty("user.dir") + File.separator + "poi" + File.separator + "poi.db"; connection = DriverManager.getConnection("jdbc:sqlite:" + dbPath); - } catch (Exception e) { - throw new RuntimeException("SQLite连接初始化失败", e); + logger.info("POI数据库连接初始化成功,路径:{}", dbPath); } } @@ -38,6 +43,16 @@ public class PoiController { public ApiResponse data(@Parameter(description = "分页页码") Integer pageNum, @Parameter(description = "分页大小") Integer pageSize, @Parameter(description = "名称搜索") String name) { + // 检查功能是否开启 + if (!poiEnabled) { + return ApiResponse.failure("全国POI搜索功能已关闭"); + } + + // 检查分页参数合法性 + if (pageNum == null || pageSize == null || pageNum < 1 || pageSize < 1) { + return ApiResponse.failure("无效的分页参数"); + } + int offset = (pageNum - 1) * pageSize; StringBuilder dataSql = new StringBuilder("SELECT id, name, lng, lat FROM data WHERE 1=1"); List params = new ArrayList<>(); @@ -51,8 +66,10 @@ public class PoiController { // 添加分页条件 dataSql.append(" LIMIT ? OFFSET ?"); try { + // 初始化连接(如果未初始化) + initConnection(); + List poiList = new ArrayList<>(); - long dataStartTime = System.currentTimeMillis(); try (PreparedStatement dataPs = connection.prepareStatement(dataSql.toString())) { int paramIndex = 1; for (Object param : params) { @@ -74,7 +91,11 @@ public class PoiController { } return ApiResponse.success(poiList); } catch (SQLException e) { + logger.error("POI数据查询失败", e); return ApiResponse.failure("POI数据查询失败:" + e.getMessage()); + } catch (ClassNotFoundException e) { + logger.error("POI数据库驱动加载失败", e); + return ApiResponse.failure("POI功能初始化失败:驱动未找到"); } } } diff --git a/src/main/java/com/yj/earth/business/controller/RoleController.java b/src/main/java/com/yj/earth/business/controller/RoleController.java index 5c8de56..05b9fb3 100644 --- a/src/main/java/com/yj/earth/business/controller/RoleController.java +++ b/src/main/java/com/yj/earth/business/controller/RoleController.java @@ -30,7 +30,7 @@ import java.util.Map; import java.util.stream.Collectors; @Tag(name = "角色数据管理") -@CheckAuth + @RestController @RequestMapping("/role") public class RoleController { diff --git a/src/main/java/com/yj/earth/business/controller/RoleSourceController.java b/src/main/java/com/yj/earth/business/controller/RoleSourceController.java index 715cff9..24d2ab6 100644 --- a/src/main/java/com/yj/earth/business/controller/RoleSourceController.java +++ b/src/main/java/com/yj/earth/business/controller/RoleSourceController.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.stream.Collectors; @Tag(name = "角色资源管理") -@CheckAuth + @RestController @RequestMapping("/roleSource") public class RoleSourceController { diff --git a/src/main/java/com/yj/earth/business/controller/SourceController.java b/src/main/java/com/yj/earth/business/controller/SourceController.java index 12894f4..98aa392 100644 --- a/src/main/java/com/yj/earth/business/controller/SourceController.java +++ b/src/main/java/com/yj/earth/business/controller/SourceController.java @@ -36,7 +36,7 @@ import static com.yj.earth.common.constant.GlobalConstant.SHOW; @Slf4j @Tag(name = "树形结构管理") -@CheckAuth + @RestController @RequestMapping("/source") public class SourceController { diff --git a/src/main/java/com/yj/earth/business/controller/SystemController.java b/src/main/java/com/yj/earth/business/controller/SystemController.java index 182245c..1e864fa 100644 --- a/src/main/java/com/yj/earth/business/controller/SystemController.java +++ b/src/main/java/com/yj/earth/business/controller/SystemController.java @@ -177,7 +177,7 @@ public class SystemController { source.setSourceType(resultSet.getString("source_type")); source.setSourcePath(resultSet.getString("source_path")); - // 关键修改:读取原始parent_id,而非覆盖为新父节点ID + // 关键修改:读取原始parent_id、而非覆盖为新父节点ID source.setParentId(resultSet.getString("parent_id")); Integer treeIndex = resultSet.getObject("tree_index") != null diff --git a/src/main/java/com/yj/earth/business/domain/Matter.java b/src/main/java/com/yj/earth/business/domain/Matter.java index 7d69c5f..7020abb 100644 --- a/src/main/java/com/yj/earth/business/domain/Matter.java +++ b/src/main/java/com/yj/earth/business/domain/Matter.java @@ -25,6 +25,8 @@ public class Matter implements Serializable { private String name; @Schema(description = "数量") private Integer num; + @Schema(description = "单位") + private String unit; @Schema(description = "创建时间") @TableField(fill = FieldFill.INSERT) private LocalDateTime createdAt; diff --git a/src/main/java/com/yj/earth/business/domain/PoiInfo.java b/src/main/java/com/yj/earth/business/domain/PoiInfo.java index d35cea3..e834337 100644 --- a/src/main/java/com/yj/earth/business/domain/PoiInfo.java +++ b/src/main/java/com/yj/earth/business/domain/PoiInfo.java @@ -1,6 +1,8 @@ package com.yj.earth.business.domain; +import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -23,7 +25,9 @@ public class PoiInfo implements Serializable { @Schema(description = "是否启用") private Integer isEnable; @Schema(description = "创建时间") + @TableField(fill = FieldFill.INSERT) private LocalDateTime createdAt; @Schema(description = "更新时间") + @TableField(fill = FieldFill.UPDATE) private LocalDateTime updatedAt; } diff --git a/src/main/java/com/yj/earth/business/service/impl/FileInfoServiceImpl.java b/src/main/java/com/yj/earth/business/service/impl/FileInfoServiceImpl.java index 110bd18..807ce35 100644 --- a/src/main/java/com/yj/earth/business/service/impl/FileInfoServiceImpl.java +++ b/src/main/java/com/yj/earth/business/service/impl/FileInfoServiceImpl.java @@ -1,6 +1,7 @@ package com.yj.earth.business.service.impl; import cn.hutool.core.io.FileUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.drew.imaging.ImageMetadataReader; import com.drew.lang.Rational; import com.drew.metadata.Metadata; @@ -8,14 +9,10 @@ import com.drew.metadata.exif.GpsDirectory; import com.yj.earth.business.domain.FileInfo; import com.yj.earth.business.mapper.FileInfoMapper; import com.yj.earth.business.service.FileInfoService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yj.earth.datasource.DatabaseManager; -import io.swagger.v3.oas.annotations.Parameter; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.multipart.MultipartFile; import java.io.File; diff --git a/src/main/java/com/yj/earth/common/config/GlobalExceptionHandler.java b/src/main/java/com/yj/earth/common/config/GlobalExceptionHandler.java index 364a530..9da1fe6 100644 --- a/src/main/java/com/yj/earth/common/config/GlobalExceptionHandler.java +++ b/src/main/java/com/yj/earth/common/config/GlobalExceptionHandler.java @@ -1,5 +1,6 @@ package com.yj.earth.common.config; +import cn.dev33.satoken.exception.NotLoginException; import com.yj.earth.common.exception.UnAuthException; import com.yj.earth.common.util.ApiResponse; import lombok.extern.slf4j.Slf4j; @@ -9,14 +10,20 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { - @ExceptionHandler(Exception.class) - public ApiResponse handleException(Exception e) { - return ApiResponse.failure(e.getMessage()); - } - @ExceptionHandler(UnAuthException.class) public ApiResponse handleUnAuthException(UnAuthException e) { return ApiResponse.failureWithNoAuth(e.getMessage()); } + + @ExceptionHandler(NotLoginException.class) + public ApiResponse handleNotLoginException(NotLoginException e) { + return ApiResponse.failureWithNoAuth(e.getMessage()); + } + + @ExceptionHandler(Exception.class) + public ApiResponse handleException(Exception e) { + log.error("Exception: ", e); + return ApiResponse.failure(e.getMessage()); + } } diff --git a/src/main/java/com/yj/earth/common/util/PoiExporter.java b/src/main/java/com/yj/earth/common/util/PoiExporter.java index 7117010..e53d0aa 100644 --- a/src/main/java/com/yj/earth/common/util/PoiExporter.java +++ b/src/main/java/com/yj/earth/common/util/PoiExporter.java @@ -131,7 +131,7 @@ public class PoiExporter { } // 批量插入(带进度日志) - int batchSize = 5000; + int batchSize = 1000; int totalCount = 0; // 总处理数据量 try (ResultSet rs = queryPs.executeQuery()) { while (rs.next()) { @@ -165,7 +165,7 @@ public class PoiExporter { public static void main(String[] args) { try { - new PoiExporter().exportPoiByArea("兰州市"); + new PoiExporter().exportPoiByArea("重庆市"); } catch (SQLException e) { e.printStackTrace(); } diff --git a/src/main/java/com/yj/earth/datasource/DatabaseManager.java b/src/main/java/com/yj/earth/datasource/DatabaseManager.java index c95d043..64e109a 100644 --- a/src/main/java/com/yj/earth/datasource/DatabaseManager.java +++ b/src/main/java/com/yj/earth/datasource/DatabaseManager.java @@ -3,11 +3,13 @@ package com.yj.earth.datasource; import com.yj.earth.design.*; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Component; import org.yaml.snakeyaml.Yaml; -import java.io.IOException; -import java.io.InputStream; +import javax.annotation.PostConstruct; +import java.io.*; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.nio.file.Files; @@ -21,14 +23,31 @@ import java.util.Map; @Data @Slf4j +@Component public class DatabaseManager { + public static String getRecommendedCacheDirectory() { + return FOLDER_NAME; + } + public enum DatabaseType { SQLITE, MYSQL } + @Value("${server.path}") + private String path; + + private static String FOLDER_NAME; + private static boolean isPathInitialized = false; + + @PostConstruct + public void init() { + FOLDER_NAME = this.path; + isPathInitialized = true; + log.info("数据库路径已初始化: {}", FOLDER_NAME); + } + private static final String EXCLUDE_SERIAL_FIELD = "serialVersionUID"; private static final List> ENTITY_CLASSES; - private static final String FOLDER_NAME = "yjearth"; private static final String DB_FILE_NAME = "app.db"; private static String sqliteDbFilePath; private static boolean isSqliteInitialized = false; @@ -64,6 +83,15 @@ public class DatabaseManager { ENTITY_CLASSES = Collections.unmodifiableList(classes); } + // 新增方法:提前初始化路径 + public static void initializePath(String path) { + if (!isPathInitialized) { + FOLDER_NAME = path; + isPathInitialized = true; + log.info("数据库路径已提前初始化: {}", FOLDER_NAME); + } + } + public static void initDatabase(DatabaseType dbType) { if (dbType == null) { log.error("数据库类型不能为空"); @@ -112,6 +140,16 @@ public class DatabaseManager { } public static String getSqliteDbFilePath() { + if (!isPathInitialized || FOLDER_NAME == null) { + throw new IllegalStateException("数据库路径尚未初始化,请先调用 initializePath 方法或等待 @PostConstruct 完成"); + } + + if (sqliteDbFilePath == null) { + // 如果没有预先创建,则动态构建路径 + Path appDir = Paths.get(FOLDER_NAME); + Path dbFile = appDir.resolve(DB_FILE_NAME); + sqliteDbFilePath = dbFile.toAbsolutePath().toString(); + } return sqliteDbFilePath; } @@ -132,7 +170,13 @@ public class DatabaseManager { } private static boolean validateConfig(DatabaseType dbType) { - if (dbType == DatabaseType.SQLITE) return true; + if (dbType == DatabaseType.SQLITE) { + if (!isPathInitialized || FOLDER_NAME == null) { + log.error("SQLite配置缺失: server.path 尚未初始化"); + return false; + } + return true; + } if (mysqlUrl == null || mysqlUrl.isEmpty()) { log.error("MySQL配置缺失: spring.datasource.mysql.url"); @@ -162,31 +206,44 @@ public class DatabaseManager { private static void preProcess(DatabaseType dbType) throws IOException { if (dbType != DatabaseType.SQLITE) return; - Path systemCacheDir = getRecommendedCacheDirectory(); - if (systemCacheDir == null) { - throw new IOException("无法获取有效的系统缓存目录、无法创建SQLite文件"); + // 直接使用配置的绝对路径 + if (FOLDER_NAME == null || FOLDER_NAME.trim().isEmpty()) { + throw new IOException("server.path 配置为空,无法创建SQLite数据库文件"); } - Path appDir = systemCacheDir.resolve(FOLDER_NAME); + Path appDir = Paths.get(FOLDER_NAME); Path dbFile = appDir.resolve(DB_FILE_NAME); sqliteDbFilePath = dbFile.toAbsolutePath().toString(); + // 创建目录(如果不存在) if (!Files.exists(appDir)) { - Files.createDirectories(appDir); - log.info("创建SQLite应用目录: {}", appDir); + try { + Files.createDirectories(appDir); + log.info("创建SQLite数据库目录: {}", appDir); + } catch (IOException e) { + throw new IOException("无法创建SQLite数据库目录: " + appDir + ", 错误: " + e.getMessage(), e); + } } + + // 检查目录写入权限 if (!Files.isWritable(appDir)) { throw new IOException("无权限写入SQLite目录: " + appDir); } + // 创建数据库文件(如果不存在) if (!Files.exists(dbFile)) { - Files.createFile(dbFile); - log.info("创建SQLite新文件: {}", sqliteDbFilePath); + try { + Files.createFile(dbFile); + log.info("创建SQLite数据库文件: {}", sqliteDbFilePath); + } catch (IOException e) { + throw new IOException("无法创建SQLite数据库文件: " + dbFile + ", 错误: " + e.getMessage(), e); + } } else { - log.info("SQLite文件已存在: {}", sqliteDbFilePath); + log.info("SQLite数据库文件已存在: {}", sqliteDbFilePath); } } + // ... 其他方法保持不变 ... private static void createTablesForEntities(DatabaseType dbType) throws SQLException { if (ENTITY_CLASSES.isEmpty()) { log.warn("未配置需要创建表的实体类、跳过批量建表"); @@ -300,35 +357,6 @@ public class DatabaseManager { } } - public static Path getRecommendedCacheDirectory() { - String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - String appData = System.getenv("APPDATA"); - if (appData != null && !appData.isEmpty()) { - Path path = Paths.get(appData); - if (Files.exists(path) && Files.isWritable(path)) { - return path; - } - } - } else if (os.contains("nix") || os.contains("nux")) { - String userHome = System.getProperty("user.home"); - if (userHome != null && !userHome.isEmpty()) { - Path path = Paths.get(userHome).resolve(".cache"); - try { - if (!Files.exists(path)) { - Files.createDirectories(path); - } - if (Files.isWritable(path)) { - return path; - } - } catch (IOException e) { - log.error("无法访问Linux .cache目录: {}", e.getMessage(), e); - } - } - } - return null; - } - private static String mapJavaTypeToMysql(Class javaType) { if (javaType == int.class || javaType == Integer.class) { return "INT"; @@ -411,4 +439,55 @@ public class DatabaseManager { } return "sqlite"; } + + private static String readServerPathFromConfig() { + // 先尝试读取外部配置(JAR同级或项目根目录) + String externalConfigPath = System.getProperty("user.dir") + File.separator + "application.yml"; + File externalConfigFile = new File(externalConfigPath); + if (externalConfigFile.exists() && externalConfigFile.isFile()) { + try (InputStream input = new FileInputStream(externalConfigFile)) { + return parseServerPath(input); + } catch (Exception e) { + log.error("读取外部配置文件失败: {}", e.getMessage()); + } + } + + // 外部配置不存在、读取类路径内部配置 + try (InputStream input = new ClassPathResource("application.yml").getInputStream()) { + return parseServerPath(input); + } catch (Exception e) { + log.error("读取内部配置文件失败: {}", e.getMessage()); + } + + return null; + } + + // 从输入流中解析 server.path + private static String parseServerPath(InputStream input) { + Yaml yaml = new Yaml(); + Map yamlData = yaml.load(input); + if (yamlData.containsKey("server") && yamlData.get("server") instanceof Map) { + Map serverMap = (Map) yamlData.get("server"); + Object pathObj = serverMap.get("path"); + return pathObj != null ? pathObj.toString().trim() : null; + } + return null; + } + + /** + * 提前初始化数据库路径 + */ + public static void initializeDatabasePath() { + try { + String serverPath = readServerPathFromConfig(); + if (serverPath != null && !serverPath.trim().isEmpty()) { + DatabaseManager.initializePath(serverPath); + log.info("已提前初始化数据库路径: {}", serverPath); + } else { + log.warn("未找到 server.path 配置,将等待 @PostConstruct 初始化"); + } + } catch (Exception e) { + log.warn("提前初始化数据库路径失败,将等待 @PostConstruct 初始化: {}", e.getMessage()); + } + } } diff --git a/src/main/java/com/yj/earth/design/Matter.java b/src/main/java/com/yj/earth/design/Matter.java index d943bbd..d7ea60e 100644 --- a/src/main/java/com/yj/earth/design/Matter.java +++ b/src/main/java/com/yj/earth/design/Matter.java @@ -13,6 +13,8 @@ public class Matter { private String name; @Schema(description = "数量") private Integer num; + @Schema(description = "单位") + private String unit; @Schema(description = "创建时间") private LocalDateTime createdAt; @Schema(description = "更新时间") diff --git a/src/main/java/com/yj/earth/dto/matter/AddMatterDto.java b/src/main/java/com/yj/earth/dto/matter/AddMatterDto.java index a30d3ce..619ac6f 100644 --- a/src/main/java/com/yj/earth/dto/matter/AddMatterDto.java +++ b/src/main/java/com/yj/earth/dto/matter/AddMatterDto.java @@ -9,4 +9,6 @@ public class AddMatterDto { private String name; @Schema(description = "数量") private Integer num; + @Schema(description = "单位") + private String unit; } diff --git a/src/main/java/com/yj/earth/dto/matter/UpdateMatterDto.java b/src/main/java/com/yj/earth/dto/matter/UpdateMatterDto.java index 2d387c7..d401742 100644 --- a/src/main/java/com/yj/earth/dto/matter/UpdateMatterDto.java +++ b/src/main/java/com/yj/earth/dto/matter/UpdateMatterDto.java @@ -11,4 +11,6 @@ public class UpdateMatterDto { private String name; @Schema(description = "数量") private Integer num; + @Schema(description = "单位") + private String unit; } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3999805..e2d0628 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,10 +1,15 @@ server: host: 127.0.0.1 port: 8848 + path: C:\abcdefghijklmnopqrstuvwxyz sdk: port: 8888 +poi: + global: + enabled: false + spring: main: banner-mode: off @@ -16,6 +21,7 @@ spring: url: jdbc:mysql://192.168.110.65:6975/yjearth?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: yjearth password: kNGxrsSSYMexZ2t4 + servlet: multipart: max-file-size: 1024MB