锁定老帖子 主题:动态properties转换
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-05-08
armorking 写道 ajoo 写道 bottom 写道 BeanUtils.copyProperties(foo, map);
这个,不管在必须的property不存在的情况下报错吧?而且,BeanUtils是1.5以前的吧?管enum么? BeanUtils与ConvertUtilsBean都是“org.apache.commons.beanutils ”提供的 而且BeanUtils.copyProperties方法正是用ConvertUtilsBean实现的类型转换 如果BeanUtils搞不定enum的话,ConvertUtilsBean就可以了么? ConvertUtilsBean和enum或者jdk1.5没有任何关系的,不就是进行enum转换嘛,你写个EnumConverter注册到ConvertUtilsBean就行了。 |
|
返回顶楼 | |
发表时间:2008-05-08
myyate 写道 armorking 写道 ajoo 写道 bottom 写道 BeanUtils.copyProperties(foo, map);
这个,不管在必须的property不存在的情况下报错吧?而且,BeanUtils是1.5以前的吧?管enum么? BeanUtils与ConvertUtilsBean都是“org.apache.commons.beanutils ”提供的 而且BeanUtils.copyProperties方法正是用ConvertUtilsBean实现的类型转换 如果BeanUtils搞不定enum的话,ConvertUtilsBean就可以了么? ConvertUtilsBean和enum或者jdk1.5没有任何关系的,不就是进行enum转换嘛,你写个EnumConverter注册到ConvertUtilsBean就行了。 Converter接口的convert方法签名如下: public Object convert(Class type, Object value); 而Enum的valueOf方法签名如下: public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name); 我没用过JDK1.5,手边也没有合适的环境 所以,我想问一下:这个基于范型的EnumConverter类真的能实现么? |
|
返回顶楼 | |
发表时间:2008-05-08
引用 很优雅,很有创意,改进了两点
1.能够自动为基本类型赋默认值,比如 int id();不用写成 int id() default 0,还有支持enum类型转化; 原始的需求是所有的域都是缺省强制的,如果map里面没有是要抛异常的。所以不能自动提供默认值。enum本来就是支持的,只要自己在converter bean里面注册一个enum converter就是了。ConvertUtils不能直接用,它对非法字符串保持沉默而不抛异常。所以要自己用ConvertUtilsBean。 引用 2.支持getter,方便jstl,ognl之类的表达式, name()和getName()是一样的
哦,在annotation里,没有getName()这个命名规范的。不用操心的吧? 其实,可以另外弄一个annotation来处理key的名字和方法名不匹配的情况: @Rentention(RUNTIME) @Target(METHOD) @interface Property { String value(); } @interface Foo { @Property("标识符") int id(); String name() default ""; } |
|
返回顶楼 | |
发表时间:2008-05-08
myyate 写道 armorking 写道 ajoo 写道 bottom 写道 BeanUtils.copyProperties(foo, map);
这个,不管在必须的property不存在的情况下报错吧?而且,BeanUtils是1.5以前的吧?管enum么? BeanUtils与ConvertUtilsBean都是“org.apache.commons.beanutils ”提供的 而且BeanUtils.copyProperties方法正是用ConvertUtilsBean实现的类型转换 如果BeanUtils搞不定enum的话,ConvertUtilsBean就可以了么? ConvertUtilsBean和enum或者jdk1.5没有任何关系的,不就是进行enum转换嘛,你写个EnumConverter注册到ConvertUtilsBean就行了。 convert()函数就是这么用的。问题是,BeanUtils.copyProperties()能自动使用我的enum converter么?还有报错怎么解决? |
|
返回顶楼 | |
发表时间:2008-05-09
ajoo 写道 引用 很优雅,很有创意,改进了两点
1.能够自动为基本类型赋默认值,比如 int id();不用写成 int id() default 0,还有支持enum类型转化; 原始的需求是所有的域都是缺省强制的,如果map里面没有是要抛异常的。所以不能自动提供默认值。enum本来就是支持的,只要自己在converter bean里面注册一个enum converter就是了。ConvertUtils不能直接用,它对非法字符串保持沉默而不抛异常。所以要自己用ConvertUtilsBean。 引用 2.支持getter,方便jstl,ognl之类的表达式, name()和getName()是一样的
哦,在annotation里,没有getName()这个命名规范的。不用操心的吧? 其实,可以另外弄一个annotation来处理key的名字和方法名不匹配的情况: @Rentention(RUNTIME) @Target(METHOD) @interface Property { String value(); } @interface Foo { @Property("标识符") int id(); String name() default ""; } 1.需要手动注册enum converter还不如直接写在这个里面,也就是两行代码 2.在annotation里面增加getName()是为了能够在EL里面可以用xxx.name 还有这个@Property("标识符")起什么作用?也不能用EL在UI上面显示出来. |
|
返回顶楼 | |
发表时间:2008-05-09
quaff 写道 ajoo 写道 引用 很优雅,很有创意,改进了两点
1.能够自动为基本类型赋默认值,比如 int id();不用写成 int id() default 0,还有支持enum类型转化; 原始的需求是所有的域都是缺省强制的,如果map里面没有是要抛异常的。所以不能自动提供默认值。enum本来就是支持的,只要自己在converter bean里面注册一个enum converter就是了。ConvertUtils不能直接用,它对非法字符串保持沉默而不抛异常。所以要自己用ConvertUtilsBean。 引用 2.支持getter,方便jstl,ognl之类的表达式, name()和getName()是一样的
哦,在annotation里,没有getName()这个命名规范的。不用操心的吧? 其实,可以另外弄一个annotation来处理key的名字和方法名不匹配的情况: @Rentention(RUNTIME) @Target(METHOD) @interface Property { String value(); } @interface Foo { @Property("标识符") int id(); String name() default ""; } 1.需要手动注册enum converter还不如直接写在这个里面,也就是两行代码 2.在annotation里面增加getName()是为了能够在EL里面可以用xxx.name 还有这个@Property("标识符")起什么作用?也不能用EL在UI上面显示出来. 怎么转换enum就是具体实现方法了。我是因为有一个单独可重用的ConvertUtilsBean负责转换所有类型,所以直接拿过来用了,你自己写也可以的。 至于@Property么,用来处理你的Map里面的key和方法名不能匹配的情况,比如例子里面Map的key是“老婆,出来看标识符”,你总不能把方法名字也写这么一大长串吧?(除非你是中文编程的扇子)。ui么,呵呵,俺不知道。这个ui不能被定制的么? |
|
返回顶楼 | |
发表时间:2008-05-09
ajoo 写道 主要是这个默认值,除了annotation想不到别的好办法解决。
别的人也给了些建议,比如自己写一个Property<T>类,在这个类里面实现类型转换和默认值处理。不过都要求比较多的代码,而且用起来客户代码还要依赖于一个不是很容易mock的Property类。反而不如动态代理简单干净,侵入性基本没有。用起来可以注射进一个接口,而不是PropertyConverter类,这样最容易测试。 你要用随便啦。反正都贴在blog里了,随便拷贝。 我比较笨,想不出来为什么写一个类负责转换会要求更多的代码,如下(木有写过 java,语法错误莫怪): public abstract class Base { private final Map<String, String> _map; public Base(Map<String, String> map) { _map = map; } public T GetProperty<T>(String key, T defaultValue) { String value = _map.get(key); if (value == null) { if (defaultValue == null) { throw ...; } return defaultValue; } return convert(value); } } public final class Foo : Base { public Foo(Map<String, String> map) : base(map) {} public int id() { return Base.GetProperty<int>("id", null); } public String name() { return Base.GetProperty<String>("name", ""); } Gender sex() { return Base.GetProperty<Gender>("sex", null); } } Map<String, String> map = ...; Foo foo = new Foo(map); foo.id(); foo.name(); 当然啦,这个看起来木有你原来那个帅,不过相对而言要好懂一些吧?而且处理方法名和属性名不同的情况也不用额外多费手脚了。 |
|
返回顶楼 | |
发表时间:2008-05-09
ajoo 写道 quaff 写道 ajoo 写道 引用 很优雅,很有创意,改进了两点
1.能够自动为基本类型赋默认值,比如 int id();不用写成 int id() default 0,还有支持enum类型转化; 原始的需求是所有的域都是缺省强制的,如果map里面没有是要抛异常的。所以不能自动提供默认值。enum本来就是支持的,只要自己在converter bean里面注册一个enum converter就是了。ConvertUtils不能直接用,它对非法字符串保持沉默而不抛异常。所以要自己用ConvertUtilsBean。 引用 2.支持getter,方便jstl,ognl之类的表达式, name()和getName()是一样的
哦,在annotation里,没有getName()这个命名规范的。不用操心的吧? 其实,可以另外弄一个annotation来处理key的名字和方法名不匹配的情况: @Rentention(RUNTIME) @Target(METHOD) @interface Property { String value(); } @interface Foo { @Property("标识符") int id(); String name() default ""; } 1.需要手动注册enum converter还不如直接写在这个里面,也就是两行代码 2.在annotation里面增加getName()是为了能够在EL里面可以用xxx.name 还有这个@Property("标识符")起什么作用?也不能用EL在UI上面显示出来. 怎么转换enum就是具体实现方法了。我是因为有一个单独可重用的ConvertUtilsBean负责转换所有类型,所以直接拿过来用了,你自己写也可以的。 至于@Property么,用来处理你的Map里面的key和方法名不能匹配的情况,比如例子里面Map的key是“老婆,出来看标识符”,你总不能把方法名字也写这么一大长串吧?(除非你是中文编程的扇子)。ui么,呵呵,俺不知道。这个ui不能被定制的么? 叫@Alias更好一些,我以为你把它当label显示在UI上面,UI上面一般都是用EL来获取值,如果你要在UI里面写java代码也没说不可以. |
|
返回顶楼 | |
发表时间:2008-05-09
Elminster 写道 ajoo 写道 主要是这个默认值,除了annotation想不到别的好办法解决。
别的人也给了些建议,比如自己写一个Property<T>类,在这个类里面实现类型转换和默认值处理。不过都要求比较多的代码,而且用起来客户代码还要依赖于一个不是很容易mock的Property类。反而不如动态代理简单干净,侵入性基本没有。用起来可以注射进一个接口,而不是PropertyConverter类,这样最容易测试。 你要用随便啦。反正都贴在blog里了,随便拷贝。 我比较笨,想不出来为什么写一个类负责转换会要求更多的代码,如下(木有写过 java,语法错误莫怪): public abstract class Base { private final Map<String, String> _map; public Base(Map<String, String> map) { _map = map; } public T GetProperty<T>(String key, T defaultValue) { String value = _map.get(key); if (value == null) { if (defaultValue == null) { throw ...; } return defaultValue; } return convert(value); } } public final class Foo : Base { public Foo(Map<String, String> map) : base(map) {} public int id() { return Base.GetProperty<int>("id", null); } public String name() { return Base.GetProperty<String>("name", ""); } Gender sex() { return Base.GetProperty<Gender>("sex", null); } } Map<String, String> map = ...; Foo foo = new Foo(map); foo.id(); foo.name(); 当然啦,这个看起来木有你原来那个帅,不过相对而言要好懂一些吧?而且处理方法名和属性名不同的情况也不用额外多费手脚了。 这种代码差不多所有人都会写,还不如GetProperty做成静态方法然后引入,还去掉了必须继承Base这个限制 |
|
返回顶楼 | |
发表时间:2008-05-09
怎么回事?javaeye bug?删除 |
|
返回顶楼 | |