拾贝壳

走过的路
随笔 - 39, 文章 - 1, 评论 - 14, 引用 - 0
数据加载中……

Ten Reasons Why Blogging is Good For Your Career

  1. You have to get noticed to get promoted.

  2. You have to get noticed to get hired.

  3. It really impresses people when you say “Oh, I’ve written about that, just google for XXX and I’m on the top page” or “Oh, just google my name.”

  4. No matter how great you are, your career depends on communicating. The way to get better at anything, including communication, is by practicing. Blogging is good practice.

  5. Bloggers are better-informed than non-bloggers. Knowing more is a career advantage.

  6. Knowing more also means you’re more likely to hear about interesting jobs coming open.

  7. Networking is good for your career. Blogging is a good way to meet people.

  8. If you’re an engineer, blogging puts you in intimate contact with a worse-is-better 80/20 success story. Understanding this mode of technology adoption can only help you.

  9. If you’re in marketing, you’ll need to understand how its rules are changing as a result of the current whirlwind, which nobody does, but bloggers are at least somewhat less baffled.

  10. It’s a lot harder to fire someone who has a public voice, because it will be noticed.

    from http://www.tbray.org/ongoing/When/200x/2005/03/08/BloggingIsGood

posted @ 2006-06-16 15:25 binge 阅读(296) | 评论 (0)编辑 收藏

JAVA开发者应该去的20个英文网站

http://www.javaalmanac.com

    Java开发者年鉴一书的在线版本. 要想快速查到某种Java技巧的用法及示例代码, 这是一个不错的去处.

http://www.onjava.com

    O'Reilly的Java网站. 每周都有新文章

http://java.sun.com

    官方的Java开发者网站 - 每周都有新文章发表

http://www.developer.com/java

    由Gamelan.com 维护的Java技术文章网站

http://www.java.net

    Sun公司维护的一个Java社区网站

http://www.builder.com

    Cnet的Builder.com网站 - 所有的技术文章, 以Java为主.

http://www.ibm.com/developerworks/java

    IBM的Developerworks技术网站; 这是其中的Java技术主页

http://www.javaworld.com

    最早的一个Java站点. 每周更新Java技术文章

http://www.devx.com/java

    DevX维护的一个Java技术文章网站

http://www.fawcette.com/javapro

    JavaPro在线杂志网站.

http://www.sys-con.com/java

    Java Developers Journal的在线杂志网站.

http://www.javadesktop.org

    位于Java.net的一个Java桌面技术社区网站.

http://www.theserverside.com

    这是一个讨论所有Java服务器端技术的网站.

http://www.jars.com

    提供Java评论服务. 包括各种framework和应用程序

http://www.jguru.com

    一个非常棒的采用Q&A形式的Java技术资源社区.

http://www.javaranch.com

     一个论坛,得到Java问题答案的地方,初学者的好去处。

http://www.ibiblio.org/javafaq/javafaq.html

    comp.lang.java的FAQ站点 - 收集了来自comp.lang.java新闻组的问题和答案的分类目录.

http://java.sun.com/docs/books/tutorial/

    来自SUN公司的官方Java指南 - 对于了解几乎所有的java技术特性非常有帮助.

http://www.javablogs.com

    互联网上最活跃的一个Java Blog网站.

http://java.about.com/

转自51cto

posted @ 2006-06-16 14:11 binge 阅读(775) | 评论 (0)编辑 收藏

JTA和JDBC事务

 一般情况下,J2EE应用服务器支持JDBC事务、JTA事务、容器管理事务。这里讨论JTA和JDBC事务的区别。这2个是常用的DAO模式事务界定方式。
JDBC 事务
 JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。
