我的 Springboot 控制器的端点之一定义为:
@GetMapping(path = "/{custId}/items", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@AuthorizationValidationStrategy
public List<ItemDTO> getCustItemsByItemType(@PathVariable @SecureResource(CUST) Long custId, @RequestParam("itemType") List<ItemType> itemTypes) {
return this.myFeignClient.findItemsByCustIdAndItemTypes(custId, itemTypes);
}
其中
ItemType
是一个枚举,遵循我们部门的编码约定,因此所有枚举常量(“枚举实例”)都将被命名为 ALL_UPPER_CASE。
当查询指定大写的项目类型时,此端点效果很好。
如果项目类型指定为小写,那么 Spring 会立即抛出异常,在将其交给 Feign 客户端之前没有机会将其转为大写。这是预料之中的,我明白为什么。
有没有办法使这样的端点“灵活”,因为它可以同等地接受小写和大写枚举常量?
例如:
http://127.0.0.1:8080/1.0/custs/2/items?itemType=bread
http://127.0.0.1:8080/1.0/custs/2/items?itemType=BREAD
我实际上使用众所周知的
@JsonCreator
技术实现了这个枚举,虽然它的比较不区分大小写,但 HTTP 请求永远不会到达这个阶段。
在 Java 中,用大写字母定义枚举值被认为是很好的做法,因为它们是常量。但是,我们可能希望在请求 URL 中支持小写字母。
在这种情况下,我们需要创建一个自定义转换器:
public class StringToEnumConverter implements Converter<String, Modes> {
@Override
public Modes convert(String source) {
return Modes.valueOf(source.toUpperCase());
}
}
Modes 是我的枚举。您可以在此处替换为您的枚举。
要使用我们的自定义转换器,我们需要在 Spring 配置中注册它:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToEnumConverter());
}
}