chore: 项目环境升级为 JDK25,Spring 4.1,项目重构为多模块

This commit is contained in:
2026-09-08 15:02:18 +08:00
parent d392436620
commit 81a0d81f11
168 changed files with 2785 additions and 1375 deletions

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>tech.easyflow</groupId>
<artifactId>manuagent-parent</artifactId>
<version>0.1.0</version>
</parent>
<artifactId>manuagent-common</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,15 @@
package tech.easyflow.manuagent.common;
import java.time.Instant;
/**
* 统一接口错误响应。
*
* @param code 稳定错误码
* @param message 可理解错误信息
* @param traceId 日志关联标识
* @param timestamp 发生时间
*/
public record ApiError(String code, String message, String traceId, Instant timestamp) {
}

View File

@@ -0,0 +1,44 @@
package tech.easyflow.manuagent.common;
import org.springframework.http.HttpStatus;
/**
* 可安全返回给调用方的业务异常。
*/
public class ApiException extends RuntimeException {
private final HttpStatus status;
private final String code;
/**
* 创建业务异常。
*
* @param status HTTP 状态
* @param code 稳定错误码
* @param message 可操作错误说明
*/
public ApiException(HttpStatus status, String code, String message) {
super(message);
this.status = status;
this.code = code;
}
/**
* 返回 HTTP 状态。
*
* @return HTTP 状态
*/
public HttpStatus status() {
return status;
}
/**
* 返回稳定错误码。
*
* @return 错误码
*/
public String code() {
return code;
}
}

View File

@@ -0,0 +1,56 @@
package tech.easyflow.manuagent.common.typehandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
/**
* 将 JSON 文本映射到数据库的原生 JSON/JSONB 列。
*
* <p>当前 PostgreSQL 阶段使用 JDBC {@link Types#OTHER} 发送 JSON 文本,使驱动按目标列类型完成绑定,
* 避免在业务 SQL 中重复书写字符串拼接或手工创建驱动专有对象。未来适配国产数据库时,只需替换
* 该类型处理器或按数据库方言提供对应实现,实体和服务层无需感知。</p>
*/
@MappedTypes(String.class)
@MappedJdbcTypes(JdbcType.OTHER)
public class JsonbStringTypeHandler extends BaseTypeHandler<String> {
/**
* 以数据库原生扩展类型绑定非空 JSON 文本。
*
* @param statement 预编译语句
* @param index 参数位置
* @param parameter JSON 文本
* @param jdbcType MyBatis 推断的 JDBC 类型
* @throws SQLException 参数绑定失败时抛出
*/
@Override
public void setNonNullParameter(
PreparedStatement statement, int index, String parameter, JdbcType jdbcType) throws SQLException {
statement.setObject(index, parameter, Types.OTHER);
}
/** 按列名读取 JSON 文本。 */
@Override
public String getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
return resultSet.getString(columnName);
}
/** 按列序号读取 JSON 文本。 */
@Override
public String getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
return resultSet.getString(columnIndex);
}
/** 从存储过程结果读取 JSON 文本。 */
@Override
public String getNullableResult(CallableStatement statement, int columnIndex) throws SQLException {
return statement.getString(columnIndex);
}
}

View File

@@ -0,0 +1,98 @@
package tech.easyflow.manuagent.common.typehandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
/**
* 在 Java {@link UUID} 与数据库 UUID 值之间进行显式转换。
*
* <p>PostgreSQL 驱动读取 {@code uuid} 列时通常直接返回 {@link UUID},但不同驱动或查询表达式也可能
* 返回字符串。该处理器同时兼容两种结果,并通过 {@link PreparedStatement#setObject(int, Object)}
* 保留数据库驱动对原生 UUID 类型的绑定能力,避免把 UUID 降级成易产生隐式转换的 VARCHAR。</p>
*/
@MappedTypes(UUID.class)
@MappedJdbcTypes(value = JdbcType.OTHER, includeNullJdbcType = true)
public class UuidTypeHandler extends BaseTypeHandler<UUID> {
/**
* 将非空 UUID 作为驱动原生对象写入预编译语句。
*
* @param statement 预编译语句
* @param index 参数位置
* @param parameter 待写入的 UUID
* @param jdbcType MyBatis 推断的 JDBC 类型
* @throws SQLException 数据库驱动拒绝绑定参数时抛出
*/
@Override
public void setNonNullParameter(
PreparedStatement statement, int index, UUID parameter, JdbcType jdbcType) throws SQLException {
statement.setObject(index, parameter);
}
/**
* 按列名读取 UUID。
*
* @param resultSet 查询结果集
* @param columnName 列名
* @return UUID数据库值为空时返回 {@code null}
* @throws SQLException 读取或转换失败时抛出
*/
@Override
public UUID getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
return toUuid(resultSet.getObject(columnName));
}
/**
* 按列序号读取 UUID。
*
* @param resultSet 查询结果集
* @param columnIndex 列序号
* @return UUID数据库值为空时返回 {@code null}
* @throws SQLException 读取或转换失败时抛出
*/
@Override
public UUID getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
return toUuid(resultSet.getObject(columnIndex));
}
/**
* 从存储过程结果中读取 UUID。
*
* @param statement 存储过程调用语句
* @param columnIndex 列序号
* @return UUID数据库值为空时返回 {@code null}
* @throws SQLException 读取或转换失败时抛出
*/
@Override
public UUID getNullableResult(CallableStatement statement, int columnIndex) throws SQLException {
return toUuid(statement.getObject(columnIndex));
}
/**
* 统一处理驱动返回的 UUID 对象或字符串。
*
* @param value 驱动返回值
* @return 规范化后的 UUID空值返回 {@code null}
* @throws SQLException 返回值不是合法 UUID 时抛出并保留数据库访问语义
*/
private UUID toUuid(Object value) throws SQLException {
if (value == null) {
return null;
}
if (value instanceof UUID uuid) {
return uuid;
}
try {
return UUID.fromString(value.toString());
} catch (IllegalArgumentException exception) {
throw new SQLException("数据库返回了无法转换为 UUID 的值: " + value, exception);
}
}
}