★ 在jdbc中,事务操作缺省是自动提交。也就是说,一条对数据库的更新表达式代表一项事务操作,操作成功后,系统将自动调用commit()来提交,否则将调用rollback()来回滚。
★ 在jdbc中,可以通过调用setAutoCommit(false)来禁止自动提交。之后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()来进行整体提交,倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响应的异常;此时就可以在异常捕获时调用rollback()进行回滚。这样做可以保持多次更新操作后,相关数据的一致性,示例如下:

    try {

conn = 

DriverManager.getConnection    

("jdbc:oracle:thin:@host:1521:SID","username","userpwd";

       conn.setAutoCommit(false);//禁止自动提交,设置回滚点

       stmt = conn.createStatement();

stmt.executeUpdate(“alter table …”); //数据库更新操作1

stmt.executeUpdate(“insert into table …”); //数据库更新操作2

       conn.commit(); //事务提交

     }catch(Exception ex) {    

         ex.printStackTrace();

         try {

          conn.rollback(); //操作不成功则回滚

          }catch(Exception e) {

e.printStackTrace();

           }

}

 JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。
JTA事务
 JTA(Java Transaction API) 为 J2EE 平台提供了分布式事务服务。
 要用 JTA 进行事务界定,应用程序要调用 javax.transaction.UserTransaction 接口中的方法。例如:
 utx.begin();
      // ...
      DataSource ds = obtainXADataSource();
      Connection conn = ds.getConnection();
      pstmt = conn.prepareStatement("UPDATE MOVIES ...");
      pstmt.setString(1, "Spinal Tap");
      pstmt.executeUpdate();
      // ...
      utx.commit();

 让我们来关注下面的话:
 “用 JTA 界定事务,那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。 XAConnection s 是参与 JTA 事务的 JDBC 连接。”
 要使用JTA事务,必须使用XADataSource来产生数据库连接,产生的连接为一个XA连接。
 XA连接(javax.sql.XAConnection)和非XA(java.sql.Connection)连接的区别在于:XA可以参与JTA的事务,而且不支持自动提交。
     Note:
Oracle, Sybase, DB2, SQL Server等大型数据库才支持XA, 支持分布事务。
My SQL 连本地都支持不好,更别说分布事务了。
JTA方式的实现过程
   用XADataSource产生的XAConnection它扩展了一个getXAResource()方法,事务通过这个方法把它加入到事务容器中进行管理.对于调用者来说,根本看不到事务是如果管理的,你只要声明开始事务,告诉容器我下面的操作要求事务参与了,最后告诉事务说到这儿可以提交或回滚了,别的都是黑箱操作。
 在使用JTA之前,你必须首先实现一个Xid类用来标识事务(在普通情况下这将由事务管理程序来处理)。Xid包含三个元素:formatID、gtrid(全局事务标识符)和bqual(分支修饰词标识符)。
 下面的例子说明Xid的实现:

import javax.transaction.xa.*;
public class MyXid implements Xid
{
 protected int formatId;
 protected byte gtrid[];
 protected byte bqual[];
 public MyXid()
 {
 }
 public MyXid(int formatId, byte gtrid[], byte bqual[])
 {
  this.formatId = formatId;
  this.gtrid = gtrid;
  this.bqual = bqual;
 }

 public int getFormatId()
 {
  return formatId;
 }

 public byte[] getBranchQualifier()
 {
  return bqual;
 }

 public byte[] getGlobalTransactionId()
 {
  return gtrid;
 }

}
 其次,你需要创建一个你要使用的数据库的数据源:

public DataSource getDataSource()
 throws SQLException
 {
  SQLServerDataSource xaDS = new
  com.merant.datadirect.jdbcx.sqlserver.SQLServerDataSource();
  xaDS.setDataSourceName("SQLServer");
  xaDS.setServerName("server");
  xaDS.setPortNumber(1433);
  xaDS.setSelectMethod("cursor");
  return xaDS;
}

  例1?这个例子是用“两步提交协议”来提交一个事务分支:

XADataSource xaDS;
XAConnection xaCon;
XAResource xaRes;
Xid xid;
Connection con;
Statement stmt;
int ret;
xaDS = getDataSource();
xaCon = xaDS.getXAConnection("jdbc_user", "jdbc_password");
xaRes = xaCon.getXAResource();
con = xaCon.getConnection();
stmt = con.createStatement();
xid = new MyXid(100, new byte[]{0x01}, new byte[]{0x02});
try {
  xaRes.start(xid, XAResource.TMNOFLAGS);
  stmt.executeUpdate("insert into test_table values (100)");
  xaRes.end(xid, XAResource.TMSUCCESS);
  ret = xaRes.prepare(xid);
  if (ret == XAResource.XA_OK) {
    xaRes.commit(xid, false);
   }
}
catch (XAException e) {
 e.printStackTrace();
}
finally {
 stmt.close();
 con.close();
 xaCon.close();
}
 当然,实际过程中,我们不需要写这些代码,这些代码是JTA最终的实现代码。
关于“两步提交协议”,可以参看下面的文章:
http://www.jspcn.net/htmlnews/11049371131251752.html

 http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html


选择最好的方式
用 JDBC API 进事务界定来构建 DAO 类的。这些 DAO 类可以总结如下:

事务界定代码嵌入在 DAO 类中。
DAO 类使用 JDBC API 进行事务界定。
调用者不能界定事务。
事务范围局限于单个 JDBC 连接。
JDBC 事务并不总是适合复杂的企业应用程序。如果您的事务要跨越多个 DAO 或者多个数据库,那么下列实现策略也许更合适:

事务用 JTA 界定。
事务界定代码从 DAO 中分离出来。
调用者负责界定事务。
DAO 加入一个全局事务。
JDBC 方式由于其简单性而具有吸引力,JTA 方式提供了更大的灵活性。您所选择的实现将取决于应用程序的特定需求。
XADataSource例子:
<?xml version="1.0" encoding="UTF-8"?>

<!-- ===================================================================== -->
<!--    -->
<!--  JBoss Server Configuration    -->
<!-- Thanks to Horia Muntean <horia@bvb.ro>   -->
<!-- ===================================================================== -->

<!-- $Id: db2-xa-ds.xml,v 1.1.2.1 2003/05/30 18:25:57 d_jencks Exp $ -->


<datasources>
   <!--
       XADatasource for DB2 V8.1 (app driver)
       copy $db2_install_dir/java/db2java.zip into $jboss_install_dir/server/default/lib
   -->

   <xa-datasource>
     <jndi-name>DB2XADS</jndi-name>
     <xa-datasource-class>COM.ibm.db2.jdbc.DB2XADataSource</xa-datasource-class>
     <xa-datasource-property name="DatabaseName">yout_database_name</xa-datasource-property>
     <xa-datasource-property name="User">your_user</xa-datasource-property>
     <xa-datasource-property name="Password">your_password</xa-datasource-property>
   </xa-datasource>
</datasources>

引用:
 http://www.jspcn.net/htmlnews/11049371131251752.html
http://www-128.ibm.com/developerworks/cn/java/j-dao/
http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html

 

posted @ 2006-06-15 15:53 binge 阅读(5184) | 评论 (1)编辑 收藏

JMS初读

33.2 基本的jms api概念
   33.2.1 jms api体系结构
     jms应用程序组成部分:
    a. jms提供者--------j2ee平台.
    b.jms客户端--------需要用户完成的应用程序.
    c.消息----在客户端之间传递信息的对象
   d.管理的对象----连接工厂和目的地
 33.2.2 消息域
   分为"点到点消息传递域"和"发表/订阅小心传递域"
 33.2.3 消费消息
   两种方式:同步和异步.同步直接用receive方法提取消息.异步需要可湖段为消费者注册一个见听器.通过调用见听器的onMessage方法来分发消息.
33.3 jms api编程模型
  33.3.1 管理的对象
   a.连接工厂
    通常是执行jndi查找获得连接工厂.eg:
  Context ctx= new InitialContext();
  ConnectionFactory cf=(ConnectionFactory ) ctx.lookup("jms/QueueConnectionFactory");
ConnectionFactory cf=(ConnectionFactory ) ctx.lookup("jms/TopicConnectionFactory");
 b.目的地
   在ptp中,目的地是"队列".在发表/订阅中,目的地是"主题".
  eg:
Destination mydest=(Topic)ctx.lookup("jms/mytopic");
33.3.2 连接
 连接由连接工厂来创建.eg:
Connection conn=ConnectionFactory .createConnection();
33.3.3 会话
会话 由 Connection来创建
Session session=Connection.createSession(false,Session.AUTO_ACKOWLEDGE);
事务性的会话
Session session=Connection.createSession(true,0);
33.3.4 消息生产者
由session 来创建,实现MessageProducer接口.
   MessageProducer mp=session.createProducer(myQueue);
发送动作
mp.send(message);
33.3.5 消息消费者
 由session创建,实现MessageConsumer接口.
eg:
MessageConsumer mc=session.createConsumer(myQueue);
bwt:
利用session.createDurableSubscriber可以创建长期的订阅者.
  ========获得消息==
同步方式.
connection.start();
Message m=consumer.receive();
connection.start();
Message m=consumer.receive(1000); //time out afer a second
异步方式.
构造一个消息舰艇器,用setMessageListener方法向具体的MessageConsumer中注册.eg:
  Listener myListener= new Listener ();
consumer.setMessageListener (myListener );
33.3.6 消息
分为消息头,消息属性和消息体,只有消息头是必须的.
消息头存放了可护短和提供者用来识别和路由消息的值.
常见的消息体的格式(消息类型)有5种.
 
 

posted @ 2006-05-31 22:25 binge 阅读(416) | 评论 (0)编辑 收藏

[转]一篇不错的讲解Java异常的文章

六种异常处理的陋习

  你觉得自己是一个Java专家吗?是否肯定自己已经全面掌握了Java的异常处理机制?在下面这段代码中,你能够迅速找出异常处理的六个问题吗?

  1 OutputStreamWriter out = ...

  2 java.sql.Connection conn = ...

  3 try { // ⑸

  4  Statement stat = conn.createStatement();

  5  ResultSet rs = stat.executeQuery(

  6   "select uid, name from user");

  7  while (rs.next())

  8  {

  9   out.println("ID:" + rs.getString("uid") // ⑹

  10    ",姓名:" + rs.getString("name"));

  11  }

  12  conn.close(); // ⑶

  13  out.close();

  14 }

  15 catch(Exception ex) // ⑵

  16 {

  17  ex.printStackTrace(); //⑴,⑷

  18 }

  作为一个Java程序员,你至少应该能够找出两个问题。但是,如果你不能找出全部六个问题,请继续阅读本文。

  本文讨论的不是Java异常处理的一般性原则,因为这些原则已经被大多数人熟知。我们要做的是分析各种可称为“反例”(anti-pattern)的违背优秀编码规范的常见坏习惯,帮助读者熟悉这些典型的反面例子,从而能够在实际工作中敏锐地察觉和避免这些问题。

  反例之一:丢弃异常

  代码:15行-18行。

  这段代码捕获了异常却不作任何处理,可以算得上Java编程中的杀手。从问题出现的频繁程度和祸害程度来看,它也许可以和C/C++程序的一个恶名远播的问题相提并论??不检查缓冲区是否已满。如果你看到了这种丢弃(而不是抛出)异常的情况,可以百分之九十九地肯定代码存在问题(在极少数情况下,这段代码有存在的理由,但最好加上完整的注释,以免引起别人误解)。

  这段代码的错误在于,异常(几乎)总是意味着某些事情不对劲了,或者说至少发生了某些不寻常的事情,我们不应该对程序发出的求救信号保持沉默和无动于衷。调用一下printStackTrace算不上“处理异常”。不错,调用printStackTrace对调试程序有帮助,但程序调试阶段结束之后,printStackTrace就不应再在异常处理模块中担负主要责任了。

  丢弃异常的情形非常普遍。打开JDK的ThreadDeath类的文档,可以看到下面这段说明:“特别地,虽然出现ThreadDeath是一种‘正常的情形’,但ThreadDeath类是Error而不是Exception的子类,因为许多应用会捕获所有的Exception然后丢弃它不再理睬。”这段话的意思是,虽然ThreadDeath代表的是一种普通的问题,但鉴于许多应用会试图捕获所有异常然后不予以适当的处理,所以JDK把ThreadDeath定义成了Error的子类,因为Error类代表的是一般的应用不应该去捕获的严重问题。可见,丢弃异常这一坏习惯是如此常见,它甚至已经影响到了Java本身的设计。

  那么,应该怎样改正呢?主要有四个选择:

  1、处理异常。针对该异常采取一些行动,例如修正问题、提醒某个人或进行其他一些处理,要根据具体的情形确定应该采取的动作。再次说明,调用printStackTrace算不上已经“处理好了异常”。

  2、重新抛出异常。处理异常的代码在分析异常之后,认为自己不能处理它,重新抛出异常也不失为一种选择。

  3、把该异常转换成另一种异常。大多数情况下,这是指把一个低级的异常转换成应用级的异常(其含义更容易被用户了解的异常)。

  4、不要捕获异常。

  结论一:既然捕获了异常,就要对它进行适当的处理。不要捕获异常之后又把它丢弃,不予理睬。

  反例之二:不指定具体的异常

  代码:15行。

  许多时候人们会被这样一种“美妙的”想法吸引:用一个catch语句捕获所有的异常。最常见的情形就是使用catch(Exception ex)语句。但实际上,在绝大多数情况下,这种做法不值得提倡。为什么呢?

  要理解其原因,我们必须回顾一下catch语句的用途。catch语句表示我们预期会出现某种异常,而且希望能够处理该异常。异常类的作用就是告诉Java编译器我们想要处理的是哪一种异常。由于绝大多数异常都直接或间接从java.lang.Exception派生,catch(Exception ex)就相当于说我们想要处理几乎所有的异常。

  再来看看前面的代码例子。我们真正想要捕获的异常是什么呢?最明显的一个是SQLException,这是JDBC操作中常见的异常。另一个可能的异常是IOException,因为它要操作OutputStreamWriter。显然,在同一个catch块中处理这两种截然不同的异常是不合适的。如果用两个catch块分别捕获SQLException和IOException就要好多了。这就是说,catch语句应当尽量指定具体的异常类型,而不应该指定涵盖范围太广的Exception类。

  另一方面,除了这两个特定的异常,还有其他许多异常也可能出现。例如,如果由于某种原因,executeQuery返回了null,该怎么办?答案是让它们继续抛出,即不必捕获也不必处理。实际上,我们不能也不应该去捕获可能出现的所有异常,程序的其他地方还有捕获异常的机会??直至最后由JVM处理。

  结论二:在catch语句中尽可能指定具体的异常类型,必要时使用多个catch。不要试图处理所有可能出现的异常。

  反例之三:占用资源不释放

  代码:3行-14行。

  异常改变了程序正常的执行流程。这个道理虽然简单,却常常被人们忽视。如果程序用到了文件、Socket、JDBC连接之类的资源,即使遇到了异常,也要正确释放占用的资源。为此,Java提供了一个简化这类操作的关键词finally。

  finally是样好东西:不管是否出现了异常,Finally保证在try/catch/finally块结束之前,执行清理任务的代码总是有机会执行。遗憾的是有些人却不习惯使用finally。

  当然,编写finally块应当多加小心,特别是要注意在finally块之内抛出的异常??这是执行清理任务的最后机会,尽量不要再有难以处理的错误。

  结论三:保证所有资源都被正确释放。充分运用finally关键词。

  反例之四:不说明异常的详细信息

  代码:3行-18行。

  仔细观察这段代码:如果循环内部出现了异常,会发生什么事情?我们可以得到足够的信息判断循环内部出错的原因吗?不能。我们只能知道当前正在处理的类发生了某种错误,但却不能获得任何信息判断导致当前错误的原因。

  printStackTrace的堆栈跟踪功能显示出程序运行到当前类的执行流程,但只提供了一些最基本的信息,未能说明实际导致错误的原因,同时也不易解读。

  因此,在出现异常时,最好能够提供一些文字信息,例如当前正在执行的类、方法和其他状态信息,包括以一种更适合阅读的方式整理和组织printStackTrace提供的信息。

  结论四:在异常处理模块中提供适量的错误原因信息,组织错误信息使其易于理解和阅读。

  反例之五:过于庞大的try块

  代码:3行-14行。

  经常可以看到有人把大量的代码放入单个try块,实际上这不是好习惯。这种现象之所以常见,原因就在于有些人图省事,不愿花时间分析一大块代码中哪几行代码会抛出异常、异常的具体类型是什么。把大量的语句装入单个巨大的try块就象是出门旅游时把所有日常用品塞入一个大箱子,虽然东西是带上了,但要找出来可不容易。

  一些新手常常把大量的代码放入单个try块,然后再在catch语句中声明Exception,而不是分离各个可能出现异常的段落并分别捕获其异常。这种做法为分析程序抛出异常的原因带来了困难,因为一大段代码中有太多的地方可能抛出Exception。
结论五:尽量减小try块的体积。

  反例之六:输出数据不完整

  代码:7行-11行。

  不完整的数据是Java程序的隐形杀手。仔细观察这段代码,考虑一下如果循环的中间抛出了异常,会发生什么事情。循环的执行当然是要被打断的,其次,catch块会执行??就这些,再也没有其他动作了。已经输出的数据怎么办?使用这些数据的人或设备将收到一份不完整的(因而也是错误的)数据,却得不到任何有关这份数据是否完整的提示。对于有些系统来说,数据不完整可能比系统停止运行带来更大的损失。

  较为理想的处置办法是向输出设备写一些信息,声明数据的不完整性;另一种可能有效的办法是,先缓冲要输出的数据,准备好全部数据之后再一次性输出。

  结论六:全面考虑可能出现的异常以及这些异常对执行流程的影响。

  改写后的代码

  根据上面的讨论,下面给出改写后的代码。也许有人会说它稍微有点?嗦,但是它有了比较完备的异常处理机制。

  OutputStreamWriter out = ...

  java.sql.Connection conn = ...

  try {

  Statement stat = conn.createStatement();

  ResultSet rs = stat.executeQuery(

  "select uid, name from user");

  while (rs.next())

  {

  out.println("ID:" + rs.getString("uid") + ",姓名: " + rs.getString("name"));

  }

  }

  catch(SQLException sqlex)

  {

  out.println("警告:数据不完整");

  throw new ApplicationException("读取数据时出现SQL错误", sqlex);

  }

  catch(IOException ioex)

  {

  throw new ApplicationException("写入数据时出现IO错误", ioex);

  }

  finally

  {

  if (conn != null) {

  try {

   conn.close();

  }

  catch(SQLException sqlex2)

  {

   System.err(this.getClass().getName() + ".mymethod - 不能关闭数据库连接: " + sqlex2.toString());

  }

  }

  if (out != null) {

  try {

   out.close();

  }

  catch(IOException ioex2)

  {

  System.err(this.getClass().getName() + ".mymethod - 不能关闭输出文件" + ioex2.toString());

  }

  }

  }


  本文的结论不是放之四海皆准的教条,有时常识和经验才是最好的老师。如果你对自己的做法没有百分之百的信心,务必加上详细、全面的注释。

  另一方面,不要笑话这些错误,不妨问问你自己是否真地彻底摆脱了这些坏习惯。即使最有经验的程序员偶尔也会误入歧途,原因很简单,因为它们确确实实带来了“方便”。所有这些反例都可以看作Java编程世界的恶魔,它们美丽动人,无孔不入,时刻诱惑着你。也许有人会认为这些都属于鸡皮蒜毛的小事,不足挂齿,但请记住:勿以恶小而为之,勿以善小而不为。

posted @ 2006-05-31 22:20 binge 阅读(296) | 评论 (0)编辑 收藏

Commons Configuration

     摘要: Configuration 简介  Configuration 的参数可能来自下面的资源:     *  Properties files    * XML documents    * Property list files (.plist)    * JNDI    * JDBC Datasource    * System prope...  阅读全文

posted @ 2006-05-31 10:30 binge 阅读(2946) | 评论 (0)编辑 收藏

Commons Lang

官方地址:http://jakarta.apache.org/commons/lang/

概述:
   标准的java库并没有提供足够的处理他的核心类的方法,Lang组件提供了这些扩展的方法
   lang 组件为java.lang API提供了一套帮助类。特别是String处理方法,基本的数字处理方法,对象反射,创建和序列化和系统属性。另外他包含了一个可继承的
enum类型,一个exception结构,对java.util.Date的基本加强以及一系列构建方法,比如hashCode,toString和equals
可以点击下面的连接获得体验:
http://www.j2medev.com/bbs/dispbbs.asp?boardid=3&id=3835&star=1&page=3

http://www.sentom.net/list.asp?id=76
  
lang.*
    String字符串处理-StringUtils,StringEscapeUtils,RondomStringUtils,Tokenizer,WordUtils.
    RandomStringUtils 顾名思义,它提供了一段文本,常用来做默认密码的值。 StringEscapeUtils 包含了escape和unescape "java,javascript,html,xml和sql"的方法。 Tokenizer 是java.util.StringTokenizer的改良。
   另外,WordUtils是另一个String处理类。他在String的单词层次上工作,比如,WordUtils.capitalize方法会将一段文本中的每个单词都首字母大写。WordUtils也包含了包装文本的方法。
   字符处理- CharSetUtils, CharSet, CharRange, CharUtils
字符的处理也很重要,CharUtils因此而存在。CharSetUtils则是为了对字符串作批处理。注意,尽管CharSetUtils接受一个String参数,但却把它当成一组字符。比如:CharSetUtils.delete("testtest", "tr")将删除所有的t和所有的r,而不仅仅是tr这个字符串。
CharRange和CharSet是CharSetUtils内部将要用到的类。
JVM交互-SystemUtils, CharEncoding
SystemUtils是个很小的类,他将使你获得你的JVM平台信息变得更为简单。比如:SystemUtils.isJavaVersionAtLeast(1.3f) 。CharEncoding也是被用来做和jvm的交互,可能会被用来查看特定的环境上支持那种字符编码。
序列化-SerializationUtils, SerializationException
 序列化并不难!一个简单的工具类就可以刈除你的痛苦。而且,他提供一个方法通过反序列化和重序列化来克隆对象,这是个很老的java诀窍。
Assorted functions -ObjectUtils,ClassUtils,ArrayUtils,BooleanUtils
  ObjectUtils提供了许多对对象便利的操作,以及大部分的对java.lang.Object的方法的null-safe实现。
   ClassUtils提供了一套用于反射的帮助函数。值得留意的是在ClassUtils隐含的comparators,他可以对Class和package按名称进行排序。这个排序仅仅是字典排序。
   接下来,我们介绍ArrayUtils.他有很多方法和这些方法的重载方法。这个类值得我们深入的了解一下。开始之前,我们假设所有的被提及的方法都被重载(无论是基本类型还是对象类型)。而且,‘xxx’代表了一个基本类型,有时候也包含了对象。
  • ArrayUtils 为基本类型提供了一个单态的空疏组.这些将被Collections API的toArray()方法中用到, 也可以在用在那些希望在发生错误时返回空数组的方法中.
  • add(xxx[], xxx) 添加一个原始类型到一个数组, 自动调整数组的大小. 对象类型可以用.
  • clone(xxx[]) 克隆一个基本类型或者对象数组.
  • contains(xxx[], xxx) 在一个基本类型或者对象类型的数组中查找一个基本类型或者对象类型.
  • getLength(Object) 返回一个数组的大小.如果参数不是一个数组,将会返回一个IllegalArgumentException异常。
  •  hashCode(Object), equals(Object, Object), toString(Object)
  • indexOf(xxx[], xxx)indexOf(xxx[], xxx, int) 是仿照String的相关方法, 但是他用来处理primitive/Object数组. 另外, lastIndexOf 系列的方法也存在.
  • isEmpty(xxx[]) 判断一个数组是否为null或者空.
  • isSameLength(xxx[], xxx[]) 判断2个数组的大小是否相等.
  • 除了添加的方法, 这里也提供了2类删除的方法. 第一种是根据索引删除:remove(xxx[], int), 第二种删除数组中的第一个值:remove(xxx[], xxx)
  •  reverse(xxx[]) 翻转一个数组.
  • The subarray(xxx[], int, int) 取出一个大数组的一部分.
  • 基本类型和基本类型的包装类之间的转换可以通过 toObject(xxx[])toPrimitive(Xxx[]) 方法.
   ArrayUtils.toMap(Object[])用来将一个数组转化为一个map,比如:
       Map colorMap = MapUtils.toMap(new String[][] {{
           {"RED", "#FF0000"},
           {"GREEN", "#00FF00"},
           {"BLUE", "#0000FF"}
       });
     BooleanUtils,对这个类,或许你有时候会对他的BooleanUtils.toBoolean(String)方法感兴趣。
异常-IllegalClassException, IncompleteArgumentException, NotImplementedException, NullArgumentException, UnhandledException

 lang.builder.*
  
提供了HashCodeBuilder,EqualsBuilder, CompareToBuilder, ToStringBuilder。笔者在项目中经常用到HashCodeBuilder,具体用法参照文章前面给出的连接。
lang.enums.* (formerly lang.enum)
   
他主要的功能就是为你的常量赋值,并且给定他们的顺序. For example:
public final class ColorEnum extends Enum {
     public static final ColorEnum RED = new ColorEnum("Red");
     public static final ColorEnum GREEN = new ColorEnum("Green");
     public static final ColorEnum BLUE = new ColorEnum("Blue");

     private ColorEnum(String color) {
          super(color);
     }

     public static ColorEnum getEnum(String color) {
          return (ColorEnum) getEnum(ColorEnum.class, color);
     }

     public static Iterator iterator() {
          return iterator(ColorEnum.class);
     }
}

 

posted @ 2006-05-26 12:48 binge 阅读(467) | 评论 (0)编辑 收藏

Commons BeanUtils

BeanUtils简介

这个组件的全称是Bean Introspection Utilites。是属于Jakarta Commons项目组的。主要是帮助构建javabean的属性操作的(getter,setter),已经提供一种动态定义和访问bean的属性。
接口摘要
Converter  通用数据类型转换器,可以被注册、使用用来管理对象类型的转换
DynaBean  一个java对象,这个对象的属性的名称,数据类型和值都能被动态改变
DynaClass  java.lang.class的一个模拟,用来给其它类实现DynaBean接口(类似java.lang.Object和java.lang.Class的关系)
MutableDynaClass  一个DynaClass的专门的扩展,允许属性动态的增加和减少。

类摘要
BasicDynaBean  
    DynaBean接口的最小实现
BasicDynaClass 
     DynaClass接口的最小实现
BeanUtils 
    工具方法,通过反射组装(populating)javabens的属性。
BeanUtilsBean 
    JavaBean属性的总体方法
ConstructorUtils 
   提供反射工具方法,用于构造函数, MethodUtils与此相仿
ContextClassLoaderLocal 
  
 A value that is provided per (thread) context classloader. 一个值,被提供了per (thread) context classloader.
ConvertingWrapDynaBean 
   DynaBean的一个实现,包装了标准的JavaBean实例,因此DynaBean APIs可以访问他的属性,尽管这些实现允许在属性设值的时候发生类型转换
ConvertUtils 
工具方法类,用于转换String类型变量的值到特定的类型变量的值,String类型的数组到特定类型的数组。
ConvertUtilsBean  
同上
DynaProperty 
METADATA,描述了一个DynaBean的一个属性
JDBCDynaClass 
提供常用的逻辑,用于JDBC实现 DynaClass
LazyDynaBean 
一种DynaBean,能够自动添加属性到DynaClass,而且提供 Lazy List和Lazy Map的性质
LazyDynaClass 
一种DynaClass,实现了MutableDynaClass接口
LazyDynaMap 
Provides a light weight DynaBean facade to a Map with lazy map/list processing.
为Map提供了轻量级的DynaBean facade
 MappedPropertyDescriptor  
一个MappedPropertyDescriptor描述了一个map化的属性
MethodUtils  
工具映射方法类,应用于一般方法而不是特定属性。
 MethodUtils.MethodDescriptor  Represents the key to looking up a Method by reflection. 代表了通过反射查找方法的KEY
 
PropertyUtils  
工具方法,用于利用Java Reflection APIs来帮助一般属性getter and setter的操作在Java对象上。
 PropertyUtilsBean   同上
 
ResultSetDynaClass  
DynaClass的实现,用于 DynaBeans,DynaBeans包装了java.sql.ResultSet的java.sql.Row对象
 
ResultSetIterator  
java.util.Iterator的实现,用ResultSetDynaClass .的iterator()方法得到。
 
RowSetDynaClass  
DynaClass 的实现,创建了一个 包含DynaBean的in-memory容器,代表了SQL查询的结果。
 
WrapDynaBean  
DynaBean的实现,他包装了一个标准的JavaBean实例,因此DynaBean APIs可以被用来访问它的属性
 
WrapDynaClass  
DynaClass的实现,用于包装了标准的 JavaBean实例的DynaBeans
 

异常摘要

BeanAccessLanguageException
    用于指出Bean Access Language 不能再给出的bean上执行查询

ConversionException
    
用于指出对Converter.convert()的调用没有成功

NestedNullException
  
用于指出Bean Access Language 不能再给出的bean上执行查询的原因是因为嵌套的bean引用为空

 

概要: 

背景:

JavaBeans 符合java api命名规范,它是它是java语言的组成体系之一。按照JavaBeans 设计模式可以带来许多便利。

JavaBeans Specification描述了完整的一套特点用来把任意一个类变成JavaBeans ,你最好读读这个文档,一些最基本的在此列出:

  •    类必须声明为public,提供一个不带参数的public构造函数。这样可以让其他工具或者应用程序动态的创建这个类的实例,而不需要事先知道被使用的类的名字。比如:
    String className = ...;
            Class beanClass = Class.forName(className);
            Object beanInstance = beanClass.newInstance();
  • 作为不带参数构造函数的一个结果,类的初始化和bean的行为的配置必须完全分离。典型的做法是定义一套properties,用来修改它的行为和和这个bean代表的数据。属性取名习惯做法是,以小写字母开头,由java合法字符组成。
  • 典型的,每一个property都有一个public的getter和setter方法来分别设置和取回属性的值 ,JavaBeans Specification 定义了这个规范。用get或者set作为前缀,并把属性的第一个字母大写紧跟其后。比如:
    public class Employee {
                public Employee();   // Zero-arguments constructor
                public String getFirstName();
                public void setFirstName(String firstName);
                public String getLastName();
                public void setLastName(String lastName);
                public Date getHireDate();
                public void setHireDate(Date hireDate);
                public boolean isManager();
                public void setManager(boolean manager);
                public String getFullName();
            }
  • 上面的例子,有个boolean值。boolean类型的属性是以is为前缀的,这样更容易理解。
  • 如果你既有getter又有setter,注意getter的返回值类型和setter的形参类型。另外,对同一个名字定义一个以上的类型不同的setter方法是和java规范不符的。
  • 并不是每个属性都需要get和set方法。由上面的例子我们就可以印证这一点。
  • 创建一些get和set方法不符合上面的规范也是有可能的。具体的您可以参照完整的java规范。
  • JavaBeans Specification 还定义了其他的一些规范。

用标准的java编码技术,在你事先知道调用的类,事先知道要关注的属性的情况下处理javabeans 是十分方便的。

外部支持:

commons-beanutils 需要一下一些包来运行:

Standard JavaBeans

背景:

如上所述,标准的写法可以给你的使用带来方便。但是当你事先并不知道哪个类会被调用或者哪个属性需要修改的时候怎么办呢?java提供了一些类(比如java.beans.Introspector,他能够在运行时检查类而且标志出属性的getter和setter方法),加上Reflection 机制来动态调用方法。但是,这些方法很难使用,而且暴露了过多的程序使用者不需要了解的基本结构的细节,BeanUtils的APIs企图简化动态setter和getter的方法。

PropertyUtils很好的满足我们的需求,这一章我们将深入介绍。

首先,这里来介绍一些深入的定义:

javabean提供的属性可以分成三类,一些被标准的JavaBeans规范所支持,而一些只被BeanUtils所支持

  • 简单类型(simple),最基本的属性类型包括java最原始的数据类型(整形,字符串形),或者稍微复杂一点的对象。
  • 索引类型(index),一个索引类型的属性存储了一个有序的对象(相同类型)容器,可以通过整型,非负索引值单独访问。或者,你可以干脆用一个数组来整体访问这个属性。作为JavaBeans specification扩展,BeanUtils包认为java.util.list类型的属性也可以这样来访问。
  • mapped,作为JavaBeans specification扩展,BeanUtils包认为java.util.map类型的属性是map化,你可以设置和取回这个属性通过String-valued键(key).

PropertyUtils 类中提共了get和set以上各种属性类型的多种多样的方法。在下面的代码片断中,假设这个类有两个实例。

 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);
    }
