Grails 开发日志-View查找规则、Data-Binding

View 文件查找规则

类:

  • grails.views.ResolvableGroovyTemplateEngine#resolveTemplate(java.lang.String, java.util.Locale, java.lang.String…)
  • grails.views.ResolvableGroovyTemplateEngine#templateByPath
  • grails.views.resolve.GenericGroovyTemplateResolver#resolveTemplate 这个方法是实际查找view文件的方法

可以添加 locale 相关的文件,例如 locale = en 则优先找 “view_en.gsp” 文件。

Data-Binding

https://docs.grails.org/4.0.3/guide/single.html#dataBinding
If type conversion fails for any reason, the argument will have its default value per normal Java behavior (null for type wrapper references, false for booleans and zero for numbers) and a corresponding error will be added to the errors property of the defining controller.

所以 controller 也有一个 errors 属性。

@grails.web.RequestParameter annotation 可以指定参数名,这样方法的参数名可以和请求参数名不一样。

@BindUsing annotation 可以自定义一个转换器,可以加在类上也可以加在属性上。

加在字段上的例子

class SomeClass {
    @BindUsing({obj, source ->

        //source is DataSourceBinding which is similar to a Map
        //and defines getAt operation but source.name cannot be used here.
        //In order to get name from source use getAt instead as shown below.
        // 不能用 source.name 要用 source['name'] 方式来取属性值
        source['name']?.toUpperCase()
    })
    String name
}

加在类上的例子,需要实现接口 BindingHelper 的类,但是注意,如果在 类 上使用@BindUsing注解,那么这个类所有的属性都需要自己在 BindingHelper 类中绑定。

并且 getPropertyValue() 方法只会被请求参数中出现的参数调用,没有出现的参数不会被调用。

加在类上时,如果转换失败,可以添加一个 IllegalArgumentException 异常告诉 data-binding 出错了

@BindUsing(SomeClassWhichImplementsBindingHelper)
class SomeClass {
    String someProperty
    Integer someOtherProperty
}
public interface BindingHelper<T> {

    /**
     * The value returned from this method will be bound to
     * the property specified by propertyName.
     *
     * @param obj The object that data binding is being applied to
     * @param propertyName The name of the property data binding is being applied to
     * @param source The Map containing all of the values being bound to this object
     * @return The value which should be bound to propertyName
     */
    T getPropertyValue(Object obj, String propertyName, DataBindingSource source);
}

所以,我们可以用 @BindUsing 和 BindingHelper 来实现一个自动从 int id 请求参数转换为 枚举 值的 data-binding 机制。
使用 支持枚举的数据绑定功能,

扫描二维码关注公众号,回复: 11185824 查看本文章

代码示例如下:

@BindUsing(EnumBindHelper)
class MyCommand {
  int someEnumId
  
  @EnumBind("someEnumId")
  SomeEnum someEnum
}

当绑定失败时 Command 对象的errors 属性有相应记录。

进过尝试,发现上面的方法是行不通的。原因有两个:

  1. 如果在 类 上使用@BindUsing注解,那么这个类所有的属性都需要自己在 BindingHelper 类中绑定。
  2. getPropertyValue() 方法只会被请求参数中出现的参数调用,没有出现的参数不会被调用。

最后用了这样的方法

class GuessCommand implements Validateable {

    /**
     * 支持的选手类型,1=红,0=黑
     * 参考 RedBlack 枚举
     */
    @BindUsing({ obj, source -> RedBlack.valueFromId(source["playerType"] as Integer) })
    RedBlack playerType
}

/**
 * 能从 id 查找枚举对象的 trait
 *
 * @param < T >    枚举类
 */
trait IdEnum<T> {

    /**
     * 从id获取枚举值
     *
     * @param id
     * @return null 如果id没有对应的枚举对象
     */
    static T valueFromId(int id) {
        values().find { it.id == id }
    }
}

enum RedBlack implements IdEnum<RedBlack> {

    BLACK(0),
    RED(1)

    int id

    RedBlack(int id) {
        this.id = id
    }
}

The BindInitializer Annotation
The BindInitializer annotation may be used to initialize an associated field in a class if it is undefined.

本地 MySQL 数据库不起会导致集成测试挂起

如果本地 MySQL 数据库不起会导致执行 gradle build 时,集成测试被一直挂起。

原创文章 80 获赞 40 访问量 8万+

猜你喜欢

转载自blog.csdn.net/yangbo_hr/article/details/105579606