Spring MVC中REST API字典字段转ID的冗余代码优化咨询
消除字典转ID冗余代码的可行方案
1. 封装通用字典查询服务
- 抽象所有字典表的共性逻辑:无论
t_dict1/t_dict2/t_dict3,核心都是根据编码/名称查询对应ID,因此可以封装一个通用的字典服务层,统一处理查询、参数校验和转换失败的异常抛出。 - 通过
dictType参数区分不同字典表,在DAO层动态指定表名,避免为每张表写重复的查询方法。 - 示例代码:
// 通用字典服务类 @Service public class DictService { @Autowired private DictMapper dictMapper; public Long getDictId(String dictType, String codeOrName) { if (StringUtils.isBlank(codeOrName)) { throw new IllegalArgumentException("字典编码/名称不能为空"); } Long id = dictMapper.selectIdByCodeOrName(dictType, codeOrName); if (id == null) { throw new RuntimeException(String.format("字典[%s]不存在对应编码/名称: %s", dictType, codeOrName)); } return id; } } // 通用Mapper接口 @Mapper public interface DictMapper { @Select("SELECT id FROM ${dictType} WHERE code = #{codeOrName} OR name = #{codeOrName}") Long selectIdByCodeOrName(@Param("dictType") String dictType, @Param("codeOrName") String codeOrName); }
- 所有API只需调用
DictService.getDictId()方法,无需重复写校验、查询和异常处理代码。
2. 注解+AOP实现自动转换
- 定义自定义注解标记DTO中需要转换的字段,指定对应的字典类型:
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface DictConvert { String dictType(); // 对应t_dict1/t_dict2/t_dict3的标识 }
- 编写AOP切面,拦截API入参的DTO对象,自动扫描带有
@DictConvert的字段,调用通用字典服务完成转换,失败直接抛出异常。 - 示例切面逻辑:
@Aspect @Component public class DictConvertAspect { @Autowired private DictService dictService; @Before("execution(* com.yourpackage.api.*.*(..))") public void autoConvertDictParams(JoinPoint point) throws IllegalAccessException { Object[] args = point.getArgs(); for (Object arg : args) { if (arg == null) continue; Field[] fields = arg.getClass().getDeclaredFields(); for (Field field : fields) { DictConvert annotation = field.getAnnotation(DictConvert.class); if (annotation != null) { field.setAccessible(true); String codeOrName = (String) field.get(arg); Long id = dictService.getDictId(annotation.dictType(), codeOrName); field.set(arg, id); // 将字段值替换为对应ID } } } } }
- 后续新增API时,只需给DTO字段加
@DictConvert注解,无需手动编写转换代码,彻底消除冗余。
3. 策略模式适配差异化场景
- 如果不同字典表存在特殊查询逻辑(比如部分表需要额外过滤条件),可以用策略模式拆分转换逻辑:
- 定义统一的
DictConverter接口:Long convert(String codeOrName); - 为每张字典表实现对应的转换器(如
Dict1Converter、Dict2Converter),各自处理特殊逻辑 - 用工厂类根据
dictType获取对应转换器,统一对外提供转换服务
- 定义统一的
- 这种方式既避免了重复代码,又保留了各字典表的个性化处理空间。
4. 可选:缓存优化
- 把字典数据缓存到本地(如Guava Cache)或Redis中,减少数据库查询次数,缓存逻辑统一封装在通用字典服务里,无需在各API中重复实现。
内容的提问来源于stack exchange,提问作者smileis2333
相关产品推荐
相关产品推荐