Basic Property Access(基本属性访问方式)

利用如下apis:

  • 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");
    ... manipulate the values ...
    PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
    PropertyUtils.setSimpleProperty(employee, "lastName", lastName);
For indexed properties, you have two choices,你有两种选择,可以参照下面的例子,要用到的APIS如下:

  • 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属性,也有两种方式。先参照apis

  • 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 Property Access(嵌套属性访问方式)

如果你的属性也是一个对象,你想访问属性对象的属性时,该怎么访问呢?

或许,用标准的java技术直接访问这个属性,会写成这样:

String city = employee.getAddress("home").getCity();

用PropertyUtils类的如下apis:

  • PropertyUtils.getNestedProperty(Object bean, String name)
  • PropertyUtils.setNestedProperty(Object bean, String name, Object value)

我们可以这样啊来访问:

String city = (String)
      PropertyUtils.getNestedProperty(employee, "address(home).city");

为了方便,PropertyUtils提供了一般化的访问方式,可以访问任意嵌套,sample,indexed,mapped类型的属性

  • PropertyUtils.getProperty(Object bean, String name)
  • PropertyUtils.setProperty(Object bean, String name, Object value)

例子:

Employee employee = ...;
    String city = (String) PropertyUtils.getProperty(employee,
      "subordinate[3].address(home).city");

