适用于所有Enums的Spring自定义转换器

我已经使用int getID()MyEnum withID(int)方法构建了许多Enum类,这些方法允许我将ID专用于枚举值以用于持久性目的(从而避免由于关于外部存储的顺序/名称更改而导致的更改)枚举)。

我想构建一个自定义转换器来做一些reflection来查找这些方法,并在找不到它们时使用它们或备份到Ordinal / String转换。

一个通用的Enum转换器似乎对任何人都有可能吗? 这只是我第二次涉足转换器。

我会说你正试图解决错误的问题。 我通常坚持将字符串作为字符串,从而避免这个问题。 缺点当然是更大的DB字段,但这并不重要。


那说:

我会说这一般是可能的,但不是一个干净的方式。 我要做的是让所有这些枚举实现一个公共接口(只是一个标记接口或一个包含int getId()方法的接口)。 现在仅为此接口注册PropertyEditor,然后您不会破坏太多标准function。

然后,您的下一个问题是您依赖于静态工厂方法,而这些方法无法以通用方式完成。 当然,您的PropertyEditor可以:

 enumClass.getDeclaredMethod("withId", int.class).invoke(id) 

但我称之为非常hacky。 这样的事情怎么样:

 Object target = null; for(Object e : EnumSet.allOf(yourEnumClass)){ if(e instanceof MyInterface && ((MyInterface)e).getId()==thisId){ target = e; break; } } return target; 

现在您没有使用任何静态工厂方法,只要您的枚举实现了一个通用接口,您就具有编译时安全性。


更新:使用新的Converter SPI,它变得更容易。 使用自定义ConverterFactory :

 public class CustomEnumConverterFactory implements ConverterFactory>{ @Override public > Converter getConverter( final Class targetType){ return WithId.class.isAssignableFrom(targetType) ? new EnumWithIdConverter(targetType) : new StandardEnumConverter(targetType); } } 

像这样注册:

       

从WebMvcConfigurerAdapter扩展

 @Override @SuppressWarnings("unchecked") public void addFormatters(FormatterRegistry registry) { registry.addConverterFactory(new ConverterFactory() { @Override public  Converter getConverter(Class targetType) { return source -> { try { return (T) Enum.valueOf(targetType, source); } catch (Exception e) { return targetType.getEnumConstants()[Integer.parseInt(source)]; } }; } }); super.addFormatters(registry); }