目前 Commons 簡(jiǎn)介
目前已經(jīng)開發(fā)有 release 出來(lái)的版本有 BeanUtils, Betwixt, CLI, Collections, DBCP, Digester, Discovery, EL, FileUpload, HttpClient, Jelly, Jexl, JXPath, Lang, Latka, Logging, Modeler, Net, Pool, Validator 等等
每個(gè)版本都不太一樣, 隨時(shí)都有更新的可能, 至于還沒有 release 出來(lái)正式的版本, 有一些項(xiàng)目, 可能也正在 使用了 !! 也是有可能因?yàn)槠渌?xiàng)目做出來(lái)的一些元件, 可以抽出來(lái)共用的, 例如目前 struts 用的 Resources ( Resource bundle component ) , 也被列入 SandBox 研發(fā)中, 準(zhǔn)備 release 更符合所有項(xiàng)目的 組件.
jakarta 為何要有 commons 這個(gè) project 出現(xiàn), 就是希望大家不用重復(fù)開發(fā)一樣的組件, 達(dá)到 reusable 的 目的 !! 而且他們都有容易使用的特性, 也是各個(gè) jakarta committer 牛人們的精華杰作, 因此, 絕對(duì)不能錯(cuò) 過(guò)這一個(gè) open source project !! 各位親愛的 java 同胞們 .................
BeanUtils 介紹
當(dāng)我在選擇要先介紹哪一個(gè)組件, 實(shí)在猶豫了很久, 因?yàn)槊恳粋€(gè)實(shí)在都是精華, 久久無(wú)法做出決定, 所以呢, 只好按照是否 release 再按照字母的先后, 做一個(gè)排序, 希望大家明白 ....
所謂 BeanUtils 為何要開發(fā)呢, 每個(gè)工程師或許在寫 JavaBean 的時(shí)候, 都會(huì)乖乖地去寫 getters 和 setters, 就是 getXXX() 及 setXXX() methods, 但是當(dāng)你的 object 是動(dòng)態(tài)產(chǎn)生的, 也許是用文件, 也許是 其他原因, 那你該如何去存取數(shù)據(jù)呢 !!
幾個(gè)例子你可能會(huì)用到 BeanUtils, 當(dāng)然, 這是已經(jīng)存在的項(xiàng)目了
你大可以使用 java api 中的 java.lang.reflect 及 java.beans 來(lái)達(dá)到這些數(shù)據(jù)交換 ~~ 不過(guò)呢, 難度有點(diǎn) 高 =.="" ,但是, BeanUtils 將會(huì)減低你開發(fā)的時(shí)間 !!
目前最新的版本為 1.6.1 (2003/2/18 released),
下載位置為
Binary &
Source
BeanUtils API 介紹
BeanUtils 的 Java API 主要的 package 總共四項(xiàng)
- org.apache.commons.beanutils
- org.apache.commons.beanutils.converters
- org.apache.commons.beanutils.locale
- org.apache.commons.beanutils.locale.converters
其實(shí)除了第一項(xiàng)之外, 其他的都是后來(lái)的版本才加上去的, converters 就是專門處理不同傳入的 object 該如 何轉(zhuǎn)換, locale 呢, 就是為了國(guó)際化的處理, 所以重點(diǎn)我都會(huì)擺在第一項(xiàng)!!
而其中最常用到的 class 是 PropertyUtils 及 ConvertUtils 還有 DynaBeans( 有用 struts dynaform 的應(yīng) 該不陌生 )
BeanUtils.PropertyUtils 介紹
基本上, 我假設(shè)大家對(duì) JavaBean 的開發(fā)都沒有問題, 就是對(duì) getters 及 setters 都了解是什么. 先假設(shè), Employee class
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 中會(huì)區(qū)分為三種 method 狀態(tài)
- Simple - 如果你是用到 primitive 語(yǔ)法, 如 int, String 或其他自行開發(fā)的 objects 等等, 只需要單一的對(duì)象就可以取得數(shù)據(jù)
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 實(shí)作出來(lái)的 objects , 只需要使用一個(gè) index 數(shù)值就可以取得對(duì)象的狀態(tài)
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 延伸出來(lái)的 objects , 只需要使用一個(gè) key 值就可以取 得數(shù)據(jù)
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)的數(shù)據(jù)結(jié)構(gòu), 你該如何取得你要的數(shù)據(jù)呢
PropertyUtils.getNestedProperty(Object bean, String name)
PropertyUtils.setNestedProperty(Object bean, String name, Object value)
你只需要簡(jiǎn)單地使用 ".", 就可以得到你要的數(shù)據(jù)了
String city = (String)
PropertyUtils.getNestedProperty(employee, "address(home).city");
千萬(wàn)要記住, BeanUtils 是要讓你隨心所欲使用, 所以呢 index , mapped 當(dāng)然都可以這樣使用
Employee employee = ...;
String city = (String) PropertyUtils.getProperty(employee,
"subordinate[3].address(home).city");
BeanUtils.DynaBean and BeanUtils.DynaClass 介紹
所有的 Dynamic JavaBean 都是實(shí)現(xiàn) DynaBean 或 DynaClass 這兩個(gè) interface, 也可能會(huì)用到 DynaProperty class 來(lái)存取 properties . 我們?yōu)楹我玫?Dynamic JavaBean 呢, 例如, 你從數(shù)據(jù)庫(kù)取出來(lái) 的數(shù)據(jù), 有時(shí)候可能是三個(gè)欄位, 有時(shí)候是四個(gè)欄位, 如果我們對(duì)于每個(gè) Bean 都要去寫一個(gè) class, 就會(huì)很 累, 所以對(duì)于每一種 javabean 我們就設(shè)定他的屬性有哪些, 接著就可以使用 PropertyUtils 來(lái)將他的數(shù)值取 出, 如此, 可以減少很多開發(fā)工時(shí). 在 Struts 的課程中, 很多人問到我, 請(qǐng)問每一個(gè) ActionForm 都必須寫 成 java 文件嗎, 當(dāng)然, 不需要的, 否則一個(gè)網(wǎng)頁(yè)一個(gè) ActionForm ( 假設(shè)都不一樣 ), 那么, 這么浪費(fèi)時(shí)間 的工作, 為何還要使用 Struts 來(lái)作為 Framework 呢, 所以我們都是使用 org.apache.struts.action.DynaActionForm!!
MutableDynaClass ( since $1.5 ) 這是蠻新的一個(gè) DynaClass, 是為了動(dòng)態(tài)可以調(diào)整 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 設(shè)為 false , 返回的數(shù)據(jù)欄位名將根據(jù) JDBC 返回的為準(zhǔn). 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 設(shè)為 false , 返回的數(shù)據(jù)欄位名將根據(jù) JDBC 返回的為準(zhǔn). 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 - 包裝過(guò)的 Dynamic JavaBean
如果你對(duì)于 DynaBean 的功能強(qiáng)大, 非常佩服的同時(shí), 手邊的 JavaBean 又不能隨隨便便就不用 那 你就把他包裝起來(lái) ....
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 的參數(shù), 需要轉(zhuǎn)換成 正確的數(shù)據(jù)類型, 所以 ConvertUtils 就是來(lái)處理這些動(dòng)作.
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
目前支持的類型有
- 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
也可以建立自己的 converter
Converter myConverter =
new org.apache.commons.beanutils.converter.IntegerConverter();
ConvertUtils.register(myConverter, Integer.TYPE); // Native type
ConvertUtils.register(myConverter, Integer.class); // Wrapper class