2009-11-20 119 views
10

我的Grails应用程序有大量枚举看起来像这样:Grails的绑定请求参数枚举

public enum Rating { 
    BEST("be"), GOOD("go"), AVERAGE("av"), BAD("ba"), WORST("wo") 
    final String id 

    private RateType(String id) { 
     this.id = id 
    } 

    static public RateType getEnumFromId(String value) { 
     values().find {it.id == value } 
    } 
} 

如果我有一个命令对象,像这样:

class MyCommand { 
    Rating rating 
} 

我想(例如)自动将值为“wo”的请求参数转换为Rating.WORST。

定义自定义转换器的过程描述为here(在将字符串转换为日期的上下文中)。虽然这个过程没问题,但我不想为每个枚举创建一个实现PropertyEditorSupport的类。有更好的选择吗?

回答

11

我找到了一个解决方案,我用很高兴。

步骤1:创建PropertyEditorSupport的实施方案将文本转换到/从相关的Enum

public class EnumEditor extends PropertyEditorSupport { 

    private Class<? extends Enum<?>> clazz 

    public EnumEditor(Class<? extends Enum<?>> clazz) { 
     this.clazz = clazz 
    } 

    public String getAsText() { 
     return value?.id 
    } 

    public void setAsText(String text) { 
     value = clazz.getEnumFromId(text) 
    } 
} 

步骤2:定义,其登记EnumEditor作为各种枚举类的转换器的一类。要改变这种状况是由ID绑定枚举类的列表,只需修改BINDABLE_ENUMS

public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar { 

    private static final String REQUIRED_METHOD_NAME = 'getEnumFromId' 

    // Add any enums that you want to bind to by ID into this list 
    private static final BINDABLE_ENUMS = [Rating, SomeOtherEnum, SomeOtherEnum2] 

    public void registerCustomEditors(PropertyEditorRegistry registry) {    

     BINDABLE_ENUMS.each {enumClass -> 
      registerEnum(registry, enumClass) 
     } 
    } 

    /** 
    * Register an enum to be bound by ID from a request parameter 
    * @param registry Registry of types eligible for data binding 
    * @param enumClass Class of the enum 
    */ 
    private registerEnum(PropertyEditorRegistry registry, Class<? extends Enum<?>> enumClass) { 

     boolean hasRequiredMethod = enumClass.metaClass.methods.any {MetaMethod method -> 
      method.isStatic() && method.name == REQUIRED_METHOD_NAME && method.parameterTypes.size() == 1 
     } 

     if (!hasRequiredMethod) { 
      throw new MissingMethodException(REQUIRED_METHOD_NAME, enumClass, [String].toArray()) 
     } 
     registry.registerCustomEditor(enumClass, new EnumEditor(enumClass)) 
    } 
} 

第3步:让春天注意注册表的上述由grails-app/conf/spring/resources.grooovy

customPropertyEditorRegistrar(CustomPropertyEditorRegistrar) 
+0

干得好!我正在努力解决同样的问题。为什么这不是Grails的标准部分? Grails支持将请求参数绑定到域/命令对象是非常糟糕的。 – mcv 2009-12-17 18:40:33

+3

Grails不支持将枚举的绑定请求参数,但默认情况下按名称绑定。如果你想通过一些其他的枚举属性(例如通过id,如上)来绑定,你需要自己定义绑定 – 2011-09-30 08:12:12

10

因此,默认的Databinding绑定在Enum名称上,而不是Enum的单独定义的属性。您可以create your own PropertyEditor如你所提到的或做一个变通与此类似:

class MyCommand { 
String ratingId 
    Rating getRating() { 
    return Rating.getEnumFromId(this.ratingId) 
    } 
    static constraints = { 
    ratingId(validator:{val, obj -> Rating.getEnumFromId(val) != null }) 
    } 
} 
+0

真棒定义下面的Spring bean解决方法科林! – 2016-05-08 09:37:54