Java枚举与DTO处理优化指南
作者:技术全栈探索
发布日期:2023年10月
引言:优化代码的必要性
在Java开发中,枚举类型与DTO(数据传输对象)的设计直接影响系统的可维护性和扩展性。本文针对用户提供的代码,提出关键优化点,涵盖枚举处理、MyBatis配置、Jackson序列化及参数校验等方面,助你构建更高效的微服务架构。
目录
1. 枚举查找优化
1.1 问题分析
原始代码通过遍历枚举值查找code,时间复杂度为O(n),不适用于枚举项较多的场景。
1.2 优化方案
使用静态Map缓存枚举实例,实现O(1)查找:
@Getter
@AllArgsConstructor
public enum OrderStatusEnum {
UNPAID(0, "未支付"),
PAID(1, "已支付");
private static final Map<Integer, OrderStatusEnum> CODE_MAP = new HashMap<>();
static {
for (OrderStatusEnum status : values()) {
CODE_MAP.put(status.getCode(), status);
}
}
private final Integer code;
private final String desc;
public static OrderStatusEnum getByCode(Integer code) {
return CODE_MAP.get(code);
}
}
2. 通用MyBatis类型处理器
2.1 定义通用接口
public interface CodeEnum {
Integer getCode();
}
2.2 实现通用类型处理器
@MappedTypes(CodeEnum.class)
public class GenericEnumTypeHandler<E extends Enum<E> & CodeEnum> extends BaseTypeHandler<E> {
private final Class<E> enumType;
private final Map<Integer, E> codeMap = new HashMap<>();
public GenericEnumTypeHandler(Class<E> enumType) {
this.enumType = enumType;
for (E constant : enumType.getEnumConstants()) {
codeMap.put(constant.getCode(), constant);
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getCode());
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
return codeMap.get(rs.getInt(columnName));
}
// 其他方法类似...
}
2.3 MyBatis配置
<result column="status" property="status"
typeHandler="com.example.handler.GenericEnumTypeHandler"/>
3. Jackson序列化简化
3.1 通用序列化器
public class CodeEnumSerializer extends JsonSerializer<CodeEnum> {
@Override
public void serialize(CodeEnum value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeNumber(value.getCode());
}
}
3.2 通用反序列化器
public class CodeEnumDeserializer extends JsonDeserializer<CodeEnum> {
@Override
public CodeEnum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode node = p.getCodec().readTree(p);
Class<? extends CodeEnum> enumClass = (Class<? extends CodeEnum>) ctxt.getContextualType().getRawClass();
int code = node.asInt();
for (CodeEnum enumConstant : enumClass.getEnumConstants()) {
if (enumConstant.getCode() == code) {
return enumConstant;
}
}
throw new IllegalArgumentException("Invalid code for " + enumClass.getSimpleName());
}
}
3.3 Jackson配置
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(CodeEnum.class, new CodeEnumSerializer());
module.addDeserializer(CodeEnum.class, new CodeEnumDeserializer());
mapper.registerModule(module);
return mapper;
}
4. 参数校验与日期处理
4.1 增强参数校验
@Data
public class HotelOrderPageReqDTO {
@NotNull(message = "用户ID不能为空")
@Schema(description = "用户ID", example = "123456")
private Long userId;
@PastOrPresent(message = "开始时间不能晚于当前时间")
@Schema(description = "开始时间", example = "2023-01-01")
private LocalDate startTime;
}
4.2 使用Java 8日期类型
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
5. Swagger注解规范
5.1 简化注解使用
@Schema(description = "订单状态", example = "1")
private OrderStatusEnum status;
6. 流程图完善
6.1 PlantUML完整示例
@startuml
start
:接收前端请求参数;
note right: 包含文本、数值、枚举等类型
:参数验证;
if (验证通过?) then (是)
else (否)
:返回错误信息;
stop
endif
:参数转换;
note left: 字符串→枚举\n字符串→日期
:构建查询条件;
note: 组合精确匹配、模糊查询、范围查询
:执行分页查询;
:结果转换;
note: 枚举→文本\n日期格式化
:返回分页结果;
stop
@enduml
总结与最佳实践
- 枚举优化:使用静态Map提升查找效率,通用接口减少冗余。
- 类型处理:通过泛型实现通用MyBatis和Jackson处理。
- 校验强化:结合Spring Validation确保数据合法性。
- 现代化日期:优先使用
LocalDate替代Date。 - 工具整合:利用PlantUML清晰展示业务流程。
动手实践:
- 在现有项目中应用通用
CodeEnum接口 - 使用PlantUML重新绘制关键流程图
- 为所有DTO添加参数校验注解
通过上述优化,系统代码将更简洁、高效且易于维护,为后续功能扩展奠定坚实基础!🚀