BeanUtils 介绍
所谓 BeanUtils 为何要开发呢, 每个工程师或许在写 JavaBean 的时候, 都会乖乖地去写 getters 和 setters, 就是 getXXX() 及 setXXX() methods, 但是当你的 object 是动态产生的, 也许是用档案, 也许是其它原因, 那你该如何去存取数据呢 !!
几个例子你可能会用到 BeanUtils, 当然, 这是已经存在的项目了
∙BSF: Script Language 和 Java Object Model 之间
∙Velocity/ JSP: 使用 template 建立相似的网页
∙jakarta taglibs/ Struts/ Cocoon: 建立自己特殊的 Tag Libraries for JSP 或 XSP
∙ant build.xml/ tomcat server.xml: XML-based 的 设定档案 ( configuration resources )
你大可以使用 java api 中的 java.lang.reflect 及 java.beans 来达到这些数据交换 ~~ 不过呢, 难度有点高 ,但是, BeanUtils 将会减低你开发的时间 !!
目前最新的 stable 版本为 1.7.0 (2003/2/18 released),
BeanUtils 的 Java API 主要的 package 总共四项
1.org.apache.commons.beanutils
2.org.apache.commons.beanutils.converters
3.org.apache.commons.beanutils.locale
4.org.apache.commons.beanutils.locale.converters
其实除了第一项之外, 其它的都是后来版本才加上去的, converters 就是专门处理不同传入的 object 该如何转换, locale 呢, 就是为了国际化的处理, 所以重点我都会摆在第一项!!
而其中最常用到的 class 是 PropertyUtils 及 ConvertUtils 还有 DynaBeans( 有用 struts dynaform 的应该不陌生 )
BeanUtils.PropertyUtils 介绍
基本上, 我假设大家对 JavaBean 的开发都没有问题, 就是 对 getters 及 setters 都了解是什么. 先假设,
Employee.java
public class Employee {
public Address getAddress(String type);
public void setAddress(String type, Address address);
public Employee getSubordinate(int index);
public void setSubordinate(int index, Employee subordinate);
public String getFirstName();
public void setFirstName(String firstName);
public String getLastName();
public void setLastName(String lastName);
}
在 PropertyUtils 中会区分为三种 method 状态
∙Simple - 如果你是用到 primitive 语法, 如 int, String 或其它自行开发的 objects 等等, 只需要单一的对象就可以取得数据
∙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");
.............
PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
PropertyUtils.setSimpleProperty(employee, "lastName", lastName);
∙Indexed - 如果你是用到 Collection 或 List 实作出来的 objects , 只需要使用一个 index 数值就可以取得数据的型态
∙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);
Employee employee = ...;
int index = ...;
Employee subordinate = (Employee)
PropertyUtils.getIndexedProperty(employee, "subordinate", index);
∙Mapped - 如果你是用到 Map 延伸出来的 objects , 只需要使用一个 key 值就可以取得资料
∙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)的数据结构, 你该如何取得你要的数据呢
PropertyUtils.getNestedProperty(Object bean, String name)
PropertyUtils.setNestedProperty(Object bean, String name, Object value)
你只需要简单地使用 ".", 就可以得到你要的数据了
String city = (String)
PropertyUtils.getNestedProperty(employee, "address(home).city");
千万要记住, BeanUtils 是要让你随心所欲使用, 所以呢 index , mapped 当然都可以这样使用
Employee employee = ...;
String city = (String)
PropertyUtils.getProperty(employee, "subordinate[3].address(home).city");
BeanUtils.DynaBean and BeanUtils.DynaClass 介绍
所有的 Dynamic JavaBean 都是实作 DynaBean 或 DynaClass 这两个 interface, 也可能会用到 DynaProperty class 来存取 properties . 我们为何要用到 Dynamic JavaBean 呢, 例如, 你从数据库捞出来的数据, 有时候可能是三个字段, 有时候是四个字段, 如果我们对于每个 Bean 都要去写一个 class, 就会很累, 所以对于每一种 javabean 我们就设定他的属性有哪些, 接着就可以使用 PropertyUtils 来将他的数值取出, 如此, 可以减少很多开发工时. 在 Struts 的课程中, 很多人问到我, 请问每一个 ActionForm 都必须写成 java 档吗, 当然, 不需要的, 否则一个网页一个 ActionForm ( 假设都不一样 ), 那么, 这么浪费时间的工作, 为何还要使用 Struts 来作为 Framework 呢, 所以我们都是使用 org.apache.struts.action.DynaActionForm!!
MutableDynaClass 这是一个 DynaClass, 是为了动态可以调整 properties !
∙BasicDynaBean and BasicDynaClass - 基本的 Dynamic 型态
∙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
∙ResultSetDynaClass(java.sql.ResultSet resultSet)
ResultSetDynaClass(java.sql.ResultSet resultSet, boolean lowerCase)
如果 lowerCase 设为 false , 回传的数据域位名将根据 JDBC 回传的为准. default 为 true.
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()) {
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
∙RowSetDynaClass(java.sql.ResultSet resultSet)
RowSetDynaClass(java.sql.ResultSet resultSet, boolean lowerCase)
如果 lowerCase 设为 false , 回传的数据域位名将根据 JDBC 回传的为准. default 为 true.
Connection conn = ...; // Acquire connection from pool
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT ...");
RowSetDynaClass rsdc = new RowSetDynaClass(rs);
rs.close();
stmt.close();
...; // Return connection to pool
List rows = rsdc.getRows();
...; // Process the rows as desired
∙WrapDynaBean and WrapDynaClass - 包装过的 Dynamic JavaBean
如果你对于 DynaBean 的功能强大, 非常佩服的同时, 手边的 JavaBean 又不能随随便便就不用 那你就把他包装起来 ....
∙WrapDynaClass(java.lang.Class beanClass)
∙WrapDynaBean(java.lang.Object instance)
ConvertingWrapDynaBean(java.lang.Object instance)
MyBean bean = ...;
DynaBean wrapper = new WrapDynaBean(bean);
String firstName = wrapper.get("firstName");
BeanUtils.ConvertUtils 介绍
在很多情况, 例如 struts framework 中, 就常常用到 request.getParameter 的参数, 需要转换成 正确的数据型态, 所以 ConvertUtils 就是来处理这些动作.
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);// it will use ConvertUtils for convertings
目前支持的型态有
∙java.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
也可以建立自己的 converter
Converter myConverter =
new org.apache.commons.beanutils.converter.IntegerConverter();
ConvertUtils.register(myConverter, Integer.TYPE);
// Native type
ConvertUtils.register(myConverter, Integer.class);
// Wrapper class