Dynamic Beans (DynaBeans)

背景

PropertyUtils如前所述被设计用来访问存在的class的属性的访问方式,而不是以任何方式修改他们。一个不同的动态属性访问案例是,当你有一套合适的动态属性,想用一个javabean来展示,但是你并不想真实的写出一个类文件。除了不必保存和创建一个单独的class文件,它的功能意味着你可以处理这样一些情况,在这种情况下,你所关心的属性值是动态决定的。(比如sql语句查询出来的结果)。

为了支持这种情况,BeanUtils提供了DynaBean接口。通过实现他的接口方法可以实现他。并且与DynaClass 接口相关联。DynaClass 接口 定义了一个特定的DynaBean的组的属性。就像java.lang.Class定义了所有的javabean实例的属性一样。

据个例子:

如果上面例子中的Employee是DynaBean的实现。那么我们可以这样来访问它的属性。

DynaBean employee = ...; // Details depend on which
                             // DynaBean implementation you use
    String firstName = (String) employee.get("firstName");
    Address homeAddress = (Address) employee.get("address", "home");
    Object subordinate = employee.get("subordinate", 2);
注意:PropertyUtils的属性getter和setter方法知道如何访问DynaBean的属性。因此,你可以把你的应用中的所有属性访问方式都用PropertyUtils APIs。这样你就可以不用事先考虑某个特定bean到底是如何实现的。

