16 Commits

Author SHA1 Message Date
wzy-warehouse d4f892fad6 水库不显示的问题 2026-06-17 16:02:12 +08:00
wzy-warehouse bfd80887b2 调整返回前端的数据顺序 2026-06-17 15:42:10 +08:00
wzy-warehouse e33105a467 添加预测概率 2026-06-17 14:22:53 +08:00
wzy-warehouse f4af9975d6 添加崩塌隐患点 2026-06-16 10:19:22 +08:00
wzy-warehouse 3c6b716007 统一数据库映射 2026-06-12 10:08:20 +08:00
wzy-warehouse 7ff67f8a37 修改配置文件 2026-06-02 10:25:42 +08:00
wzy-warehouse 9d95700787 对降雨栅格添加websocket响应 2026-05-18 17:26:00 +08:00
wzy-warehouse 2fe0db36df websocket配置 2026-05-18 10:17:02 +08:00
wzy-warehouse d2fc460c35 去掉隐藏字符 2026-05-18 10:16:41 +08:00
wzy-warehouse e4e3a09c47 修改加解密逻辑,允许使用通配符进行过滤 2026-05-18 10:16:26 +08:00
wzy-warehouse 2b40f2e13b 暴雨图层加载功能 2026-05-05 19:22:25 +08:00
wzy-warehouse 0018d43f09 添加geoserver说明 2026-05-05 19:19:12 +08:00
wzy-warehouse babb835ca4 修改名称 2026-04-28 10:06:58 +08:00
wzy-warehouse 668190dcd9 细化隐患点类型 2026-04-28 09:28:48 +08:00
wzy-warehouse 233959e918 细化隐患点类型 2026-04-27 22:50:32 +08:00
wzy-warehouse 601cb300bc 为所有点类表映射name属性 2026-04-27 21:34:48 +08:00
48 changed files with 1308 additions and 150 deletions
+15
View File
@@ -106,5 +106,20 @@ bin\package.bat
- `application-database-dev.yml`: 开发环境数据库配置
- `application-database-prod.yml`: 生产环境数据库配置
# geo_server相关说明
1. 版本:2.28.3
2. 安装:
```
docker pull docker.osgeo.org/geoserver:2.28.3
docker run -d \
--log-driver none \
--name geoserver \
-p 8080:4020 \
-e GEOSERVER_ADMIN_USER=admin \
-e GEOSERVER_ADMIN_PASSWORD=geoserver \
-v /mydata/geoserver/data_dir:/data_dir \
kartoza/geoserver
```
## 许可证
本项目基于 [MIT License](LICENSE) 开源,详情请查看LICENSE文件。
@@ -5,12 +5,14 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 后台启动入口
* 启动时过滤DataSourceAutoConfiguration,避免数据源自动配置
*/
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableScheduling // 启用定时任务支持
@MapperScan("com.gis.xian.mapper") // 扫描MyBatis的Mapper接口
public class XianApplication {
@@ -0,0 +1,19 @@
package com.gis.xian.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 算法服务器配置属性
*/
@Data
@Component
@ConfigurationProperties(prefix = "algorithm.server")
public class AlgorithmServerProperties {
/**
* 算法服务器地址
*/
private String url;
}
@@ -0,0 +1,25 @@
package com.gis.xian.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 降雨网格配置属性类
* 从application.yml中读取rainfall.grid配置
*/
@Data
@Component
@ConfigurationProperties(prefix = "rainfall.grid")
public class RainfallGridProperties {
/**
* 降雨站点网格数据 Redis Key
*/
private String stationGrid;
/**
* 降雨站点标识符 Redis Key
*/
private String stationIdentifier;
}
@@ -0,0 +1,28 @@
package com.gis.xian.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker // 启用WebSocket消息代理
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 启用简单的内存消息代理,客户端订阅以 "/topic" 开头的目的地
registry.enableSimpleBroker("/topic");
// 设置客户端发送消息的前缀,即 "/app"
registry.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注册端点 "/websocket",客户端将通过此路径建立连接
registry.addEndpoint("/websocket")
.setAllowedOriginPatterns("*") // 允许所有源,支持携带凭证
.withSockJS();
}
}
@@ -0,0 +1,222 @@
package com.gis.xian.controller;
import com.alibaba.fastjson2.JSON;
import com.gis.xian.config.AlgorithmServerProperties;
import com.gis.xian.domain.ApiResponse;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Map;
/**
* 算法代理控制器
* 所有以 /algorithm-api 开头的请求都会转发到算法服务器
*/
@RestController
@RequestMapping("/algorithm-api")
@Slf4j
public class AlgorithmProxyController extends BaseController {
@Resource
private AlgorithmServerProperties algorithmServerProperties;
private final RestTemplate restTemplate = new RestTemplate();
/**
* 处理所有 GET 请求
*/
@GetMapping("/**")
public ApiResponse<Object> proxyGet(HttpServletRequest request) {
return proxyRequest(request, HttpMethod.GET);
}
/**
* 处理所有 POST 请求
*/
@PostMapping("/**")
public ApiResponse<Object> proxyPost(HttpServletRequest request) throws IOException {
return proxyRequest(request, HttpMethod.POST);
}
/**
* 处理所有 PUT 请求
*/
@PutMapping("/**")
public ApiResponse<Object> proxyPut(HttpServletRequest request) throws IOException {
return proxyRequest(request, HttpMethod.PUT);
}
/**
* 处理所有 DELETE 请求
*/
@DeleteMapping("/**")
public ApiResponse<Object> proxyDelete(HttpServletRequest request) {
return proxyRequest(request, HttpMethod.DELETE);
}
/**
* 处理所有 PATCH 请求
*/
@PatchMapping("/**")
public ApiResponse<Object> proxyPatch(HttpServletRequest request) throws IOException {
return proxyRequest(request, HttpMethod.PATCH);
}
/**
* 通用的请求代理方法
*/
@SuppressWarnings("unchecked")
private ApiResponse<Object> proxyRequest(HttpServletRequest request, HttpMethod httpMethod) {
long startTime = System.currentTimeMillis();
try {
// 构建目标 URL
String targetUrl = buildTargetUrl(request);
log.info("代理请求: {} -> {}", request.getRequestURI(), targetUrl);
// 构建请求头
HttpHeaders headers = buildRequestHeaders(request);
// 构建请求体
Object requestBody = null;
if (httpMethod == HttpMethod.POST || httpMethod == HttpMethod.PUT || httpMethod == HttpMethod.PATCH) {
String contentType = request.getContentType();
if (contentType != null && !contentType.isEmpty()) {
headers.setContentType(MediaType.parseMediaType(contentType));
// 读取请求体
byte[] bodyBytes = StreamUtils.copyToByteArray(request.getInputStream());
if (bodyBytes.length > 0) {
// 尝试解析为 JSON,如果不是 JSON 则直接使用字节数组
if (contentType.contains("application/json")) {
String jsonBody = new String(bodyBytes, StandardCharsets.UTF_8);
try {
requestBody = JSON.parse(jsonBody);
} catch (Exception e) {
requestBody = jsonBody;
}
} else {
requestBody = bodyBytes;
}
}
}
}
// 创建 HTTP 实体
HttpEntity<Object> entity = new HttpEntity<>(requestBody, headers);
// 发送请求到算法服务器
ResponseEntity<String> response = restTemplate.exchange(
targetUrl,
httpMethod,
entity,
String.class
);
// 解析响应
long endTime = System.currentTimeMillis();
log.info("代理请求完成: {} -> {}, 耗时: {}ms, 状态码: {}",
request.getRequestURI(), targetUrl, (endTime - startTime), response.getStatusCode());
// 尝试将响应解析为 ApiResponse
String responseBody = response.getBody();
if (responseBody != null && !responseBody.isEmpty()) {
try {
// 尝试解析为 ApiResponse 格式
Map<String, Object> responseMap = JSON.parseObject(responseBody, Map.class);
if (responseMap.containsKey("code") && responseMap.containsKey("message")) {
// 如果已经是 ApiResponse 格式,直接返回
Integer code = (Integer) responseMap.get("code");
String message = (String) responseMap.get("message");
Object data = responseMap.get("data");
return new ApiResponse<>(code, message, data);
}
} catch (Exception e) {
log.debug("响应不是标准 ApiResponse 格式,将作为数据返回");
}
// 如果不是 ApiResponse 格式,将整个响应作为 data 返回
return ApiResponse.ok((Object) responseBody);
}
return ApiResponse.ok((Object) null);
} catch (Exception e) {
long endTime = System.currentTimeMillis();
log.error("代理请求失败: {} , 耗时: {}ms, 错误: {}",
request.getRequestURI(), (endTime - startTime), e.getMessage(), e);
return ApiResponse.error(502, "算法服务调用失败: " + e.getMessage(), null);
}
}
/**
* 构建目标 URL
*/
private String buildTargetUrl(HttpServletRequest request) {
// 获取原始请求路径,去掉 /algorithm-api 前缀
String requestUri = request.getRequestURI();
String path = requestUri.substring("/algorithm-api".length());
// 确保路径以 / 开头
if (!path.startsWith("/")) {
path = "/" + path;
}
// 拼接算法服务器地址和路径
String baseUrl = algorithmServerProperties.getUrl();
if (baseUrl.endsWith("/") && path.startsWith("/")) {
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
}
String targetUrl = baseUrl + path;
// 添加查询参数
String queryString = request.getQueryString();
if (queryString != null && !queryString.isEmpty()) {
targetUrl += "?" + queryString;
}
return targetUrl;
}
/**
* 构建请求头
*/
private HttpHeaders buildRequestHeaders(HttpServletRequest request) {
HttpHeaders headers = new HttpHeaders();
// 复制所有请求头(排除一些特定的头)
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
// 排除一些不应该转发的头
if (!shouldExcludeHeader(headerName)) {
Enumeration<String> headerValues = request.getHeaders(headerName);
while (headerValues.hasMoreElements()) {
headers.add(headerName, headerValues.nextElement());
}
}
}
return headers;
}
/**
* 判断是否应该排除该请求头
*/
private boolean shouldExcludeHeader(String headerName) {
String lowerName = headerName.toLowerCase();
// 排除 Host、Content-Length 等头
return lowerName.equals("host") ||
lowerName.equals("content-length") ||
lowerName.equals("transfer-encoding");
}
}
@@ -0,0 +1,82 @@
package com.gis.xian.controller;
import com.gis.xian.domain.ApiResponse;
import com.gis.xian.service.RainfallGridService;
import com.gis.xian.vo.RainfallGridVo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.atomic.AtomicReference;
/**
* 降雨网格控制器
*/
@Slf4j
@RestController
public class RainfallGridController extends BaseController {
@Resource
private SimpMessagingTemplate messagingTemplate;
@Resource
private RainfallGridService rainfallGridService;
// 存储上一次的 ID,用于检测变化
private final AtomicReference<String> lastIdentifier = new AtomicReference<>(null);
/**
* 处理客户端订阅请求,首次订阅时返回当前数据
* 客户端发送任意消息到 /app/rainfall/grid 即可触发
*/
@MessageMapping("/rainfall/grid")
@SendTo("/topic/rainfall/grid/messages")
public ApiResponse<RainfallGridVo> handleSubscription() {
RainfallGridVo data = rainfallGridService.getRainfallGridData();
// 记录当前 identifier,用于后续变化检测
String currentIdentifier = rainfallGridService.getCurrentIdentifier();
if (currentIdentifier != null) {
lastIdentifier.set(currentIdentifier);
log.info("客户端订阅,记录初始 identifier: {}", currentIdentifier);
}
log.info("响应客户端订阅请求: id={}", data.getId());
return ApiResponse.ok(data);
}
/**
* 每秒检查 Redis 中的 identifier 是否变化,如果变化则推送新数据
*/
@Scheduled(fixedRate = 1000)
public void checkAndPushIfChanged() {
try {
String currentIdentifier = rainfallGridService.getCurrentIdentifier();
// 如果 identifier 为空,跳过
if (currentIdentifier == null) {
return;
}
// 检查 identifier 是否发生变化
String previousIdentifier = lastIdentifier.get();
if (previousIdentifier == null || !previousIdentifier.equals(currentIdentifier)) {
log.info("检测到 identifier 变化: {} -> {}", previousIdentifier, currentIdentifier);
// 获取最新数据并推送
RainfallGridVo data = rainfallGridService.getRainfallGridData();
messagingTemplate.convertAndSend("/topic/rainfall/grid/messages", ApiResponse.ok(data));
log.info("推送更新数据: id={}", data.getId());
// 更新记录的 identifier
lastIdentifier.set(currentIdentifier);
}
} catch (Exception e) {
log.error("检查并推送数据失败: {}", e.getMessage(), e);
}
}
}
@@ -17,12 +17,13 @@ public class XianHiddenDangerSpotsController extends BaseController{
private XianHiddenDangerSpotsService xianHiddenDangerSpotsService;
@GetMapping("/base-points")
public ApiResponse<List<XianHiddenDangerSpotsBasePointVo>> getBasePoints(@RequestParam String disasterType) {
public ApiResponse<List<XianHiddenDangerSpotsBasePointVo>> getBasePoints(
@RequestParam(required = false) String disasterType) {
return ApiResponse.ok(xianHiddenDangerSpotsService.getBasePoints(disasterType));
}
@GetMapping("point-detail/{id}")
public ApiResponse<XianHiddenDangerSpotsPointDetailVo> getPointDetailById(@PathVariable String id) {
return ApiResponse.ok(xianHiddenDangerSpotsService.getPointDetailById(Long.parseLong(id)));
@GetMapping("point-detail/{id}/{simulationId}")
public ApiResponse<XianHiddenDangerSpotsPointDetailVo> getPointDetailById(@PathVariable String id, @PathVariable String simulationId) {
return ApiResponse.ok(xianHiddenDangerSpotsService.getPointDetailById(Long.parseLong(id), Long.parseLong(simulationId)));
}
}
@@ -24,8 +24,8 @@ public class XianRiskSpotsController {
return ApiResponse.ok(xianRiskSpotsService.getBasePoints());
}
@GetMapping("point-detail/{id}")
public ApiResponse<XianRiskSpotsPointDetailVo> getPointDetailById(@PathVariable String id) {
return ApiResponse.ok(xianRiskSpotsService.getPointDetailById(Long.parseLong(id)));
@GetMapping("point-detail/{id}/{simulationId}")
public ApiResponse<XianRiskSpotsPointDetailVo> getPointDetailById(@PathVariable String id, @PathVariable String simulationId) {
return ApiResponse.ok(xianRiskSpotsService.getPointDetailById(Long.parseLong(id), Long.parseLong(simulationId)));
}
}
@@ -86,7 +86,7 @@ public class XianBridge {
/**
* 位置
*/
private Object point;
private Object geom;
/**
* 逻辑删除标识,0未删除,1已删除
@@ -120,7 +120,7 @@ public class XianBridge {
&& (this.getMaster() == null ? other.getMaster() == null : this.getMaster().equals(other.getMaster()))
&& (this.getMaint() == null ? other.getMaint() == null : this.getMaint().equals(other.getMaint()))
&& (this.getNote() == null ? other.getNote() == null : this.getNote().equals(other.getNote()))
&& (this.getPoint() == null ? other.getPoint() == null : this.getPoint().equals(other.getPoint()))
&& (this.getGeom() == null ? other.getGeom() == null : this.getGeom().equals(other.getGeom()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
}
@@ -143,7 +143,7 @@ public class XianBridge {
result = prime * result + ((getMaster() == null) ? 0 : getMaster().hashCode());
result = prime * result + ((getMaint() == null) ? 0 : getMaint().hashCode());
result = prime * result + ((getNote() == null) ? 0 : getNote().hashCode());
result = prime * result + ((getPoint() == null) ? 0 : getPoint().hashCode());
result = prime * result + ((getGeom() == null) ? 0 : getGeom().hashCode());
result = prime * result + ((getIsDelete() == null) ? 0 : getIsDelete().hashCode());
return result;
}
@@ -169,7 +169,7 @@ public class XianBridge {
sb.append(", master=").append(master);
sb.append(", maint=").append(maint);
sb.append(", note=").append(note);
sb.append(", point=").append(point);
sb.append(", geom=").append(geom);
sb.append(", isDelete=").append(isDelete);
sb.append("]");
return sb.toString();
@@ -201,7 +201,7 @@ public class XianDangerousSource {
/**
*
*/
private Object point;
private Object geom;
/**
* 逻辑删除标识,0未删除,1已删除
@@ -258,7 +258,7 @@ public class XianDangerousSource {
&& (this.getWriteTime() == null ? other.getWriteTime() == null : this.getWriteTime().equals(other.getWriteTime()))
&& (this.getLon() == null ? other.getLon() == null : this.getLon().equals(other.getLon()))
&& (this.getLat() == null ? other.getLat() == null : this.getLat().equals(other.getLat()))
&& (this.getPoint() == null ? other.getPoint() == null : this.getPoint().equals(other.getPoint()))
&& (this.getGeom() == null ? other.getGeom() == null : this.getGeom().equals(other.getGeom()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
}
@@ -304,7 +304,7 @@ public class XianDangerousSource {
result = prime * result + ((getWriteTime() == null) ? 0 : getWriteTime().hashCode());
result = prime * result + ((getLon() == null) ? 0 : getLon().hashCode());
result = prime * result + ((getLat() == null) ? 0 : getLat().hashCode());
result = prime * result + ((getPoint() == null) ? 0 : getPoint().hashCode());
result = prime * result + ((getGeom() == null) ? 0 : getGeom().hashCode());
result = prime * result + ((getIsDelete() == null) ? 0 : getIsDelete().hashCode());
return result;
}
@@ -353,7 +353,7 @@ public class XianDangerousSource {
sb.append(", writeTime=").append(writeTime);
sb.append(", lon=").append(lon);
sb.append(", lat=").append(lat);
sb.append(", point=").append(point);
sb.append(", geom=").append(geom);
sb.append(", isDelete=").append(isDelete);
sb.append("]");
return sb.toString();
@@ -71,7 +71,7 @@ public class XianEmergencyShelter {
/**
* 位置
*/
private Object point;
private Object geom;
/**
* 逻辑删除标识,0未删除,1已删除
@@ -102,7 +102,7 @@ public class XianEmergencyShelter {
&& (this.getEffectiveNumberOfRefugees() == null ? other.getEffectiveNumberOfRefugees() == null : this.getEffectiveNumberOfRefugees().equals(other.getEffectiveNumberOfRefugees()))
&& (this.getLon() == null ? other.getLon() == null : this.getLon().equals(other.getLon()))
&& (this.getLat() == null ? other.getLat() == null : this.getLat().equals(other.getLat()))
&& (this.getPoint() == null ? other.getPoint() == null : this.getPoint().equals(other.getPoint()))
&& (this.getGeom() == null ? other.getGeom() == null : this.getGeom().equals(other.getGeom()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
}
@@ -122,7 +122,7 @@ public class XianEmergencyShelter {
result = prime * result + ((getEffectiveNumberOfRefugees() == null) ? 0 : getEffectiveNumberOfRefugees().hashCode());
result = prime * result + ((getLon() == null) ? 0 : getLon().hashCode());
result = prime * result + ((getLat() == null) ? 0 : getLat().hashCode());
result = prime * result + ((getPoint() == null) ? 0 : getPoint().hashCode());
result = prime * result + ((getGeom() == null) ? 0 : getGeom().hashCode());
result = prime * result + ((getIsDelete() == null) ? 0 : getIsDelete().hashCode());
return result;
}
@@ -145,7 +145,7 @@ public class XianEmergencyShelter {
sb.append(", effectiveNumberOfRefugees=").append(effectiveNumberOfRefugees);
sb.append(", lon=").append(lon);
sb.append(", lat=").append(lat);
sb.append(", point=").append(point);
sb.append(", geom=").append(geom);
sb.append(", isDelete=").append(isDelete);
sb.append("]");
return sb.toString();
@@ -281,7 +281,7 @@ public class XianFirefighter {
/**
*
*/
private Object point;
private Object geom;
/**
* 逻辑删除标识,0未删除,1已删除
@@ -354,7 +354,7 @@ public class XianFirefighter {
&& (this.getWriteTime() == null ? other.getWriteTime() == null : this.getWriteTime().equals(other.getWriteTime()))
&& (this.getLon() == null ? other.getLon() == null : this.getLon().equals(other.getLon()))
&& (this.getLat() == null ? other.getLat() == null : this.getLat().equals(other.getLat()))
&& (this.getPoint() == null ? other.getPoint() == null : this.getPoint().equals(other.getPoint()))
&& (this.getGeom() == null ? other.getGeom() == null : this.getGeom().equals(other.getGeom()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
}
@@ -416,7 +416,7 @@ public class XianFirefighter {
result = prime * result + ((getWriteTime() == null) ? 0 : getWriteTime().hashCode());
result = prime * result + ((getLon() == null) ? 0 : getLon().hashCode());
result = prime * result + ((getLat() == null) ? 0 : getLat().hashCode());
result = prime * result + ((getPoint() == null) ? 0 : getPoint().hashCode());
result = prime * result + ((getGeom() == null) ? 0 : getGeom().hashCode());
result = prime * result + ((getIsDelete() == null) ? 0 : getIsDelete().hashCode());
return result;
}
@@ -481,7 +481,7 @@ public class XianFirefighter {
sb.append(", writeTime=").append(writeTime);
sb.append(", lon=").append(lon);
sb.append(", lat=").append(lat);
sb.append(", point=").append(point);
sb.append(", geom=").append(geom);
sb.append(", isDelete=").append(isDelete);
sb.append("]");
return sb.toString();
@@ -3,7 +3,7 @@ package com.gis.xian.entity;
import lombok.Data;
/**
* 地质灾害隐患点
* 隐患点(滑坡、泥石流、山洪、内涝)
* @TableName xian_hidden_danger_spots
*/
@Data
@@ -111,23 +111,23 @@ public class XianHiddenDangerSpots {
}
XianHiddenDangerSpots other = (XianHiddenDangerSpots) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
&& (this.getFieldCode() == null ? other.getFieldCode() == null : this.getFieldCode().equals(other.getFieldCode()))
&& (this.getProvince() == null ? other.getProvince() == null : this.getProvince().equals(other.getProvince()))
&& (this.getProvinceId() == null ? other.getProvinceId() == null : this.getProvinceId().equals(other.getProvinceId()))
&& (this.getCity() == null ? other.getCity() == null : this.getCity().equals(other.getCity()))
&& (this.getCityId() == null ? other.getCityId() == null : this.getCityId().equals(other.getCityId()))
&& (this.getCounty() == null ? other.getCounty() == null : this.getCounty().equals(other.getCounty()))
&& (this.getCountyId() == null ? other.getCountyId() == null : this.getCountyId().equals(other.getCountyId()))
&& (this.getVillage() == null ? other.getVillage() == null : this.getVillage().equals(other.getVillage()))
&& (this.getDisasterName() == null ? other.getDisasterName() == null : this.getDisasterName().equals(other.getDisasterName()))
&& (this.getLon() == null ? other.getLon() == null : this.getLon().equals(other.getLon()))
&& (this.getLat() == null ? other.getLat() == null : this.getLat().equals(other.getLat()))
&& (this.getGeom() == null ? other.getGeom() == null : this.getGeom().equals(other.getGeom()))
&& (this.getPosition() == null ? other.getPosition() == null : this.getPosition().equals(other.getPosition()))
&& (this.getDisasterType() == null ? other.getDisasterType() == null : this.getDisasterType().equals(other.getDisasterType()))
&& (this.getScaleGrade() == null ? other.getScaleGrade() == null : this.getScaleGrade().equals(other.getScaleGrade()))
&& (this.getRiskGrade() == null ? other.getRiskGrade() == null : this.getRiskGrade().equals(other.getRiskGrade()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
&& (this.getFieldCode() == null ? other.getFieldCode() == null : this.getFieldCode().equals(other.getFieldCode()))
&& (this.getProvince() == null ? other.getProvince() == null : this.getProvince().equals(other.getProvince()))
&& (this.getProvinceId() == null ? other.getProvinceId() == null : this.getProvinceId().equals(other.getProvinceId()))
&& (this.getCity() == null ? other.getCity() == null : this.getCity().equals(other.getCity()))
&& (this.getCityId() == null ? other.getCityId() == null : this.getCityId().equals(other.getCityId()))
&& (this.getCounty() == null ? other.getCounty() == null : this.getCounty().equals(other.getCounty()))
&& (this.getCountyId() == null ? other.getCountyId() == null : this.getCountyId().equals(other.getCountyId()))
&& (this.getVillage() == null ? other.getVillage() == null : this.getVillage().equals(other.getVillage()))
&& (this.getDisasterName() == null ? other.getDisasterName() == null : this.getDisasterName().equals(other.getDisasterName()))
&& (this.getLon() == null ? other.getLon() == null : this.getLon().equals(other.getLon()))
&& (this.getLat() == null ? other.getLat() == null : this.getLat().equals(other.getLat()))
&& (this.getGeom() == null ? other.getGeom() == null : this.getGeom().equals(other.getGeom()))
&& (this.getPosition() == null ? other.getPosition() == null : this.getPosition().equals(other.getPosition()))
&& (this.getDisasterType() == null ? other.getDisasterType() == null : this.getDisasterType().equals(other.getDisasterType()))
&& (this.getScaleGrade() == null ? other.getScaleGrade() == null : this.getScaleGrade().equals(other.getScaleGrade()))
&& (this.getRiskGrade() == null ? other.getRiskGrade() == null : this.getRiskGrade().equals(other.getRiskGrade()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
}
@Override
@@ -182,4 +182,4 @@ public class XianHiddenDangerSpots {
sb.append("]");
return sb.toString();
}
}
}
@@ -316,7 +316,7 @@ public class XianHospitals {
/**
*
*/
private Object point;
private Object geom;
/**
* 逻辑删除标识,0未删除,1已删除
@@ -396,7 +396,7 @@ public class XianHospitals {
&& (this.getWriteTime() == null ? other.getWriteTime() == null : this.getWriteTime().equals(other.getWriteTime()))
&& (this.getLon() == null ? other.getLon() == null : this.getLon().equals(other.getLon()))
&& (this.getLat() == null ? other.getLat() == null : this.getLat().equals(other.getLat()))
&& (this.getPoint() == null ? other.getPoint() == null : this.getPoint().equals(other.getPoint()))
&& (this.getGeom() == null ? other.getGeom() == null : this.getGeom().equals(other.getGeom()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
}
@@ -465,7 +465,7 @@ public class XianHospitals {
result = prime * result + ((getWriteTime() == null) ? 0 : getWriteTime().hashCode());
result = prime * result + ((getLon() == null) ? 0 : getLon().hashCode());
result = prime * result + ((getLat() == null) ? 0 : getLat().hashCode());
result = prime * result + ((getPoint() == null) ? 0 : getPoint().hashCode());
result = prime * result + ((getGeom() == null) ? 0 : getGeom().hashCode());
result = prime * result + ((getIsDelete() == null) ? 0 : getIsDelete().hashCode());
return result;
}
@@ -537,7 +537,7 @@ public class XianHospitals {
sb.append(", writeTime=").append(writeTime);
sb.append(", lon=").append(lon);
sb.append(", lat=").append(lat);
sb.append(", point=").append(point);
sb.append(", geom=").append(geom);
sb.append(", isDelete=").append(isDelete);
sb.append("]");
return sb.toString();
@@ -0,0 +1,221 @@
package com.gis.xian.entity;
import java.util.Date;
/**
* 推理结果表
* @TableName xian_inference_result
*/
public class XianInferenceResult {
/**
* 主键ID
*/
private Long id;
/**
* 名称
*/
private String name;
/**
* 事件类型
*/
private String eventType;
/**
* 发生时间
*/
private Date occurredTime;
/**
* 操作类型
*/
private String operationType;
/**
* 推理结果(JSONB
*/
private Object result;
/**
* 条件(JSONB
*/
private Object condition;
/**
* 文件路径(JSONB
*/
private Object filePath;
/**
* 创建时间
*/
private Date createTime;
/**
* 是否删除(0: 未删除, 1: 已删除)
*/
private Integer isDelete;
// 构造方法
public XianInferenceResult() {
}
public XianInferenceResult(Long id, String name, String eventType, Date occurredTime,
String operationType, Object result, Object condition,
Object filePath, Date createTime, Integer isDelete) {
this.id = id;
this.name = name;
this.eventType = eventType;
this.occurredTime = occurredTime;
this.operationType = operationType;
this.result = result;
this.condition = condition;
this.filePath = filePath;
this.createTime = createTime;
this.isDelete = isDelete;
}
// Getter 和 Setter 方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public Date getOccurredTime() {
return occurredTime;
}
public void setOccurredTime(Date occurredTime) {
this.occurredTime = occurredTime;
}
public String getOperationType() {
return operationType;
}
public void setOperationType(String operationType) {
this.operationType = operationType;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
public Object getCondition() {
return condition;
}
public void setCondition(Object condition) {
this.condition = condition;
}
public Object getFilePath() {
return filePath;
}
public void setFilePath(Object filePath) {
this.filePath = filePath;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Integer getIsDelete() {
return isDelete;
}
public void setIsDelete(Integer isDelete) {
this.isDelete = isDelete;
}
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
XianInferenceResult other = (XianInferenceResult) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
&& (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()))
&& (this.getEventType() == null ? other.getEventType() == null : this.getEventType().equals(other.getEventType()))
&& (this.getOccurredTime() == null ? other.getOccurredTime() == null : this.getOccurredTime().equals(other.getOccurredTime()))
&& (this.getOperationType() == null ? other.getOperationType() == null : this.getOperationType().equals(other.getOperationType()))
&& (this.getResult() == null ? other.getResult() == null : this.getResult().equals(other.getResult()))
&& (this.getCondition() == null ? other.getCondition() == null : this.getCondition().equals(other.getCondition()))
&& (this.getFilePath() == null ? other.getFilePath() == null : this.getFilePath().equals(other.getFilePath()))
&& (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
result = prime * result + ((getEventType() == null) ? 0 : getEventType().hashCode());
result = prime * result + ((getOccurredTime() == null) ? 0 : getOccurredTime().hashCode());
result = prime * result + ((getOperationType() == null) ? 0 : getOperationType().hashCode());
result = prime * result + ((getResult() == null) ? 0 : getResult().hashCode());
result = prime * result + ((getCondition() == null) ? 0 : getCondition().hashCode());
result = prime * result + ((getFilePath() == null) ? 0 : getFilePath().hashCode());
result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
result = prime * result + ((getIsDelete() == null) ? 0 : getIsDelete().hashCode());
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", name=").append(name);
sb.append(", eventType=").append(eventType);
sb.append(", occurredTime=").append(occurredTime);
sb.append(", operationType=").append(operationType);
sb.append(", result=").append(result);
sb.append(", condition=").append(condition);
sb.append(", filePath=").append(filePath);
sb.append(", createTime=").append(createTime);
sb.append(", isDelete=").append(isDelete);
sb.append("]");
return sb.toString();
}
}
@@ -251,7 +251,7 @@ public class XianStorePoints {
/**
*
*/
private Object point;
private Object geom;
/**
*
@@ -318,7 +318,7 @@ public class XianStorePoints {
&& (this.getOverwriteTime() == null ? other.getOverwriteTime() == null : this.getOverwriteTime().equals(other.getOverwriteTime()))
&& (this.getLon() == null ? other.getLon() == null : this.getLon().equals(other.getLon()))
&& (this.getLat() == null ? other.getLat() == null : this.getLat().equals(other.getLat()))
&& (this.getPoint() == null ? other.getPoint() == null : this.getPoint().equals(other.getPoint()))
&& (this.getGeom() == null ? other.getGeom() == null : this.getGeom().equals(other.getGeom()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
}
@@ -374,7 +374,7 @@ public class XianStorePoints {
result = prime * result + ((getOverwriteTime() == null) ? 0 : getOverwriteTime().hashCode());
result = prime * result + ((getLon() == null) ? 0 : getLon().hashCode());
result = prime * result + ((getLat() == null) ? 0 : getLat().hashCode());
result = prime * result + ((getPoint() == null) ? 0 : getPoint().hashCode());
result = prime * result + ((getGeom() == null) ? 0 : getGeom().hashCode());
result = prime * result + ((getIsDelete() == null) ? 0 : getIsDelete().hashCode());
return result;
}
@@ -433,7 +433,7 @@ public class XianStorePoints {
sb.append(", overwriteTime=").append(overwriteTime);
sb.append(", lon=").append(lon);
sb.append(", lat=").append(lat);
sb.append(", point=").append(point);
sb.append(", point=").append(geom);
sb.append(", isDelete=").append(isDelete);
sb.append("]");
return sb.toString();
@@ -61,7 +61,7 @@ public class XianSubwayStations {
/**
* 站点经纬度
*/
private Object point;
private Object geom;
/**
* 逻辑删除标识,0未删除,1已删除
@@ -90,7 +90,7 @@ public class XianSubwayStations {
&& (this.getPointOtherDefenses() == null ? other.getPointOtherDefenses() == null : this.getPointOtherDefenses().equals(other.getPointOtherDefenses()))
&& (this.getLon() == null ? other.getLon() == null : this.getLon().equals(other.getLon()))
&& (this.getLat() == null ? other.getLat() == null : this.getLat().equals(other.getLat()))
&& (this.getPoint() == null ? other.getPoint() == null : this.getPoint().equals(other.getPoint()))
&& (this.getGeom() == null ? other.getGeom() == null : this.getGeom().equals(other.getGeom()))
&& (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
}
@@ -108,7 +108,7 @@ public class XianSubwayStations {
result = prime * result + ((getPointOtherDefenses() == null) ? 0 : getPointOtherDefenses().hashCode());
result = prime * result + ((getLon() == null) ? 0 : getLon().hashCode());
result = prime * result + ((getLat() == null) ? 0 : getLat().hashCode());
result = prime * result + ((getPoint() == null) ? 0 : getPoint().hashCode());
result = prime * result + ((getGeom() == null) ? 0 : getGeom().hashCode());
result = prime * result + ((getIsDelete() == null) ? 0 : getIsDelete().hashCode());
return result;
}
@@ -129,7 +129,7 @@ public class XianSubwayStations {
sb.append(", pointOtherDefenses=").append(pointOtherDefenses);
sb.append(", lon=").append(lon);
sb.append(", lat=").append(lat);
sb.append(", point=").append(point);
sb.append(", geom=").append(geom);
sb.append(", isDelete=").append(isDelete);
sb.append("]");
return sb.toString();
@@ -4,12 +4,30 @@ import lombok.Getter;
@Getter
public enum DisasterTypeEnum {
RAINSTORM("rainstorm"),
EARTHQUAKE("earthquake");
// 具体灾害类型
LANDSLIDE("landslide", "滑坡"),
COLLAPSE("collapse", "崩塌"),
DEBRIS_FLOW("debris_flow", "泥石流"),
FLASH_FLOOD("flash_flood", "山洪"),
WATER_LOGGING("water_logging", "内涝");
private final String type;
private final String description;
DisasterTypeEnum(String type) {
DisasterTypeEnum(String type, String description) {
this.type = type;
this.description = description;
}
/**
* 根据type获取枚举
*/
public static DisasterTypeEnum getByType(String type) {
for (DisasterTypeEnum e : values()) {
if (e.getType().equals(type)) {
return e;
}
}
return null;
}
}
@@ -3,6 +3,7 @@ package com.gis.xian.filter;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.gis.xian.config.CryptoProperties;
import com.gis.xian.utils.PathMatcherUtils;
import com.gis.xian.utils.safety.SM2Utils;
import com.gis.xian.utils.safety.SM4Utils;
import com.gis.xian.wrapper.Sm4KeyHolder;
@@ -85,15 +86,10 @@ public class DecryptFilter implements Filter {
}
/**
* 检查是否为无需解密的路径
* 检查是否为无需解密的路径(支持通配符匹配)
*/
private boolean isNoDecryptPath(String requestUri) {
for (String path : cryptoProperties.getNoDecryptPaths()) {
if (requestUri.contains(path)) {
return true;
}
}
return false;
return PathMatcherUtils.matches(requestUri, cryptoProperties.getNoDecryptPaths());
}
/**
@@ -13,6 +13,7 @@ import java.util.List;
public interface XianHiddenDangerSpotsMapper {
/**
* 获取所有基础点:滑坡、泥石流、山洪、内涝
* @param disasterType 具体灾害类型(landslide-滑坡, debris_flow-泥石流, flash_flood-山洪, water_logging-内涝),可选
* @return 基础点列表
*/
List<XianHiddenDangerSpots> getBasePoints(String disasterType);
@@ -0,0 +1,21 @@
package com.gis.xian.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @author wzy
* @description 针对表【xian_inference_result(预测结果表)】的数据库操作Mapper
* @createDate 2026-06-17 11:58:32
* @Entity com.gis.xian.entity.XianInferenceResult
*/
@Mapper
public interface XianInferenceResultMapper {
/**
* 根据id和pointId获取概率
* @param id 预测结果id
* @param pointId 隐患点/风险点id和类型
* @return 预测概率
*/
String getProbabilityByIdAndPointId(@Param("id") Long id, @Param("pointId") String pointId);
}
@@ -0,0 +1,21 @@
package com.gis.xian.service;
import com.gis.xian.vo.RainfallGridVo;
/**
* 降雨网格服务接口
*/
public interface RainfallGridService {
/**
* 从 Redis 获取降雨网格数据
* @return 降雨网格数据
*/
RainfallGridVo getRainfallGridData();
/**
* 获取当前的降雨站点标识符
* @return 标识符
*/
String getCurrentIdentifier();
}
@@ -9,6 +9,7 @@ public interface XianHiddenDangerSpotsService {
/**
* 获取所有基础点:滑坡、泥石流、山洪、内涝
* @param disasterType 具体灾害类型(landslide-滑坡, debris_flow-泥石流, flash_flood-山洪, water_logging-内涝),可选
* @return 基础点列表
*/
List<XianHiddenDangerSpotsBasePointVo> getBasePoints(String disasterType);
@@ -16,7 +17,8 @@ public interface XianHiddenDangerSpotsService {
/**
* 根据id获取隐患点详情
* @param id 隐患点id
* @param simulationId 模拟id
* @return 隐患点详情
*/
XianHiddenDangerSpotsPointDetailVo getPointDetailById(Long id);
XianHiddenDangerSpotsPointDetailVo getPointDetailById(Long id, Long simulationId);
}
@@ -15,7 +15,8 @@ public interface XianRiskSpotsService {
/**
* 根据id获取风险点详情
* @param id 风险点id
* @param simulationId 模拟id
* @return 风险点详情
*/
XianRiskSpotsPointDetailVo getPointDetailById(Long id);
XianRiskSpotsPointDetailVo getPointDetailById(Long id, Long simulationId);
}
@@ -2,9 +2,9 @@ package com.gis.xian.service.impl;
import com.alibaba.fastjson2.JSON;
import com.gis.xian.entity.XianHiddenDangerSpots;
import com.gis.xian.mapper.XianInferenceResultMapper;
import com.gis.xian.vo.XianHiddenDangerSpotsBasePointVo;
import com.gis.xian.vo.XianHiddenDangerSpotsPointDetailVo;
import com.gis.xian.enums.DisasterTypeEnum;
import com.gis.xian.mapper.XianHiddenDangerSpotsMapper;
import com.gis.xian.service.XianHiddenDangerSpotsService;
import jakarta.annotation.Resource;
@@ -23,39 +23,80 @@ public class IXianHiddenDangerSpotsServiceImpl implements XianHiddenDangerSpotsS
@Resource
private XianHiddenDangerSpotsMapper xianHiddenDangerSpotsMapper;
@Value("${init.data.base-points.hidden-danger.rainstorm}")
private String rainstormBasePointsKey;
@Resource
private XianInferenceResultMapper xianInferenceResultMapper;
@Value("${init.data.base-points.hidden-danger.earthquake}")
private String earthquakeBasePointsKey;
@Value("${init.data.base-points.hidden-danger.all}")
private String allBasePointsKey;
@Value("${init.data.base-points.hidden-danger.landslide}")
private String landslideKey;
@Value("${init.data.base-points.hidden-danger.collapse}")
private String collapseKey;
@Value("${init.data.base-points.hidden-danger.debris-flow}")
private String debrisFlowKey;
@Value("${init.data.base-points.hidden-danger.flash-flood}")
private String flashFloodKey;
@Value("${init.data.base-points.hidden-danger.water-logging}")
private String waterLoggingKey;
@Override
public List<XianHiddenDangerSpotsBasePointVo> getBasePoints(String disasterType) {
// 构建Redis key
String redisKey = buildRedisKey(disasterType);
// 从redis中读取基础点信息
Object data = null;
if(DisasterTypeEnum.RAINSTORM.getType().equals(disasterType)) {
data = redisTemplate.opsForValue().get(rainstormBasePointsKey);
}else {
data = redisTemplate.opsForValue().get(earthquakeBasePointsKey);
}
Object data = redisTemplate.opsForValue().get(redisKey);
if (data == null) {
List<XianHiddenDangerSpotsBasePointVo> basePoints = XianHiddenDangerSpotsBasePointVo.entity2Vo(xianHiddenDangerSpotsMapper.getBasePoints(disasterType));
if(DisasterTypeEnum.RAINSTORM.getType().equals(disasterType)) {
redisTemplate.opsForValue().set(rainstormBasePointsKey, JSON.toJSONString(basePoints));
}else {
redisTemplate.opsForValue().set(earthquakeBasePointsKey, JSON.toJSONString(basePoints));
}
// 从数据库查询
List<XianHiddenDangerSpotsBasePointVo> basePoints =
XianHiddenDangerSpotsBasePointVo.entity2Vo(xianHiddenDangerSpotsMapper.getBasePoints(disasterType));
// 存入Redis
redisTemplate.opsForValue().set(redisKey, JSON.toJSONString(basePoints));
return basePoints;
}
return JSON.parseArray(data.toString(), XianHiddenDangerSpotsBasePointVo.class);
}
/**
* 根据disasterType构建Redis key
*/
private String buildRedisKey(String disasterType) {
if (disasterType == null || disasterType.isEmpty()) {
return allBasePointsKey;
}
switch (disasterType) {
case "landslide":
return landslideKey;
case "collapse":
return collapseKey;
case "debris_flow":
return debrisFlowKey;
case "flash_flood":
return flashFloodKey;
case "water_logging":
return waterLoggingKey;
default:
return allBasePointsKey;
}
}
@Override
public XianHiddenDangerSpotsPointDetailVo getPointDetailById(Long id) {
return XianHiddenDangerSpotsPointDetailVo.entity2Vo(xianHiddenDangerSpotsMapper.getPointDetailById(id));
public XianHiddenDangerSpotsPointDetailVo getPointDetailById(Long id, Long simulationId) {
XianHiddenDangerSpotsPointDetailVo pointDetail = XianHiddenDangerSpotsPointDetailVo.entity2Vo(xianHiddenDangerSpotsMapper.getPointDetailById(id));
// 根据模拟id和id获取预测结果
if(simulationId != null && simulationId != -1L) {
pointDetail.setProbability(xianInferenceResultMapper.getProbabilityByIdAndPointId(simulationId, id + "_1") + "%");
}
return pointDetail;
}
}
@@ -1,6 +1,8 @@
package com.gis.xian.service.impl;
import com.alibaba.fastjson2.JSON;
import com.gis.xian.mapper.XianInferenceResultMapper;
import com.gis.xian.vo.XianHiddenDangerSpotsPointDetailVo;
import com.gis.xian.vo.XianRiskSpotsBasePointVo;
import com.gis.xian.vo.XianRiskSpotsPointDetailVo;
import com.gis.xian.mapper.XianRiskSpotsMapper;
@@ -21,6 +23,9 @@ public class IXianRiskSpotsServiceImpl implements XianRiskSpotsService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private XianInferenceResultMapper xianInferenceResultMapper;
@Value("${init.data.base-points.risk}")
private String riskPointKey;
@@ -39,7 +44,14 @@ public class IXianRiskSpotsServiceImpl implements XianRiskSpotsService {
}
@Override
public XianRiskSpotsPointDetailVo getPointDetailById(Long id) {
return XianRiskSpotsPointDetailVo.entity2Vo(xianRiskSpotsMapper.getPointDetailById(id));
public XianRiskSpotsPointDetailVo getPointDetailById(Long id, Long simulationId) {
XianRiskSpotsPointDetailVo pointDetail = XianRiskSpotsPointDetailVo.entity2Vo(xianRiskSpotsMapper.getPointDetailById(id));
// 根据模拟id和id获取预测结果
if(simulationId != null && simulationId != -1L) {
pointDetail.setProbability(xianInferenceResultMapper.getProbabilityByIdAndPointId(simulationId, id + "_2") + "%");
}
return pointDetail;
}
}
@@ -0,0 +1,173 @@
package com.gis.xian.service.impl;
import com.alibaba.fastjson2.JSON;
import com.gis.xian.config.RainfallGridProperties;
import com.gis.xian.service.RainfallGridService;
import com.gis.xian.service.ex.ServiceException;
import com.gis.xian.vo.RainfallGridVo;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
/**
* 降雨网格服务实现类
*/
@Service
public class RainfallGridServiceImpl implements RainfallGridService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private RainfallGridProperties rainfallGridProperties;
@Override
public RainfallGridVo getRainfallGridData() {
try {
String redisKey = rainfallGridProperties.getStationGrid();
Object gridDataObj = redisTemplate.opsForValue().get(redisKey);
if (gridDataObj == null) {
throw new ServiceException("降雨网格数据不存在,Redis Key: " + redisKey);
}
// 将 Redis 中的 JSON 字符串解析为 Map
String gridDataJson;
if (gridDataObj instanceof String) {
gridDataJson = (String) gridDataObj;
} else {
gridDataJson = JSON.toJSONString(gridDataObj);
}
// 解析 JSON 为 Map(下划线命名)
Map<String, Object> gridDataMap = JSON.parseObject(gridDataJson, Map.class);
// 转换为 RainfallGridVo(小驼峰命名)
return convertToVo(gridDataMap);
} catch (Exception e) {
throw new ServiceException("解析降雨网格数据失败: " + e.getMessage(), e);
}
}
@Override
public String getCurrentIdentifier() {
try {
String redisKey = rainfallGridProperties.getStationIdentifier();
Object identifierObj = redisTemplate.opsForValue().get(redisKey);
if (identifierObj == null) {
return null;
}
return identifierObj.toString();
} catch (Exception e) {
throw new ServiceException("获取降雨站点标识符失败: " + e.getMessage(), e);
}
}
/**
* 将 Map 转换为 RainfallGridVo
*/
@SuppressWarnings("unchecked")
private RainfallGridVo convertToVo(Map<String, Object> gridDataMap) {
RainfallGridVo vo = new RainfallGridVo();
// 基本字段
vo.setId(getLongValue(gridDataMap, "id"));
vo.setPngPath((String) gridDataMap.get("png_path"));
vo.setResolution(getDoubleValue(gridDataMap, "resolution"));
vo.setStationCount(getIntValue(gridDataMap, "station_count"));
// 解析 query_time
String queryTimeStr = (String) gridDataMap.get("query_time");
if (queryTimeStr != null) {
vo.setQueryTime(LocalDateTime.parse(
queryTimeStr.replace(" ", "T"),
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")
));
}
// 解析 cesium_config
Map<String, Object> cesiumConfigMap = (Map<String, Object>) gridDataMap.get("cesium_config");
if (cesiumConfigMap != null) {
vo.setCesiumConfig(parseCesiumConfig(cesiumConfigMap));
}
return vo;
}
/**
* 解析 Cesium 配置
*/
@SuppressWarnings("unchecked")
private RainfallGridVo.CesiumConfig parseCesiumConfig(Map<String, Object> cesiumConfigMap) {
RainfallGridVo.CesiumConfig cesiumConfig = new RainfallGridVo.CesiumConfig();
cesiumConfig.setWidth(getDoubleValue(cesiumConfigMap, "width"));
cesiumConfig.setHeight(getDoubleValue(cesiumConfigMap, "height"));
// 解析 rectangle
Map<String, Object> rectangleMap = (Map<String, Object>) cesiumConfigMap.get("rectangle");
if (rectangleMap != null) {
cesiumConfig.setRectangle(parseRectangle(rectangleMap));
}
return cesiumConfig;
}
/**
* 解析矩形区域
*/
private RainfallGridVo.CesiumConfig.Rectangle parseRectangle(Map<String, Object> rectangleMap) {
RainfallGridVo.CesiumConfig.Rectangle rectangle = new RainfallGridVo.CesiumConfig.Rectangle();
rectangle.setWest(getDoubleValue(rectangleMap, "west"));
rectangle.setSouth(getDoubleValue(rectangleMap, "south"));
rectangle.setEast(getDoubleValue(rectangleMap, "east"));
rectangle.setNorth(getDoubleValue(rectangleMap, "north"));
return rectangle;
}
/**
* 辅助方法:从 Map 中获取 Long 值
*/
private Long getLongValue(Map<String, Object> map, String key) {
Object value = map.get(key);
if (value == null) {
return null;
}
if (value instanceof Number) {
return ((Number) value).longValue();
}
return Long.parseLong(value.toString());
}
/**
* 辅助方法:从 Map 中获取 Double 值
*/
private Double getDoubleValue(Map<String, Object> map, String key) {
Object value = map.get(key);
if (value == null) {
return null;
}
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
return Double.parseDouble(value.toString());
}
/**
* 辅助方法:从 Map 中获取 Integer 值
*/
private Integer getIntValue(Map<String, Object> map, String key) {
Object value = map.get(key);
if (value == null) {
return null;
}
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
}
@@ -1,7 +1,6 @@
package com.gis.xian.task;
import com.alibaba.fastjson2.JSON;
import com.gis.xian.enums.DisasterTypeEnum;
import com.gis.xian.mapper.*;
import com.gis.xian.vo.*;
import jakarta.annotation.Resource;
@@ -58,11 +57,23 @@ public class InitializeData {
@Resource
RedisTemplate<String, Object> redisTemplate;
@Value("${init.data.base-points.hidden-danger.rainstorm}")
private String rainstormBasePointsKey;
@Value("${init.data.base-points.hidden-danger.all}")
private String allBasePointsKey;
@Value("${init.data.base-points.hidden-danger.earthquake}")
private String earthquakeBasePointsKey;
@Value("${init.data.base-points.hidden-danger.landslide}")
private String landslideKey;
@Value("${init.data.base-points.hidden-danger.collapse}")
private String collapseKey;
@Value("${init.data.base-points.hidden-danger.debris-flow}")
private String debrisFlowKey;
@Value("${init.data.base-points.hidden-danger.flash-flood}")
private String flashFloodKey;
@Value("${init.data.base-points.hidden-danger.water-logging}")
private String waterLoggingKey;
@Value("${init.data.base-points.risk}")
private String riskBasePointsKey;
@@ -99,22 +110,65 @@ public class InitializeData {
public void init() {
log.info("开始初始化数据");
// 并行执行所有数据库查询和Redis写入
CompletableFuture<Void> rainstormFuture = CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(rainstormBasePointsKey, JSON.toJSONString(
// 隐患点 - 总体
CompletableFuture<Void> allFuture = CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(allBasePointsKey, JSON.toJSONString(
XianHiddenDangerSpotsBasePointVo.entity2Vo(
xianHiddenDangerSpotsMapper.getBasePoints(DisasterTypeEnum.RAINSTORM.getType()))
xianHiddenDangerSpotsMapper.getBasePoints(null))
)
);
log.info("加载暴雨隐患点信息并写入redis完成");
log.info("加载隐患点信息(总体)并写入redis完成");
});
// 隐患点 - 滑坡
CompletableFuture<Void> landslideFuture = CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(landslideKey, JSON.toJSONString(
XianHiddenDangerSpotsBasePointVo.entity2Vo(
xianHiddenDangerSpotsMapper.getBasePoints("landslide"))
)
);
log.info("加载隐患点信息(滑坡)并写入redis完成");
});
CompletableFuture<Void> earthquakeFuture = CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(earthquakeBasePointsKey, JSON.toJSONString(
// 隐患点 - 崩塌
CompletableFuture<Void> collapseFuture = CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(collapseKey, JSON.toJSONString(
XianHiddenDangerSpotsBasePointVo.entity2Vo(
xianHiddenDangerSpotsMapper.getBasePoints(DisasterTypeEnum.EARTHQUAKE.getType()))
xianHiddenDangerSpotsMapper.getBasePoints("collapse"))
)
);
log.info("加载地震隐患点信息并写入redis完成");
log.info("加载隐患点信息(崩塌)并写入redis完成");
});
// 隐患点 - 泥石流
CompletableFuture<Void> debrisFlowFuture = CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(debrisFlowKey, JSON.toJSONString(
XianHiddenDangerSpotsBasePointVo.entity2Vo(
xianHiddenDangerSpotsMapper.getBasePoints("debris_flow"))
)
);
log.info("加载隐患点信息(泥石流)并写入redis完成");
});
// 隐患点 - 山洪
CompletableFuture<Void> flashFloodFuture = CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(flashFloodKey, JSON.toJSONString(
XianHiddenDangerSpotsBasePointVo.entity2Vo(
xianHiddenDangerSpotsMapper.getBasePoints("flash_flood"))
)
);
log.info("加载隐患点信息(山洪)并写入redis完成");
});
// 隐患点 - 内涝
CompletableFuture<Void> waterLoggingFuture = CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(waterLoggingKey, JSON.toJSONString(
XianHiddenDangerSpotsBasePointVo.entity2Vo(
xianHiddenDangerSpotsMapper.getBasePoints("water_logging"))
)
);
log.info("加载隐患点信息(内涝)并写入redis完成");
});
CompletableFuture<Void> riskFuture = CompletableFuture.runAsync(() -> {
@@ -209,7 +263,9 @@ public class InitializeData {
// 等待所有任务完成
CompletableFuture.allOf(
rainstormFuture, earthquakeFuture, riskFuture, hospitalsFuture,
allFuture, landslideFuture, collapseFuture, debrisFlowFuture,
flashFloodFuture, waterLoggingFuture,
riskFuture, hospitalsFuture,
dangerousSourceFuture, emergencyShelterFuture, firefighterFuture, storePointsFuture, schoolFuture,
bridgeFuture, reservoirFuture, subwayFuture
).join();
@@ -0,0 +1,38 @@
package com.gis.xian.utils;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import java.util.List;
/**
* 路径匹配工具类
* 支持 Ant 风格通配符:
* - ? 匹配一个字符
* - * 匹配零个或多个字符(不包括路径分隔符)
* - ** 匹配零个或多个目录
*/
public class PathMatcherUtils {
private static final PathMatcher pathMatcher = new AntPathMatcher();
/**
* 检查请求路径是否匹配给定的模式列表
*
* @param requestUri 请求URI
* @param patterns 通配符模式列表
* @return 如果匹配返回true,否则返回false
*/
public static boolean matches(String requestUri, List<String> patterns) {
if (patterns == null || patterns.isEmpty()) {
return false;
}
for (String pattern : patterns) {
if (pathMatcher.match(pattern, requestUri)) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,44 @@
package com.gis.xian.vo;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class RainfallGridVo {
public RainfallGridVo() {
this.cesiumConfig = new CesiumConfig();
}
private Long id;
private String pngPath;
private LocalDateTime queryTime;
private Double resolution;
private Integer stationCount;
private CesiumConfig cesiumConfig;
@Data
public static class CesiumConfig {
public CesiumConfig() {
this.rectangle = new Rectangle();
}
private Rectangle rectangle;
private Double width;
private Double height;
@Data
public static class Rectangle {
public Rectangle() {
this.west = 0.0;
this.south = 0.0;
this.east = 0.0;
this.north = 0.0;
}
private Double west;
private Double south;
private Double east;
private Double north;
}
}
}
@@ -23,6 +23,11 @@ public class XianBridgeBasePointVo {
*/
private String bridgeName;
/**
* 通用名称字段(用于统一访问)
*/
private String name;
/**
* 经度
*/
@@ -37,17 +42,18 @@ public class XianBridgeBasePointVo {
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
XianBridgeBasePointVo that = (XianBridgeBasePointVo) o;
return Objects.equals(id, that.id) && Objects.equals(bridgeName, that.bridgeName) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
return Objects.equals(id, that.id) && Objects.equals(bridgeName, that.bridgeName) && Objects.equals(name, that.name) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
}
@Override
public int hashCode() {
return Objects.hash(id, bridgeName, lon, lat);
return Objects.hash(id, bridgeName, name, lon, lat);
}
public static XianBridgeBasePointVo entity2Vo(XianBridge entity) {
XianBridgeBasePointVo vo = new XianBridgeBasePointVo();
vo.setId(entity.getId());
vo.setBridgeName(entity.getBridgeName());
vo.setName(entity.getBridgeName()); // 设置通用name字段
vo.setLon(entity.getLon() != null ? entity.getLon().doubleValue() : null);
vo.setLat(entity.getLat() != null ? entity.getLat().doubleValue() : null);
return vo;
@@ -22,6 +22,11 @@ public class XianFirefighterBasePointVo {
*/
private String teamName;
/**
* 通用名称字段(用于统一访问)
*/
private String name;
/**
* 经度
@@ -37,6 +42,7 @@ public class XianFirefighterBasePointVo {
XianFirefighterBasePointVo vo = new XianFirefighterBasePointVo();
vo.setId(entity.getId());
vo.setTeamName(entity.getTeamName());
vo.setName(entity.getTeamName()); // 设置通用name字段
vo.setLon(entity.getLon() != null ? entity.getLon().doubleValue() : null);
vo.setLat(entity.getLat() != null ? entity.getLat().doubleValue() : null);
return vo;
@@ -55,11 +61,11 @@ public class XianFirefighterBasePointVo {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
XianFirefighterBasePointVo that = (XianFirefighterBasePointVo) o;
return Objects.equals(id, that.id) && Objects.equals(teamName, that.teamName) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
return Objects.equals(id, that.id) && Objects.equals(teamName, that.teamName) && Objects.equals(name, that.name) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
}
@Override
public int hashCode() {
return Objects.hash(id, teamName,lon, lat);
return Objects.hash(id, teamName, name, lon, lat);
}
}
@@ -22,6 +22,11 @@ public class XianHiddenDangerSpotsBasePointVo {
* 灾害点名称
*/
private String disasterName;
/**
* 通用名称字段(用于统一访问)
*/
private String name;
/**
* 经度
*/
@@ -36,6 +41,7 @@ public class XianHiddenDangerSpotsBasePointVo {
XianHiddenDangerSpotsBasePointVo vo = new XianHiddenDangerSpotsBasePointVo();
vo.setId(entity.getId());
vo.setDisasterName(entity.getDisasterName());
vo.setName(entity.getDisasterName()); // 设置通用name字段
vo.setLon(entity.getLon());
vo.setLat(entity.getLat());
vo.setDisasterType(entity.getDisasterType());
@@ -60,11 +66,11 @@ public class XianHiddenDangerSpotsBasePointVo {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
XianHiddenDangerSpotsBasePointVo that = (XianHiddenDangerSpotsBasePointVo) o;
return Objects.equals(id, that.id) && Objects.equals(disasterName, that.disasterName) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat) && Objects.equals(disasterType, that.disasterType);
return Objects.equals(id, that.id) && Objects.equals(disasterName, that.disasterName) && Objects.equals(name, that.name) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat) && Objects.equals(disasterType, that.disasterType);
}
@Override
public int hashCode() {
return Objects.hash(id, disasterName, lon, lat, disasterType);
return Objects.hash(id, disasterName, name, lon, lat, disasterType);
}
}
@@ -9,6 +9,11 @@ import java.util.Objects;
@Data
public class XianHiddenDangerSpotsPointDetailVo {
/**
* 概率
*/
private String probability;
/**
* 序号
*/
@@ -23,6 +23,11 @@ public class XianReservoirListBasePointVo {
*/
private String reservoirName;
/**
* 通用名称字段(用于统一访问)
*/
private String name;
/**
* 经度
*/
@@ -37,6 +42,7 @@ public class XianReservoirListBasePointVo {
XianReservoirListBasePointVo vo = new XianReservoirListBasePointVo();
vo.setId(entity.getId());
vo.setReservoirName(entity.getReservoirName());
vo.setName(entity.getReservoirName()); // 设置通用name字段
vo.setLon(entity.getLon());
vo.setLat(entity.getLat());
return vo;
@@ -55,12 +61,12 @@ public class XianReservoirListBasePointVo {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
XianReservoirListBasePointVo that = (XianReservoirListBasePointVo) o;
return Objects.equals(id, that.id) && Objects.equals(reservoirName, that.reservoirName)
return Objects.equals(id, that.id) && Objects.equals(reservoirName, that.reservoirName) && Objects.equals(name, that.name)
&& Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
}
@Override
public int hashCode() {
return Objects.hash(id, reservoirName, lon, lat);
return Objects.hash(id, reservoirName, name, lon, lat);
}
}
@@ -19,6 +19,11 @@ public class XianRiskSpotsBasePointVo {
*/
private String riskName;
/**
* 通用名称字段(用于统一访问)
*/
private String name;
/**
* 经度
*/
@@ -33,6 +38,7 @@ public class XianRiskSpotsBasePointVo {
XianRiskSpotsBasePointVo vo = new XianRiskSpotsBasePointVo();
vo.setId(entity.getId());
vo.setRiskName(entity.getRiskName());
vo.setName(entity.getRiskName()); // 设置通用name字段
vo.setLon(entity.getLon());
vo.setLat(entity.getLat());
return vo;
@@ -51,11 +57,11 @@ public class XianRiskSpotsBasePointVo {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
XianRiskSpotsBasePointVo that = (XianRiskSpotsBasePointVo) o;
return Objects.equals(id, that.id) && Objects.equals(riskName, that.riskName) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
return Objects.equals(id, that.id) && Objects.equals(riskName, that.riskName) && Objects.equals(name, that.name) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
}
@Override
public int hashCode() {
return Objects.hash(id, riskName, lon, lat);
return Objects.hash(id, riskName, name, lon, lat);
}
}
@@ -9,6 +9,11 @@ import java.util.Objects;
@Data
public class XianRiskSpotsPointDetailVo {
/**
* 概率
*/
private String probability;
/**
* 序号
*/
@@ -23,6 +23,11 @@ public class XianSchoolBasePointVo {
*/
private String schoolName;
/**
* 通用名称字段(用于统一访问)
*/
private String name;
/**
* 经度
*/
@@ -37,6 +42,7 @@ public class XianSchoolBasePointVo {
XianSchoolBasePointVo vo = new XianSchoolBasePointVo();
vo.setId(entity.getId());
vo.setSchoolName(entity.getSchoolName());
vo.setName(entity.getSchoolName()); // 设置通用name字段
vo.setLon(entity.getLon());
vo.setLat(entity.getLat());
return vo;
@@ -55,11 +61,11 @@ public class XianSchoolBasePointVo {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
XianSchoolBasePointVo that = (XianSchoolBasePointVo) o;
return Objects.equals(id, that.id) && Objects.equals(schoolName, that.schoolName) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
return Objects.equals(id, that.id) && Objects.equals(schoolName, that.schoolName) && Objects.equals(name, that.name) && Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
}
@Override
public int hashCode() {
return Objects.hash(id, schoolName, lon, lat);
return Objects.hash(id, schoolName, name, lon, lat);
}
}
@@ -23,6 +23,11 @@ public class XianSubwayStationsBasePointVo {
*/
private String stationName;
/**
* 通用名称字段(用于统一访问)
*/
private String name;
/**
* 经度
*/
@@ -37,6 +42,7 @@ public class XianSubwayStationsBasePointVo {
XianSubwayStationsBasePointVo vo = new XianSubwayStationsBasePointVo();
vo.setId(entity.getId());
vo.setStationName(entity.getStationName());
vo.setName(entity.getStationName()); // 设置通用name字段
vo.setLon(entity.getLon());
vo.setLat(entity.getLat());
return vo;
@@ -55,12 +61,12 @@ public class XianSubwayStationsBasePointVo {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
XianSubwayStationsBasePointVo that = (XianSubwayStationsBasePointVo) o;
return Objects.equals(id, that.id) && Objects.equals(stationName, that.stationName)
return Objects.equals(id, that.id) && Objects.equals(stationName, that.stationName) && Objects.equals(name, that.name)
&& Objects.equals(lon, that.lon) && Objects.equals(lat, that.lat);
}
@Override
public int hashCode() {
return Objects.hash(id, stationName, lon, lat);
return Objects.hash(id, stationName, name, lon, lat);
}
}
@@ -2,6 +2,7 @@ package com.gis.xian.wrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gis.xian.config.CryptoProperties;
import com.gis.xian.utils.PathMatcherUtils;
import com.gis.xian.utils.safety.SM4Utils;
import jakarta.annotation.Resource;
import org.springframework.core.MethodParameter;
@@ -29,7 +30,7 @@ public class EncryptResponseAdvice implements ResponseBodyAdvice<Object> {
private CryptoProperties cryptoProperties;
/**
* 判断是否需要加密:排除特定路径,其余全部加密
* 判断是否需要加密:排除特定路径,其余全部加密(支持通配符匹配)
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
@@ -41,19 +42,12 @@ public class EncryptResponseAdvice implements ResponseBodyAdvice<Object> {
HttpServletRequest request = attributes.getRequest();
String requestUri = request.getRequestURI();
// 检查是否为无需加密的路径
for (String path : cryptoProperties.getNoEncryptPaths()) {
if (requestUri.contains(path)) {
return false; // 排除路径,不加密
}
}
// 其余路径均需要加密
return true;
// 检查是否为无需加密的路径(支持通配符)
return !PathMatcherUtils.matches(requestUri, cryptoProperties.getNoEncryptPaths());
}
/**
* 响应体加密逻辑(保持不变)
* 响应体加密逻辑
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
@@ -61,15 +55,17 @@ public class EncryptResponseAdvice implements ResponseBodyAdvice<Object> {
ServerHttpRequest request, ServerHttpResponse response) {
try {
String sm4Key = Sm4KeyHolder.getSm4Key();
// 如果SM4密钥不存在,直接返回原始数据(不加密)
if (sm4Key == null || sm4Key.length() != 32) {
throw new RuntimeException("SM4密钥不存在或格式错误,无法加密响应");
return body;
}
String plaintext = objectMapper.writeValueAsString(body);
String encryptedText = SM4Utils.encrypt(sm4Key, plaintext);
return encryptedText;
} catch (Exception e) {
throw new RuntimeException("响应数据加密失败: " + e.getMessage(), e);
// 加密失败时返回原始数据,避免影响业务
return body;
} finally {
Sm4KeyHolder.clear(); // 清除线程本地存储,避免内存泄漏
}
+11 -1
View File
@@ -41,7 +41,17 @@ safety:
no-encrypt-paths:
- /crypto/sm2/public-key
- /druid
- /websocket/info
- /websocket/**
# 请求无需解密的路径
no-decrypt-paths:
- /crypto/sm2/public-key
- /druid
- /druid
- /websocket/info
- /websocket/**
# 算法服务器配置
algorithm:
server:
# 开发环境算法服务器地址
url: http://localhost:8082
+9 -1
View File
@@ -41,6 +41,14 @@ safety:
# 响应无需加密的路径
no-encrypt-paths:
- /crypto/sm2/public-key
- /websocket/**
# 请求无需解密的路径
no-decrypt-paths:
- /crypto/sm2/public-key
- /crypto/sm2/public-key
- /websocket/**
# 算法服务器配置
algorithm:
server:
# 生产环境算法服务器地址
url: http://localhost:8081
+2 -2
View File
@@ -7,7 +7,7 @@ spring:
# MyBatis 配置
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.gis.basic_template_not_login_back.entity
mapper-locations: classpath:com/gis/xian/mapper/*.xml
type-aliases-package: com.gis.xian.entity
configuration:
map-underscore-to-camel-case: true
@@ -25,19 +25,31 @@
<result property="isDelete" column="is_delete" />
</resultMap>
<!-- 获取所有基础点:滑坡、泥石流、山洪、内涝 -->
<!-- 获取所有基础点:滑坡、崩塌、泥石流、山洪、内涝 -->
<select id="getBasePoints" resultMap="XianHiddenDangerSpotsResultMap">
SELECT id, disaster_name, lon, lat, disaster_type FROM xian_hidden_danger_spots
<where>
<choose>
<when test='disasterType == "rainstorm"'>
disaster_type IN('滑坡', '泥石流', '山洪', '内涝')
</when>
<otherwise>
disaster_type IN('滑坡', '泥石流')
</otherwise>
</choose>
AND is_delete = 0
is_delete = 0
AND disaster_type IN('滑坡', '崩塌', '泥石流', '山洪', '内涝')
<if test="disasterType != null and disasterType != ''">
<choose>
<when test="disasterType == 'landslide'">
AND disaster_type = '滑坡'
</when>
<when test="disasterType == 'collapse'">
AND disaster_type = '崩塌'
</when>
<when test="disasterType == 'debris_flow'">
AND disaster_type = '泥石流'
</when>
<when test="disasterType == 'flash_flood'">
AND disaster_type = '山洪'
</when>
<when test="disasterType == 'water_logging'">
AND disaster_type = '内涝'
</when>
</choose>
</if>
</where>
</select>
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gis.xian.mapper.XianInferenceResultMapper">
<resultMap id="XianInferenceResultResultMap" type="com.gis.xian.entity.XianInferenceResult">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="eventType" column="event_type" />
<result property="occurredTime" column="occurred_time" />
<result property="operationType" column="operation_type" />
<result property="result" column="result" />
<result property="condition" column="condition" />
<result property="filePath" column="file_path" />
<result property="createTime" column="create_time" />
<result property="isDelete" column="is_delete" />
</resultMap>
<!-- 根据id和pointId获取概率 -->
<select id="getProbabilityByIdAndPointId" resultType="java.lang.String">
SELECT result->>#{pointId} FROM xian_inference_result
<where>
id = #{id}
</where>
</select>
</mapper>
@@ -17,15 +17,15 @@
<result property="projectScale" column="project_scale" />
<result property="hasHiddenDanger" column="has_hidden_danger" />
<result property="note1" column="note1" />
<result property="lon" column="longitude" />
<result property="lat" column="latitude" />
<result property="lon" column="lon" />
<result property="lat" column="lat" />
<result property="geom" column="geom" />
<result property="isDelete" column="is_delete" />
</resultMap>
<!-- 获取所有水库基础点 -->
<select id="getBasePoints" resultMap="BaseResultMap">
SELECT id, reservoir_name, longitude, latitude FROM xian_reservoir_list
SELECT id, reservoir_name, lon, lat FROM xian_reservoir_list
<where>
is_delete = 0
</where>
@@ -33,7 +33,7 @@
<!-- 根据id获取水库详情 -->
<select id="getPointDetailById" resultMap="BaseResultMap">
SELECT id, reservoir_name, location, safety_assess_result, longitude, latitude FROM xian_reservoir_list
SELECT id, reservoir_name, location, safety_assess_result, lon, lat FROM xian_reservoir_list
<where>
id = #{id} AND is_delete = 0
</where>
+15 -2
View File
@@ -5,14 +5,27 @@ safety:
global: 'xian:sm2:keypair:global'
# 降雨网格数据
rainfall:
grid:
# 降雨站点网格数据
station-grid: 'xian:rainfall:rain_station_grid'
# 降雨站点标识符
station-identifier: 'xian:rainfall:rain_station_identifier'
# 初始化数据存储
init:
data:
# 基础信息点数据:滑坡、泥石流、山洪、内涝
base-points:
hidden-danger:
rainstorm: 'xian:init:data:base-points:hidden-danger:rainstorm'
earthquake: 'xian:init:data:base-points:hidden-danger:earthquake'
all: 'xian:init:data:base-points:hidden-danger:all'
landslide: 'xian:init:data:base-points:hidden-danger:landslide'
collapse: 'xian:init:data:base-points:hidden-danger:collapse'
debris-flow: 'xian:init:data:base-points:hidden-danger:debris_flow'
flash-flood: 'xian:init:data:base-points:hidden-danger:flash_flood'
water-logging: 'xian:init:data:base-points:hidden-danger:water_logging'
risk: 'xian:init:data:base-points:risk'
hospitals: 'xian:init:data:base-points:hospitals'
dangerous-source: 'xian:init:data:base-points:dangerous-source'