设为首页 收藏本站
查看: 1284|回复: 0

[经验分享] Apache Commons Beanutils 二 (动态Bean

[复制链接]

尚未签到

发表于 2017-12-24 20:45:16 | 显示全部楼层 |阅读模式
相关背景
  上一篇介绍了PropertyUtils的用法,PropertyUtils主要是在不修改bean结构的前提下,动态访问bean的属性;
  但是有时候,我们会经常希望能够在不定义一个Java类的前提下,动态决定这个类中包含哪些属性,并动态访问它们的属性值,比较典型的使用场景是作为SQL查询的结果集的bean;
  为了支持以上特性,Apache Commons Beanutils包为我们提供了DynaBean接口、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 Employee[]{...});  
employee.set(
"firstName", "Fred");  
employee.set(
"lastName", "Flintstone");  

  
DynaBean employee
= ...; // 具体的DynaBean实现类  
      
  
String firstName = (String) employee.get("firstName");
  
Address homeAddress = (Address) employee.get("address", "home");
  
Object subordinate = employee.get("subordinate", 2);
  

  由于DynaBean和DynaClass都是接口,它们可以有多种实现形式,应用于多种场景。
  接下来,会介绍在Apache Commons Beanutils包下,DynaBean和DynaClass接口不同的实现类;
  当然,我们也可以自定义实现类来满足我们特定的需求;

基础实现类:BasicDynaBean和BasicDynaClass
  先了解下这两个重要的实现,这两个类为DynaBean和DynaClass接口的基础实现类;
  首先,我们可以这样创建一个DynaClass实例,其中类的成员属性是用DynaProperty类来描述的:
  

        DynaProperty[] props = new DynaProperty[]  
{
  

new DynaProperty("address", java.util.Map.class),  

new DynaProperty("subordinate", Employee[].class),  

new DynaProperty("firstName", String.class),  

new DynaProperty("lastName", String.class)  
};
  
BasicDynaClass dynaClass
= new BasicDynaClass("employee", null, props);  

  注意这里的Class<?> dynaBeanClass参数为空,看下源码就发现,如果为null的话,默认会使用BasicDynaBean.class;
  有了BasicDynaClass实例后,我们就可以开始创建DynaBean实例了,并且可以调用DynaBean接口中定义的方法,如get和set来读写属性值,如下所示:
  

        DynaBean employee = dynaClass.newInstance();  
employee.set(
"address", new HashMap<String, Object>());  
employee.set(
"subordinate", new Employee[0]);  
employee.set(
"firstName", "Fred");  
employee.set(
"lastName", "Flintstone");  

  System.out.println(employee.get("firstName"));

实现类:ResultSetDynaClass,处理数据库查询结果集
  ResultSetDynaClass主要用于包装java.sql.ResultSet,即SQL查询时候返回的结果集;
  不使用DynaBean的话,通常我们是这样处理的:
  

            String sql = "SELECT>
stmt = conn.prepareStatement(sql);  
ResultSet rs
= stmt.executeQuery(sql);  

  