因为 DynaBean 和 DynaClass都是接口,他们需要频繁的,很多不同场合地被实现。下面的章节提供了一些标准的beanutils包,当然,如果不符合您的要求,您也可以自己去实现他们。

BasicDynaBean and BasicDynaClass

  BasicDynaBean和BasicDynaClass提供了一套基本的动态属性性能,可以应用在你需要动态定义属性(是DynaProperty的实例)的时候。你需要先创建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);

注意,dynaBeanClass得引数(在BasicDynaClass的构造函数中)可以为空。在这种情况下,dynaClass.getDynaBeanClass的值仅仅只是BasicDynaBean的类(In this case, the value of dynaClass.getDynaBeanClass will just be the Class for BasicDynaBean)。

另外,你用DynaClass的newInstance()方法来实例化一个符合DynaClass的DynaBean实例,然后给他的属性赋初始值。(和你实例一个普通的javabean,然后赋值,是一样的)。

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

注意你可以这里的DynaBean类可以声明为DynaBean取代了BasicDynaBean。一般的,如果你使用DynaBeans,你不会在意DynaBeans的具体的实际实现---你只是在乎它是一个DynaBeans,而且可以用DynaBeans的apis.

 如上面所讲的,你可以传递一个DynaBean实例作为第一个引数给PropertyUtils访问和设置属性的方法,而且它会如你所愿的被解释---DynaBean 的动态属性可以被取回和修改。

