我知道这个领域已经有很多话题了,但是没有一个能让我满意的答案。我有以下端点和enum:
@RestController
public class MyController {
@PostMapping
public void doStuff(@RequestParam MyEnum myEnum){
...
}
}
public enum MyEnum {
PROPERTY_A("foo"),
PROPERTY_B("bar");
private String name;
MyEnum(String name) {
this.name = name;
}
}
我想注册一个自定义转换器,将foo和bar的字符串值转换为PROPERTY_A, PROPERTY_B的正确enum值。有些东西应该很容易解决,用一个简单的@Override在某个地方劫持标准转换器,无法转换这个,然而我看到的所有答案都要求你在三四个地方注册代码,这不是一个令人满意的答案。
应该很容易解决,用一个简单的
@Override
在某处劫持标准转换器
如果你说的标准转换器指的是MyEnum.valueOf(String)
方法,那么答案是你不能。
因为方法valueOf()
是static
而没有覆盖Java中static
方法的概念。更有趣的是,valueOf(String)
甚至不存在于隐式父类java.lang.Enum
中,它由编译器以及values()
方法在编译过程中添加到每个枚举中。
换句话说,您无法以任何方式控制valueOf(String)
方法。
3 - 4位的寄存器码
由于您的方法doStuff()
期望MyEnum
的实例,而您没有提到任何其他枚举类,我假设您只对将字符串转换为MyEnum
的成员感兴趣。您可以通过在MyEnum
中添加一个方法来实现这一点(不需要在多个地方引入新代码):
public enum MyEnum {
PROPERTY_A("foo"),
PROPERTY_B("bar");
private String name;
MyEnum(String name) {
this.name = name;
}
public static MyEnum getByName(String name) {
return Arrays.stream(values())
.filter(e -> e.name.equals(name))
.findFirst()
.orElseThrow(); // throw NoSuchElementException if no constant with a matching property has been found
}
}
方法getByName()
将抛出NoSuchElementException
,如果给定名称的enum-member不存在。
如果您对这样的行为不满意,您可以更改实现。例如,返回一个可选对象(这比返回null
更可取):
public static Optional<MyEnum> getByName(String name) {
return Arrays.stream(values())
.filter(e -> e.name.equals(name))
.findFirst();
}
或者您可以使用orElse()
代替orElseThrow()
来返回一个特定的枚举常量,这将表示缺少数据,即实现空对象模式。