- 浏览: 453823 次
-
最新评论
-
carlos23:
我想知道用WriterLogger后,里面的writer在外面 ...
论面向组合子程序设计方法 之 燃烧的荆棘 -
marsyoung:
讲的什么。。没看懂。例子太抽象。。
论面向组合子程序设计方法 之 创世纪 -
wanghhao:
优雅的方式!
论面向组合子程序设计方法 之 微步毂纹生 -
ykdsg:
有源码吗?
论面向组合子程序设计方法 之 monad -
咱不怕:
如果在一个函数中多次使用到这个不变temp对象,按照Marti ...
关于 Replace Temp With Query
今天同事和我讨论他遇到的一个问题。具体要求是这样的,在运行时,我们会从模块G得到一个Map,这个Map里面都是一些字符串对,你可以理解成一个字典,有字符串的key和字符串的value。简短节说,就是
非常非常复杂深奥。
好,现在我们事先知道要从这个map里读取一些数据点,比如:id, name, sex等等。
对id,我们知道读出来的是int;对name,是string;对sex,应该对应一个叫Gender的enum类型。
这就涉及一个自动类型转换的问题。我们希望不用对每个数据点做手工类型转换。
另外一个需求,一些数据点是有缺省值的。比如name我们可以缺省为空字符串。
这样,如果map里面没有某个值,我们就看缺省值,如果有,就用这个缺省值,如果没有,就抛异常。
手工做的话,大概是这样:
比较痛苦。于是做了一个动态代理:
convert()函数是调用apache的ConvertUtilsBean做的,没什么说的。
那么,用法呢?
这里面,对annotation的用法比较特别。不过不这么做,java也不提供一个简单并且类型安全的指定缺省值的方法。当然,如果你凑巧不需要缺省值,那么也不用annotation,直接用interface就好。
原始的需求是所有的域都是缺省强制的,如果map里面没有是要抛异常的。所以不能自动提供默认值。enum本来就是支持的,只要自己在converter bean里面注册一个enum converter就是了。ConvertUtils不能直接用,它对非法字符串保持沉默而不抛异常。所以要自己用ConvertUtilsBean。
哦,在annotation里,没有getName()这个命名规范的。不用操心的吧?
其实,可以另外弄一个annotation来处理key的名字和方法名不匹配的情况:
这个,不管在必须的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方法签名如下:
而Enum的valueOf方法签名如下:
我没用过JDK1.5,手边也没有合适的环境
所以,我想问一下:这个基于范型的EnumConverter类真的能实现么?
这个,不管在必须的property不存在的情况下报错吧?而且,BeanUtils是1.5以前的吧?管enum么?
BeanUtils与ConvertUtilsBean都是“org.apache.commons.beanutils ”提供的
而且BeanUtils.copyProperties方法正是用ConvertUtilsBean实现的类型转换
如果BeanUtils搞不定enum的话,ConvertUtilsBean就可以了么?
ConvertUtilsBean和enum或者jdk1.5没有任何关系的,不就是进行enum转换嘛,你写个EnumConverter注册到ConvertUtilsBean就行了。
这个,不管在必须的property不存在的情况下报错吧?而且,BeanUtils是1.5以前的吧?管enum么?
BeanUtils与ConvertUtilsBean都是“org.apache.commons.beanutils ”提供的
而且BeanUtils.copyProperties方法正是用ConvertUtilsBean实现的类型转换
如果BeanUtils搞不定enum的话,ConvertUtilsBean就可以了么?
这个,不管在必须的property不存在的情况下报错吧?而且,BeanUtils是1.5以前的吧?管enum么?
Map<String, String>
非常非常复杂深奥。
好,现在我们事先知道要从这个map里读取一些数据点,比如:id, name, sex等等。
对id,我们知道读出来的是int;对name,是string;对sex,应该对应一个叫Gender的enum类型。
这就涉及一个自动类型转换的问题。我们希望不用对每个数据点做手工类型转换。
另外一个需求,一些数据点是有缺省值的。比如name我们可以缺省为空字符串。
这样,如果map里面没有某个值,我们就看缺省值,如果有,就用这个缺省值,如果没有,就抛异常。
手工做的话,大概是这样:
String idValue = map.get("id"); if (idValue == null) { throw ...; } int id = Integer.parseInt(idValue); String name = map.get("name"); if (name == null) { name = ""; } String sexValue = map.get("sex"); if (sexValue == null) { throw ...; } Gender sex = Gender.valueOf(sexValue); ...
比较痛苦。于是做了一个动态代理:
public final class PropertyConverter<T> { private final Class<T> targetType; private PropertyConverter(Class<T> targetType) {...} public static <T> PropertyConverter<T> to(Class<T> targetType) { return new PropertyConverter<T>(targetType); } public T from(final Map<String, String> map) { return Proxy.newProxyInstance( new Class[]{targetType}, targetType.getClassLoader(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) { String value = map.get(method.getName()); if (value == null) { Object defaultValue = method.getDefaultValue(); if (defaultValue == null) { throw ...; } return defaultValue; } return convert(value, method.getReturnType()); } }); } }
convert()函数是调用apache的ConvertUtilsBean做的,没什么说的。
那么,用法呢?
@interface Foo { int id(); String name() default ""; Gender sex(); } Map<String, String> map = ...; Foo foo = PropertyConverter.to(Foo.class).from(map); foo.id(); foo.name();
这里面,对annotation的用法比较特别。不过不这么做,java也不提供一个简单并且类型安全的指定缺省值的方法。当然,如果你凑巧不需要缺省值,那么也不用annotation,直接用interface就好。
评论
12 楼
ajoo
2008-05-08
引用
很优雅,很有创意,改进了两点
1.能够自动为基本类型赋默认值,比如 int id();不用写成 int id() default 0,还有支持enum类型转化;
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 ""; }
11 楼
armorking
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类真的能实现么?
10 楼
myyate
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就行了。
9 楼
quaff
2008-05-08
现在才知道@interface也是interface的一种,可以用来做动态代理的接口也可以被类实现.
8 楼
quaff
2008-05-08
很优雅,很有创意,改进了两点
1.能够自动为基本类型赋默认值,比如 int id();不用写成 int id() default 0,还有支持enum类型转化;
2.支持getter,方便jstl,ognl之类的表达式, name()和getName()是一样的
1.能够自动为基本类型赋默认值,比如 int id();不用写成 int id() default 0,还有支持enum类型转化;
2.支持getter,方便jstl,ognl之类的表达式, name()和getName()是一样的
public final class PropertyConverter<T> { private final Class<T> targetType; private PropertyConverter(Class<T> targetType) { this.targetType = targetType; } public static <T> PropertyConverter<T> to(Class<T> targetType) { return new PropertyConverter<T>(targetType); } public T from(final Map<String, String> map) { return (T) Proxy.newProxyInstance(targetType.getClassLoader(), new Class[] { targetType }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) { String name = method.getName(); Class type = method.getReturnType(); if (name.startsWith("get")) name = Character.toLowerCase(name.charAt(3)) + name.substring(4); if (name.startsWith("is") && type == boolean.class) name = Character.toLowerCase(name.charAt(2)) + name.substring(3); String value = map.get(name); if (value == null && !type.isPrimitive()) return method.getDefaultValue(); if(Enum.class.isAssignableFrom(type)) return Enum.valueOf(type, value); return ConvertUtils.convert(value, type); } }); } }
7 楼
armorking
2008-05-08
我也给一个基于org.apache.commons.collections.BeanMap的实现
Foo
测试结果
import java.math.BigDecimal; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.commons.collections.BeanMap; public abstract class MapInstantUtil { public static void putAllPropertiesFromMap( Object targetObj, Map sourceMap) { if (targetObj == null ){ return; } String className = targetObj.getClass().getName(); Set essentialKeySet = searchEssentialKeySet(className); if (sourceMap == null ){ if (essentialKeySet.size() > 0 ){ throw new IllegalArgumentException("this bean can not be instanted by an empty map!"); } sourceMap = Collections.EMPTY_MAP; } Map beanMap = new BeanMap(targetObj); for (Iterator i = sourceMap.keySet().iterator(); i.hasNext() ; ) { String key = (String)i.next(); if (!beanMap.containsKey(key) ){ continue; } Object value = sourceMap.get(key); if (value == null ){ continue; } beanMap.put(key, value); } Map defaultValueMap = searchDefaultValueMap(className); for (Iterator i = defaultValueMap.keySet().iterator(); i.hasNext() ; ) { String key = (String)i.next(); if (!beanMap.containsKey(key) ){ continue; } Object value = sourceMap.get(key); if (value != null ){ continue; } beanMap.put(key, defaultValueMap.get(key)); } for (Iterator i = essentialKeySet.iterator(); i.hasNext() ; ) { String key = (String)i.next(); if (!beanMap.containsKey(key) ){ continue; } Object value = beanMap.get(key); if (value == null ){ throw new IllegalArgumentException("the property(" + key + ") must not be null!"); } } } //Map<String className, Map<String key, Object defaultValue>> private static Map DefaultValueMap_MAP; //Map<String className, Set<String essentialKey>> private static Map EssentialKeySet_MAP; static { DefaultValueMap_MAP = new HashMap(); EssentialKeySet_MAP = new HashMap(); //for Foo String className = Foo.class.getName(); Map fooDefaultValueMap = new HashMap(); fooDefaultValueMap.put("int_1", new Integer("1")); fooDefaultValueMap.put("int_1", "1"); fooDefaultValueMap.put("bigdecimal_2", new BigDecimal("2")); fooDefaultValueMap.put("string_3", "3"); fooDefaultValueMap.put("long_4", new Long("4")); fooDefaultValueMap.put("integer_7", new Integer("7")); DefaultValueMap_MAP.put(className, fooDefaultValueMap); Set fooEssentialKeySet = new HashSet(); fooEssentialKeySet.add("short_5"); fooEssentialKeySet.add("string_6"); EssentialKeySet_MAP.put(className, fooEssentialKeySet); //TODO : for others } private static Map searchDefaultValueMap(String className) { return DefaultValueMap_MAP.containsKey(className) ? (Map)DefaultValueMap_MAP.get(className) : Collections.EMPTY_MAP ; } private static Set searchEssentialKeySet(String className) { return EssentialKeySet_MAP.containsKey(className) ? (Set)EssentialKeySet_MAP.get(className) : Collections.EMPTY_SET ; } }
Foo
import java.math.BigDecimal; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.apache.commons.collections.BeanMap; public class Foo { //properties private int int_1; private BigDecimal bigdecimal_2; private String string_3; private long long_4; private short short_5; private String string_6; private Integer integer_7; //getter & setter public BigDecimal getBigdecimal_2() { return this.bigdecimal_2; } public void setBigdecimal_2(BigDecimal bigdecimal_2) { this.bigdecimal_2 = bigdecimal_2; } public int getInt_1() { return this.int_1; } public void setInt_1(int int_1) { this.int_1 = int_1; } public long getLong_4() { return this.long_4; } public void setLong_4(long long_4) { this.long_4 = long_4; } public short getShort_5() { return this.short_5; } public void setShort_5(short short_5) { this.short_5 = short_5; } public String getString_3() { return this.string_3; } public void setString_3(String string_3) { this.string_3 = string_3; } public String getString_6() { return this.string_6; } public void setString_6(String string_6) { this.string_6 = string_6; } public Integer getInteger_7() { return this.integer_7; } public void setInteger_7(Integer integer_7) { this.integer_7 = integer_7; } public static void main(String[] args) { Map sourceMap = new HashMap(); sourceMap.put("short_5", new Short("55")); sourceMap.put("string_6", new String("66")); Foo foo = new Foo(); MapInstantUtil.putAllPropertiesFromMap(foo, sourceMap); Map beanMap = new BeanMap(foo); for (Iterator i = beanMap.keySet().iterator(); i.hasNext() ; ) { String key = (String)i.next(); System.out.println("key : " + key + "\t\tvalue : " + beanMap.get(key)); } } }
测试结果
key : integer_7 value : 7 key : short_5 value : 55 key : string_3 value : 3 key : long_4 value : 4 key : bigdecimal_2 value : 2 key : int_1 value : 1 key : string_6 value : 66
6 楼
ajoo
2008-05-08
主要是这个默认值,除了annotation想不到别的好办法解决。
别的人也给了些建议,比如自己写一个Property<T>类,在这个类里面实现类型转换和默认值处理。不过都要求比较多的代码,而且用起来客户代码还要依赖于一个不是很容易mock的Property类。反而不如动态代理简单干净,侵入性基本没有。用起来可以注射进一个接口,而不是PropertyConverter类,这样最容易测试。
你要用随便啦。反正都贴在blog里了,随便拷贝。
别的人也给了些建议,比如自己写一个Property<T>类,在这个类里面实现类型转换和默认值处理。不过都要求比较多的代码,而且用起来客户代码还要依赖于一个不是很容易mock的Property类。反而不如动态代理简单干净,侵入性基本没有。用起来可以注射进一个接口,而不是PropertyConverter类,这样最容易测试。
你要用随便啦。反正都贴在blog里了,随便拷贝。
![](/images/smiles/icon_smile.gif)
5 楼
sorphi
2008-05-08
主贴的价值不在于类型转换,而是展示了annotation的优点。再说一句,真的用的很妙。
ajoo大哥,我能不能拿来用啊
/*
* @author ajoo.iteye.com
* @See http://www.iteye.com/topic/190440
*/
ajoo大哥,我能不能拿来用啊
/*
* @author ajoo.iteye.com
* @See http://www.iteye.com/topic/190440
*/
4 楼
armorking
2008-05-08
ajoo 写道
bottom 写道
BeanUtils.copyProperties(foo, map);
这个,不管在必须的property不存在的情况下报错吧?而且,BeanUtils是1.5以前的吧?管enum么?
BeanUtils与ConvertUtilsBean都是“org.apache.commons.beanutils ”提供的
而且BeanUtils.copyProperties方法正是用ConvertUtilsBean实现的类型转换
如果BeanUtils搞不定enum的话,ConvertUtilsBean就可以了么?
3 楼
ajoo
2008-05-08
bottom 写道
BeanUtils.copyProperties(foo, map);
这个,不管在必须的property不存在的情况下报错吧?而且,BeanUtils是1.5以前的吧?管enum么?
2 楼
bottom
2008-05-08
BeanUtils.copyProperties(foo, map);
1 楼
sorphi
2008-05-07
签名、类型、默认值,这个方案,实在是高
发表评论
-
为中国的未来担忧,我,上过大学,学过计算机,英语六级,当过DBA,架构师,软件工程师,还得自己扫雪!
2008-03-23 03:06 5616哎,一到下雪我就头疼。又得推着扫雪机吭哧吭哧扫雪。就说是三月学 ... -
祝贺Guice拿了Jolt Award
2008-03-10 12:21 5313我对计算机界的八卦一 ... -
rparsec在《Pracical Ruby Projects》中
2008-03-04 02:37 4517最近发现《Practical Ruby Projects》用r ... -
中了annotation的毒了
2008-01-31 08:27 4806在1.4上,我最喜欢玩的是dynamic proxy。以前的那 ... -
俺摸,俺摸,俺默默摸
2008-01-16 23:50 4475猪肉炖粉:“那啥,猪 ... -
摹客测试蛛丝程序中的绑匪
2007-10-11 10:45 4342为了响应伟大的“抵制中英文夹杂的资本主义不良思潮”运动,本文将 ... -
JUnit Sucks
2007-08-05 10:16 8655好象貌似有本书是用写 ...
相关推荐
在IT行业中,数据管理和配置管理经常涉及到不同格式的文件转换,比如Excel和Properties文件。Excel是一种广泛用于数据处理和分析的电子表格工具,而Properties文件则常见于Java开发中,用于存储配置信息。两者之间的...
为了解决这个问题,开发人员通常需要使用特定的工具来批量处理和转换`.properties`文件,以确保它们正确地支持中文字符。 本话题将介绍一种Java `.properties`中文资源批量转换工具的使用方法,帮助开发者高效地...
此文件可以批量的将properties转换成json字符串并输出为txt文件. 使用:PropToJson.toJSONString(resourseArr,true) resourseArr为资源文件地址数组 true为对应txt文件到本地; false为不输出到本地
"properties资源文件转换插件"是一款专为Eclipse开发环境设计的工具,旨在简化对.properties配置文件进行中文转换的过程。通常,在Java开发中,.properties文件用于存储应用程序的配置信息,如国际化(i18n)的文本。...
java_properties编辑器支持自动转换ascii,方便快捷无需再用JDK自动工具转换。
使用 native2ascii 工具可以将 Properties 文件转换为 Unicode 编码字符的文件,然后将转换后的文件内容替换为原始文件的内容。这样可以解决 Properties 文件文中乱码问题。 Properties 文件是一种资源文件,用于...
4. **将Properties转换为Map** `Properties`类本身就是一个`Map`,可以直接通过`entrySet()`方法访问键值对。但如果你需要一个标准的`Map, String>`,可以进行转换: ```java Map, String> map = new HashMap(); ...
2. **自动编码检测和转换**:该插件能够自动检测`.properties`文件的编码,并允许用户选择不同的字符集进行转换,确保国际化文本的正确显示。 3. **支持Unicode和特殊字符**:由于国际化的需要,Properties Editor...
博主分享了一个实用的方法,即通过Unicode转换工具来处理含有中文字符的properties文件,以确保数据的正确性。 首先,我们需要理解Java Properties文件的编码问题。默认情况下,Java Properties类在读取和写入文件...
利用java的反射解析Properties文件转成对象 /** * 解析properties文件为对象 * @param * @param propPath * @param cls * @return * @throws InstantiationException * @throws ...
有时候,将.properties文件转换为JSON格式会更方便,因为JSON与JavaScript天生兼容。可以使用在线工具或者自定义脚本完成转换,然后在JavaScript中使用`JSON.parse()`来解析。 7. **错误处理** 在处理文件读取和...
Properties Editor是一款专为Eclipse开发的插件,主要用于编辑Struts2框架中的资源文件,尤其在处理Unicode编码和中文字符转换方面提供了极大的便利。这款插件解决了开发人员在使用Eclipse进行国际化(i18n)开发时...
yml properties相互转换 工具 java小工具 命令:java -jar properties-yml.jar application.properties 生成application.properties 命令:java -jar properties-yml.jar application.yml 生成application.yml
以下是一个简单的示例,展示如何使用Properties类加载文件并将其内容转换为Map: ```java import java.io.*; import java.util.*; public class PropertyHandler { public static Map, String> loadProperties...
这个问题通常由两个主要因素引起:编码格式不匹配和读写过程中的编码转换不当。 首先,Properties文件默认使用ISO-8859-1编码,这是Java的标准编码。如果在文件中直接写入中文,而编辑器或程序以UTF-8或其他支持...
将Java .properties文件转换为JSON(使用JavaScript)。 函数propertiesToJSON接受一个字符串并返回一个JavaScript对象。 读取node的本地文件: const fs = require ( "fs" ) ; const path = require ( "path" ) ;...
1. **预处理**:在编辑`.properties`文件时,可以使用Java提供的`native2ascii`工具或Eclipse的属性编辑器将中文字符转换为对应的UTF-8编码表示形式。 2. **程序中转换**:在代码中,可以使用`new String...
然而,尽管Eclipse本身已经提供了对`properties`文件的基本编辑功能,但有时开发者可能需要更高级的功能,如语法高亮、自动完成、编码转换等,这就是`myeclipse插件properties插件`的作用。 这个插件专为解决`...
2. **编码检测与转换**:插件可以自动检测文件的编码,并允许用户转换文件的编码格式,以适应不同的项目需求。 3. **语法高亮**:通过颜色区分关键字和普通文本,提高代码可读性。 4. **自动完成**:提供属性键的...
- 如果需要将读取出的时间字符串转换回日期对象,可以使用`SimpleDateFormat.parse`或`java.time.format.DateTimeFormatter.parse`方法。例如: ```java try { Date lastUpdateTime = new SimpleDateFormat(...