ResultSetDynaClass (Wraps ResultSet in DynaBeans)

  一个很普通的DynaBean 的USER CASE就是用它来包装其他原始集合,这些集合不是以JAVABEAN的形式展示的。最常见的情况就是当你请求JDBC驱动查询SQL语句返回java.sql.ResultSet类型的记录的时候,BeanUtils提供了标准的机制来把每一行resultset转变为一个 DynaBean,参照下列:

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)

尽管ResultSetDynaClass是一个用来展示sql查询的很好的技术(当成DynaBean),但是最大的问题就是在MVC的结构之中,我们需要离线的取出查询的所有数据,而ResultSetDynaClass必须保持和数据库相连。

RowSetDynaClass展示了解决这个问题的不同方法。当你构造这样的实例,那些原始的数据被复制到一系列in-memory 的DynaBeans来代表这些结果。这个技术的优势是,理所当然,你可以立即关闭ResultSet(和他相连的Statement),这些操作都可以在你处理被返回的数据之前。缺点就是,你需要为复制数据所需要的性能和内存买单,而且数据的大小还得让堆内存可以适合。在许多情况下(特别是WEB APPS),这种折衷是有益处的。

  额外的方便就是,RowSetDynaClass 被定义为java.io.Serializable的实现,因此它可以被序列化和反序列化。因此RowSetDynaClass展示了一种十分便利的方法来传输SQL结果到远程Java-based 客户端应用程序(比如APPLET).

 基本的RowSetDynaClass使用模式如下所示:

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

 下面的E文比较EASY,偶偷懒不翻了,

