Java枚举与DTO处理优化指南

108 阅读3分钟

image.png


Java枚举与DTO处理优化指南

作者:技术全栈探索
发布日期:2023年10月


引言:优化代码的必要性

在Java开发中,枚举类型与DTO(数据传输对象)的设计直接影响系统的可维护性和扩展性。本文针对用户提供的代码,提出关键优化点,涵盖枚举处理、MyBatis配置、Jackson序列化及参数校验等方面,助你构建更高效的微服务架构。


目录

  1. 枚举查找优化
  2. 通用MyBatis类型处理器
  3. Jackson序列化简化
  4. 参数校验与日期处理
  5. Swagger注解规范
  6. 流程图完善

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

总结与最佳实践

  1. 枚举优化:使用静态Map提升查找效率,通用接口减少冗余。
  2. 类型处理:通过泛型实现通用MyBatis和Jackson处理。
  3. 校验强化:结合Spring Validation确保数据合法性。
  4. 现代化日期:优先使用LocalDate替代Date
  5. 工具整合:利用PlantUML清晰展示业务流程。

动手实践

  • 在现有项目中应用通用CodeEnum接口
  • 使用PlantUML重新绘制关键流程图
  • 为所有DTO添加参数校验注解

通过上述优化,系统代码将更简洁、高效且易于维护,为后续功能扩展奠定坚实基础!🚀