【问题标题】:Grails bind request parameters to enumGrails 将请求参数绑定到枚举
【发布时间】:2009-11-20 18:02:45
【问题描述】:

我的 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 的类。有没有更好的选择?

【问题讨论】:

    标签: data-binding grails enums


    【解决方案1】:

    我找到了一个我非常满意的解决方案。

    第 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 中定义以下 Spring bean,让 Spring 了解上面的注册表

    customPropertyEditorRegistrar(CustomPropertyEditorRegistrar)
    

    【讨论】:

    • 干得好!我正在努力解决同样的问题。为什么这不是 Grails 的标准部分? Grails 对将请求参数绑定到域/命令对象的支持非常糟糕。
    • Grails 确实支持将请求参数绑定到枚举,但默认按名称绑定。如果你想通过其他一些枚举属性绑定(例如通过 id,如上所述),你需要自己定义绑定
    【解决方案2】:

    因此,默认数据绑定绑定在 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 })
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-01-10
      • 2011-11-05
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 2015-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多