OK, you've tried the DynaBeans APIs and they are cool -- very simple get() and set() methods provide easy access to all of the dynamically defined simple, indexed, and mapped properties of your DynaBeans. You'd like to use the DynaBean APIs to access all of your beans, but you've got a bunch of existing standard JavaBeans classes to deal with as well. This is where the WrapDynaBean (and its associated WrapDynaClass) come into play. As the name implies, a WrapDynaBean is used to "wrap" the DynaBean APIs around an existing standard JavaBean class. To use it, simply create the wrapper like this:

MyBean bean = ...; DynaBean wrapper = new WrapDynaBean(bean); String firstName = wrapper.get("firstName");

Note that, although appropriate WrapDynaClass instances are created internally, you never need to deal with them.

Lazy DynaBeans(LazyDynaBean, LazyDynaMap and LazyDynaClass)

  你钟情于DynaBeans是因为有了它你不必对每个pojo来编码成一个class文件。这样能够实现的原因是因为lazy--延迟加载。是以下的一些特性使得DynaBeans可以lazy:

  •   Lazy property addition (lazy属性添加)---lazy beans 使用 实现了MutableDynaClass 接口的DynaClass,DynaClass提供了添加和删除属性的能力。当set方法调用的时候,Lazy beans 利用这个特性来自动添加DynaClass中没有的属性
  • Lazy List/Array growth(lazy list/array 增长)---如果一个索引化的属性没有足够的容量来容纳要设置的属性,那么List or Array 将会自动增长。
  • Lazy List/Array instantiation(Lazy List/Array实例化) ---如果一个索引化的属性并不存在,那么他将会调用 DynaBean的indexed property getter/setter methods(比如 get(name, index) or set(name, index, value))返回一个List 或者一个Array实例。如果一个索引化的属性没有在DynaClass中被定义,那么他将会被自动添加而且生成一个默认的list实现的实例。
  • Lazy Map instantiation-------if a mapped property doesn't exist then calling the DynaBean's mapped property getter/setter methods (i.e. get(name, key) or set(name, key, value)) results in a new Map being instantiated. If the mapped property has not been defined in the DynaClass then it is automatically added and a default Map implementation instantiated.
  • Lazy Bean instantiation -------如果一个DynaClass 中的属性被定义成DynaBean 或者普通的bean,但是这个属性并不在DynaBean中存在,那么LazyDynaBean将会采用默认的empty constructor来实例化这个 bean

