﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-ID刀-文章分类-JAVA_Base</title><link>http://www.blogjava.net/zzs/category/37917.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 07 Apr 2009 16:25:38 GMT</lastBuildDate><pubDate>Tue, 07 Apr 2009 16:25:38 GMT</pubDate><ttl>60</ttl><item><title>连接池的配置与维护</title><link>http://www.blogjava.net/zzs/articles/258022.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Thu, 05 Mar 2009 08:06:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/258022.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/258022.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/258022.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/258022.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/258022.html</trackback:ping><description><![CDATA[　连接池中到底应该放置多少连接，才能使系统的性能最佳？系统可采取设置最小连接数（minConn）和最大连接数（maxConn）来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多，则系统启动就慢，但创建后系统的响应速度会很快；如果创建过少，则系统启动的很快，响应起来却慢。这样，可以在开发时，设置较小的最小连接数，开发起来会快，而在系统实际使用时设置较大的，因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目，具体设置多少，要看系统的访问量，可通过反复测试，找到最佳点。
<div align="left">　　如何确保连接池中的最小连接数呢？有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测，如果发现连接数量小于最小连接数，则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。<br />
连接池的实现
<div align="left">　　1、连接池模型</div>
<div align="left">　　本文讨论的连接池包括一个连接池类（DBConnectionPool）和一个连接池管理类（DBConnetionPoolManager）和一个配置文件操作类(ParseDSConfig)。连接池类是对某一<a href="http://db.rdxx.com/" target="_blank"><font color="#3080cb"><u>数据库</u></font></a>所有连接的&#8220;缓冲池&#8221;，主要实现以下功能：①从连接池获取或创建可用连接；②使用完毕之后，把连接返还给连接池；③在系统关闭前，断开所有连接并释放连接占用的系统资源；④还能够处理无效连接（原来登记为可用的连接，由于某种原因不再可用，如超时，通讯问题），并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。(5)当多数据库时,且数据库是动态增加的话,将会加到配置文件中。</div>
<div align="left">　　连接池管理类是连接池类的外覆类（wrapper）,符合单例模式，即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理，具有以下功能：①装载并注册特定数据库的JDBC驱动程序；②根据属性文件给定的信息，创建连接池对象；③为方便管理多个连接池对象，为每一个连接池对象取一个名字，实现连接池名字与其实例之间的映射；④跟踪客户使用连接情况，以便需要是关闭连接释放资源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理，如系统需要连接不同的数据库，或连接相同的数据库但由于<a href="http://net.rdxx.com/Safe/SafeTech/" target="_blank"><font color="#3080cb"><u>安全</u></font></a>性问题，需要不同的用户使用不同的名称和密码。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、连接池实现(经过本人改版,可以适用多数据库类型的应用以及一种数据库类型多个数据库且数据&nbsp; 库的数量可以动态增加的应用程序)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1),DBConnectionPool.java&nbsp;&nbsp; 数据库连接池类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2),DBConnectionManager&nbsp;.java&nbsp;&nbsp; 数据库管理类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3),DSConfigBean&nbsp;.java&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单个数据库连接信息Bean<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4),ParseDSConfig.java&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 操作多(这个'多'包括不同的数据库和同一种数据库有多个数据库)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据 配置文件xml<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5),ds.config.xml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据库配置文件xml<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 原代码如下:&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DBConnectionPool.java&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------------------------------------------------------<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;*&nbsp;数据库连接池类<br />
&nbsp;*/<br />
package <a href="http://www.tjyj.account.db/"><font color="#000000"><u>com.chunkyo.db</u></font></a>;</div>
<div align="left">import java.sql.Connection;<br />
import java.sql.DriverManager;<br />
import java.sql.SQLException;<br />
import java.util.ArrayList;<br />
import java.util.Iterator;<br />
import java.util.Timer;</div>
<div align="left">/**<br />
&nbsp;* @author chenyanlin<br />
&nbsp;*<br />
&nbsp;*/<br />
public class DBConnectionPool implements TimerListener {</div>
<div align="left">&nbsp;private Connection con=null;<br />
&nbsp;private int inUsed=0;&nbsp;&nbsp;&nbsp; //使用的连接数<br />
&nbsp;private ArrayList freeConnections = new ArrayList();//容器，空闲连接<br />
&nbsp;private int minConn;&nbsp;&nbsp;&nbsp;&nbsp; //最小连接数<br />
&nbsp;private int maxConn;&nbsp;&nbsp;&nbsp;&nbsp; //最大连接<br />
&nbsp;private String name;&nbsp;&nbsp;&nbsp;&nbsp; //连接池名字<br />
&nbsp;private String password; //密码<br />
&nbsp;private String url;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //数据库连接地址<br />
&nbsp;private String driver;&nbsp;&nbsp; //驱动<br />
&nbsp;private String user;&nbsp;&nbsp;&nbsp;&nbsp; //用户名<br />
&nbsp;public Timer timer;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定时<br />
&nbsp;/**<br />
&nbsp; * <br />
&nbsp; */<br />
&nbsp;public DBConnectionPool() {<br />
&nbsp;&nbsp;// TODO Auto-generated constructor stub<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 创建连接池<br />
&nbsp; * @param driver<br />
&nbsp; * @param name<br />
&nbsp; * @param URL<br />
&nbsp; * @param user<br />
&nbsp; * @param password<br />
&nbsp; * @param maxConn<br />
&nbsp; */<br />
&nbsp;public DBConnectionPool(String name, String driver,String URL, String user, String password, int maxConn)<br />
&nbsp;{<br />
&nbsp;&nbsp;this.name=name;<br />
&nbsp;&nbsp;this.driver=driver;<br />
&nbsp;&nbsp;this.url=URL;<br />
&nbsp;&nbsp;this.user=user;<br />
&nbsp;&nbsp;this.password=password;<br />
&nbsp;&nbsp;this.maxConn=maxConn;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 用完，释放连接<br />
&nbsp; * @param con<br />
&nbsp; */<br />
&nbsp;public synchronized void freeConnection(Connection con) <br />
&nbsp;{<br />
&nbsp;&nbsp;this.freeConnections.add(con);//添加到空闲连接的末尾<br />
&nbsp;&nbsp;this.inUsed--;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * timeout&nbsp; 根据timeout得到连接<br />
&nbsp; * @param timeout<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;public synchronized Connection getConnection(long timeout)<br />
&nbsp;{<br />
&nbsp;&nbsp;Connection con=null;<br />
&nbsp;&nbsp;if(this.freeConnections.size()&gt;0)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;con=(Connection)this.freeConnections.get(0);<br />
&nbsp;&nbsp;&nbsp;if(con==null)con=getConnection(timeout); //继续获得连接<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;con=newConnection(); //新建连接<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if(this.maxConn==0||this.maxConn&lt;this.inUsed)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;con=null;//达到最大连接数，暂时不能获得连接了。<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if(con!=null)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;this.inUsed++;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return con;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * <br />
&nbsp; * 从连接池里得到连接<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;public synchronized Connection getConnection()<br />
&nbsp;{<br />
&nbsp;&nbsp;Connection con=null;<br />
&nbsp;&nbsp;if(this.freeConnections.size()&gt;0)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;con=(Connection)this.freeConnections.get(0);<br />
&nbsp;&nbsp;&nbsp;this.freeConnections.remove(0);//如果连接分配出去了，就从空闲连接里删除<br />
&nbsp;&nbsp;&nbsp;if(con==null)con=getConnection(); //继续获得连接<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;con=newConnection(); //新建连接<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if(this.maxConn==0||this.maxConn&lt;this.inUsed)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;con=null;//等待 超过最大连接时<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if(con!=null)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;this.inUsed++;<br />
&nbsp;&nbsp;&nbsp;System.out.println("得到　"+this.name+"　的连接，现有"+inUsed+"个连接在使用!");<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return con;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; *释放全部连接<br />
&nbsp; *<br />
&nbsp; */<br />
&nbsp;public synchronized void release()<br />
&nbsp;{<br />
&nbsp;&nbsp;Iterator allConns=this.freeConnections.iterator();<br />
&nbsp;&nbsp;while(allConns.hasNext())<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;Connection con=(Connection)allConns.next();<br />
&nbsp;&nbsp;&nbsp;try<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;con.close();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;catch(SQLException e)<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;this.freeConnections.clear();<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 创建新连接<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;private Connection newConnection()<br />
&nbsp;{<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;Class.forName(driver);<br />
&nbsp;&nbsp;&nbsp;con=DriverManager.getConnection(url, user, password);<br />
&nbsp;&nbsp;} catch (ClassNotFoundException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;System.out.println("sorry can't find db driver!");<br />
&nbsp;&nbsp;} catch (SQLException e1) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e1.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;System.out.println("sorry can't create Connection!");<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return con;<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 定时处理函数<br />
&nbsp; */<br />
&nbsp;public synchronized void TimerEvent() <br />
&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp; //暂时还没有实现以后会加上的<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</div>
<div align="left">&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @return the driver<br />
&nbsp; */<br />
&nbsp;public String getDriver() {<br />
&nbsp;&nbsp;return driver;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @param driver the driver to set<br />
&nbsp; */<br />
&nbsp;public void setDriver(String driver) {<br />
&nbsp;&nbsp;this.driver = driver;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @return the maxConn<br />
&nbsp; */<br />
&nbsp;public int getMaxConn() {<br />
&nbsp;&nbsp;return maxConn;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @param maxConn the maxConn to set<br />
&nbsp; */<br />
&nbsp;public void setMaxConn(int maxConn) {<br />
&nbsp;&nbsp;this.maxConn = maxConn;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @return the minConn<br />
&nbsp; */<br />
&nbsp;public int getMinConn() {<br />
&nbsp;&nbsp;return minConn;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @param minConn the minConn to set<br />
&nbsp; */<br />
&nbsp;public void setMinConn(int minConn) {<br />
&nbsp;&nbsp;this.minConn = minConn;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @return the name<br />
&nbsp; */<br />
&nbsp;public String getName() {<br />
&nbsp;&nbsp;return name;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @param name the name to set<br />
&nbsp; */<br />
&nbsp;public void setName(String name) {<br />
&nbsp;&nbsp;this.name = name;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @return the password<br />
&nbsp; */<br />
&nbsp;public String getPassword() {<br />
&nbsp;&nbsp;return password;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @param password the password to set<br />
&nbsp; */<br />
&nbsp;public void setPassword(String password) {<br />
&nbsp;&nbsp;this.password = password;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @return the url<br />
&nbsp; */<br />
&nbsp;public String getUrl() {<br />
&nbsp;&nbsp;return url;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @param url the url to set<br />
&nbsp; */<br />
&nbsp;public void setUrl(String url) {<br />
&nbsp;&nbsp;this.url = url;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @return the user<br />
&nbsp; */<br />
&nbsp;public String getUser() {<br />
&nbsp;&nbsp;return user;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @param user the user to set<br />
&nbsp; */<br />
&nbsp;public void setUser(String user) {<br />
&nbsp;&nbsp;this.user = user;<br />
&nbsp;}</div>
<div align="left">}<br />
</div>
</div>
-------------------------------------------<br />
&nbsp;DBConnectionManager&nbsp;.java<br />
------------------------------------------<br />
/**<br />
&nbsp;*&nbsp;数据库连接池管理类<br />
&nbsp;*/<br />
package <a href="http://www.tjyj.account.db/"><font color="#000000"><u>com.chunkyo.db</u></font></a>;
<div align="left">import java.sql.Connection;<br />
import java.util.ArrayList;<br />
import java.util.Enumeration;<br />
import java.util.HashMap;<br />
import java.util.Hashtable;<br />
import java.util.Iterator;<br />
import java.util.Properties;<br />
import java.util.Vector;</div>
<div align="left">import <a href="http://www.tjyj.account.db.parsedsconfig/"><font color="#000000"><u>com.chunkyo.db.ParseDSConfig</u></font></a>;<br />
import <a href="http://www.tjyj.account.db.dsconfigbean/"><font color="#000000"><u>com.chunkyo.db.DSConfigBean</u></font></a>;<br />
import <a href="http://www.tjyj.account.db.dbconnectionpool/"><font color="#000000"><u>com.chunkyo.db.DBConnectionPool</u></font></a>;</div>
<div align="left">/**<br />
&nbsp;* @author chenyanlin<br />
&nbsp;*<br />
&nbsp;*/<br />
public class DBConnectionManager {</div>
<div align="left">&nbsp;static private DBConnectionManager instance;//唯一数据库连接池管理实例类<br />
&nbsp;static private int clients;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //客户连接数<br />
&nbsp;private Vector drivers&nbsp; = new Vector();//驱动信息<br />
&nbsp;private Hashtable pools=new Hashtable();//连接池<br />
&nbsp;<br />
&nbsp;/**<br />
&nbsp; * 实例化管理类<br />
&nbsp; */<br />
&nbsp;public DBConnectionManager() {<br />
&nbsp;&nbsp;// TODO Auto-generated constructor stub<br />
&nbsp;&nbsp;this.init();<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 得到唯一实例管理类<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;static synchronized public DBConnectionManager getInstance()<br />
&nbsp;{<br />
&nbsp;&nbsp;if(instance==null)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;instance=new DBConnectionManager();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return instance;<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 释放连接<br />
&nbsp; * @param name<br />
&nbsp; * @param con<br />
&nbsp; */<br />
&nbsp;public void freeConnection(String name, Connection con)<br />
&nbsp;{<br />
&nbsp;&nbsp;DBConnectionPool pool=(DBConnectionPool)pools.get(name);//根据关键名字得到连接池<br />
&nbsp;&nbsp;if(pool!=null)<br />
&nbsp;&nbsp;pool.freeConnection(con);//释放连接 <br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 得到一个连接根据连接池的名字name<br />
&nbsp; * @param name<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;public Connection getConnection(String name)<br />
&nbsp;{<br />
&nbsp;&nbsp;DBConnectionPool pool=null;<br />
&nbsp;&nbsp;Connection con=null;<br />
&nbsp;&nbsp;pool=(DBConnectionPool)pools.get(name);//从名字中获取连接池<br />
&nbsp;&nbsp;con=pool.getConnection();//从选定的连接池中获得连接<br />
&nbsp;&nbsp;if(con!=null)<br />
&nbsp;&nbsp;System.out.println("得到连接。。。");<br />
&nbsp;&nbsp;return con;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 得到一个连接，根据连接池的名字和等待时间<br />
&nbsp; * @param name<br />
&nbsp; * @param time<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;public Connection getConnection(String name, long timeout)<br />
&nbsp;{<br />
&nbsp;&nbsp;DBConnectionPool pool=null;<br />
&nbsp;&nbsp;Connection con=null;<br />
&nbsp;&nbsp;pool=(DBConnectionPool)pools.get(name);//从名字中获取连接池<br />
&nbsp;&nbsp;con=pool.getConnection(timeout);//从选定的连接池中获得连接<br />
&nbsp;&nbsp;System.out.println("得到连接。。。");<br />
&nbsp;&nbsp;return con;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 释放所有连接<br />
&nbsp; */<br />
&nbsp;public synchronized void release()<br />
&nbsp;{<br />
&nbsp;&nbsp;Enumeration allpools=pools.elements();<br />
&nbsp;&nbsp;while(allpools.hasMoreElements())<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;DBConnectionPool pool=(DBConnectionPool)allpools.nextElement();<br />
&nbsp;&nbsp;&nbsp;if(pool!=null)pool.release();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;pools.clear();<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * 创建连接池<br />
&nbsp; * @param props<br />
&nbsp; */<br />
&nbsp;private void createPools(DSConfigBean dsb)<br />
&nbsp;{<br />
&nbsp;&nbsp;DBConnectionPool dbpool=new DBConnectionPool();<br />
&nbsp;&nbsp;dbpool.setName(dsb.getName());<br />
&nbsp;&nbsp;dbpool.setDriver(dsb.getDriver());<br />
&nbsp;&nbsp;dbpool.setUrl(dsb.getUrl());<br />
&nbsp;&nbsp;dbpool.setUser(dsb.getUsername());<br />
&nbsp;&nbsp;dbpool.setPassword(dsb.getPassword());<br />
&nbsp;&nbsp;dbpool.setMaxConn(dsb.getMaxconn());<br />
&nbsp;&nbsp;System.out.println("ioio:"+dsb.getMaxconn());<br />
&nbsp;&nbsp;pools.put(dsb.getName(), dbpool);<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 初始化连接池的参数<br />
&nbsp; */<br />
&nbsp;private void init()<br />
&nbsp;{<br />
&nbsp;&nbsp;//加载驱动程序<br />
&nbsp;&nbsp;this.loadDrivers();<br />
&nbsp;&nbsp;//创建连接池<br />
&nbsp;&nbsp;Iterator alldriver=drivers.iterator();<br />
&nbsp;&nbsp;while(alldriver.hasNext())<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;this.createPools((DSConfigBean)alldriver.next());<br />
&nbsp;&nbsp;&nbsp;System.out.println("创建连接池。。。");<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;System.out.println("创建连接池完毕。。。");<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * 加载驱动程序<br />
&nbsp; * @param props<br />
&nbsp; */<br />
&nbsp;private void loadDrivers()<br />
&nbsp;{<br />
&nbsp;&nbsp;ParseDSConfig pd=new ParseDSConfig();<br />
&nbsp;//读取数据库配置文件<br />
&nbsp;&nbsp;drivers=pd.readConfigInfo("ds.config.xml");<br />
&nbsp;&nbsp;System.out.println("加载驱动程序。。。");<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</div>
<div align="left">&nbsp;}</div>
<div align="left">}<br />
----------------------------------------<br />
DSConfigBean.java<br />
----------------------------------------<br />
/**<br />
&nbsp;*&nbsp;配置文件Bean类<br />
&nbsp;*/<br />
package <a href="http://www.tjyj.account.db/"><font color="#000000"><u>com.chunkyo.db</u></font></a>;</div>
<div align="left">/**<br />
&nbsp;* @author chenyanlin<br />
&nbsp;*<br />
&nbsp;*/<br />
public class DSConfigBean {</div>
<div align="left">&nbsp;private String type&nbsp;&nbsp;&nbsp;&nbsp; =""; //数据库类型<br />
&nbsp;private String name&nbsp;&nbsp;&nbsp;&nbsp; =""; //连接池名字<br />
&nbsp;private String driver&nbsp;&nbsp; =""; //数据库驱动<br />
&nbsp;private String url&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =""; //数据库url<br />
&nbsp;private String username =""; //用户名<br />
&nbsp;private String password =""; //密码<br />
&nbsp;private int maxconn&nbsp; =0; //最大连接数<br />
&nbsp;/**<br />
&nbsp; * <br />
&nbsp; */<br />
&nbsp;public DSConfigBean() {<br />
&nbsp;&nbsp;// TODO Auto-generated constructor stub<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</div>
<div align="left">&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @return the driver<br />
&nbsp; */<br />
&nbsp;public String getDriver() {<br />
&nbsp;&nbsp;return driver;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @param driver the driver to set<br />
&nbsp; */<br />
&nbsp;public void setDriver(String driver) {<br />
&nbsp;&nbsp;this.driver = driver;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @return the maxconn<br />
&nbsp; */<br />
&nbsp;public int getMaxconn() {<br />
&nbsp;&nbsp;return maxconn;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @param maxconn the maxconn to set<br />
&nbsp; */<br />
&nbsp;public void setMaxconn(int maxconn) {<br />
&nbsp;&nbsp;this.maxconn = maxconn;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @return the name<br />
&nbsp; */<br />
&nbsp;public String getName() {<br />
&nbsp;&nbsp;return name;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @param name the name to set<br />
&nbsp; */<br />
&nbsp;public void setName(String name) {<br />
&nbsp;&nbsp;this.name = name;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @return the password<br />
&nbsp; */<br />
&nbsp;public String getPassword() {<br />
&nbsp;&nbsp;return password;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @param password the password to set<br />
&nbsp; */<br />
&nbsp;public void setPassword(String password) {<br />
&nbsp;&nbsp;this.password = password;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @return the type<br />
&nbsp; */<br />
&nbsp;public String getType() {<br />
&nbsp;&nbsp;return type;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @param type the type to set<br />
&nbsp; */<br />
&nbsp;public void setType(String type) {<br />
&nbsp;&nbsp;this.type = type;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @return the url<br />
&nbsp; */<br />
&nbsp;public String getUrl() {<br />
&nbsp;&nbsp;return url;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @param url the url to set<br />
&nbsp; */<br />
&nbsp;public void setUrl(String url) {<br />
&nbsp;&nbsp;this.url = url;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @return the username<br />
&nbsp; */<br />
&nbsp;public String getUsername() {<br />
&nbsp;&nbsp;return username;<br />
&nbsp;}</div>
<div align="left">&nbsp;/**<br />
&nbsp; * @param username the username to set<br />
&nbsp; */<br />
&nbsp;public void setUsername(String username) {<br />
&nbsp;&nbsp;this.username = username;<br />
&nbsp;}</div>
<div align="left">}<br />
-----------------------------------------------------<br />
ParseDSConfig.java<br />
-----------------------------------------------------<br />
/**<br />
&nbsp;*&nbsp;操作配置文件类 读&nbsp; 写 修改 删除等操作 <br />
&nbsp;*/<br />
package <a href="http://www.tjyj.account.db/"><font color="#000000"><u>com.chunkyo.db</u></font></a>;</div>
<div align="left">import java.io.FileInputStream;<br />
import java.io.FileNotFoundException;<br />
import java.io.FileOutputStream;<br />
import java.io.IOException;<br />
import java.io.InputStream;<br />
import java.util.List;<br />
import java.util.Vector;<br />
import java.util.Iterator;</div>
<div align="left">import org.jdom.Document;<br />
import org.jdom.Element;<br />
import org.jdom.JDOMException;<br />
import org.jdom.input.SAXBuilder;<br />
import org.jdom.output.Format;<br />
import org.jdom.output.XMLOutputter;</div>
<div align="left">/**<br />
&nbsp;* @author chenyanlin<br />
&nbsp;*<br />
&nbsp;*/<br />
public class ParseDSConfig {</div>
<div align="left">&nbsp;/**<br />
&nbsp; * 构造函数<br />
&nbsp; */<br />
&nbsp;public ParseDSConfig() {<br />
&nbsp;&nbsp;// TODO Auto-generated constructor stub<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 读取xml配置文件<br />
&nbsp; * @param path<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;public Vector readConfigInfo(String path)<br />
&nbsp;{<br />
&nbsp;&nbsp;String rpath=this.getClass().getResource("").getPath().substring(1)+path;<br />
&nbsp;&nbsp;Vector dsConfig=null;<br />
&nbsp;&nbsp;FileInputStream fi = null;<br />
&nbsp;&nbsp;try<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;fi=new FileInputStream(rpath);//读取路径文件<br />
&nbsp;&nbsp;&nbsp;dsConfig=new Vector();<br />
&nbsp;&nbsp;&nbsp;SAXBuilder sb=new SAXBuilder();<br />
&nbsp;&nbsp;&nbsp;Document doc=sb.build(fi);<br />
&nbsp;&nbsp;&nbsp;Element root=doc.getRootElement();<br />
&nbsp;&nbsp;&nbsp;List pools=root.getChildren();<br />
&nbsp;&nbsp;&nbsp;Element pool=null;<br />
&nbsp;&nbsp;&nbsp;Iterator allPool=pools.iterator();<br />
&nbsp;&nbsp;&nbsp;while(allPool.hasNext())<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;pool=(Element)allPool.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;DSConfigBean dscBean=new DSConfigBean();<br />
&nbsp;&nbsp;&nbsp;&nbsp;dscBean.setType(pool.getChild("type").getText());<br />
&nbsp;&nbsp;&nbsp;&nbsp;dscBean.setName(pool.getChild("name").getText());<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(dscBean.getName());<br />
&nbsp;&nbsp;&nbsp;&nbsp;dscBean.setDriver(pool.getChild("driver").getText());<br />
&nbsp;&nbsp;&nbsp;&nbsp;dscBean.setUrl(pool.getChild("url").getText());<br />
&nbsp;&nbsp;&nbsp;&nbsp;dscBean.setUsername(pool.getChild("username").getText());<br />
&nbsp;&nbsp;&nbsp;&nbsp;dscBean.setPassword(pool.getChild("password").getText());<br />
&nbsp;&nbsp;&nbsp;&nbsp;dscBean.setMaxconn(Integer.parseInt(pool.getChild("maxconn").getText()));<br />
&nbsp;&nbsp;&nbsp;&nbsp;dsConfig.add(dscBean);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;} catch (FileNotFoundException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (JDOMException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;finally<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;fi.close();<br />
&nbsp;&nbsp;&nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;return dsConfig;<br />
&nbsp;}<br />
</div>
<div align="left">/**<br />
&nbsp;*修改配置文件 没时间写 过段时间再贴上去 其实一样的 <br />
&nbsp;*/<br />
&nbsp;public void modifyConfigInfo(String path,DSConfigBean dsb) throws Exception<br />
&nbsp;{<br />
&nbsp;&nbsp;String rpath=this.getClass().getResource("").getPath().substring(1)+path;<br />
&nbsp;&nbsp;FileInputStream fi=null; //读出<br />
&nbsp;&nbsp;FileOutputStream fo=null; //写入<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
/**<br />
&nbsp;*增加配置文件<br />
&nbsp;*<br />
&nbsp;*/<br />
&nbsp;public void addConfigInfo(String path,DSConfigBean dsb) <br />
&nbsp;{<br />
&nbsp;&nbsp;String rpath=this.getClass().getResource("").getPath().substring(1)+path;<br />
&nbsp;&nbsp;FileInputStream fi=null;<br />
&nbsp;&nbsp;FileOutputStream fo=null;<br />
&nbsp;&nbsp;try<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;fi=new FileInputStream(rpath);//读取xml流<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;SAXBuilder sb=new SAXBuilder();<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Document doc=sb.build(fi); //得到xml<br />
&nbsp;&nbsp;&nbsp;Element root=doc.getRootElement();<br />
&nbsp;&nbsp;&nbsp;List pools=root.getChildren();//得到xml子树<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Element newpool=new Element("pool"); //创建新连接池<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Element pooltype=new Element("type"); //设置连接池类型<br />
&nbsp;&nbsp;&nbsp;pooltype.setText(dsb.getType());<br />
&nbsp;&nbsp;&nbsp;newpool.addContent(pooltype);<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Element poolname=new Element("name");//设置连接池名字<br />
&nbsp;&nbsp;&nbsp;poolname.setText(dsb.getName());<br />
&nbsp;&nbsp;&nbsp;newpool.addContent(poolname);<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Element pooldriver=new Element("driver"); //设置连接池驱动<br />
&nbsp;&nbsp;&nbsp;pooldriver.addContent(dsb.getDriver());<br />
&nbsp;&nbsp;&nbsp;newpool.addContent(pooldriver);<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Element poolurl=new Element("url");//设置连接池url<br />
&nbsp;&nbsp;&nbsp;poolurl.setText(dsb.getUrl());<br />
&nbsp;&nbsp;&nbsp;newpool.addContent(poolurl);<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Element poolusername=new Element("username");//设置连接池用户名<br />
&nbsp;&nbsp;&nbsp;poolusername.setText(dsb.getUsername());<br />
&nbsp;&nbsp;&nbsp;newpool.addContent(poolusername);<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Element poolpassword=new Element("password");//设置连接池密码<br />
&nbsp;&nbsp;&nbsp;poolpassword.setText(dsb.getPassword());<br />
&nbsp;&nbsp;&nbsp;newpool.addContent(poolpassword);<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Element poolmaxconn=new Element("maxconn");//设置连接池最大连接<br />
&nbsp;&nbsp;&nbsp;poolmaxconn.setText(String.valueOf(dsb.getMaxconn()));<br />
&nbsp;&nbsp;&nbsp;newpool.addContent(poolmaxconn);<br />
&nbsp;&nbsp;&nbsp;pools.add(newpool);//将child添加到root<br />
&nbsp;&nbsp;&nbsp;Format format = Format.getPrettyFormat();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.setIndent("");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.setEncoding("utf-8");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XMLOutputter outp = new XMLOutputter(format);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fo = new FileOutputStream(rpath);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outp.output(doc, fo);<br />
&nbsp;&nbsp;} catch (FileNotFoundException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (JDOMException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;finally<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; *删除配置文件<br />
&nbsp; */<br />
&nbsp;public void delConfigInfo(String path,String name)<br />
&nbsp;{<br />
&nbsp;&nbsp;String rpath=this.getClass().getResource("").getPath().substring(1)+path;<br />
&nbsp;&nbsp;FileInputStream fi = null;<br />
&nbsp;&nbsp;FileOutputStream fo=null;<br />
&nbsp;&nbsp;try<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;fi=new FileInputStream(rpath);//读取路径文件<br />
&nbsp;&nbsp;&nbsp;SAXBuilder sb=new SAXBuilder();<br />
&nbsp;&nbsp;&nbsp;Document doc=sb.build(fi);<br />
&nbsp;&nbsp;&nbsp;Element root=doc.getRootElement();<br />
&nbsp;&nbsp;&nbsp;List pools=root.getChildren();<br />
&nbsp;&nbsp;&nbsp;Element pool=null;<br />
&nbsp;&nbsp;&nbsp;Iterator allPool=pools.iterator();<br />
&nbsp;&nbsp;&nbsp;while(allPool.hasNext())<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;pool=(Element)allPool.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(pool.getChild("name").getText().equals(name))<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pools.remove(pool);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;Format format = Format.getPrettyFormat();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.setIndent("");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.setEncoding("utf-8");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XMLOutputter outp = new XMLOutputter(format);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fo = new FileOutputStream(rpath);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outp.output(doc, fo);</div>
<div align="left">&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;} catch (FileNotFoundException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (JDOMException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;finally<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;fi.close();<br />
&nbsp;&nbsp;&nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; * @throws Exception <br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) throws Exception {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</div>
<div align="left">&nbsp;&nbsp;ParseDSConfig pd=new ParseDSConfig();<br />
&nbsp;&nbsp;String path="ds.config.xml";<br />
&nbsp;&nbsp;pd.readConfigInfo(path);<br />
&nbsp;&nbsp;//pd.delConfigInfo(path, "tj012006");<br />
&nbsp;&nbsp;DSConfigBean dsb=new DSConfigBean();<br />
&nbsp;&nbsp;dsb.setType("oracle");<br />
&nbsp;&nbsp;dsb.setName("yyy004");<br />
&nbsp;&nbsp;dsb.setDriver("org.oracle.jdbc");<br />
&nbsp;&nbsp;dsb.setUrl("jdbc:oracle://localhost");<br />
&nbsp;&nbsp;dsb.setUsername("sa");<br />
&nbsp;&nbsp;dsb.setPassword("");<br />
&nbsp;&nbsp;dsb.setMaxconn(1000);<br />
&nbsp;&nbsp;pd.addConfigInfo(path, dsb);<br />
&nbsp;&nbsp;pd.delConfigInfo(path, "yyy001");<br />
&nbsp;}</div>
<div align="left">}<br />
<br />
--------------------------------------<br />
ds.config.xml&nbsp;&nbsp; 配置文件<br />
--------------------------------------<br />
<br />
<br />
&lt;ds-config&gt;<br />
&lt;pool&gt;<br />
&lt;type&gt;mysql&lt;/type&gt;<br />
&lt;name&gt;user&lt;/name&gt;<br />
&lt;driver&gt;com.mysql.jdbc.driver&lt;/driver&gt;<br />
&lt;url&gt;jdbc:mysql://localhost:3306/user&lt;/url&gt;<br />
&lt;username&gt;sa&lt;/username&gt;<br />
&lt;password&gt;123456&lt;/password&gt;<br />
&lt;maxconn&gt;100&lt;/maxconn&gt;<br />
&lt;/pool&gt;<br />
&lt;pool&gt;<br />
&lt;type&gt;mysql&lt;/type&gt;<br />
&lt;name&gt;user2&lt;/name&gt;<br />
&lt;driver&gt;com.mysql.jdbc.driver&lt;/driver&gt;<br />
&lt;url&gt;jdbc:mysql://localhost:3306/user2&lt;/url&gt;<br />
&lt;username&gt;sa&lt;/username&gt;<br />
&lt;password&gt;1234&lt;/password&gt;<br />
&lt;maxconn&gt;10&lt;/maxconn&gt;<br />
&lt;/pool&gt;<br />
&lt;pool&gt;<br />
&lt;type&gt;sql2000&lt;/type&gt;<br />
&lt;name&gt;books&lt;/name&gt;<br />
&lt;driver&gt;com.microsoft.sqlserver.driver&lt;/driver&gt;<br />
&lt;url&gt;jdbc:sqlserver://localhost:1433/books:databasename=books&lt;/url&gt;<br />
&lt;username&gt;sa&lt;/username&gt;<br />
&lt;password&gt;&lt;/password&gt;<br />
&lt;maxconn&gt;100&lt;/maxconn&gt;<br />
&lt;/pool&gt;<br />
&lt;/ds-config&gt;<br />
<br />
<br />
3. 连接池的使用<br />
&nbsp; 1。Connection的获得和释放<br />
&nbsp; DBConnectionManager&nbsp;&nbsp; connectionMan=DBConnectionManager&nbsp;.getInstance();//得到唯一实例<br />
&nbsp;&nbsp; //得到连接<br />
&nbsp;&nbsp; String name="mysql";//从上下文得到你要访问的数据库的名字<br />
&nbsp;&nbsp; Connection&nbsp; con=connectionMan.getConnection(name);<br />
&nbsp; //使用<br />
&nbsp; 。。。。。。。<br />
&nbsp; // 使用完毕<br />
&nbsp;connectionMan.freeConnection(name,con);//释放，但并未断开连接<br />
&nbsp;2。数据库连接的动态增加和连接池的动态增加<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1。调用xml操作增加类<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2。重新实例华连接池管理池类<br />
<br />
&lt;转&gt;<br />
</div>
<img src ="http://www.blogjava.net/zzs/aggbug/258022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-03-05 16:06 <a href="http://www.blogjava.net/zzs/articles/258022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>上下文</title><link>http://www.blogjava.net/zzs/articles/257365.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Mon, 02 Mar 2009 09:07:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/257365.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/257365.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/257365.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/257365.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/257365.html</trackback:ping><description><![CDATA[<font size="2"><strong><span style="color: #339966">Context</span></strong><a name="baidusnap1"></a></font><font color="#ff99cc"><font size="2"><span style="color: #339966"><strong>在Java</strong>中的出现是如此频繁，但其中文翻译&#8220;上下文&#8221;又是如此诡异拗口，因此导致很多人不是很了解Context的具体含义是指什么，所以很有必要来深究一下这词的含义。<br />
<br />
先来举几个JAVA中用到Context的例子<br />
<br />
（1）JNDI的一个类javax.naming.InitialContext，它读取JNDI的一些配置信息，并内含对象和其在JNDI中的注册名称的映射信息。请看下面的代码<br />
</span></font></font>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><font size="2"><span style="color: #339966"><span style="color: #000000">InitialContext ic</span><span style="color: #000000">=</span><span style="color: #0000ff">new </span></span></font><font size="2"><span style="color: #339966"><span style="color: #000000">InitialContext();<br />
RMIAdaptor server</span><span style="color: #000000">=</span><span style="color: #000000">(RMIAdaptor)ic.lookup(</span><span style="color: #000000">"</span><span style="color: #000000">jmx/invoker/RMIAdaptor</span><span style="color: #000000">"</span></span></font><span style="color: #000000"><span style="color: #339966">);<br />
</span></span></div>
<br />
<span style="color: #339966">这是一段JBoss中获取MBean的远程调用类的代码。在这里面通过InitialContext中JNDI注册的名称&#8220;jmx/invoker/RMIAdaptor&#8221;来获得RMIAdaptor<br />
对象。这和JAVA集合中的MAP有点象，有一个String的key，key对映着它的对象。<br />
<br />
（2）再来看看下面Spring中最常见的几句代码。<span style="color: #000000"><font color="#ff99cc"><span style="color: #339966"><font color="#ff99cc"><span style="color: #339966"><font color="#ff99cc"><font color="#ff99cc"><span style="color: #ff0000"><font color="#ff99cc"><font color="#ff99cc"><font color="#ff99cc"><font color="#ff99cc">ApplicationContext 是内含</font></font>configuration.xml配置文件的信息，使得可以通过getBean用名称得到相应的注册对象</font></font></span></font></font></span>。</font><br />
<br />
</span></font></span></span>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><font color="#ff99cc"><font size="2"><span style="color: #339966"><span style="color: #000000">ApplicationContext ctx</span><span style="color: #000000">= </span><span style="color: #0000ff">new </span><span style="color: #000000">FileSystemXmlApplicationContext(</span><span style="color: #000000">"</span><span style="color: #000000">configuration.xml</span><span style="color: #000000">"</span></span></font></font><font color="#ff99cc"><font size="2"><span style="color: #339966"><span style="color: #000000">);<br />
Object obj</span><span style="color: #000000">= </span><span style="color: #000000">ctx.getBean(</span><span style="color: #000000">"</span><span style="color: #000000">Object_Name</span><span style="color: #000000">"</span><span style="color: #000000">);</span></span></font></font></div>
<p><br />
<br />
<span style="color: #339966">从上面的代码，我很能体会到Context所代表的意义：公用信息、环境、容器....。所以我觉得Context翻译成上下文并不直观，按照语言使用的环境，翻译成&#8220;环境&#8221;、&#8220;容器&#8221;可能更好。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(转)<br />
</span></p>
<img src ="http://www.blogjava.net/zzs/aggbug/257365.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-03-02 17:07 <a href="http://www.blogjava.net/zzs/articles/257365.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WEB测试(转)</title><link>http://www.blogjava.net/zzs/articles/257328.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Mon, 02 Mar 2009 05:33:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/257328.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/257328.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/257328.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/257328.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/257328.html</trackback:ping><description><![CDATA[<p align="center">&nbsp;</p>
<div class="postTitle"><a class="postTitle2" id="viewpost1_TitleUrl" href="http://www.blogjava.net/qq13367612/articles/16017.html">Web应用程序测试方法和测试技术详述</a> </div>
<p><font face="宋体"><span lang="EN-US">1. </span>概述</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>随着<span lang="EN-US">web</span>应用的增多，新的模式解决方案中以<span lang="EN-US">web</span>为核心的应用也越来越多， 很多公司各种应用的架构都以<span lang="EN-US">B/S</span>及<span lang="EN-US">web</span>应用为主，但是有关<span lang="EN-US">WEB</span>测试方面的内容并没有相应的总结，所以我在这里对<span lang="EN-US">web</span>的测试方法和采用的测试技术进行总结，便于内部交流。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>测试方法尽量涵盖<span lang="EN-US">web</span>程序的各个方面，测试技术方面在继承传统测试技术的技术上结合<span lang="EN-US">web</span>应用的特点。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>相关的测试和实现技术也有着很大的关系，由于本公司使用<span lang="EN-US">J2EE</span>体系，也许例子中只有<span lang="EN-US">JAVA</span>平台可以使用，<span lang="EN-US">.NET</span>平台测试技术暂时不涉及，如果你有请与我联系。</font><font face="宋体"><span lang="EN-US"> <br />
2. </span>测试方法</font><font face="宋体"><span lang="EN-US"> <br />
</span>说明：测试方法的选择取决你的测试策略。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>一般的<span lang="EN-US">web</span>测试和以往的应用程序的测试的侧重点不完全相同，基本包括以下几个方面。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>当然圆满的完成测试还要有好的团体和流程等的方方面面的支持，你同样应该对这些方面进行注意。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>有些测试方法设计到了流程，哪些应该在你的测试团队建设中建立。 <span lang="EN-US"><o:p></o:p></span></font></p>
<p><font face="宋体"><span lang="EN-US">2.1 </span>界面测试</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>现在一般人都有使用浏览器浏览网页的经历，用户虽然不是专业人员但是对界面效果的印象是很重要的。如果你注重这方面的测试，那么验证应用程序是否易于使用就非常重要了。很多人认为这是测试中最不重要的部分，但是恰恰相反界面对不懂技术的客户来说那相当关键，慢慢体会你会明白的。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>方法上可以根据设计文档，如果够专业的话可以专业美工人员，来确定整体风格页面风格，然后根据这个可以页面人员可以生成静态的<span lang="EN-US">HTML</span>，<span lang="EN-US">CSS</span>等甚至生成几套不用的方案来讨论，或者交给客户评审，最后形成统一的风格的页面<span lang="EN-US">/</span>框架。注意不要靠程序员的美术素养形成你的<span lang="EN-US">web</span>风格，那样可能会很糟糕。</font><font face="宋体"><span lang="EN-US"> <br />
</span>主要包括以下几个方面的内容：</font><font face="宋体"><span lang="EN-US"> <br />
</span>站点地图和导航条 位置、是否合理、是否可以导航等内容布局 布局是否合理，滚动条等简介说明 说明文字是否合理，位置，是否正确</font><font face="宋体"><span lang="EN-US"> <br />
</span>背景<span lang="EN-US">/</span>色调 是否正确、美观，是否符合用户需求；</font><font face="宋体"><span lang="EN-US"> <br />
</span>页面在窗口中的显示是否正确、美观（在调整浏览器窗口大小时，屏幕刷新是否正确）表单样式 大小，格式，是否对提交数据进行验证（如果在页面部分进行验证的话）等</font><font face="宋体"><span lang="EN-US"> <br />
</span>连接 连接的形式，位置，是否易于理解等</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span>web</span>测试的主要页面元素</font><font face="宋体"><span lang="EN-US"> <br />
</span>页面元素的容错性列表（如输入框、时间列表或日历）</font><font face="宋体"><span lang="EN-US"> <br />
</span>页面元素清单（为实现功能，是否将所需要的元素全部都列出来了，如按钮、单选框、复选框、列表框、超连接、输入框等等）</font><font face="宋体"><span lang="EN-US"> <br />
</span>页面元素的容错性是否存在</font><font face="宋体"><span lang="EN-US"> <br />
</span>页面元素的容错性是否正确</font><font face="宋体"><span lang="EN-US"> <br />
</span>页面元素基本功能是否实现（如文字特效、动画特效、按钮、超连接）</font><font face="宋体"><span lang="EN-US"> <br />
</span>页面元素的外形、摆放位置（如按钮、列表框、核选框、输入框、超连接等）</font><font face="宋体"><span lang="EN-US"> <br />
</span>页面元素是否显示正确（主要针对文字、图形、签章）</font><font face="宋体"><span lang="EN-US"> <br />
</span>元素是否显示（元素是否存在）</font><font face="宋体"><span lang="EN-US"> <br />
</span>页面元素清单（为实现功能，是否将所需要的元素全部都列出来了，如按钮、单选框、复选框、列表框、超连接、输入框等等）</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>测试技术</font><font face="宋体"><span lang="EN-US"> <br />
&nbsp;&nbsp;&nbsp;&nbsp; </span>通过页面走查，浏览确定使用的页面是否符合需求。可以结合兼容性测试对不用分辨率下页面显示效果，如果有影响应该交给设计人员提出解决方案。</font><font face="宋体"><span lang="EN-US">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span>可以结合数据定义文档查看表单项的内容，长度等信息。</font><font face="宋体"><span lang="EN-US"> <br />
&nbsp;&nbsp;&nbsp;&nbsp;</span>对于动态生成的页面最好也能进行浏览查看。如<span lang="EN-US">Servelet</span>部分可以结合编码规范，进行代码走查。是否支持中文，如果数据用<span lang="EN-US">XM<span style="mso-spacerun: yes">&nbsp; </span></span>封装要做的工作会多一点等等。 <span lang="EN-US"><o:p></o:p></span></font></p>
<p><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>界面测试要素</font><font face="宋体"><span lang="EN-US">: <br />
</span>符合标准和规范<span lang="EN-US">,</span>灵活性<span lang="EN-US">,</span>正确性<span lang="EN-US">,</span>直观性<span lang="EN-US">,</span>舒适性<span lang="EN-US">,</span>实用性<span lang="EN-US">,</span>一致性</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span>1.</span>直观性</font><font face="宋体"><span lang="EN-US">: <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>用户界面是否洁净<span lang="EN-US">,</span>不唐突<span lang="EN-US">,</span>不拥挤<span lang="EN-US">.</span>界面不应该为用户制造障碍<span lang="EN-US">.</span>所需功能或者期待的响应应该明显<span lang="EN-US">,</span>并在预期出现的地方</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>界面组织和布局合理吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>是否允许用户轻松地从一个功能转到另一个功能<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>下一步做什么明显吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>任何时刻都可以决定放弃或者退回<span lang="EN-US">,</span>退出吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>输入得到承认了吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>菜单或者窗口是否深藏不露</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>有多余功能吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>软件整体抑或局部是否做得太多<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>是否有太多特性把工作复杂化了<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>是否感到信息太庞杂</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>如果其他所有努力失败<span lang="EN-US">,</span>帮助系统真能帮忙吗</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span>2.</span>一致性</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>快速键和菜单选项<span lang="EN-US">.</span>在<span lang="EN-US">Windows </span>中按<span lang="EN-US">F1</span>键总是得到帮助信息</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>术语和命令<span lang="EN-US">.</span>整个软件使用同样的术语吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>特性命名一致吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>例如<span lang="EN-US">,Find</span>是否一直叫<span lang="EN-US">Find,</span>而不是有时叫</font><font face="宋体"><span lang="EN-US">Search<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>软件是否一直面向同一级别用户<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>带有花哨用户界面的趣味贺卡程序不应该显示泄露技术机密的错误提示信息</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>按钮位置和等价的按键<span lang="EN-US">.</span>大家是否注意到对话框有<span lang="EN-US">OK</span>按钮和<span lang="EN-US">Canc<span style="mso-spacerun: yes">&nbsp; </span>e</span>按钮时<span lang="EN-US">,OK</span>按钮总是在上方或者左方<span lang="EN-US">,</span>而<span lang="EN-US">Canc<span style="mso-spacerun: yes">&nbsp; </span>e</span>按钮总是在下方或右方<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>同样原因<span lang="EN-US">,Canc<span style="mso-spacerun: yes">&nbsp; </span>e</span>按钮的等价按键通常是<span lang="EN-US">Esc,</span>而选中按钮的等价按钮通常是<span lang="EN-US">Enter.</span>保持一致</font><font face="宋体"><span lang="EN-US">. <br />
<br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span>3.</span>灵活性</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>状态跳转<span lang="EN-US">.</span>灵活的软件实现同一任务有多种选择方式</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>状态终止和跳过<span lang="EN-US">,</span>具有容错处理能力</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>数据输入和输出<span lang="EN-US">.</span>用户希望有多种方法输入数据和查看结果<span lang="EN-US">.</span>例如<span lang="EN-US">,</span>在写字板插入文字可用键盘输入<span lang="EN-US">,</span>粘贴<span lang="EN-US">,</span>从<span lang="EN-US">6</span>种文件格式读入<span lang="EN-US">,</span>作为对象插入<span lang="EN-US">,</span>或者用鼠标从其他程序拖动</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span>4.</span>舒适性</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>恰当<span lang="EN-US">.</span>软件外观和感觉应该与所做的工作和使用者相符</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>错误处理<span lang="EN-US">.</span>程序应该在用户执行严重错误的操作之前提出警告<span lang="EN-US">,</span>并允许用户恢复由于错误操作导致丢失的数据<span lang="EN-US">.</span>如大家认为<span lang="EN-US">undo /redo</span>是当然的</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>性能<span lang="EN-US">.</span>快不见得是好事<span lang="EN-US">.</span>要让用户看得清程序在做什么<span lang="EN-US">,</span>它是有反应的<span lang="EN-US">. <o:p></o:p></span></font></p>
<p><font face="宋体"><span lang="EN-US">2.2 </span>功能测试</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>对功能测试是测试中的重点</font><font face="宋体"><span lang="EN-US"> <br />
</span>主要包括一下几个方面的内容</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>连接这个连接和界面测试中的连接不同那里注重的是连接方式和位置，如是图像还是文字放置的位置等，还是其他的方式。这里的连接注重功能。如是否有连接，连接的是否是说明的位置等。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>表单提交应当模拟用户提交，验证是否完成功能，如注册信息，要测试这些程序，需要验证服务器能正确保存这些数据，而且后台运行的程序能正确解释和使用这些信息。还有数据正确性验证，异常处理等，最好结合易用性要求等。<span lang="EN-US">B/S</span>结构实现的功能可能主要的就在这里，提交数据，处理数据等如果有固定的操作流程可以考虑自动化测试工具的录制功能，编写可重复使用的脚本代码，可以在测试、回归测试时运行以便减轻测试人员工作量。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span>Cookies </span>验证 如果系统使用了<span lang="EN-US">cookie</span>，测试人员需要对它们进行检测。如果在<span lang="EN-US"> cookies </span>中保存了注册信息，请确认该<span lang="EN-US"> cookie</span>能够正常工作而且已对这些信息已经加密。如果使用<span lang="EN-US"> cookie </span>来统计次数，需要验证次数累计正确。关于<span lang="EN-US">cookie</span>的使用可以参考浏览器的帮助信息。如果使用<span lang="EN-US">B/S</span>结构<span lang="EN-US">cookies</span>中存放的信息更多。功能易用性测试 完成了功能测试可以对应用性进行了解，最好听听客户的反映，在可以的情况下对程序进行改进是很有必要的，和客户保持互动对系统满意度也是很有帮助的。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>测试技术功能测试的测试技术可是很多的，我们可以结合实际环境选择使用</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>白盒测试技术<span lang="EN-US">(White Box Testing) </span>深入到代码一级的测试，使用这种技术发现问题最早，效果也是最好的。该技术主要的特征是测试对象进入了代码内部<span lang="EN-US">,</span>根据开发人员对代码和对程序的熟悉程度<span lang="EN-US">,</span>对有需要的部分进行在软件编码阶段，开发人员根据自己对代码的理解和接触所进行的软件测试叫做白盒测试。这一阶段测试以软件开发人员为主，在<span lang="EN-US">JAVA</span>平台使用<span lang="EN-US">Xunit</span>系列工具进行测试，<span lang="EN-US">Xunit</span>测试工具是类一级的测试工具对每一个类和该类的方法进行测试。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>黑盒测试技术（<span lang="EN-US">Black Box Testing</span>）黑盒测试的内容主要有以下几个方面，但是主要还是功能部分。主要是覆盖全部的功能，可以结合兼容，性能测试等方面进行，根据软件需求，设计文档，模拟客户场景随系统进行实际的测试，这种测试技术是使用最多的测试技术涵盖了测试的方方面面，可以考虑以下方面</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span></span>正确性<span lang="EN-US"> (Correctness)</span>：计算结果，命名等方面</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span></span>可用性<span lang="EN-US"> (Usability)</span>：是否可以满足软件的需求说明。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span></span>边界条件<span lang="EN-US"> (Boundary Condition)</span>输入部分的边界值<span lang="EN-US">,</span>就是使用一般书中说的等价类划分<span lang="EN-US">,</span>试试最大最小和非法数据等等</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span></span>性能<span lang="EN-US"> (Performance) </span>正常使用的时间内系统完成一个任务需要的时间<span lang="EN-US">,</span>多人同时使用的时候响应时间<span lang="EN-US">,</span>在可以接受范围内<span lang="EN-US">.J2EE</span>技术实现的系统在性能方面更是需要照顾的<span lang="EN-US">,</span>一般原则是<span lang="EN-US">3</span>秒以下接受<span lang="EN-US">,3-5</span>秒可以接受<span lang="EN-US">,5</span>秒以上就影响易用性了<span lang="EN-US">. </span>如果在测试过程中发现性能问题，修复起来是非常艰难的，因为这常常意味着</font><font face="宋体"><span lang="EN-US"> <br />
</span>程序的算法不好，结构不好，或者设计有问题。因此在产品开发的开始阶段，就要考虑到软件的性能问题</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span></span>压力测试<span lang="EN-US"> (Stress) </span>多用户情况 可以考虑使用压力测试工具<span lang="EN-US">,</span>建议将压力和性能测试结合起来进行<span lang="EN-US">.</span>如果有负载平衡的话还要在服务器端打开监测工具<span lang="EN-US">,</span>查看服务器<span lang="EN-US">CPU</span>使用率<span lang="EN-US">,</span>内存占用情况<span lang="EN-US">,</span>如果有必要可以模拟大量数据输入<span lang="EN-US">,</span>对硬盘的影响等等信息<span lang="EN-US">.</span>如果有必要的话必须进行性能优化<span lang="EN-US">(</span>软硬件都可以<span lang="EN-US">).</span>这里的压力测试针对的是某几项功能</font><font face="宋体"><span lang="EN-US">,. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span></span>错误恢复<span lang="EN-US"> (Error Recovery) </span>错误处理，页面数据验证<span lang="EN-US">,</span>包括突然间断电<span lang="EN-US">,</span>输入脏数据等</font><font face="宋体"><span lang="EN-US">. <br />
</span>安全性测试<span lang="EN-US">(Security)</span>这个领域正在研究中<span lang="EN-US">,</span>不过防火墙<span lang="EN-US">,</span>补丁包<span lang="EN-US">.</span>杀毒软件等的就不必说了<span lang="EN-US">,</span>不过可以考虑破坏性测试时任意<span lang="EN-US">.</span>看了一些资料后得知<span lang="EN-US">,</span>这里面设计到的知识<span lang="EN-US">\</span>内容可以写本书了<span lang="EN-US">,</span>不是一两句可以说清的<span lang="EN-US">,</span>特别是一些商务网站<span lang="EN-US">,</span>或者跟钱有关<span lang="EN-US">,</span>或者和公司秘密有关的<span lang="EN-US">web</span>更是<span lang="EN-US">,</span>需要这方面的测试<span lang="EN-US">,</span>在外国有一种专门干这一行的人叫安全顾问<span lang="EN-US">,</span>可以审核代码<span lang="EN-US">,</span>提出安全建议<span lang="EN-US">,</span>出现紧急事件是的处理办法等<span lang="EN-US">,</span>在国内没有听说哪里有专门搞安全技术测试的内容</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span></span>兼容性<span lang="EN-US"> (Compatibility) </span>不同浏览器，不同应用程序版本在实现功能时的表现<span lang="EN-US">,</span>不同的上网方式<span lang="EN-US">,</span>如果你测试的是一个公共网站的话</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>兼容性测试内容详述</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>硬件平台</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>浏览器软件和版本<span lang="EN-US">:</span>浏览器插件<span lang="EN-US">,</span>浏览器选项<span lang="EN-US">,</span>视频分辨率和色深<span lang="EN-US">.</span>文字大小<span lang="EN-US">,</span>调制解调器速率</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span></span>软件配置<span lang="EN-US"> (Configuration) </span>如<span lang="EN-US">IE</span>浏览器的不用选项<span lang="EN-US">-</span>安全设定最高<span lang="EN-US">,</span>禁用脚本程序<span lang="EN-US">,</span>等等<span lang="EN-US">,</span>你们的程序在各种不用的设置下表现如何<span lang="EN-US">. <o:p></o:p></span></font></p>
<p><font face="宋体">单元测试技术</font><font face="宋体"><span lang="EN-US">(Unit Test): <br />
2.2.1 </span>下面是对白盒测试和单元测试的区别的论述</font><font face="宋体"><span lang="EN-US">: <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>单元测试和白盒测试是不同的<span lang="EN-US">,</span>虽然单元测试和白盒测试都是关注功能虽然他们都需要代码支持<span lang="EN-US">,</span>但是级别不同<span lang="EN-US">,</span>白盒测试关注的是类中一个方法的功能是更小的单位<span lang="EN-US">,</span>但是完成一个单元测试可能需要<span lang="EN-US">N</span>多类<span lang="EN-US">,</span>所以说作单元测试需要什么写驱动和稳定桩<span lang="EN-US">,</span>比如查询单元是一个查询包包<span lang="EN-US">N</span>多的测试类<span lang="EN-US">,</span>测试数据<span lang="EN-US">,</span>运行他需要提供数据的部分<span lang="EN-US">,</span>输入参数和发出命令的驱动等等<span lang="EN-US">.</span>是比类大的一个整体进行的</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>另一个明显的区别是白盒测试不会关注类接口<span lang="EN-US">,</span>但是单元测试主要的内容就是类接口测试</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>不过很多时候是很少区分的<span lang="EN-US">,</span>因为这两种技术实现起来有很多相互关联的部分<span lang="EN-US">.</span>不过要看你对质量的关注程度来决定</font><font face="宋体"><span lang="EN-US">. <br />
2.2.2 </span>功能测试边界测试<span lang="EN-US">\</span>越界测试技术详述</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>边界条件</font><font face="宋体"><span lang="EN-US"> <br />
</span>边界条件是指软件计划的操作界限所在的边缘条件</font><font face="宋体"><span lang="EN-US">. <br />
</span>如果软件测试问题包含确定的边界<span lang="EN-US">,</span>那么数据类型可能是</font><font face="宋体"><span lang="EN-US">: <br />
</span>数值 速度 字符 地址 位置 尺寸 数量</font><font face="宋体"><span lang="EN-US"> <br />
</span>同时<span lang="EN-US">,</span>考虑这些类型的下述特征</font><font face="宋体"><span lang="EN-US">: <br />
</span>第一个<span lang="EN-US">/</span>最后一个 最小值<span lang="EN-US">/</span>最大值</font><font face="宋体"><span lang="EN-US"> <br />
</span>开始<span lang="EN-US">/</span>完成 超过<span lang="EN-US">/</span>在内</font><font face="宋体"><span lang="EN-US"> <br />
</span>空<span lang="EN-US">/</span>满 最短<span lang="EN-US">/</span>最长</font><font face="宋体"><span lang="EN-US"> <br />
</span>最慢<span lang="EN-US">/</span>最快 最早<span lang="EN-US">/</span>最迟</font><font face="宋体"><span lang="EN-US"> <br />
</span>最大<span lang="EN-US">/</span>最小 最高<span lang="EN-US">/</span>最低</font><font face="宋体"><span lang="EN-US"> <br />
</span>相邻<span lang="EN-US">/</span>最远</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>越界测试</font><font face="宋体"><span lang="EN-US"> <br />
</span>通常是简单加<span lang="EN-US">1</span>或者很小的数<span lang="EN-US">(</span>对于最大值<span lang="EN-US">)</span>和减少<span lang="EN-US">1</span>或者很小的数<span lang="EN-US">(</span>对于最小值<span lang="EN-US">),</span>例如</font><font face="宋体"><span lang="EN-US">: <br />
</span>第一个减<span lang="EN-US">1/</span>最后一个加</font><font face="宋体"><span lang="EN-US">1 <br />
</span>开始减<span lang="EN-US">1/</span>完成加</font><font face="宋体"><span lang="EN-US">1 <br />
</span>空了再减<span lang="EN-US">/</span>满了再加</font><font face="宋体"><span lang="EN-US"> <br />
</span>慢上加慢<span lang="EN-US">/</span>快上加快</font><font face="宋体"><span lang="EN-US"> <br />
</span>最大数加<span lang="EN-US">1/</span>最小数减</font><font face="宋体"><span lang="EN-US">1 <br />
</span>最小值减<span lang="EN-US">1/</span>最大值加</font><font face="宋体"><span lang="EN-US">1 <br />
</span>刚好超过<span lang="EN-US">/</span>刚好在内</font><font face="宋体"><span lang="EN-US"> <br />
</span>短了再短<span lang="EN-US">/</span>长了再长</font><font face="宋体"><span lang="EN-US"> <br />
</span>早了更早<span lang="EN-US">/</span>晚了更晚</font><font face="宋体"><span lang="EN-US"> <br />
</span>最高加<span lang="EN-US">1/</span>最低减</font><font face="宋体"><span lang="EN-US">1 <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>另一些该注意的输入<span lang="EN-US">:</span>默认<span lang="EN-US">,</span>空白<span lang="EN-US">,</span>空值<span lang="EN-US">,</span>零值和无<span lang="EN-US">;</span>非法<span lang="EN-US">,</span>错误<span lang="EN-US">,</span>不正确和垃圾数据</font><font face="宋体"><span lang="EN-US">. <br />
2.2.3 </span>状态测试技术</font><font face="宋体"><span lang="EN-US"> <br />
<br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>软件可能进入的每一种独立状态</font><font face="宋体"><span lang="EN-US">; <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>从一种状态转入另一种状态所需的输入和条件</font><font face="宋体"><span lang="EN-US">; <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>进入或退出某种状态时的设置条件及输入结果</font><font face="宋体"><span lang="EN-US">. <br />
<br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>具体测试方法可以参考如下</font><font face="宋体"><span lang="EN-US">: <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>每种状态至少访问一次</font><font face="宋体"><span lang="EN-US">; <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>测试看起来最常见最普遍的状态转换</font><font face="宋体"><span lang="EN-US">; <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>测试状态之间最不常用的分支</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>测试所有错误状态及其返回值</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>测试随机状态转换</font><font face="宋体"><span lang="EN-US"> <br />
2.2.4 </span>竞争条件测试技术</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>竞争条件典型情形参考如下</font><font face="宋体"><span lang="EN-US">: <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>两个不同的程序同时保存或打开同一个文档</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>共享同一台打印机<span lang="EN-US">,</span>通信端口或者其他外围设备</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>当软件处于读取或者修改状态时按键或者单击鼠标</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>同时关闭或者启动软件的多个实例</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>同时使用不同的程序访问一个共同数据库 <span lang="EN-US"><o:p></o:p></span></font></p>
<p><font face="宋体"><span lang="EN-US">2.3 </span>负载<span lang="EN-US">\</span>压力测试</font><font face="宋体"><span lang="EN-US">(StressTest) <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>在这里的负载<span lang="EN-US">\</span>压力和功能测试中的不同<span lang="EN-US">,</span>他是系统测试的内容<span lang="EN-US">,</span>是基本功能已经通过后进行的<span lang="EN-US">.</span>可以在集成测试阶段<span lang="EN-US">,</span>亦可以在系统测试阶段进行</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>使用负载测试工具进行<span lang="EN-US">,</span>虚拟一定数量的用户看一看系统的表现<span lang="EN-US">,</span>是否满足定义中的指标</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>负载测试一般使用工具完成，<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span>oadrunner</span>，<span lang="EN-US">web<span style="mso-spacerun: yes">&nbsp; </span>oad</span>，<span lang="EN-US">was</span>，<span lang="EN-US">ew<span style="mso-spacerun: yes">&nbsp; </span></span>，<span lang="EN-US">e-test</span>等，主要的内容都是编写出测试脚本，脚本中一般包括用户一般常用的功能，然后运行，得出报告。所以负载测试包括的主要内容就不介绍了。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>负载测试技术在各种极限情况下对产品进行测试<span lang="EN-US"> (</span>如很多人同时使用该软件，或者反复运行该软件<span lang="EN-US">)</span>，以检查产品的长期稳定性。例如，使用压力测试工具对<span lang="EN-US">web</span>服务器进行压力测试<span lang="EN-US">. </span>本项测试可以帮助找到一些大型的问题，如死机、崩损、内存泄漏等，因为有些存在内存泄漏问题的程序，在运行一两次时可能不会出现问题，但是如果运行了成千上万次，内存泄漏得越来越多，就会导致系统崩滑。用<span lang="EN-US">J2EE</span>实现的系统很少但是并不是没有内存问题</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>无论什么工具基本的技术都是利用线程技术模仿和虚拟用户，在这里主要的难点在与测试脚本的编写，每种工具使用的脚本都不一样，但是大多数工具都提供录制功能就算是不会编码的测试人员同样可以测试。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>对负载工具的延伸使用可以进行系统稳定性测试，系统极限测试，如使用<span lang="EN-US">100</span>的<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span>oad Size</span>连续使用<span lang="EN-US">24</span>小时，微软定义的通过准则是通过<span lang="EN-US">72</span>小时测试的程序一般不会出现稳定性的问题。 <span lang="EN-US"><o:p></o:p></span></font></p>
<p><font face="宋体"><span lang="EN-US">2.4 </span>回归测试</font><font face="宋体"><span lang="EN-US"> (Regression Test) <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>过一段时间以后，再回过头来对以前修复过的<span lang="EN-US">Bug</span>重新进行测试，看该<span lang="EN-US">Bug </span>是否会重新出现。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>回归测试技术可以在测试的各个阶段出现，无论是单元测试还是集成测试还是系统测试。是对以前问题进行验证的过程。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>回归测试的目的就是保证以前已经修复的<span lang="EN-US">Bug</span>不会再出现。实际上，许多<span lang="EN-US">Bug</span>都是在回归测试时发现的，在此阶段，我们首先要检查以前找到的<span lang="EN-US">Bug </span>是否已经更正了。值得注意的是，已经更正的<span lang="EN-US">Bug </span>也可能又回来了，有的<span lang="EN-US">Bug </span>经过修改之后可能又产生了新的<span lang="EN-US">Bug</span>。所以，回归测试可保证已更正的<span lang="EN-US">Bug</span>不再重现，不产生新的<span lang="EN-US">Bug</span>。</font><font face="宋体"><span lang="EN-US"> <br />
2.5 A<span style="mso-spacerun: yes">&nbsp; </span>pha </span>和<span lang="EN-US">Beta </span>测试</font><font face="宋体"><span lang="EN-US"> (A<span style="mso-spacerun: yes">&nbsp; </span>pha and Beta Test): <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>在正式发布产品之前往往要先发布一些测试版，让用户能够反馈出相关信息，或者找到存在的<span lang="EN-US">Bug</span>，以便在正式版中得到解决。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>特别是在有客户参加的情况下，对系统进行测试可能会出现一些我们没有考虑的情况，还可以解决一些客户实际关心的问题 <span lang="EN-US"><o:p></o:p></span></font></p>
<p><font face="宋体">不同的测试技术区分</font><font face="宋体"><span lang="EN-US"> <br />
3.1 </span>覆盖测试技术</font><font face="宋体"><span lang="EN-US"> <br />
</span>说明<span lang="EN-US">:</span>测试覆盖率可以看出测试的完成度<span lang="EN-US">,</span>在测试分析报告中可以作为量化指标的依据，测试覆盖率越高效果越好。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>覆盖测试可以是程序代码的执行路径覆盖，亦可以是功能实现的步骤覆盖（可以理解成流程图的路径覆盖）。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>该技术可以用在任何测试阶段，包括单元测坏死、集成测试、系统测试。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>使用该技术时可以使用以上的任何测试方法和测试技术。</font><font face="宋体"><span lang="EN-US"> <br />
3.2 </span>白盒测试和黑盒测试技术</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>白盒测试技术<span lang="EN-US"> (White Box Testing)</span>该技术主要的特征是测试对象进入了代码内部<span lang="EN-US">,</span>根据开发人员对代码和对程序的熟悉程度<span lang="EN-US">,</span>对有需要的部分进行在软件编码阶段，开发人员根据自己对代码的理解和接触所进行的软件测试叫做白盒测试。这一阶段测试以软件开发人员为主，使用<span lang="EN-US">Xunit</span>系列工具进行测试，可以包括很多方面如功能性能等。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>黑盒测试<span lang="EN-US"> (Black Box Testing)</span>测试的主体部分黑盒测试的内容主要有以下几个方面，但是主要还是功能部分。主要是覆盖全部的功能，可以结合兼容，性能测试等方面进行<span lang="EN-US">,</span>包括的不同测试类型请参考以上内容。</font><font face="宋体"><span lang="EN-US"> <br />
3.3 </span>手工测试和自动化测试</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>手工测试（<span lang="EN-US">Manual <span style="mso-spacerun: yes">&nbsp;</span>Testing</span>）：即依靠人力来查找<span lang="EN-US">Bug</span>。方法可以参考上边的测试，也可以根据对实现技术及经验等进行不同的测试。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>自动测试（<span lang="EN-US">Automation Testing</span>）使用有针对工具实行。可以作出自动化测试的计划<span lang="EN-US">,</span>对可以进行自动化测试的部分编写或者录制相应的脚本<span lang="EN-US">,</span>可以加入功能<span lang="EN-US">,</span>容错<span lang="EN-US">,</span>表单提交等<span lang="EN-US">,</span>可以参考<span lang="EN-US">MI,Rationa<span style="mso-spacerun: yes">&nbsp; </span></span>或者其他类测试工具说明</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>根据权威的软件测试经验，手工测试还是主要的测试方法，自动测试不够灵活，在这里不再详述。微软的测试过程<span lang="EN-US">80</span>％还是手工完成。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>自动测试永远也代替不了手工测试，但是手工测试的工作量很大是不争的事实。</font><font face="宋体"><span lang="EN-US"> <br />
3.4 </span>根据<span lang="EN-US">RUP</span>标准按阶段区分测试</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>单元测试在上边有详细的叙述，还有针对单元测试和集成测试的论述，请参考。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>集成测试分为功能集成测试和系统集成测试，相互有调用的功能集成，在系统环境下功能相互调用的影响等，使用方法可以任意选用上面的内容。注重功能方面。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>系统测试在功能实现的基础上，可以加入兼容性，易用性，性能等等</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>验收测试可以包括<span lang="EN-US">Alpha</span>和<span lang="EN-US">Beta</span>测试，在这里就不再详述。 <span lang="EN-US"><o:p></o:p></span></font></p>
<p><font face="宋体"><span lang="EN-US">4. </span>存在风险及解决方法</font><font face="宋体"><span lang="EN-US"> <br />
</span>说明：测试不能找出所有的问题，只是尽量将问题在开发阶段解决大多数的问题而已。</font><font face="宋体"><span lang="EN-US"> <br />
</span>测试风险如下：</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>软硬件的测试环境提供上也对测试结果有很大的影响。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>测试团队的水平，经验，合作效果等</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>整个开发流程对测试的重视程度，测试的进入时间等</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>由于测试环境操作系统，网络环境，带宽等情况可能产生的测试结果可能不同这是就需要经验以及对测试环境的保护等方面下一些功夫。</font><font face="宋体"><span lang="EN-US"> <br />
5. </span>软件缺陷的原则</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>软件缺陷区别于软件<span lang="EN-US">bug,</span>它是在测试过程中出现的对系统有影响的<span lang="EN-US">,</span>但是在设计中没有的或者对修改后的<span lang="EN-US">bug</span>测试和开发人员有不同意见等</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>软件未达到产品说明书标明的功能。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>软件出现了产品说明书指明不会出现的错误。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>软件功能超出产品说明书指明范围。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>软件未达到产品说明书虽未指出但应达到的目标。</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>软件测试员认为软件难以理解、不易使用、运行速度缓慢，或者最终用户认为不好。 <span lang="EN-US"><o:p></o:p></span></font></p>
<p><font face="宋体"><span lang="EN-US">6. </span>文档测试</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>产品说明书属性检查清单</font><font face="宋体"><span lang="EN-US"> <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>完整<span lang="EN-US">.</span>是否有遗漏和丢失<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>完全吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>单独使用是否包含全部内容</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>准确<span lang="EN-US">.</span>既定解决方案正确吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>目标明确吗<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>有没有错误</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>精确<span lang="EN-US">,</span>不含糊<span lang="EN-US">,</span>清晰<span lang="EN-US">.</span>描述是否一清二楚<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>还是自说自话<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>容易看懂和理解吗</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>一致<span lang="EN-US">.</span>产品功能能描述是否自相矛盾<span lang="EN-US">,</span>与其他功能有没有冲突</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>贴切<span lang="EN-US">.</span>描述功能的陈述是否必要<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>有没有多余信息<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>功能是否原来的客户要求</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>合理<span lang="EN-US">.</span>在特定的预算和进度下<span lang="EN-US">,</span>以现有人力<span lang="EN-US">,</span>物力和资源能否实现</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>代码无关<span lang="EN-US">.</span>是否坚持定义产品<span lang="EN-US">,</span>而不是定义其所信赖的软件设计<span lang="EN-US">,</span>架构和代码</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>可测试性<span lang="EN-US">.</span>特性能否测试<span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span></span>测试员建立验证操作的测试程序是否提供足够的信息</font><font face="宋体"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><br />
<br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>产品说明书用语检查清单</font><font face="宋体"><span lang="EN-US"> <br />
</span>说明 对问题的描述通常表现为粉饰没有仔细考虑的功能<span lang="EN-US">----</span>可归结于前文所述的属性<span lang="EN-US">.</span>从产品说明书上找出这样的用语<span lang="EN-US">,</span>仔细审视它们在文中是怎样使用的<span lang="EN-US">.</span>产品说明书可能会为其掩饰和开脱<span lang="EN-US">,</span>也可能含糊其词<span lang="EN-US">----</span>无论是哪一种情况都可视为软件缺陷</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>总是<span lang="EN-US">,</span>每一种<span lang="EN-US">,</span>所有<span lang="EN-US">,</span>没有<span lang="EN-US">,</span>从不<span lang="EN-US">.</span>如果看到此类绝对或肯定的<span lang="EN-US">,</span>切实认定的叙述<span lang="EN-US">,</span>软件测试员就可以着手设计针锋相对的案例</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>当然<span lang="EN-US">,</span>因此<span lang="EN-US">,</span>明显<span lang="EN-US">,</span>显然<span lang="EN-US">,</span>必然<span lang="EN-US">.</span>这些话意图诱使接受假定情况<span lang="EN-US">.</span>不要中了圈套</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>某些<span lang="EN-US">,</span>有时<span lang="EN-US">,</span>常常<span lang="EN-US">,</span>通常<span lang="EN-US">,</span>惯常<span lang="EN-US">,</span>经常<span lang="EN-US">,</span>大多<span lang="EN-US">,</span>几乎<span lang="EN-US">.</span>这些话太过模糊<span lang="EN-US">."</span>有时<span lang="EN-US">"</span>发生作用的功能无法测试</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>等等<span lang="EN-US">,</span>诸如此类<span lang="EN-US">,</span>依此类推<span lang="EN-US">.</span>以这样的词结束的功能清单无法测试<span lang="EN-US">.</span>功能清单要绝对或者解释明确<span lang="EN-US">,</span>以免让人迷惑<span lang="EN-US">,</span>不知如何推论</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>良好<span lang="EN-US">,</span>迅速<span lang="EN-US">,</span>廉价<span lang="EN-US">,</span>高效<span lang="EN-US">,</span>小<span lang="EN-US">,</span>稳定<span lang="EN-US">.</span>这些是不确定的说法<span lang="EN-US">,</span>不可测试<span lang="EN-US">.</span>如果在产品说明书中出现<span lang="EN-US">,</span>就必须进一步指明含义</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>已处理<span lang="EN-US">,</span>已拒绝<span lang="EN-US">,</span>已忽略<span lang="EN-US">,</span>已消除<span lang="EN-US">.</span>这些廉洁可能会隐藏大量需要说明的功能</font><font face="宋体"><span lang="EN-US">. <br />
<span style="mso-spacerun: yes">&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span></span>如果<span lang="EN-US">...</span>那么<span lang="EN-US">...(</span>没有否则<span lang="EN-US">).</span>找出有<span lang="EN-US">"</span>如果<span lang="EN-US">...</span>那么<span lang="EN-US">..."</span>而缺少配套的<span lang="EN-US">"</span>否则<span lang="EN-US">"</span>结构的陈述<span lang="EN-US">.</span>想一想<span lang="EN-US">"</span>如果<span lang="EN-US">"</span>没有发生会怎样<span lang="EN-US">. <o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<img src ="http://www.blogjava.net/zzs/aggbug/257328.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-03-02 13:33 <a href="http://www.blogjava.net/zzs/articles/257328.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>annotation的作用（转）</title><link>http://www.blogjava.net/zzs/articles/257071.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Fri, 27 Feb 2009 09:23:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/257071.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/257071.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/257071.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/257071.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/257071.html</trackback:ping><description><![CDATA[annotation到底能起什么作用呢？<br />
1，&nbsp;&nbsp;&nbsp;&nbsp;编译工具或其他工具可以根据被附加在代码里的annotation信息自动生成配置文件或文档等外部文件。<br />
比如，sun公司就提供了<a href="http://java.sun.com/j2se/1.5.0/docs/guide/apt/" target="blank">apt（Annotation Processing Tool）</a>工具，apt工具是一个可以处理annotation的命令行工具，apt提供了在编译期针对源代码级别的解析，并可以在解析时生成新的源代码和其他文件，同时还可以对生成的源代码进行编译。<br />
2，&nbsp;&nbsp;&nbsp;&nbsp;其他程序可以在运行时动态解析将要被执行的程序里的annotation信息，并根据被附加的annotation信息来执行不同的操作。<br />
比如，EJB3规范就比较广泛地使用了annotation特性。比如只要在POJO为class注明@Stateless注释，EJB容器便会根据此annotation把该POJO注册为无状态的Session Bean。EJB3使用了annotation大大地简化了EJB的开发和配置过程。我们会在其他文章里专门介绍EJB Annotation的原理与使用方法，这里不做详述。<br />
<br />
本文通过一个简单地例子来说明怎么在运行期动态解析annotation。Apt工具的使用我们会在近期其他文章里对其加以介绍。<br />
<br />
比如，我们定义了MyAnnotation3注释：<br />
&nbsp;MyAnnotation3.java<br />
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">package</span> com.test.annotation;<br />
<br />
<span style="font-weight: bold; color: #7f0055">import</span> java.lang.annotation.Annotation;<br />
<span style="font-weight: bold; color: #7f0055">import</span> java.lang.annotation.Inherited;<br />
<span style="font-weight: bold; color: #7f0055">import</span> java.lang.annotation.Retention;<br />
<span style="font-weight: bold; color: #7f0055">import</span> java.lang.annotation.RetentionPolicy;<br />
<br />
@Retention(RetentionPolicy.RUNTIME)<br />
<span style="font-weight: bold; color: #7f0055">public</span> @<span style="font-weight: bold; color: #7f0055">interface</span> MyAnnotation3 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String value();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String[] multiValues();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">int</span> number() <span style="font-weight: bold; color: #7f0055">default</span> 0;<br />
}<br />
</div>
上面定义了一个名为MyAnnotation3的注释。<br />
<br />
我们再定义一个GetMyAnnotation类，该类使用了MyAnnotation3注释：<br />
GetMyAnnotation.java：<br />
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">package</span> com.test.annotation.test;<br />
<br />
<span style="font-weight: bold; color: #7f0055">import</span> java.lang.annotation.Annotation;<br />
<span style="font-weight: bold; color: #7f0055">import</span> java.lang.reflect.Field;<br />
<span style="font-weight: bold; color: #7f0055">import</span> java.lang.reflect.Method;<br />
<br />
<span style="font-weight: bold; color: #7f0055">import</span> javax.ejb.EJB;<br />
<span style="font-weight: bold; color: #7f0055">import</span> javax.naming.InitialContext;<br />
<span style="font-weight: bold; color: #7f0055">import</span> javax.naming.NamingException;<br />
<br />
<span style="font-weight: bold; color: #7f0055">import</span> com.test.annotation.MyAnnotation3;<br />
<br />
<span style="color: #3f7f5f">// 为GetMyAnnotation类附加MyAnnotation3 注释<br />
</span>@MyAnnotation3(value = "<span style="color: #2a00ff">Class GetMyAnnotation</span>", multiValues = {"<span style="color: #2a00ff">1</span>","<span style="color: #2a00ff">2</span>"})<br />
<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">class</span> GetMyAnnotation {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #3f7f5f">// 为testField1属性附加MyAnnotation3 注释<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;@MyAnnotation3(value = "<span style="color: #2a00ff">call testField1</span>", multiValues={"<span style="color: #2a00ff">1</span>"}, number = 1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">private</span> String testField1;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #3f7f5f">// 为testMethod1方法附加MyAnnotation3 注释<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;@MyAnnotation3(value = "<span style="color: #2a00ff">call testMethod1</span>", multiValues={"<span style="color: #2a00ff">1</span>", "<span style="color: #2a00ff">2</span>"}, number = 1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">void</span> testMethod1() {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Deprecated<br />
&nbsp;&nbsp;&nbsp;&nbsp;@MyAnnotation3(value = "<span style="color: #2a00ff">call testMethod2</span>", multiValues={"<span style="color: #2a00ff">3</span>", "<span style="color: #2a00ff">4</span>", "<span style="color: #2a00ff">5</span>"}) <br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">void</span> testMethod2() {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</div>
上面的例子GetMyAnnotation非常简单，里面没有任何功能，但是分别为类（class），属性（field），方法（method）申明（附加）了MyAnnotation3 注释。<br />
<br />
下面我们用程序TestMyAnnotation3对GetMyAnnotation里MyAnnotation3注释进行解析。<br />
<br />
<strong>运行时解析annotation</strong><br />
TestMyAnnotation3.java<br />
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">class</span> TestMyAnnotation3 {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">static</span> <span style="font-weight: bold; color: #7f0055">void</span> main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("<span style="color: #2a00ff">--Class Annotations--</span>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">if</span> (GetMyAnnotation.class.isAnnotationPresent(MyAnnotation3.<span style="font-weight: bold; color: #7f0055">class</span>)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("<span style="color: #2a00ff">[GetMyAnnotation].annotation:</span>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyAnnotation3 classAnnotation = GetMyAnnotation.class.getAnnotation(MyAnnotation3.<span style="font-weight: bold; color: #7f0055">class</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printMyAnnotation3(classAnnotation);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("<span style="color: #2a00ff">--Fields Annotations--</span>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field [] fields = GetMyAnnotation.class.getDeclaredFields();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">for</span> (Field field : fields) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">if</span> (field.isAnnotationPresent(MyAnnotation3.<span style="font-weight: bold; color: #7f0055">class</span>)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("<span style="color: #2a00ff">[GetMyAnnotation.</span>" + field.getName() + "<span style="color: #2a00ff">].annotation:</span>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyAnnotation3 fieldAnnotation = field.getAnnotation(MyAnnotation3.<span style="font-weight: bold; color: #7f0055">class</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printMyAnnotation3(fieldAnnotation);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("<span style="color: #2a00ff">--Methods Annotations--</span>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method[] methods = GetMyAnnotation.class.getDeclaredMethods();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">for</span> (Method method : methods) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("<span style="color: #2a00ff">[GetMyAnnotation.</span>" + method.getName() + "<span style="color: #2a00ff">].annotation:</span>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">if</span> (method.isAnnotationPresent(MyAnnotation3.<span style="font-weight: bold; color: #7f0055">class</span>)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyAnnotation3 methodAnnotation = method.getAnnotation(MyAnnotation3.<span style="font-weight: bold; color: #7f0055">class</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printMyAnnotation3(methodAnnotation);&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">private</span> <span style="font-weight: bold; color: #7f0055">static</span> <span style="font-weight: bold; color: #7f0055">void</span> printMyAnnotation3(MyAnnotation3 annotation3) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">if</span> (annotation3 == <span style="font-weight: bold; color: #7f0055">null</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("<span style="color: #2a00ff">{value=</span>" + annotation3.value());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String multiValues = "";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">for</span> (String value: annotation3.multiValues()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;multiValues += "<span style="color: #2a00ff">,</span>" + value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("<span style="color: #2a00ff">multiValues=</span>" + multiValues);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("<span style="color: #2a00ff">number=</span>" + annotation3.number() + "<span style="color: #2a00ff">}</span>");<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</div>
<br />
输出：<br />
<div class="tf_edit_html_box10" id="tf_edit_html_box10">--Class Annotations--<br />
[GetMyAnnotation].annotation:<br />
{value=Class GetMyAnnotation<br />
multiValues=,1,2<br />
number=0}<br />
--Fields Annotations--<br />
[GetMyAnnotation.testField1].annotation:<br />
{value=call testField1<br />
multiValues=,1<br />
number=1}<br />
--Methods Annotations--<br />
[GetMyAnnotation.testMethod1].annotation:<br />
{value=call testMethod1<br />
multiValues=,1,2<br />
number=1}<br />
[GetMyAnnotation.testMethod2].annotation:<br />
{value=call testMethod2<br />
multiValues=,3,4,5<br />
number=0}<br />
</div>
<br />
<br />
<strong>JDK1.5以后的版本提供的跟annotation有关的接口：</strong><br />
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">interface</span> java.lang.reflect.AnnotatedElement {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">boolean</span> isAnnotationPresent(Class&lt;? <span style="font-weight: bold; color: #7f0055">extends</span> Annotation&gt; annotationClass);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;T <span style="font-weight: bold; color: #7f0055">extends</span> Annotation&gt; T getAnnotation(Class&lt;T&gt; annotationClass);<br />
&nbsp;&nbsp;&nbsp;&nbsp;Annotation[] getAnnotations();<br />
&nbsp;&nbsp;&nbsp;&nbsp;Annotation[] getDeclaredAnnotations();<br />
}<br />
</div>
该接口主要用来取得附加在类（class），构造方法（constructor），属性（field），方法（method），包（package）上的annotation信息。<br />
<br />
JDK1.5与此有关的几个类都实现了AnnotatedElement接口：<br />
<div class="tf_edit_html_box2" id="tf_edit_html_box2">java.lang.reflect.AccessibleObject, <br />
java.lang.reflect.Class, <br />
java.lang.reflect.Constructor, <br />
java.lang.reflect.Field, <br />
java.lang.reflect.Method, <br />
java.lang.reflect.Package<br />
</div>
所以可以利用反射（reflection）功能在程序里动态解析附加的annotation信息。<br />
<br />
<br />
<strong>总结：</strong><br />
本文通过举例简单地说明了怎么动态解析annotation，大家可以举一反三，利用Java的annotation特性，完成更复杂功能等。&nbsp;&nbsp;&nbsp;&nbsp; 
<img src ="http://www.blogjava.net/zzs/aggbug/257071.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-02-27 17:23 <a href="http://www.blogjava.net/zzs/articles/257071.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自定义 Java Annotation(转)</title><link>http://www.blogjava.net/zzs/articles/257070.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Fri, 27 Feb 2009 09:21:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/257070.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/257070.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/257070.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/257070.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/257070.html</trackback:ping><description><![CDATA[<span>Annotation是一种特殊的interface。所以可以在annotation里定义方法，属性；也可以让某个类从annotation继承（implements）。<br />
<br />
下面从简单地范例开始，让我们一步步加深对annotation的了解。<br />
</span><span>
<div class="tf_edit_html_title1" id="tf_edit_html_title1">无任何方法/属性Annotation范例：</div>
<p>MyAnnotation0.java</p>
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">package</span> com.test.annotation;<br />
<br />
<span style="font-weight: bold; color: #7f0055">public</span> @<span style="font-weight: bold; color: #7f0055">interface</span> MyAnnotation0 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}<br />
</div>
<p>MyAnnotation0为一个无任何方法和属性的annotation。<br />
<br />
使用MyAnnotation0：<br />
</span></p>
TestMyAnnotation0.java
<div class="tf_edit_html_code" id="tf_edit_html_code">@MyAnnotation0<br />
<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">class</span> TestMyAnnotation0 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;@MyAnnotation0<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">void</span> testMethod() {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</div>
<p><br />
<br />
&nbsp;具有一个value方法Annotation范例：</p>
<p>MyAnnotation1.java</p>
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">public</span> @<span style="font-weight: bold; color: #7f0055">interface</span> MyAnnotation1 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #3f5fbf">/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * value method<br />
&nbsp;&nbsp;&nbsp;&nbsp; * <span style="font-weight: bold; color: #7f9fbf">@return</span> value<br />
&nbsp;&nbsp;&nbsp;&nbsp; */</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String value();<br />
}<br />
</div>
<p>MyAnnotation1具有一个名为value的方法。<br />
<br />
MyAnnotation1使用：<br />
TestMyAnnotation1.java</p>
<div class="tf_edit_html_code" id="tf_edit_html_code">@MyAnnotation1("<span style="color: #2a00ff">hello</span>")<br />
<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">class</span> TestMyAnnotation1 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;@MyAnnotation1(value="<span style="color: #2a00ff">world</span>")<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">void</span> testMethod() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</div>
<p>可以通过@Annotation名(方法名1=值1, 方法名2=值2, &#8230;)的形式给annotation赋值。只有一个方法的时候，可以直接省略为：@Annotation名(值1) 的赋值形式。当方法返回一个数组时，可以用 方法名={值1, 值2, &#8230;}给其赋值。<br />
</p>
<div class="tf_edit_html_title1" id="tf_edit_html_title1">具有一个value方法和一个属性Annotation范例：</div>
<p>如果必要，还可以在annotation里为其定义属性。如下：<br />
MyAnnotation2.java</p>
<div class="tf_edit_html_code" id="tf_edit_html_code">@<span style="font-weight: bold; color: #7f0055">interface</span> MyAnnotation2 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String value();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String myProperty = "<span style="color: #2a00ff">hello world</span>";<br />
}<br />
</div>
<p>其中，myProperty只能申明为public或无public修饰（无public修饰时也默认为public）为static, final属性（即使不写也默认为static, final）。<br />
<br />
使用例：<br />
TestMyAnnotation2</p>
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">class</span> TestMyAnnotation2 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">static</span> <span style="font-weight: bold; color: #7f0055">void</span> main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(MyAnnotation2.myProperty);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@MyAnnotation2("")<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">void</span> testMethod1() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</div>
<p>上例会打印出：</p>
<div class="tf_edit_html_box10" id="tf_edit_html_box10">hello world<br />
</div>
<p><br />
<br />
&nbsp;</p>
<div class="tf_edit_html_title1" id="tf_edit_html_title1">复杂型annotation的定义与使用</div>
<p>本节介绍较为复杂的annotation定义与使用。<br />
先看代码：<br />
MyAnnotation3.java</p>
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">public</span> @<span style="font-weight: bold; color: #7f0055">interface</span> MyAnnotation3 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String value();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String[] multiValues();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">int</span> number() <span style="font-weight: bold; color: #7f0055">default</span> 0;<br />
}<br />
</div>
<p>MyAnnotation3具有一个返回String的value方法，返回String[]的multiValues 方法；还有一个返回int 的number方法。其中number方法具有默认值0。<br />
<br />
使用例： <br />
TestMyAnnotation3.java</p>
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">class</span> TestMyAnnotation3 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;@MyAnnotation3(value = "<span style="color: #2a00ff">call testMethod1</span>", multiValues={"<span style="color: #2a00ff">1</span>", "<span style="color: #2a00ff">2</span>"}, number = 1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">void</span> testMethod1() {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@MyAnnotation3(value = "<span style="color: #2a00ff">call testMethod2</span>", multiValues={"<span style="color: #2a00ff">1</span>", "<span style="color: #2a00ff">2</span>"})<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">void</span> testMethod2() {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</div>
<p>number具有默认值，所以标注时可以不为其赋值。其余方法则必须通过上面介绍的方法赋值。multiValues返回一个String[]数组，所以可以通过multiValues={"1", "2"}为其赋值。<br />
</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/zzs/aggbug/257070.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-02-27 17:21 <a href="http://www.blogjava.net/zzs/articles/257070.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Annotation注释语法（转）</title><link>http://www.blogjava.net/zzs/articles/257069.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Fri, 27 Feb 2009 09:16:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/257069.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/257069.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/257069.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/257069.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/257069.html</trackback:ping><description><![CDATA[<br />
JAVA从J2SE5开始提供名为annotation（注释，标注）的功能。Java的annotation，可以附加在package, class, method, field等上面，相当于给它们添加了额外的辅助信息。附加在package, class, method, field等上的Annotation，如果没有外部解析工具等对其加以解析和处理的情况，本身不会对Java的源代码或class等产生任何影响，也不会对它们的执行产生任何影响。<br />
<br />
但借助外部工具，比如javac，EJB容器等，可以对附加在package, class, method, field的annotation进行解析，可以根据annotation而做出相应的处理，比如运行时改变对象/方法的行为。<br />
<br />
<br />
<div class="tf_edit_html_title1" id="tf_edit_html_title1">Java标准Annotation</div>
@Deprecated 相当于Javadoc的@deprecated，被@Deprecated标注的对象class, method等被注明为不推荐使用。主要用于javac等编译工具。<br />
@Override 注明对象method重载了父类的方法。javac等编译工具编译时会根据此Annotation判断重载方法是否正确。<br />
@SuppressWarnings 告诉javac等编译器忽略所指定的特定的警告信息。<br />
@Target 被定义的annotation可以附加在那些对象上。<br />
@Retention annotation的作用期间。<br />
<div class="tf_edit_html_title1" id="tf_edit_html_title1">Java标准Annotation的使用</div>
@Deprecated：<br />
<div class="tf_edit_html_code" id="tf_edit_html_code">@Deprecated<br />
<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">class</span> TestBean {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#8230;<br />
}<br />
</div>
@SuppressWarnings<br />
<div class="tf_edit_html_code" id="tf_edit_html_code">@SuppressWarnings("<span style="color: #2a00ff">serial</span>")<br />
<span style="font-weight: bold; color: #7f0055">public</span> <span style="font-weight: bold; color: #7f0055">class</span> TestBean <span style="font-weight: bold; color: #7f0055">implements</span> java.io.Serializable {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#8230;<br />
}<br />
<br />
@SuppressWarnings(value = {"<span style="color: #2a00ff">serial</span>", "<span style="color: #2a00ff">unchecked</span>"})<br />
<span style="font-weight: bold; color: #7f0055">public</span> String doSth() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#8230;<br />
}</div>
<br />
@Override <br />
<div class="tf_edit_html_code" id="tf_edit_html_code">@Override<br />
<span style="font-weight: bold; color: #7f0055">public</span> String doSth() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#8230;<br />
}<br />
</div>
<br />
<br />
<div class="tf_edit_html_title1" id="tf_edit_html_title1">Annotation的定义</div>
定义方法：<br />
@interface Annotation名 {定义体}<br />
<br />
定义例1：<br />
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">public</span> @<span style="font-weight: bold; color: #7f0055">interface</span> MyAnnotation {}<br />
</div>
该例定义了一个无任何属性/方法的Annotation。<br />
<br />
定义例2：<br />
<div class="tf_edit_html_code" id="tf_edit_html_code"><span style="font-weight: bold; color: #7f0055">public</span> @<span style="font-weight: bold; color: #7f0055">interface</span> MyAnnotation {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String value();<br />
}<br />
</div>
该例定义了只有一个方法为value()的Annotation。一般来说，只有一个方法的Annotation，方法名一定定义为value。<br />
<br />
定义例3：<br />
<div class="tf_edit_html_code" id="tf_edit_html_code">@Retention(RetentionPolicy.RUNTIME)<br />
@Target(ElementType.METHOD)<br />
<span style="font-weight: bold; color: #7f0055">public</span> @<span style="font-weight: bold; color: #7f0055">interface</span> MyAnnotation {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String value();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">public</span> String [] multiValues();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: #7f0055">int</span> number() <span style="font-weight: bold; color: #7f0055">default</span> 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}<br />
</div>
该例定义了一个具有多方法的Annotation。并设置其中一个方法number的默认值为0。multiValues 方法定义为数组类型。Annotation定义可以用MetaAnnotation（元注释）修饰。MetaAnnotation有以下2个：<br />
@Retention<br />
@Target<br />
<br />
我们将在以下对@Retention与@Target加以说明。<br />
<br />
<br />
<div class="tf_edit_html_title1" id="tf_edit_html_title1">@Retention</div>
@Retention 可以设置为RetentionPolicy类型的值。<br />
例：<br />
@Retention(RetentionPolicy.RUNTIME)<br />
<br />
<table class="defTbl" id="defTbl" border="0">
    <tbody>
        <tr class="altEventRow">
            <th>RetentionPolicy的值</th>
            <th>说明</th>
        </tr>
        <tr class="eventRow">
            <td>RetentionPolicy.CLASS</td>
            <td>annotation信息将被编译器编译时保存在class文件中，但执行时不会在VM装载。也就是说不能在执行时动态取得annotation信息。未设置@Retention时这将是默认设置值。 </td>
        </tr>
        <tr class="altEventRow">
            <td>RetentionPolicy.RUNTIME</td>
            <td>annotation信息将被编译器编译时保存在class文件中，执行时也会被VM装载。 </td>
        </tr>
        <tr class="eventRow">
            <td>RetentionPolicy.SOURCE</td>
            <td>annotation信息将被编译器编译时舍弃掉。 </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<div class="tf_edit_html_title1" id="tf_edit_html_title1">@Target</div>
@Target表明Annotation可以附加在哪种JAVA元素之上，可以设置为java.lang.annotation.ElementType数组类型的值。<br />
使用例1：<br />
<div class="tf_edit_html_code" id="tf_edit_html_code">@Target(ElementType.METHOD)<br />
</div>
<br />
使用例2：<br />
<div class="tf_edit_html_code" id="tf_edit_html_code">@Target(value={ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD})<br />
</div>
<br />
ElementType是一个枚举类型，它具有以下定义：<br />
<table class="defTbl" id="defTbl" border="0">
    <tbody>
        <tr class="altEventRow">
            <th>ElementType值</th>
            <th>说明</th>
        </tr>
        <tr class="eventRow">
            <td>ElementType.ANNOTATION_TYPE</td>
            <td>应用于其他注解的元注解</td>
        </tr>
        <tr class="altEventRow">
            <td>ElementType.CONSTRUCTOR</td>
            <td>构造函数</td>
        </tr>
        <tr class="eventRow">
            <td>ElementType.FIELD</td>
            <td>字段</td>
        </tr>
        <tr class="altEventRow">
            <td>ElementType.LOCAL_VARIABLE</td>
            <td>方法中的本地变量</td>
        </tr>
        <tr class="eventRow">
            <td>ElementType.METHOD</td>
            <td>方法</td>
        </tr>
        <tr class="altEventRow">
            <td>ElementType.PACKAGE</td>
            <td>包</td>
        </tr>
        <tr class="eventRow">
            <td>ElementType.PARAMETER</td>
            <td>方法的参数</td>
        </tr>
        <tr class="altEventRow">
            <td>ElementType.TYPE</td>
            <td>类，接口或者枚举声明</td>
        </tr>
    </tbody>
</table>
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/zzs/aggbug/257069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-02-27 17:16 <a href="http://www.blogjava.net/zzs/articles/257069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用EJB 3.0简化Java开发</title><link>http://www.blogjava.net/zzs/articles/257037.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Fri, 27 Feb 2009 07:09:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/257037.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/257037.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/257037.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/257037.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/257037.html</trackback:ping><description><![CDATA[<p align="left">来源：<a style="color: #339966" href="http://java.chinaitlab.com/EJB/743927.html">http://java.chinaitlab.com/EJB/743927.html</a><br />
<br />
</p>
<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>企业级版本，或者说<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a> EE(以前叫J2EE),对于开发<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>端的应用来说是一个强大的但却又过于复杂的的平台。从它诞生之日起，过于复杂一直是对使用Java EE犹豫不决的一个重要因素。在JavaWorld的以前的一篇文章&#8221;简化之路&#8221;中，我指出了那些让Java EE应用变复杂的因素，其中很多都是与当前的EJB 2.1规范有关。 <br />
　　在过去的三年中，Java开放源代码社区，Java社区进程(JCP)以及主要的Java EE供应商，一直致力于让Java EE更简单。举例来说:新的设计范例，比如POJO服务，服务拦截器和依赖注入，已经可以在实际应用中用来简化Java EE的开发了。还有，新的工具和框架，比如Hibernate, AOP(aspect-oriented programming，面向方面编程)，Struts,Xdoclet和Spring, 也已经被广泛用于同一目的。
<p>　　<strong>简化不是功能的减少</strong></p>
<p>　　简化一个编程模型并没有减少它的功能。简化只是把复杂的逻辑隐藏到了框架代码或可重用的组件中去了。根本上，它是把复杂的东西从需要应用开发者直接管理的地方转移到了大多数开发者看不到的地方。</p>
<p>　　上述的模板和工具让初学者更容易上手，同时也提高了有经验的Java开发者的生产力，现在它们正在被JCP合并到下一代的Java EE标准中(比如:EJB 3.0)。由Java开发人员Raghu Kodali最近所做的研究显示:将Java EE的示例程序RosterApp从EJB 2.1转到EJB 3.0可以减少百分之五十以上的代码。</p>
<p>　　Java注释是EJB3.0背后的关键，它将POJO服务，POJO持久化和依赖注入一起绑定为一个完整的企业级中间件解决方案。这篇文章中，我使用了一个示例应用:JBoss EJB 3.0 TrailBlazer，来演示使用注释开发轻量级的EJB 3.0 POJO应用。TrailBlazer的应用使用EJB 3.0中不同的工具和API重复实现了一个投资计算器。示例程序完全可以在JBoss 应用<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>4.0.3版本中运行，并且与最新的EJB 3.0标准完全兼容(完成时)。</p>
<p>　　让我们来开始体验一下注释驱动编程模型的好处吧。</p>
<p>　　EJB 3.0的注释驱动编程模型</p>
<p>　　从开发者的观点来看，EJB 3.0广泛地使用了Java 注释.注释有两个关键优势:它们取代了过多的XML配置文件并且消除了严格组件模型需求。</p>
<p>　　<strong>注释 vs XML</strong></p>
<p>　　基于XML的布署描述和注释一起都可以用来在Java EE应用中配置服务的相关属性。它们的区别在于:XML文档是与代码分开处理的，特别是在运行时刻，而注释是与代码编译在一起的并被编译器检查的。对于开发者来说这就有了一些重要的含义，正如我下面所列出的:</p>
<p>　　冗长:XML配置文件是出了名的冗长的。为了配置代码，XML文件必须复制许多信息:比如代码中类名字和方法名字。Java注释则不同，它是代码的一部分，不需要额外的引用就可以指明配置信息。</p>
<p>　　强壮性:在XML文件中重复的代码信息引入了多处龃淼目赡堋１热?如果你写错了方法的名字，那应用直到运行时刻才会出错垮掉。也就是说，XML配置文件的强壮性就不如注释，注释是被编译器检查的，并和其它代码一起被处理的。</p>
<p>　　灵活性:既然XML文件是在代码之外被单独处理的，那也就是说基于XML的配置信息不是&#8220;硬编码&#8221;的，是可以以后修改的。部署的灵活性对系统管理员来说是非常非常重要的特性。</p>
<p>　　注释是简单易用的，已证明对大多数应用来说足够了。XML文件更复杂，但能被用来处理更高级的问题。EJB 3.0允许你通过注释来配置大多数的应用。EJB 3.0也支持用XML文件来覆盖默认的注释，及配置像数据库联接这样的外部资源。</p>
<p>　　除了替换和简化XML描述符，注释也允许我们废除困扰EJB 1.x, EJB 2.x的严格组件模型。</p>
<p>　　<strong>POJO　vs 严格组件</strong></p>
<p>　　EJB 组件是容器管理(container-managed)的对象。容器在运行时刻操作Bean的状态和行为。为了让行为发生，EJB 2.1规范定义了一个Bean必须遵守的严格的组件模型。每一个EJB类必须从某一种抽象类中继承，并为容器提供了回调的钩子。既然Java只支持单继承，严格组件模型就限制了开发者使用EJB组件创建一个复杂对象结构的能力。当把复杂的应用数据映射到实体 Bean中的时候，正如我们在第二部分中看到的，这会成为一个很大的问题。</p>
<p>　　在EJB 3.0中，所有的容器服务都可以通过使用注释的POJO应用来配置和交付。大多数情况下，并不需要特殊的组件类。让我们通过JBoss EJB 3.0 TrailBlazer示例看一下如何在EJB 3.0中使用注释。</p>
<p>　　<strong>开发藕合松散的服务对象</strong></p>
<p>　　像Java EE这样的企业级中间件的一个最重要的好处是允许开发者使用藕合松散的组件来开发应用。这些组件仅仅通过他们自己发布的商业接口来藕合。因此这些组件的实现类可以在不改变应用其余部分的情况下改变自己的实现。这将会使应用更加强壮，更容易测试，更易移植。EJB 3.0使得在POJO中创建藕合松散的商业组件变得更简单了。</p>
<p>　　<strong>Session bean</strong></p>
<p>　　在EJB 3.0应用中，藕合松散的服务组件的典型应用是Session Bean。一个Session Bean至少有一个接口(也就是:商业接口)，其它应用组件通过它获得服务。下面的代码为我们的投资计算器服务提供了商业接口。它只有一个方法，根据给定的起始年龄，终止年龄，增长率，月存金额，计算出总投资额。</p>
<p>public interface Calculator {<br />
&nbsp; public double calculate (int start, int end, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double growthrate, double saving);<br />
}</p>
<p>　　Session bean类简单地实现了商业接口。你必须通过使用Stateless或Stateful注释来告诉EJB 3.0容器这个POJO类是一个Session Bean。有状态(Stateful)的session bean在不同的服务请求间维护着客户的状态。相反地，对于无状态(Stateless)的session bean，每次的请求都是被随机挑选的session bean实例处理的。这些行为是与EJB 2.1规范中的有状态和无状态session bean的定义是一致的。EJB 3.0容器算出何时实例化Bean对象，并通过商业接口让其可用。下面是session bean实现类的代码:<br />
<br />
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>@Stateless<br />
            public class CalculatorBean implements Calculator {<br />
            &nbsp; public double calculate (int start, int end, <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double growthrate, double saving) {<br />
            &nbsp;&nbsp;&nbsp; double tmp = Math.pow(1. + growthrate / 12., <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12. * (end - start) + 1);<br />
            &nbsp;&nbsp;&nbsp; return saving * 12. * (tmp - 1) / growthrate;<br />
            &nbsp; }<br />
            }</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　你也可以为一个session bean指明多个接口-一个为本地客户服务，一个为远程客户服务。只要使用@Local和@Remote注释来区分。下面的代码片断显示了同时实现了本地和远程接口的CalculatorBean。如果你没有@Local和@Remote注释，session bean接口默认为本地接口。<br />
<br />
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>@Stateless<br />
            @Local ()<br />
            @Remote ()<br />
            public class CalculatorBean implements Calculator, RemoteCalculator {
            <p>&nbsp; public double calculate (int start, int end, <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double growthrate, double saving) {<br />
            &nbsp;&nbsp;&nbsp; double tmp = Math.pow(1. + growthrate / 12., 12. * (end - start) + 1);<br />
            &nbsp;&nbsp;&nbsp; return saving * 12. * (tmp - 1) / growthrate;<br />
            &nbsp; }</p>
            <p>&nbsp; public String getServerInfo () {<br />
            &nbsp;&nbsp;&nbsp; return "This is the JBoss EJB 3.0 TrailBlazer";<br />
            &nbsp; }<br />
            }</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　Session bean用户通过JNDI得到bean的一个存根(Stub)对象。容器所提供的存根对象实现了session bean的商业接口。所有针对存根的调用都被引向了容器，由容器调用相应的实现类中的接口。对于有状态的的session bean，你必须自己在客户端缓存存根对象，这样在每次的后续调用时，容器才知道要提供相同的的bean实例。下面的片断显示如何调用session bean.在后面，你将会学到获取存根对象的更简单的方法。</p>
<p>
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>InitialContext ctx = new InitialContext();<br />
            cal = (Calculator) ctx.lookup(Calculator.class.getName());
            <p>double res = cal.calculate(start, end, growthrate, saving); </p>
            <p>Session bean生命周期的管理</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　为达到藕合松散的目的，应用把session bean实例的创建、缓存、销毁全部交给EJB 3.0容器(也就是，反向控制设计模式)。应用只和bean的商业接口打交道。</p>
<p>　　但如果应用需要对session对象更好的控制呢?比如说，应用可能需要在创建session bean的时候初始化数据库联接，而在销毁bean时关闭外部的联接。上述这些，你都可能通过在bean类中定义生命周期的回调方法来实现。这些方法将会被容器在生命周期的不同阶段调用(如:创建或销毁时)。通过使有下面所列的注释，EJB 3.0允许你将任何方法指定为回调方法。这不同于EJB 2.1，EJB 2.1中，所有的回调方法必须实现，即使这是空的。EJB 3.0中，bean可以有任意数量，任意名字的回调方法。</p>
<p>　　@PostConstruct:当bean对象完成实例化后，使用了这个注释的方法会被立即调用。这个注释同时适用于有状态和无状态的session bean。</p>
<p>　　@PreDestroy:使用这个注释的方法会在容器从它的对象池中销毁一个无用的或者过期的bean实例这前调用。同时适用于有状态和无状态的session bean.</p>
<p>　　@PrePassivate:当一个有状态的session bean实例空闲过长的时间，容器将会钝化它，并把它的状态保存下来。使用这个注释的方法会在容器钝化bean实例之前调用。适用于有状态session bean。</p>
<p>　　@PostActivate:当客户端再次使用已经被钝化的的有状态session bean时，新的实例被创建，状态被恢复。使用此注释的session bean会在bean的激活完成时调用。</p>
<p>　　@Init:这个注释指定了有状态session bean初始化的方法。它区别于@PostConstruct注释在于:多个@Init注释方法可以同时存在于有状态session bean 中，但每个bean实例只会有一个@Init注释的方法会被调用。这取决于bean是如何创建的(细节请看EJB 3.0规范)。@PostConstruct在@Init之后被调用。</p>
<p>　　另一个有用的生命周期方法注释是@Remove，特别是对于有状态session bean。当应用通过存根对象调用使用了@Remove注释的方法时，容器就知道在该方法执行完毕后，要把bean实例从对象池中移走。<br />
<br />
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>@Stateful<br />
            public class CalculatorBean implements Calculator, Serializable {
            <p>&nbsp;&nbsp;&nbsp; // ... ...<br />
            &nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; @PostConstruct<br />
            &nbsp;&nbsp;&nbsp; public void initialize () {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Initializes the history records and load<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // necessary data from database etc.<br />
            // 初始化历史记录，并从数据库中装入必需的数据。<br />
            &nbsp;&nbsp;&nbsp; }&nbsp; <br />
            &nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; @PreDestroy<br />
            &nbsp;&nbsp;&nbsp; public void exit () {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Save history records into database if necessary.<br />
            // 如有必要则将历史记录保存至数据库中<br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; @Remove<br />
            &nbsp;&nbsp;&nbsp; public void stopSession () {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Call to this method signals the container<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // to remove this bean instance and terminates<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // the session. The method body can be empty.<br />
            // 调用这个方法来通知容器将bean实例移除并中止session.<br />
            // 这个方法可以为空。<br />
            &nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; // ... ...<br />
            }</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　&nbsp; <strong>消息驱动bean</strong></p>
<p>　　Session bean服务提供了同步调用的方法。另一个重要的藕合松散服务类型是一种通过进入的消息来触发的异步服务(比如:email或Java消息服务产生的消息)。EJB 3.0的消息驱动bean(MDB)是设计用来专门处理基于消息请求的组件。</p>
<p>　　一个MDB类必须实现MessageListener接口。当容器检测到bean守候的队列一条消息时，就调用onMessage()方法，将消息作为参数传入。MDB在OnMessage()中决定如何处理该消息。你可以用注释来配置MDB侦听哪一条队列。当MDB部署时，容器将会用到其中的注释信息。在下面的例子中，CalculatorBean MDB会在JMS队列queue/mdb有消息进入时调用。MDB解析消息，并根据消息内容计算投资。<br />
<br />
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>&nbsp;@MessageDriven(activateConfig =<br />
            {<br />
            &nbsp; @ActivationConfigProperty(propertyName="destinationType",<br />
            &nbsp;&nbsp;&nbsp; propertyValue="javax.jms.Queue"),<br />
            &nbsp; @ActivationConfigProperty(propertyName="destination",<br />
            &nbsp;&nbsp;&nbsp; propertyValue="queue/mdb")<br />
            })<br />
            public class CalculatorBean implements MessageListener {
            <p>&nbsp; public void onMessage (Message msg) {<br />
            &nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TextMessage tmsg = (TextMessage) msg;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Timestamp sent =<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Timestamp(tmsg.getLongProperty("sent"));<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringTokenizer st =<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new StringTokenizer(tmsg.getText(), ",");</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int start = Integer.parseInt(st.nextToken());<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int end = Integer.parseInt(st.nextToken());<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double growthrate = Double.parseDouble(st.nextToken());<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double saving = Double.parseDouble(st.nextToken());</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double result =<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; calculate (start, end, growthrate, saving);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RecordManager.addRecord (sent, result);</p>
            <p>&nbsp;&nbsp;&nbsp; } catch (Exception e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace ();<br />
            &nbsp;&nbsp;&nbsp; }<br />
            &nbsp; }</p>
            <p>&nbsp; // ... ...<br />
            }</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　依赖注入</p>
在上一节中，你学到了如何开发藕合松散的服务组件。但是，为了存取那些服务对象，你需要通过服务器的JNDI来查找存根对象(session bean)或消息队列(MDB)。JNDI查找是把客户端与实际的服务端实现解藕的关键步骤。但是，直接使用一个字符串来进行JNDI查找并不优雅。有这样几个原因:
<p>　　客户端与服务端必须有一致的基于字符串的名字。它没有在编译时得到认证或在布署时得到检查。</p>
<p>　　从JNDI返回的服务对象的类型没有在编译时进行检查，有可能在运行时出现转换(casting)错误。</p>
<p>　　冗长的查找代码，有着自己的try-catch代码块，在应用之间是重复的和杂乱的</p>
<p>　EJB 3.0，对任何POJO,提供了一个简单的和优雅的方法来解藕服务对象和资源。使用@EJB注释，你可以将EJB存根对象注入到任何EJB 3.0容器管理的POJO中。如果注释用在一个属性变量上，容器将会在它被第一次访问之前赋值给它正确的值。下面的例了演示了怎样把CalculatorBean无状态session bean的存根注入到CalculatorMDB MDB类中。</p>
<p>public class CalculatorMDB implements MessageListener {</p>
<p>&nbsp; @EJB Calculator cal;<br />
&nbsp; <br />
&nbsp; // Use the cal variable<br />
&nbsp; // ... ...<br />
}</p>
<p>　　注释如果被用在JavaBean风格的setter方法上时，容器会在属性第一次使用之前，自动地用正确的参数调用bean的setter方法。下面的片断演示了这是如何做的:<br />
<br />
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>&nbsp;public class CalculatorMDB implements MessageListener {
            <p>&nbsp; Calculator cal;<br />
            &nbsp; <br />
            &nbsp; @EJB<br />
            &nbsp; public void setCal (Calculator cal) {<br />
            &nbsp;&nbsp;&nbsp; this.cal = cal;<br />
            &nbsp; }<br />
            &nbsp; <br />
            &nbsp; // Use the cal variable<br />
            // 使用cal变量<br />
            &nbsp; // ... ...<br />
            }</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　除@EJB注释之外，EJB 3.0也支持@Resource注释来注入来自JNDI的任何资源。下面的例子中，我演示了如何注入服务器端默入的TimerService和SessionContext对象，也演示了如何注入来自JNDI的命名数据库和JMS资源。<br />
<br />
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>&nbsp;@Resource<br />
            TimerService tms;
            <p>@Resource<br />
            SessionContext ctx;</p>
            <p>@Resource (name="DefaultDS")<br />
            DataSource myDb;</p>
            <p>@Resource (name="ConnectionFactory")<br />
            QueueConnectionFactory factory;</p>
            <p>@Resource (name="queue/A")<br />
            Queue queue;</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　此外，你也可以把一个容器管理的持久化管理器(也就是，EntityManager-类似于Hibernate session对象)注入到EJB 3.0 POJO中。</p>
<p>　　把容器服务交给POJO</p>
<p>　　除了管理生命周期和访问藕合松散的服务对象外，EJB 3.0通过简单的注释也为POJO提供了运行时刻服务。</p>
<p>　　<strong>事务</strong></p>
<p>　　最有用的容器服务可能就是事务管理服务，当应用出现失败或异常时，它保证了数据库的完整性。你可以简单地将为一个POJO方法申明它的事务属性。这样容器就可以在合适的上下文中运行这个方法。举例来说，下面的代码申明了容器在运行updateExchangeRate()时必须创建一个新的事务。当这个方法退出时提交事务。实际上，所有在updateExchangeRate()中被调用的方法都在此事务中运行，除非有特别申明。在updateExchangeRate()中的数据库操作要么全部成功，要么全部失败。<br />
<br />
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>@Stateless<br />
            public class CalculatorBean implements Calculator {
            <p>&nbsp; // ... ...</p>
            <p>&nbsp; @TransactionAttribute(TransactionAttributeType.REQUIRED)<br />
            &nbsp; public void updateExchangeRate (double newrate) throws Exception {<br />
            &nbsp;&nbsp;&nbsp; // Update the database in a loop.<br />
            // 在循环中更新数据库<br />
            &nbsp;&nbsp;&nbsp; // ... ...<br />
            &nbsp;&nbsp;&nbsp; // The operations in the loop must all be successful or<br />
            &nbsp;&nbsp;&nbsp; // the database is not updated at all.<br />
            // 循环中的操作必须全部成功或者根本不更新。<br />
            &nbsp; }<br />
            }</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　<strong><a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a></strong></p>
<p>　　容器也提供了<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>服务来进行用户认证和根据用户规则来限制对POJO的访问。对每一个POJO来说，你可以通过使用@SecurityDomain注释为它指定一个安全域, 安全域告诉容器到哪里去找密码和用户角色列表。JBoss中的other域表明文件是classpath中的users.propertes和roles.properties。这样，对每一个方法来说，我们可以使用一个安全限制注释来指定谁可以运行这个方法。比如，下面的例子，容器对所有试图调用addFund()的用户进行认证，只允许拥有AdminUser角色的用户实际运行它。如果你没有登录或者没有以管理员的身份登录，一个安全意外将会抛出。<br />
<br />
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>@Stateless<br />
            @SecurityDomain("other")<br />
            public class CalculatorBean implements Calculator {
            <p>&nbsp; @RolesAllowed()<br />
            &nbsp; public void addFund (String name, double growthrate) {<br />
            &nbsp;&nbsp;&nbsp; // ... ...<br />
            &nbsp; }</p>
            <p>&nbsp; @RolesAllowed()<br />
            &nbsp; public void addInvestor (String name, int start, int end) {<br />
            &nbsp;&nbsp;&nbsp; // ... ...<br />
            &nbsp; }</p>
            <p>&nbsp; @PermitAll<br />
            &nbsp; public Collection &lt;Fund&gt; getFunds () {<br />
            &nbsp;&nbsp;&nbsp; // ... ...<br />
            &nbsp; }<br />
            &nbsp; <br />
            &nbsp; // ... ...</p>
            <p>&nbsp; @RolesAllowed()<br />
            &nbsp; public double calculate (int fundId, int investorId, <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double saving) {<br />
            &nbsp;&nbsp;&nbsp; // ... ...<br />
            &nbsp; }<br />
            }</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　通用拦截器</p>
<p>　　事务和安全服务都可以被看作是容器管理的运行时刻拦截器。容器拦截了对EJB存根的调用，并在其上应用事务上下文或进行安全限制。</p>
<p>　　在EJB 3.0中，你可以自己写拦截器来扩展容器服务。使用@AroundInvoke注释，你可以将任意bean方法作为拦截器方法在任意bean方法之前和之后运行。下面的例子中，log()方法是一个拦截器，它计算和记录了其它bean方法的执行时间:<br />
<br />
<table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt="">
    <tbody>
        <tr>
            <td>@Stateful<br />
            public class CalculatorBean implements Calculator {
            <p>&nbsp; // Bean methods that are to be intercepted by "log()"<br />
            &nbsp; // bean方法将被log()方法拦截<br />
            // <br />
            &nbsp; // ... ...<br />
            &nbsp; <br />
            &nbsp; @AroundInvoke<br />
            &nbsp; public Object log (InvocationContext ctx)<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws Exception {</p>
            <p>&nbsp;&nbsp;&nbsp; String className = ctx.getBean().getClass().getName();<br />
            &nbsp;&nbsp;&nbsp; String methodName = ctx.getMethod().getName();<br />
            &nbsp;&nbsp;&nbsp; String target = className + "." + methodName + "()";</p>
            <p>&nbsp;&nbsp;&nbsp; long start = System.currentTimeMillis();<br />
            &nbsp;&nbsp;&nbsp; System.out.println ("Invoking " + target);<br />
            &nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ctx.proceed();<br />
            &nbsp;&nbsp;&nbsp; } catch(Exception e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw e;<br />
            &nbsp;&nbsp;&nbsp; } finally {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Exiting " + target);</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cal.setTrace(cal.getTrace() + "<br />
            " +<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Exiting " + target);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long time = System.currentTimeMillis() - start;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("This method takes " +<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time + "ms to execute");<br />
            &nbsp;&nbsp;&nbsp; }<br />
            &nbsp; }</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<img src ="http://www.blogjava.net/zzs/aggbug/257037.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-02-27 15:09 <a href="http://www.blogjava.net/zzs/articles/257037.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>程序员应用EJB 3.0必要的准备 </title><link>http://www.blogjava.net/zzs/articles/257025.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Fri, 27 Feb 2009 06:49:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/257025.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/257025.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/257025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/257025.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/257025.html</trackback:ping><description><![CDATA[来源：<a style="color: #339966" href="http://java.chinaitlab.com/EJB/356292.html">http://java.chinaitlab.com/EJB/356292.html</a><br />
<br />
EJB 3.0极其重视开发的简易性，并调整了模型。这绝非巧合，因为规范的主要设计者：Linda DeMichiel选择了广泛听取外界的意见，并借鉴TopLink等产品所取得的经验。这样一来，这项规范就可以沿着已经由流行、得到公认的技术开辟出来的道路前进，而这些道路实际上成了业内事实上的最佳实践。
<p>　　那么，作为程序员的你，面对新的规范，该做哪些准备呢？
<p><strong>　　处理好架构问题</strong>
<p>　　首先要确保你的架构可以利用持久性方面的标准及认可的设计模式。实际上，这可能需要改动你的应用程序，不过如果你期望应用程序能经得起时间的考验，那么进行这种投入是值得的。使用会话外观、数据访问对象（DAO）层或者服务层总是好主意，不过在这里它们都至关重要。如果你的应用程序已经使用远程实体构建而成——虽然这种做法并不常见，那么就需要重新设计架构。访问持久性对象之前，应当先部署可远程化服务层。如果要使用实体，它就应当完全是本地实体。
<p>　　不过，使用本地实体不是目的，因为实体还为部署人员提供了为实体声明事务和<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>需求的功能。EJB 3.0不允许任何这些属性在实体层面进行设定。相反，实体的运行环境将由调用者来确定，所以所需的任何事务或者<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>环境将由负责封闭的J2EE组件来安装或者声明。
<p><strong>　　CMP应用程序</strong>
<p>　　如果你已经是容器管理持久性（CMP）用户，那么你可能迫不及待地想获得新特性，希望抛弃无关的接口、不必要的bean代码以及繁琐的XML部署描述符，这些是与以前的实体bean开发相关的一些烦人问题。分别要扩展EJBObject和EJBLocalObject的远程和本地接口再也不需要了；现在实体只要实现普通<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>接口（POJI）即可，如果它们选择这么做的话。
<p>　　其次，你可能在想如何更容易地在容器中部署EJB，或者甚至根本不用部署，而是在独立环境中的容器外面进行测试。因为实体是具体的普通<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>对象（POJO），你就可以像一直以来创建Java对象的方式那样，即使用new()来创建。
<p><strong>　　POJO应用程序</strong>
<p>　　可以通过实体管理器（EntityManager）访问大部分新的持久性API。实体管理器可以注入到会话bean里面，或者用Java命名和目录接口（JNDI）进行查询。实体管理器代表事务的持久性上下文。一旦发现操作单元或者实体管理器管理的对象在事务结束后&#8220;很脏&#8221;，就会被写到外面的数据<a class="channel_keylink" href="http://www.storworld.com/" target="_blank">存储</a>区。
<p>　　应用程序可以通过抽取含有操作单元/会话工件（artifact）的代码，让自己不受全面变化的影响。这样一来，就可以通过可插入方式来获得所用的实际会话。定义会话、然后允许包围层把它与外界隔离开来，这类似EJB 3.0容器所采用的依赖注入范例（dependency injection paradigm）。应用程序中使用的所有资源应当采用这种模式。在EJB 3.0中，标准资源将由应用程序声明，随后在运行时被注入到bean里面。
<p><strong>　　采用标准特性</strong>
<p>　　EJB 3.0的许多特性可以在TopLink存在已久的特性当中找到影子。只要使用这些特性，你就能够拥有EJB 3.0的功能，虽然API还没有完成。
<p>　　查询就是这样一个方面，你现在可以开始使用EJB 3.0的特性。EJB 3.0查询可以从实体管理器获得，并且可以在上面执行。可以在你需要直接查询SLQ、并通过查询返回对象的少数情况下，创建本地SQL查询。
<p>　　查询语言往往是造成迁移问题的根源，因为不编写实质性或者穷举性的转换分析工具，就很难实现自动转换。EJB查询语言这种合理、有效的方法可对关系查询语言进行抽象处理，将受益于新增的几项特性。现有的EJB查询语言仍可以适用，不过EJB查询语言方面的更多构件和功能将进一步改进查询语言。使用EJB查询语言编写查询将是明智之举，因为查询语言不会出现重大改变，除了功能上有所添加外。
<p><strong>　　继承</strong>
<p>　　EJB 2.1从来没有指定真正的、自然的继承。实际上，只有在厂商不设置障碍的情况下才有可能实现继承，不过仍很难定义及管理。EJB 3.0却不会这样。由于具体的Java对象能够彼此继承，也用不着定义约束继承范围的方法，所以你能够创建任意深度及广度的实体继承层次。
<p>　　目前可以通过TopLink Mapping Workbench或JDeveloper、映射Java对象的GUI工具以及用于映射对象的基于Java的API，获得同样的这种灵活性。现在你可以创建域模型（domain model），以遵守适合你应用程序的继承策略，而不必等规范发布。
<p><strong>　　乐观锁定</strong>
<p>　　TopLink支持的乐观锁定（optimistic locking）模型现在将被采用到EJB 3.0模型里面。这种机制对应用程序非常有用，不仅仅是因为在读/写访问比通常为90：10的情况下，它可以大大提高性能；还因为它有助于获得现代系统所需的那种可扩展架构。业界的众多应用程序使用这种主要的锁定范例，来获得Web应用程序所需的可扩展性。只要使用简单方法：为每个乐观锁定的对象采用数据库列和对象版本字段，就很容易获得可移植性。
<p>　　这种锁定带来了另外的好处：能够使用非连接模式的对象。只要把数据重新并入事务、然后通过乐观锁值验证已改动的对象是不是失效副本，就很容易支持在离线状态下改动数据和关系的功能。
<p><strong>　　对象－关系映射</strong>
<p>　　想编写面向对象的Java程序，却把数据保存在关系数据库里面，这在以前是困扰应用程序开发的一个重大问题。
<p>　　决定把用于对象关系映射的标准化元数据和语义添加到EJB 3.0内，这向实现下列功能迈出了一大步：让应用程序能够灵活地把应用程序放在不同数据库上面运行，甚至可以使用不同的持久性框架来进行运行。对象－关系映射标准的第一个阶段将包括如今人们用来映射域模型的几种最流行的映射方法，譬如数据转换和一对一及多对多关系等。随后还会添加&#8220;高级&#8221;映射方法。</p>
 <img src ="http://www.blogjava.net/zzs/aggbug/257025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-02-27 14:49 <a href="http://www.blogjava.net/zzs/articles/257025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0的三大类型详解 </title><link>http://www.blogjava.net/zzs/articles/257021.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Fri, 27 Feb 2009 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/257021.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/257021.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/257021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/257021.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/257021.html</trackback:ping><description><![CDATA[来源：<a style="color: #339966" href="http://java.chinaitlab.com/EJB/356299.html">http://java.chinaitlab.com/EJB/356299.html</a><br />
<br />
无论你唇╞ean会话是为了执行特定任务，还是把表映射到实体bean以更新数据，都可以使用普通的<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>对象和接口来完成这些工作，并且可以通过在业务方法中使用注释，把方法提供给客户端。
<p>　　Enterprise <a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>Bean (EJB) 是可重用的、可移植的 J2EE 组件。EJB 由封装业务逻辑的方法组成。譬如说，EJB 可能有这样的业务逻辑：包含了更新数据库中客户数据的方法。众多远程和本地客户端可以调用该方法。另外，EJB 在容器里面运行，这样开发人员只要关注bean里面的业务逻辑，不必担心复杂、容易出错的问题，譬如事务支持、<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>性和远程对象访问等。EJB 作为普通Java对象（POJO）的形式来开发，开发人员可以使用元数据注释（metadata annotations）来指定容器如何管理这些bean。
<p>　　EJB 包括三种主要类型：会话 bean、实体 bean和消息驱动的bean。会话bean执行独立的、解除耦合的任务，譬如检查客户的信用记录。实体bean是一个复杂的业务实体，它代表数据库中存在的业务对象。消息驱动的bean用于接收异步JMS 消息。下面，让我们进一步研究EJB 3.0规范中的这些类型。
<p><strong>　　一、会话bean</strong>
<p>　　会话bean通常代表业务流程里面的操作，譬如&#8220;处理订单&#8221;。可根据对话状态的保持性，即有状态和无状态对会话bean进行分类。
<p>　　无状态的会话 bean没有内部状态。它们不跟踪记录从一个方法调用传递到另一个方法调用的信息。因此，每次调用无状态的业务方法都独立于前一次调用，譬如计算税款或者运费。用某个应税值调用计算税款的方法时，对税款值进行计算并返回给调用方法，而不必保存调用者的内部状态供以后调用。因为这些bean并不保持状态，所以容器对它们进行管理就很简单。客户端请求无状态的bean实例时，可以从容器保持的无状态的会话bean 实例池当中接收一个实例。另外，因为无状态的会话 bean可以共享，所以容器可保持数量较少的实例为许多客户端提供服务。想指定Java Bean作为无状态的会话bean加以部署及管理，只需要为该bean添加注释@Stateless。
<p>　　有状态的会话 bean在方法调用时可保持对话状态，譬如客户的网上购物车。客户开始网上购物时，可以从数据库中检索客户的详细信息。客户往购物车里面添加商品或者从里面删除商品、下订单等时调用的其他方法也可以使用这些详细信息。不过，有状态的会话bean是暂时性的，因为出现会话终止、系统崩溃或者网络故障后，状态不复存在。客户端请求有状态的会话bean实例时，就为该客户端分配一个有状态的实例，并为该客户端保持该组件的状态。要指定容器在某个方法完成后删除有状态的会话bean实例，只要为该方法添加注释@Remove。
<p>　　会话 bean示例如下：
<pre>
<p>import javax.ejb.Stateless.*;
<p>/*A simple stateless session bean implementing
the incrementValue() method of the * CalculateEJB interface.*/
<p>@Stateless(name="CalculateEJB")
<p>public class CalculateEJBBean
<p>implements CalculateEJB
<p>{
<p>int value = 0;
<p>public String incrementValue()
<p>{
<p>value++;
<p>return "value incremented by 1";
<p>}
<p>} </p>
</pre>
<p><strong>　　二、实体bean</strong>
<p>　　实体bean是管理持久性数据的一个对象，有可能使用几个相关的Java对象，并可以通过主键实现惟一性。通过添加@Entity注释，可以把某类指定为实体bean。实体bean代表数据库中的持久性数据，如客户表中的一行或者员工表中的一条员工记录。实体bean还可以在多个客户端之间共享。譬如说，某个员工实体bean可以由多个客户端用于计算某员工的年薪或者更新员工地址。实体bean对象的特定字段可以成为持久性字段。实体bean中没有被@Transient注释标记的所有字段都被视为持久性字段。EJB 3.0的一个主要特性就是，能够使用元数据注释来创建包含对象/关系映射的实体bean。譬如说，想指定把实体bean的empId字段映射到 Employees表中的EMPNO属性，就要使用@Table(name="Employees") 来注释表名，使用 @Column(name="EMPNO") 来注释字段，如下面的例子所示。另外，EJB 3.0 的一个特性是，在开发期间可以方便地测试实体bean，因为现在使用 <a class="channel_keylink" href="http://oracle.chinaitlab.com/" target="_blank">Oracle</a> 应用<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>实体测试工具，就可以在容器外面运行实体bean。
<p>　　实体 bean示例如下：
<pre>
<p>import javax.persistence.*;
<p>import java.util.ArrayList;
<p>import java.util.Collection;
<p>@Entity
<p>@Table(name = "EMPLOYEES")
<p>public class Employee implements java.io.Serializable
<p>{
<p>　private int empId;
<p>　private String eName;
<p>　private double sal;
<p>　@Id
<p>　@Column(name="EMPNO", primaryKey=true)
<p>　public int getEmpId()
<p>{ return empId;}
<p>　public void setEmpId(int empId)
<p>{ this.empId = empId; }
<p>　public String getEname()
<p>{ return eName; }
<p>　public void setEname(String eName)
<p>{ this.eName = eName; }
<p>　public double getSal()
<p>{ return sal; }
<p>　public void setSal(double sal)
<p>{ this.sal = sal; }
<p>　public String toString()
<p>{StringBuffer buf = new StringBuffer();
<p>buf.append("Class:")
<p>.append(this.getClass().getName()).append(" ::")
.append(" empId:").append(getEmpId()).append(" ename:")
.append(getEname()).append("sal:").append(getSal());
<p>return buf.toString();}
<p>} </p>
</pre>
<p><strong>　　三、消息驱动的bean</strong>
<p>　　消息驱动的bean（MDB）为实现异步通信提供了一种比使用直接的Java消息服务（JMS）更简单的方法。MDB用于接收异步JMS消息。容器处理JMS队列和主题所需的大部分设置进程。它把所有消息发送给相关的MDB。MDB允许J2EE应用程序发送异步消息，随后这些消息由应用程序来处理。要把bean指定为MDB，需要实现javax.jms.MessageListener接口，并且用@MessageDriven注释该bean。
<p>　　消息驱动的bean示例如下：
<pre>
<p>import javax.ejb.MessageDriven;
<p>import javax.ejb.ActivationConfigProperty;
<p>import javax.ejb.Inject;
<p>import javax.jms.*;
<p>import java.util.*;
<p>import javax.ejb.TimedObject;
<p>import javax.ejb.Timer;
<p>import javax.ejb.TimerService;
<p>@MessageDriven(
<p>activationConfig = {
<p>@ActivationConfigProperty(propertyName="connectionFactoryJndiName",
<p>　propertyValue="jms/TopicConnectionFactory"),
<p>@ActivationConfigProperty(propertyName=
"destinationName", propertyValue="jms/myTopic"),
<p>@ActivationConfigProperty(propertyName=
"destinationType", propertyValue="javax.jms.Topic"),
<p>@ActivationConfigProperty(propertyName=
"messageSelector", propertyValue="RECIPIENT = 'MDB'") } )
<p>/** A simple Message-Driven Bean that listens to the configured JMS Queue or
Topic and gets notified via an * invocation of it's onMessage() method
when a message has been posted to the Queue or Topic.The bean
<p>* prints the contents of the message. */
<p>public class MessageLogger implements MessageListener, TimedObject
<p>{
<p>　@Inject javax.ejb.MessageDrivenContext mc;
<p>　public void onMessage(Message message)
<p>　{ System.out.println("onMessage() - " + message);
<p>　try
<p>　{
<p>　String subject = message.getStringProperty("subject");
<p>　String inmessage = message.getStringProperty("message");
<p>　System.out.println("Message received\n\tDate:" + new java.util.Date()
+ "\n\tSubject:" + subject + "\n\tMessage:" + inmessage + "\n");
<p>　System.out.println("Creating Timer a single event timer");
<p>　TimerService ts = mc.getTimerService();
<p>　Timer timer = ts.createTimer(30000, subject);
<p>　System.out.println("Timer created by MDB at:"
+ new Date(System.currentTimeMillis()) +" with info:"+subject); }
<p>　catch (Throwable ex)
<p>　{ ex.printStackTrace(); }
<p>}
<p>　public void ejbTimeout(Timer timer)
<p>　{ System.out.println("EJB 3.0:Timer with MDB");
<p>　System.out.println("ejbTimeout() called at:"
+ new Date(System.currentTimeMillis()));
<p>　return; }
<p>} </p>
</pre>
<p><strong>　　四、使用 EJB 3.0</strong>
<p>　　EJB客户端是访问bean的应用程序。它不必位于客户端层上，但可以是独立的应用程序、Java<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>页面（JSP）、服务器小程序或者另一个EJB。客户端通过bean的远程或本地接口来使用EJB的方法，远程还是本地取决于客户端是在同一个JVM里面还是不同的JVM里面。这些接口定义了bean的方法，而bean类负责实际实现这些方法。客户端访问bean类的方法时，容器就会为bean生成一个代理，名为远程或者本地对象。远程或者本地对象接收请求后，交给相应的bean实例，并将结果返回给客户端。想调用bean的方法，客户端需要通过使用EJB部署描述符（deployment descriptor）里面定义的bean名称来找到该bean。在以下的示例中，客户端使用Context对象找到名为&#8220;Statelessejb&#8221;的bean。
<p>　　EJB 客户端示例如下：
<pre>
<p>import javax.naming.Context;
<p>import javax.naming.InitialContext;
<p>/* A simple bean client which calls methods on a stateless session bean.*/
<p>public class CalculateejbClient
<p>{
<p>public static void main(String [] args)
<p>{
<p>　Context context = new InitialContext();
<p>　CalculateEJB myejb =(CalculateEJB)context.lookup
("java:comp/env/ejb/CalculateEJB");
<p>myejb.incrementValue(); }
<p>} </p>
</pre>
 <img src ="http://www.blogjava.net/zzs/aggbug/257021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-02-27 14:35 <a href="http://www.blogjava.net/zzs/articles/257021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0学习笔记一:开发环境搭建 </title><link>http://www.blogjava.net/zzs/articles/257009.html</link><dc:creator>ID刀</dc:creator><author>ID刀</author><pubDate>Fri, 27 Feb 2009 06:04:00 GMT</pubDate><guid>http://www.blogjava.net/zzs/articles/257009.html</guid><wfw:comment>http://www.blogjava.net/zzs/comments/257009.html</wfw:comment><comments>http://www.blogjava.net/zzs/articles/257009.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zzs/comments/commentRss/257009.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zzs/services/trackbacks/257009.html</trackback:ping><description><![CDATA[<p><span style="color: #339966">来源：<a style="color: #339966" href="http://java.chinaitlab.com/EJB/757956.html">http://java.chinaitlab.com/EJB/757956.html</a></span><strong><br />
<br />
一、开发环境选择</strong></p>
<strong>
<p><br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;IDE：NetBeans IDE 6.0.1<br />
&nbsp;&nbsp;&nbsp; SERVER:Sun Application Server(9.0)<br />
<br />
<strong>二、安装NetBeans</strong></p>
<strong>
<p><br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;我使用的是NetBeans IDE 6.0.1，大家可以从sum公司网站<a class="channel_keylink" href="http://download.chinaitlab.com/" target="_blank">下载</a>。安装过程很简单，只需要点&#8220;下一部&#8221;就&nbsp;OK了，需要注意的就是在选择要安装的应用<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>的时候，选择GlassFish V2 URL，这是Sun公司在NetBeans里集成的一个应用<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>，其实也就是：Sun Application Server.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img height="450" alt="" src="http://java.chinaitlab.com/UploadFiles_8734/200807/20080730095207871.jpg" width="600" border="0" twffan="done" /><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 安装完成后启动NetBeans IDE 6.0.1,<span style="color: #0000ff" twffan="done">不知道是什么原因,当一启动IDE和应用服务器后电脑暴卡,进程java.exe占用内存达220M之大,不知道那位朋友可有什么好的解决方案,知道的文章下面留言告诉下,谢谢.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img height="300" alt="" src="http://java.chinaitlab.com/UploadFiles_8734/200807/20080730095211101.jpg" width="473" border="0" twffan="done" /><br />
</span><br />
<strong>三、建立EJB类库</strong></p>
<strong></strong>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;新建一类库EJB3.0,将开发EJB所需要的jar包导入便OK。详细步骤如下：菜单中的&#8220;工具&#8221;选项里选择&#8220;库&#8221;，在弹出的窗体中建立新库并命名为EJB3.0, 然后将EJB所需要的 jar包(所有的jar包都可以在GlassFish的安装目录下的lib目录里)导入到此类库里便OK。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img height="484" alt="" src="http://java.chinaitlab.com/UploadFiles_8734/200807/20080730095211352.jpg" width="648" border="0" twffan="done" /><br />
<br />
<strong>四、启动应用服务器</strong></p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 启动服务器很简单，在菜单里选择&#8220;窗口&#8221;里面的&#8220;服务&#8221;选项，在弹出的窗体里选中&#8220;服务器&#8221;，点开子节点，里面有个GlassFish V2的选项，右键--&gt;启动。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img height="328" alt="" src="http://java.chinaitlab.com/UploadFiles_8734/200807/20080730095212667.jpg" width="294" border="0" twffan="done" /><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OK，到这里我们的准备工作算是告一段落了，我们来测试下服务器是否可以正常启动。&nbsp;打开浏览器，在地址栏里输入：http://localhost:4848,看是不是出来如下登录界面。&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img height="354" alt="" src="http://java.chinaitlab.com/UploadFiles_8734/200807/20080730095212893.jpg" width="593" border="0" twffan="done" /><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 输入用户名和密码登陆试试。<br />
&nbsp;&nbsp;&nbsp;&nbsp; User Name:admin&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; Passwrod:adminadmin，成功登录后的控制界面如下所示：<br />
<img style="width: 756px; height: 492px" height="492" alt="" src="http://java.chinaitlab.com/UploadFiles_8734/200807/20080730095212282.jpg" width="756" border="0" twffan="done" /><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EJB开发的环境搭建基本上就搭建好了，本文就此结束</p>
<img src ="http://www.blogjava.net/zzs/aggbug/257009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zzs/" target="_blank">ID刀</a> 2009-02-27 14:04 <a href="http://www.blogjava.net/zzs/articles/257009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>