Jakarta Commons项目提供了相当丰富的API,我们之前了解到的Commons Lang只是众多API的比较核心的一小部分而已。Commons下面还有相当数量的子项目,用于解决各种各样不同方向的实际问题,BeanUtils就是其中的一个,用于处理JavaBeans。它利用Java的反射机制,从动态的生成对bean的getter和setter的调用代码,到模拟创建一个动态的bean,等等。这个包看似简单,却是很多开源项目的基石:如在著名的Struts和Spring Framework中,我们都能找到BeanUtils的影子。大家猜猜看,有哪位名人是BeanUtils的作者之一?没错,就是Struts的创始人Craig McClanahan。
BeanUtils最核心的好处在于:我们在编码时,并不需要知道我们处理的JavaBeans具体是什么类型,有哪些属性,这些信息是可以动态获取的,甚至我们都可以不必去关心事实上是否存在这样一个具体的JavaBean类。我们只需要知道有一个JavaBean的实例,我们需要从中取得某个属性,设定某个属性的值,或者仅仅是需要一个属性表。要做到这些,依靠Sun提供的JavaBean规范似乎找不到一个很直接的方式,除非硬编码,将getXxxx()和setXxxx()直接写进我们的程序。但是这样就大大增加了代码的复杂度、耦合性和维护成本。还好Commons BeanUtils对这个问题提供了一种优雅的解决方案。
我们有两种途径获取Commons BeanUtils的binary:
1- 从Struts、Spring或者任何依赖BeanUtils的开源产品的发行包中找到相应的jar文件;
2- 从http://www.apache.org/dist/jakarta/commons/beanutils/binaries/下载。
Commons BeanUtils的源码下载地址:
http://www.apache.org/dist/jakarta/commons/beanutils/source/
Commons BeanUtils一共包括如下5个包:
org.apache.commons.beanutils – 核心包,定义一组Utils类和需要用到的接口规范
org.apache.commons.beanutils.converters – 转换String到需要类型的类,实现Converter接口
org.apache.commons.beanutils.locale – beanutils的locale敏感版本
org.apache.commons.beanutils.locale.converters – converters的locale敏感版本
org.apache.commons.collections – beanutils使用到的Collection类
其中需要我们特别关注的是这个org.apache.commons.beanutils包,其他包都是起辅助作用的。接下来我们就来看看如何使用beanutils包
1.PropertyUtils
它支持三种类型的属性值-Simple,Indexed,Mapped
Simple属性访问方法
PropertyUtils.getSimpleProperty(Object bean, String name)
PropertyUtils.setSimpleProperty(Object bean, String name, Object value)
实现代码:
Employee employee = ...;
String firstName = (String)
PropertyUtils.getSimpleProperty(employee, "firstName");
String lastName = (String)
PropertyUtils.getSimpleProperty(employee, "lastName");
... manipulate the values ...
PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
PropertyUtils.setSimpleProperty(employee, "lastName", lastName);
Indexed属性访问方法
PropertyUtils.getIndexedProperty(Object bean, String name)
PropertyUtils.getIndexedProperty(Object bean, String name, int index)
PropertyUtils.setIndexedProperty(Object bean, String name, Object value)
PropertyUtils.setIndexedProperty(Object bean, String name, int index, Object value)
实现代码:
Employee employee = ...;
int index = ...;
String name = "subordinate[" + index + "]";
Employee subordinate = (Employee)
PropertyUtils.getIndexedProperty(employee, name);//根据value取得属性
Employee employee = ...;
int index = ...;
Employee subordinate = (Employee)
PropertyUtils.getIndexedProperty(employee, "subordinate", index);//根据索引
值取的属性值
Mapped属性访问方法
PropertyUtils.getMappedProperty(Object bean, String name)
PropertyUtils.getMappedProperty(Object bean, String name, String key)
PropertyUtils.setMappedProperty(Object bean, String name, Object value)
PropertyUtils.setMappedProperty(Object bean, String name, String key, Object value)
实现代码:
Employee employee = ...;
Address address = ...;
PropertyUtils.setMappedProperty(employee, "address(home)", address);//根据数组
//内的值来去的相应的属性值
Employee employee = ...;
Address address = ...;
PropertyUtils.setMappedProperty(employee, "address", "home", address);
Nested属性访问方法//Nested的意思是参数中包含组件
PropertyUtils.getNestedProperty(Object bean, String name)
PropertyUtils.setNestedProperty(Object bean, String name, Object value)
实现代码:
String city = (String) PropertyUtils.getNestedProperty(employee,
"address(home).city");
2.BeanUtils.DynaBean and BeanUtils.DynaClass 接口介绍
DynaBean必须有一个bean来实现这个接口,DynaClass必有一个bean的属性集来实现
BasicDynaBean and BasicDynaClass - 基本的 Dynamic 类型
基本的API:
BasicDynaClass(java.lang.String name, java.lang.Class dynaBeanClass, DynaProperty[] properties)
BasicDynaBean(DynaClass dynaClass)
我们定义一下基本的代码:
//定义动态属性集
DynaProperty[] props = new DynaProperty[]{
new DynaProperty("address", java.util.Map.class),
new DynaProperty("subordinate", mypackage.Employee[].class),
new DynaProperty("firstName", String.class),
new DynaProperty("lastName", String.class)
};
//创建动态类来设定动态属性值
BasicDynaClass dynaClass = new BasicDynaClass("employee", null, props);
DynaBean employee = dynaClass.newInstance();
employee.set("address", new HashMap());
employee.set("subordinate", new mypackage.Employee[0]);
employee.set("firstName", "Fred");
employee.set("lastName", "Flintstone");
ResultSetDynaClass (Wraps ResultSet in DynaBeans) - 使用 ResultSet 的
Dynamic JavaBean
API:
ResultSetDynaClass(java.sql.ResultSet resultSet)
ResultSetDynaClass(java.sql.ResultSet resultSet, boolean lowerCase)
Connection conn = ...;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery
("select account_id, name from customers");
Iterator rows = (new ResultSetDynaClass(rs)).iterator();
while (rows.hasNext()) {
//利用动态bean进行输出
DynaBean row = (DynaBean) rows.next();
System.out.println("Account number is " +
row.get("account_id") +
" and name is " + row.get("name"));
}
rs.close();
stmt.close();
RowSetDynaClass (Disconnected ResultSet as DynaBeans) - 使用 RowSet 的 Dynamic
JavaBean
API:
RowSetDynaClass(java.sql.ResultSet resultSet)
RowSetDynaClass(java.sql.ResultSet resultSet, boolean lowerCase)
Connection conn = ...; // 从缓冲池取得连接
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT ...");
RowSetDynaClass rsdc = new RowSetDynaClass(rs);
rs.close();
stmt.close();
...; //关闭连接返回缓冲池
List rows = rsdc.getRows();
...; // 处理得到的行
3.BeanUtils.ConvertUtils 介绍
这个包主要用来转换从request传递过来的函数
主要函数:
ConvertUtils().convert(java.lang.Object value)
ConvertUtils().convert(java.lang.String[] values, java.lang.Class clazz)
ConvertUtils().convert(java.lang.String value, java.lang.Class clazz)
实现例子:
HttpServletRequest request = ...;
MyBean bean = ...;
HashMap map = new HashMap();
Enumeration names = request.getParameterNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
map.put(name, request.getParameterValues(name));
}
BeanUtils.populate(bean, map);//用ConvertUtils进行转换
目前支持的转换类型:
sjava.lang.BigDecimal
java.lang.BigInteger
boolean and java.lang.Boolean
byte and java.lang.Byte
char and java.lang.Character
java.lang.Class
double and java.lang.Double
float and java.lang.Float
int and java.lang.Integer
long and java.lang.Long
short and java.lang.Short
java.lang.String
java.sql.Date
java.sql.Time
java.sql.Timestamp