LazyDynaBean

标准lazy bean 的实现。默认和实现了MutableDynaClass接口的LazyDynaClass相关联---尽管他可以和MutableDynaClass的任何实现一起使用。例子如下:

 DynaBean dynaBean = new LazyDynaBean();

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

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

    dynaBean.set("address", 0, addressLine1);     // indexed
    dynaBean.set("address", 1, addressLine2);     // indexed
    dynaBean.set("address", 2, addressLine3);     // indexed

LazyDynaMap

light wieght (轻量级)DynaBean facade to a Map with all the usual lazy features。之所以是轻量级,是因为他没有和一个包含所有属性的DynaClass相关连。事实上,他亲自实现了DynaClass。一个LazyDynaMap可以用来包装一个存在的map,也可以自己去实例化一个Map实例

例如: 

If you need a new Map then to use....

DynaBean dynaBean = new LazyDynaMap(); // create DynaBean dynaBean.set("foo", "bar"); // simple dynaBean.set("customer", "title", "Mr"); // mapped dynaBean.set("address", 0, addressLine1); // indexed Map myMap = dynaBean.getMap() // retrieve the Map

or to use with an existing Map ....

Map myMap = .... // exisitng Map DynaBean dynaBean = new LazyDynaMap(myMap); // wrap Map in DynaBean dynaBean.set("foo", "bar");

LazyDynaClass

继承BasicDynaClass并实现MutableDynaClass接口。

Either create a LazyDynaClass first... MutableDynaClass dynaClass = new LazyDynaClass(); // create DynaClass dynaClass.add("amount", java.lang.Integer.class); // add property dynaClass.add("orders", OrderBean[].class); // add indexed property dynaClass.add("orders", java.util.TreeMapp.class); // add mapped property DynaBean dynaBean = new LazyDynaBean(dynaClass); // Create DynaBean with associated DynaClass

or create a LazyDynaBean and get the DynaClass... DynaBean dynaBean = new LazyDynaBean(); // Create LazyDynaBean MutableDynaClass dynaClass = (MutableDynaClass)dynaBean.getDynaClass(); // get DynaClass dynaClass.add("amount", java.lang.Integer.class); // add property dynaClass.add("myBeans", myPackage.MyBean[].class); // add 'array' indexed property dynaClass.add("myMap", java.util.TreeMapp.class); // add mapped property

 注意:

MutableDynaClass 有一种受限(Restricted)属性。When the DynaClass is restricted ,no properties can be added or removed from the DynaClass. Neither the LazyDynaBean or LazyDynaMap will add properties automatically if the DynaClass is restricted.

关于Converters和Collections方面的知识本文不做翻译。

posted @ 2006-05-25 23:08 binge 阅读(883) | 评论 (0)编辑 收藏

proxool

官方网址:
http://proxool.sourceforge.net/


 Setting up Proxool in a Servlet environment(在servlet环境中使用proxool)
   Configuration(配置)
   有3种方式来配置proxool:
      1. XML file。
      代理到 JAXPConfigurator来处理xml文件。如果文件不是绝对路径,将会定位到应用的根目录。
<servlet>
  <servlet-name>ServletConfigurator</servlet-name>
  <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
  <init-param>
    <param-name>xmlFile</param-name>
    <param-value>WEB-INF/proxool.xml</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet> 
   2. Property file。
 代理到PropertyConfigurator去解析。如果文件不是绝对路径,将会定位到应用的根目录。
   <servlet>
  <servlet-name>ServletConfigurator</servlet-name>
  <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
  <init-param>
    <param-name>propertyFile</param-name>
    <param-value>WEB-INF/proxool.properties</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
3. Init parameters。
   代理到PropertyConfigurator去解析。根据servlet的初始化参数创建一个Property对象。
<servlet>
  <servlet-name>ServletConfigurator</servlet-name>
  <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
  <init-param>
    <param-name>jdbc-0.proxool.alias</param-name>
    <param-value>test</param-value>
  </init-param>
  <init-param>
    <param-name>jdbc-0.proxool.driver-url</param-name>
    <param-value>jdbc:hsqldb:.</param-value>
  </init-param>
  <init-param>
    <param-name>jdbc-0.proxool.driver-class</param-name>
    <param-value>org.hsqldb.jdbcDriver</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
在刈除所有的连接池后,ServletConfigurator会自动停止。
 <servlet>
  <servlet-name>ServletConfigurator</servlet-name>
  <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
  <init-param>
    <param-name>autoShutdown</param-name>
    <param-value>false</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
Installation.(安装)
   如果在你的servlet环境中有多个web应用,你需要考虑如何来安装proxool.这里有2种方案:
   1。在你应用的库目录(web-info/lib),他的理论如下:
   proxool将不会再web应用间共享。如果你重新装在web应用,一个新的实例将会产生。除非你显式关闭旧的proxool,否则他将继续使用各种资源(本地资源和数据库)。你可以用如下的办法来关闭他们:用上面提到的ServletConfigurator或者调用ProxoolFacade的shutdown方法。
   2。在容器的公用目录下或者classpath中,他的理论如下:
   你可以在多个web应用中共享proxool,这样的话,如果你重新装在单个的web应用,proxool依然在运行。如果你想冲起proxool,要么重起容器,要么全部应用停止并重新配置proxool.
----------------------
本人在CSDN上的部分翻译:
http://blog.csdn.net/huabingl/archive/2006/05/11/725155.aspx

posted @ 2006-05-24 22:19 binge 阅读(547) | 评论 (0)编辑 收藏

仅列出标题
共4页: 上一页 1 2 3 4