Chinaunix首页 | 论坛 | 博客
  • 博客访问: 29960785
  • 博文数量: 708
  • 博客积分: 12163
  • 博客等级: 上将
  • 技术积分: 8240
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-04 20:59
文章分类

全部博文(708)

分类: Java

2008-06-23 14:41:02

Beanutils用了魔术般的反射技术,实现了很多夸张有用的功能,都是C/C++时代不敢想的。无论谁的项目,始终一天都会用得上它。我算是后知后觉了,第一回看到它的时候居然错过。


1.属性的动态getter,setter
在这框架满天飞的年代,不能事事都保证执行getter,setter函数了,有时候属性是要需要根据名字动态的取得的,就像这样:

  
BeanUtils.getProperty(myBean,"code");

而BeanUtils更强的功能是直接访问内嵌对象的属性,只要使用逗号分割。
BeanUtils.getProperty(orderBean, "address.city");
其他类库的BeanUtils通常都很简单,不能访问内嵌的对象,所以经常要用Jakata的BeanUtils替换它们。

BeanUtils还支持List和Map类型的属性。如下面的语法即可取得顾客列表中第一个顾客的名字

BeanUtils.getProperty(orderBean, "customers[1].name");

其中BeanUtils会使用ConvertUtils类把字符串转为Bean属性的真正类型,方便从HttpServletRequest等对象中提取bean,或者把bean输出到页面。

而PropertyUtils就会原色的保留Bean原来的类型。


2.beanCompartor 动态排序
还是通过反射,动态设定Bean按照哪个属性来排序,而不再需要在bean的Compare接口进行复杂的条件判断。 List peoples = ...; // Person对象的列表 Collections.sort(peoples, new BeanComparator("age")); }}} 如果要支持多个属性的复合排序,如"Order By lastName,firstName"


ArrayList sortFields = new ArrayList();
sortFields.add(new BeanComparator("lastName"));
sortFields.add(new BeanComparator("firstName"));
ComparatorChain multiSort = new ComparatorChain(sortFields);
Collections.sort(rows,multiSort);

其中ComparatorChain属于jakata commons-collections包。
如果age属性不是普通类型,构造函数需要再传入一个comparator对象为age变量排序。


3.Converter 把Request中的字符串转为实际类型对象
经常要从request,resultSet等对象取出值来赋入bean中,下面的代码谁都写腻了,如果不用MVC框架的绑定功能的话。
   String a = request.getParameter("a");
   bean.setA(a);
   String b = ....

不妨改为
     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);//这个太有用了

//和这个相反转换的是map = BeanUtils.describe(bean);//这个也是

其中BeanUtils的populate方法或者getProperty,setProperty方法其实都会调用convert进行转换。
但Converter只支持一些基本的类型,甚至连java.util.Date类型也不支持。而且它比较笨的一个地方是当遇到不认识的类型时,居然会抛出异常来。

对于Date类型,我参考它的sqldate类型实现了一个Converter,而且添加了一个设置日期格式的函数。要把这个Converter注册,需要如下语句:


ConvertUtilsBean convertUtils = new ConvertUtilsBean();
    DateConverter dateConverter = new DateConverter();
    convertUtils.register(dateConverter,Date.class);
     //因为要注册converter,所以不能再使用BeanUtils的静态方法了,必须创建BeanUtilsBean实例

     BeanUtilsBean beanUtils = new BeanUtilsBean(convertUtils,new PropertyUtilsBean());
     beanUtils.setProperty(bean, name, value);

!4 其他功能

4.1 PropertyUtils,当属性为Collection,Map时的动态读取:
 
Collection: 提供index
{{{ BeanUtils.getIndexedProperty(orderBean,"items",1);
或者
  BeanUtils.getIndexedProperty(orderBean,"items[1]");
Map: 提供Key Value

BeanUtils.getMappedProperty(orderBean, "items","111");//key-value goods_no=111

或者

BeanUtils.getMappedProperty(orderBean, "items(111)");
4.2 PropertyUtils,获取属性的Class类型

     public static Class getPropertyType(Object bean, String name)
4.3 ConstructorUtils,动态创建对象

      public static Object invokeConstructor(Class klass, Object arg)
4.4 DynaClass动态类



其中ComparatorChain属于jakata commons-collections包。 经常要从request,resultSet等对象取出值来赋入bean中,下面的代码谁都写腻了,如果不用MVC框架的绑定功能的话。 不妨改为 其中BeanUtils的populate方法或者getProperty,setProperty方法其实都会调用convert进行转换。 或者 4.2 PropertyUtils,获取属性的Class类型

 

我的实验代码:

NestTest.java

/**
 *
 */

package testbeanutils;

import java.util.Date;

/**
 * @author QiBaiQuan
 *
 */

public class NestTest {
    
    private int number;
    
    private Date date;

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
    
    

}

 

Properties.java

/**
 *
 */

package testbeanutils;

/**
 * @author QiBaiQuan
 *
 */

public class Properties {

    private String id;
    
    private String name;
    
    private NestTest nt;

    public NestTest getNt() {
        return nt;
    }

    public void setNt(NestTest nt) {
        this.nt = nt;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    
    
}

 

TestMain.java

/**
 *
 */

package testbeanutils;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

/**
 * @author QiBaiQuan
 *
 */

public class TestMain {

    /**
     * @param args
     */

    public static void main(String[] args) {

        Properties p = new Properties();
        Map map = new HashMap();
        
        p.setId("123");
        p.setName("qbq");
        
        try {
            
            map = BeanUtils.describe(p);
            
            System.out.println(map.get("id"));
            System.out.println(map.get("name"));
            
            map.remove("id");
            map.put("id", "321");
            map.remove("name");
            map.put("name", "abc");
            
            //Test : property isn't in BEAN p but in MAP map

            //No exception !

            map.put("test", "aaa");
            
            //Test : nest BEAN nt in BEAN p

            map.put("number", 2);
            map.put("date", new Date());
            
            BeanUtils.populate(p, map);
            
            //The nest BEAN nt in BEAN p

            //This sentence is very important, otherwise the next sentence will not work

            //Because the PROPERTY nt in BEAN p is null

            p.setNt(new NestTest());
            BeanUtils.populate(p.getNt(), map);
            
            System.out.println(p.getId());
            System.out.println(p.getName());
            System.out.println(p.getNt().getNumber());
            System.out.println(p.getNt().getDate().toString());
            
            
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block

            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block

            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block

            e.printStackTrace();
        }
        
    }

}

阅读(883) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~