Apache Common BeanUtils

目前 Commons 简介
     目前已经开发有 release 出来的版本有 BeanUtils, Betwixt, CLI, Collections, DBCP, Digester, Discovery, EL, FileUpload, HttpClient, Jelly, Jexl, JXPath, Lang, Latka, Logging, Modeler, Net, Pool, Validator 等等 

     每个版本都不太一样, 随时都有更新的可能, 至于还没有 release 出来正式的版本, 有一些项目, 可能也正在 使用了 !! 也是有可能因为其他项目做出来的一些元件, 可以抽出来共用的, 例如目前 struts 用的 Resources ( Resource bundle component ) , 也被列入 SandBox 研发中, 准备 release 更符合所有项目的 组件. 

     jakarta 为何要有 commons 这个 project 出现, 就是希望大家不用重复开发一样的组件, 达到 reusable 的 目的 !! 而且他们都有容易使用的特性, 也是各个 jakarta committer 牛人们的精华杰作, 因此, 绝对不能错 过这一个 open source project !! 各位亲爱的 java 同胞们 .................

BeanUtils 介绍
     当我在选择要先介绍哪一个组件, 实在犹豫了很久, 因为每一个实在都是精华, 久久无法做出决定, 所以呢, 只好按照是否 release 再按照字母的先后, 做一个排序, 希望大家明白 ....

所谓 BeanUtils 为何要开发呢, 每个工程师或许在写 JavaBean 的时候, 都会乖乖地去写 getters 和 setters, 就是 getXXX() 及 setXXX() methods, 但是当你的 object 是动态产生的, 也许是用文件, 也许是 其他原因, 那你该如何去存取数据呢 !! 

     几个例子你可能会用到 BeanUtils, 当然, 这是已经存在的项目了

     你大可以使用 java api 中的 java.lang.reflect 及 java.beans 来达到这些数据交换 ~~ 不过呢, 难度有点 高 =.="" ,但是, BeanUtils 将会减低你开发的时间 !! 

     目前最新的版本为 1.6.1 (2003/2/18 released), 下载位置为 Binary & Source

BeanUtils API 介绍
     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 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 中会区分为三种 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 ( since $1.5 ) 这是蛮新的一个 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

 

     目前支持的类型有

  • 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

posted on 2009-09-19 00:16 张平辉 阅读(329) 评论(0)  编辑  收藏 所属分类: JAVA


只有注册用户登录后才能发表评论。


网站导航:
 
<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

导航

统计

留言簿

文章分类

文章档案

搜索

最新评论