2009-11-20 64 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