while (rs.next())  
{
  
Long>= rs.getLong("id");  
String name
= rs.getString("name");  
String address
= rs.getString("address");  

boolean state = rs.getBoolean("state");  

  
System.out.print(
"id: " +>
System.out.print(
", name: " + name);  
System.out.print(
", address: " + address);  
System.out.println(
", state: " + state);  
}
  

  使用ResultSetDynaClass的话,我们可以这样做:
  

            String sql = "SELECT>
stmt = conn.prepareStatement(sql);  
ResultSet rs
= stmt.executeQuery(sql);  
Iterator
<DynaBean> rows = (new ResultSetDynaClass(rs)).iterator();  

while (rows.hasNext())  
{
  
DynaBean row
= rows.next();  
System.out.print(
"id: " + row.get("id"));  
System.out.print(
", name: " + row.get("name"));  
System.out.print(
", address: " + row.get("address"));  
System.out.println(
", state: " + row.get("state"));  
}
  

  完整示例:

DSC0000.gif DSC0001.gif   

/*  
* File Name: ResultSetDyna.java
  
* Description:
  
* Author: PiChen
  
* Create Date: 2017年5月30日
  

*/  
package apache.commons.beanutils.example.dynabeans;
  

  
import java.sql.Connection;
  
import java.sql.DriverManager;
  
import java.sql.PreparedStatement;
  
import java.sql.ResultSet;
  
import java.sql.SQLException;
  
import java.util.Iterator;
  

  
import org.apache.commons.beanutils.DynaBean;
  
import org.apache.commons.beanutils.ResultSetDynaClass;
  

  
/**
  
*
  
* @author PiChen
  
* @version 2017年5月30日
  
*/
  


  
public>  
{
  
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
  
static final String DB_URL = "jdbc:mysql://localhost/demo";
  

  
static final String USER = "root";
  
static final String PASS = "root";
  

  
public static void main(String[] args)
  
{
  
Connection conn = null;
  
PreparedStatement stmt = null;
  
try
  
{
  
Class.forName("com.mysql.jdbc.Driver");
  

  
conn = DriverManager.getConnection(DB_URL, USER, PASS);
  

  
String sql = "SELECT>  
stmt = conn.prepareStatement(sql);
  

  
ResultSet rs = stmt.executeQuery(sql);
  

  
// while (rs.next())
  
// {
  
// Long>  
// String name = rs.getString("name");
  
// String address = rs.getString("address");
  
// boolean state = rs.getBoolean("state");
  
//
  
// System.out.print("id: " +>  
// System.out.print(", name: " + name);
  
// System.out.print(", address: " + address);
  
// System.out.println(", state: " + state);
  
// }
  

  
Iterator<DynaBean> rows = (new ResultSetDynaClass(rs)).iterator();
  
while (rows.hasNext())
  
{
  
DynaBean row = rows.next();
  
System.out.print("id: " + row.get("id"));
  
System.out.print(", name: " + row.get("name"));
  
System.out.print(", address: " + row.get("address"));
  
System.out.println(", state: " + row.get("state"));
  
}
  

  
rs.close();
  
stmt.close();
  
conn.close();
  
}
  
catch (SQLException se)
  
{
  
se.printStackTrace();
  
}
  
catch (Exception e)
  
{
  
e.printStackTrace();
  
}
  
finally
  
{
  
try
  
{
  
if (stmt != null)
  
stmt.close();
  
}
  
catch (SQLException se2)
  
{
  
}
  
try
  
{
  
if (conn != null)
  
conn.close();
  
}
  
catch (SQLException se)
  
{
  
se.printStackTrace();
  
}
  
}
  
}
  

  
}
  


View Code
实现类:RowSetDynaClass,处理数据库查询结果集,连接关闭后仍可使用
  ResultSetDynaClass作为SQL查询结果集中的一个动态bean非常实用,但是仍然有一个严重的缺陷,就是使用ResultSetDynaClass的前提是要保证ResultSet一直处于打开状态,这对于分层结构的Web项目来说是非常不便的,因为我们经常需要将数据从dao层传到service层传到view层,而ResultSet在DAO层使用后往往会关闭掉;
  为解决这个问题,引入了RowSetDynaClass实现类,与ResultSetDynaClass不同的是,它会自己在内存中拷贝一份数据,这样就保证了即使ResultSet关闭后,数据也能一直被访问到;不过同样也有缺点就是需要消耗性能用于拷贝数据以及占用堆内存空间;
  如下是一个示例:
  

          >

  
conn
= DriverManager.getConnection(DB_URL, USER, PASS);  

  
String sql
= "SELECT>
stmt
= conn.prepareStatement(sql);  

  
ResultSet rs
= stmt.executeQuery(sql);  

  
RowSetDynaClass rowSet
= new RowSetDynaClass(rs);  

  
rs.close();
  
stmt.close();
  
conn.close();
  

  
List
<DynaBean> rowlist = rowSet.getRows();  

for (DynaBean row : rowlist)  
{
  
System.out.print(
"id: " + row.get("id"));  
System.out.print(
", name: " + row.get("name"));  
System.out.print(
", address: " + row.get("address"));  
System.out.println(
", state: " + row.get("state"));  
}
  

  完整示例:


  

/*  
* File Name: ResultSetDyna.java
  
* Description:
  
* Author: PiChen
  
* Create Date: 2017年5月30日
  

*/  
package apache.commons.beanutils.example.dynabeans;
  

  
import java.sql.Connection;
  
import java.sql.DriverManager;
  
import java.sql.PreparedStatement;
  
import java.sql.ResultSet;
  
import java.sql.SQLException;
  
import java.util.List;
  

  
import org.apache.commons.beanutils.DynaBean;
  
import org.apache.commons.beanutils.RowSetDynaClass;
  

  
/**
  
*
  
* @author PiChen
  
* @version 2017年5月30日
  
*/
  


  
public>  
{
  
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
  
static final String DB_URL = "jdbc:mysql://localhost/demo";
  

  
static final String USER = "root";
  
static final String PASS = "root";
  

  
public static void main(String[] args)
  
{
  
Connection conn = null;
  
PreparedStatement stmt = null;
  
try
  
{
  
Class.forName("com.mysql.jdbc.Driver");
  

  
conn = DriverManager.getConnection(DB_URL, USER, PASS);
  


  
String sql = "SELECT>  
stmt = conn.prepareStatement(sql);
  

  
ResultSet rs = stmt.executeQuery(sql);
  

  
RowSetDynaClass rowSet = new RowSetDynaClass(rs);
  

  
rs.close();
  
stmt.close();
  
conn.close();
  

  
List<DynaBean> rowlist = rowSet.getRows();
  
for (DynaBean row : rowlist)
  
{
  
System.out.print("id: " + row.get("id"));
  
System.out.print(", name: " + row.get("name"));
  
System.out.print(", address: " + row.get("address"));
  
System.out.println(", state: " + row.get("state"));
  
}
  
}
  
catch (SQLException se)
  
{
  
se.printStackTrace();
  
}
  
catch (Exception e)
  
{
  
e.printStackTrace();
  
}
  
finally
  
{
  
try
  
{
  
if (stmt != null)
  
stmt.close();
  
}
  
catch (SQLException se2)
  
{
  
}
  
try
  
{
  
if (conn != null)
  
conn.close();
  
}
  
catch (SQLException se)
  
{
  
se.printStackTrace();
  
}
  
}
  
}
  

  
}
  


View Code
实现类:WrapDynaBean和WrapDynaClass,包装普通bean
  使用WrapDynaBean,我们可以将普通的javabean包装成DynaBean,并非常简便的使用DynaBean提供的API方法来访问bean成员属性
  示例:
  

        Employee e = new Employee();  
e.setFirstName(
"hello");  

  
DynaBean wrapper
= new WrapDynaBean(e);  
String firstName
= (String) wrapper.get("firstName");  
System.out.println(firstName);
  

  注意,以上代码中,会间接的创建了WrapDynaClass实例,我们不需要直接处理它;

实现类:Lazy DynaBeans,简单易用的DynaBean实现
  Lazy DynaBeans,正如其名,可以让我们省去很多工作,更加人性化的去使用DynaBean,
  Lazy DynaBeans有如下特性:
  1、自动添加bean属性,当我们调用set(name, value)方法时,如果属性不存在,会自动添加该属性;
  2、List、Array属性自动扩容,
  3、List、Array属性里的内部元素可以自动创建,实例化
  4、Map属性也可以自动创建,实例化
  5、...
  简单的说,使用Lazy DynaBeans的话,你可以大胆调用DynaBean的set、get方法,而不必担心没有属性不存在,集合数组空间不够等问题,Lazy DynaBeans会帮我们自动处理;
  如下是一个LazyDynaBean例子:
  

        DynaBean dynaBean = new LazyDynaBean();  

  
dynaBean.set(
"foo", "bar");                   // simple  

  
dynaBean.set("customer", "title", "Mr");      // mapped
  
dynaBean.set("customer", "surname", "Smith"); // mapped
  

  
dynaBean.set("users", 0, new User());     // indexed
  
dynaBean.set("users", 1, new User());     // indexed
  
dynaBean.set("users", 2, new User());     // indexed
  
        
  
System.out.println(dynaBean.get("customer", "title"));
  

  如下是一个LazyDynaMap例子:
  

       DynaBean dynaBean = new LazyDynaMap();  

  
dynaBean.set(
"foo", "bar");                   // simple  

  
dynaBean.set("customer", "title", "Mr");      // mapped
  
dynaBean.set("customer", "surname", "Smith"); // mapped
  

  
dynaBean.set("users", 0, new User());     // indexed
  
dynaBean.set("users", 1, new User());     // indexed
  
dynaBean.set("users", 2, new User());     // indexed
  
        
  
System.out.println(dynaBean.get("customer", "title"));
  

  
//转成Map对象
  
Map<String, Object> myMap = ((LazyDynaBean) dynaBean).getMap();
  
System.out.println(myMap);
  

  LazyDynaList例子,详见API文档
  

  LazyDynaList dynaBean = new LazyDynaList();  
dynaBean.setElementType(User.
class);  

  
User u
= new User();  
u.setName(
"hello");  

  
dynaBean.add(
1, u);  

  
System.out.println(dynaBean.size());
  

  
User[] users
= (User[])dynaBean.toArray();//转化为数组  
System.out.println(users[1].getName());
  

  
WrapDynaBean w = (WrapDynaBean) dynaBean.get(1);
  
System.out.println(w.get("name"));
  

  LazyDynaClass示例:
  Lazy DynaBeans可以让我们不受控制的添加任意类型的bean属性,但是有时候,我们还是希望能控制某个bean属性的数据类型,如下,是一个示例:
  

        MutableDynaClass dynaClass = new LazyDynaClass();    // create DynaClass  

  
dynaClass.add("amount", java.lang.Integer.class);    // add property
  
dynaClass.add("users", User[].class);          // add indexed property
  
dynaClass.add("orders", TreeMap.class);   // add mapped property
  

  
DynaBean dynaBean = new LazyDynaBean(dynaClass);
  
dynaBean.set("amount_", "s");
  
dynaBean.set("amount", "s");//报错,需要为整型
  
dynaBean.set("users", 1);//报错,需要维数组
  
        
  
System.out.println(dynaBean.get("amount"));
  


参考资料
  http://commons.apache.org/proper/commons-beanutils/javadocs/v1.9.3/apidocs/org/apache/commons/beanutils/package-summary.html

源码
  https://github.com/peterchenhdu/apache-commons-beanutils-example

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-427634-1-1.html 上篇帖子: Windows 下apache https配置(phpstudy) 下篇帖子: BeanUtils.copyProperties 复制bean异常org.apache.commons.beanutils.ConversionExceptio
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表