??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产精品成人综合久久久,亚洲天堂在线播放,国产成人精品亚洲2020http://www.tkk7.com/zzs/category/37917.htmlzh-cnTue, 07 Apr 2009 16:25:38 GMTTue, 07 Apr 2009 16:25:38 GMT60q接池的配置与维?/title><link>http://www.tkk7.com/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.tkk7.com/zzs/articles/258022.html</guid><wfw:comment>http://www.tkk7.com/zzs/comments/258022.html</wfw:comment><comments>http://www.tkk7.com/zzs/articles/258022.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zzs/comments/commentRss/258022.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zzs/services/trackbacks/258022.html</trackback:ping><description><![CDATA[ q接池中到底应该攄多少q接Q才能ɾpȝ的性能最佻Ipȝ可采取设|最连接数QminConnQ和最大连接数QmaxConnQ来控制q接池中的连接。最连接数是系l启动时q接池所创徏的连接数。如果创多,则系l启动就慢,但创建后pȝ的响应速度会很快;如果创徏q少Q则pȝ启动的很快,响应h却慢。这P可以在开发时Q设|较的最连接数Q开发v来会快,而在pȝ实际使用时设|较大的Q因样对讉K客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体讄多少Q要看系l的讉K量,可通过反复试Q找到最佳点? <div align="left">  如何保q接池中的最连接数呢?有动态和静态两U策略。动态即每隔一定时间就对连接池q行,如果发现q接数量于最连接数Q则补充相应数量的新q接,以保证连接池的正常运转。静态是发现I闲q接不够时再L查?br /> q接池的实现 <div align="left">  1、连接池模型</div> <div align="left">  本文讨论的连接池包括一个连接池c(DBConnectionPoolQ和一个连接池理c(DBConnetionPoolManagerQ和一个配|文件操作类(ParseDSConfig)。连接池cLҎ一<a target="_blank"><font color="#3080cb"><u>数据?/u></font></a>所有连接的“~冲?#8221;Q主要实C下功能:①从q接池获取或创徏可用q接Q②使用完毕之后Q把q接q还l连接池Q③在系l关闭前Q断开所有连接ƈ释放q接占用的系l资源;④还能够处理无效q接Q原来登Cؓ可用的连接,׃某种原因不再可用Q如时Q通讯问题Q,q能够限制连接池中的q接L不低于某个预定值和不超q某个预定倹{?5)当多数据库时,且数据库是动态增加的?会加到配置文g中?/div> <div align="left">  q接池管理类是连接池cȝ外覆c(wrapperQ?W合单例模式Q即pȝ中只能有一个连接池理cȝ实例。其主要用于对多个连接池对象的管理,h以下功能Q①装蝲q注册特定数据库的JDBC驱动E序Q②Ҏ属性文件给定的信息Q创接池对象Q③为方便管理多个连接池对象Qؓ每一个连接池对象取一个名字,实现q接池名字与其实例之间的映射Q④跟踪客户使用q接情况Q以侉K要是关闭q接释放资源。连接池理cȝ引入主要是ؓ了方便对多个q接池的使用和管理,如系l需要连接不同的数据库,或连接相同的数据库但׃<a target="_blank"><font color="#3080cb"><u>安全</u></font></a>性问题,需要不同的用户使用不同的名U和密码?br />          2、连接池实现(l过本h改版,可以适用多数据库cd的应用以及一U数据库cd多个数据库且数据  库的数量可以动态增加的应用E序)<br />          1),DBConnectionPool.java   数据库连接池c?br />          2),DBConnectionManager .java   数据库管理类<br />          3),DSConfigBean .java                单个数据库连接信息Bean<br />          4),ParseDSConfig.java                操作?q个'?包括不同的数据库和同一U数据库有多个数据库)<br />                                                             数据 配置文gxml<br />          5),ds.config.xml                           数据库配|文件xml<br />          原代码如? <br />         DBConnectionPool.java   <br />         ----------------------------------------------------------<br />       /**<br />  * 数据库连接池c?br />  */<br /> package <a ><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 />  * @author chenyanlin<br />  *<br />  */<br /> public class DBConnectionPool implements TimerListener {</div> <div align="left"> private Connection con=null;<br />  private int inUsed=0;    //使用的连接数<br />  private ArrayList freeConnections = new ArrayList();//容器Q空闲连?br />  private int minConn;     //最连接数<br />  private int maxConn;     //最大连?br />  private String name;     //q接池名?br />  private String password; //密码<br />  private String url;      //数据库连接地址<br />  private String driver;   //驱动<br />  private String user;     //用户?br />  public Timer timer;      //定时<br />  /**<br />   * <br />   */<br />  public DBConnectionPool() {<br />   // TODO Auto-generated constructor stub<br />  }<br />  /**<br />   * 创徏q接?br />   * @param driver<br />   * @param name<br />   * @param URL<br />   * @param user<br />   * @param password<br />   * @param maxConn<br />   */<br />  public DBConnectionPool(String name, String driver,String URL, String user, String password, int maxConn)<br />  {<br />   this.name=name;<br />   this.driver=driver;<br />   this.url=URL;<br />   this.user=user;<br />   this.password=password;<br />   this.maxConn=maxConn;<br />  }<br />  /**<br />   * 用完Q释放连?br />   * @param con<br />   */<br />  public synchronized void freeConnection(Connection con) <br />  {<br />   this.freeConnections.add(con);//d到空闲连接的末尾<br />   this.inUsed--;<br />  }<br />  /**<br />   * timeout  Ҏtimeout得到q接<br />   * @param timeout<br />   * @return<br />   */<br />  public synchronized Connection getConnection(long timeout)<br />  {<br />   Connection con=null;<br />   if(this.freeConnections.size()>0)<br />   {<br />    con=(Connection)this.freeConnections.get(0);<br />    if(con==null)con=getConnection(timeout); //l箋获得q接<br />   }<br />   else<br />   {<br />    con=newConnection(); //新徏q接<br />   }<br />   if(this.maxConn==0||this.maxConn<this.inUsed)<br />   {<br />    con=null;//辑ֈ最大连接数Q暂时不能获得连接了?br />   }<br />   if(con!=null)<br />   {<br />    this.inUsed++;<br />   }<br />   return con;<br />  }<br />  /**<br />   * <br />   * 从连接池里得到连?br />   * @return<br />   */<br />  public synchronized Connection getConnection()<br />  {<br />   Connection con=null;<br />   if(this.freeConnections.size()>0)<br />   {<br />    con=(Connection)this.freeConnections.get(0);<br />    this.freeConnections.remove(0);//如果q接分配出去了,׃I闲q接里删?br />    if(con==null)con=getConnection(); //l箋获得q接<br />   }<br />   else<br />   {<br />    con=newConnection(); //新徏q接<br />   }<br />   if(this.maxConn==0||this.maxConn<this.inUsed)<br />   {<br />    con=null;//{待 过最大连接时<br />   }<br />   if(con!=null)<br />   {<br />    this.inUsed++;<br />    System.out.println("得到 "+this.name+" 的连接,现有"+inUsed+"个连接在使用!");<br />   }<br />   return con;<br />  }<br />  /**<br />   *释放全部q接<br />   *<br />   */<br />  public synchronized void release()<br />  {<br />   Iterator allConns=this.freeConnections.iterator();<br />   while(allConns.hasNext())<br />   {<br />    Connection con=(Connection)allConns.next();<br />    try<br />    {<br />     con.close();<br />    }<br />    catch(SQLException e)<br />    {<br />     e.printStackTrace();<br />    }<br />    <br />   }<br />   this.freeConnections.clear();<br />    <br />  }<br />  /**<br />   * 创徏新连?br />   * @return<br />   */<br />  private Connection newConnection()<br />  {<br />   try {<br />    Class.forName(driver);<br />    con=DriverManager.getConnection(url, user, password);<br />   } catch (ClassNotFoundException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />    System.out.println("sorry can't find db driver!");<br />   } catch (SQLException e1) {<br />    // TODO Auto-generated catch block<br />    e1.printStackTrace();<br />    System.out.println("sorry can't create Connection!");<br />   }<br />   return con;<br />   <br />  }<br />  /**<br />   * 定时处理函数<br />   */<br />  public synchronized void TimerEvent() <br />  {<br />      //暂时q没有实C后会加上?br />  }</div> <div align="left"> /**<br />   * @param args<br />   */<br />  public static void main(String[] args) {<br />   // TODO Auto-generated method stub</div> <div align="left"> }<br />  /**<br />   * @return the driver<br />   */<br />  public String getDriver() {<br />   return driver;<br />  }<br />  /**<br />   * @param driver the driver to set<br />   */<br />  public void setDriver(String driver) {<br />   this.driver = driver;<br />  }<br />  /**<br />   * @return the maxConn<br />   */<br />  public int getMaxConn() {<br />   return maxConn;<br />  }<br />  /**<br />   * @param maxConn the maxConn to set<br />   */<br />  public void setMaxConn(int maxConn) {<br />   this.maxConn = maxConn;<br />  }<br />  /**<br />   * @return the minConn<br />   */<br />  public int getMinConn() {<br />   return minConn;<br />  }<br />  /**<br />   * @param minConn the minConn to set<br />   */<br />  public void setMinConn(int minConn) {<br />   this.minConn = minConn;<br />  }<br />  /**<br />   * @return the name<br />   */<br />  public String getName() {<br />   return name;<br />  }<br />  /**<br />   * @param name the name to set<br />   */<br />  public void setName(String name) {<br />   this.name = name;<br />  }<br />  /**<br />   * @return the password<br />   */<br />  public String getPassword() {<br />   return password;<br />  }<br />  /**<br />   * @param password the password to set<br />   */<br />  public void setPassword(String password) {<br />   this.password = password;<br />  }<br />  /**<br />   * @return the url<br />   */<br />  public String getUrl() {<br />   return url;<br />  }<br />  /**<br />   * @param url the url to set<br />   */<br />  public void setUrl(String url) {<br />   this.url = url;<br />  }<br />  /**<br />   * @return the user<br />   */<br />  public String getUser() {<br />   return user;<br />  }<br />  /**<br />   * @param user the user to set<br />   */<br />  public void setUser(String user) {<br />   this.user = user;<br />  }</div> <div align="left">}<br /> </div> </div> -------------------------------------------<br />  DBConnectionManager .java<br /> ------------------------------------------<br /> /**<br />  * 数据库连接池理c?br />  */<br /> package <a ><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 ><font color="#000000"><u>com.chunkyo.db.ParseDSConfig</u></font></a>;<br /> import <a ><font color="#000000"><u>com.chunkyo.db.DSConfigBean</u></font></a>;<br /> import <a ><font color="#000000"><u>com.chunkyo.db.DBConnectionPool</u></font></a>;</div> <div align="left">/**<br />  * @author chenyanlin<br />  *<br />  */<br /> public class DBConnectionManager {</div> <div align="left"> static private DBConnectionManager instance;//唯一数据库连接池理实例c?br />  static private int clients;                 //客户q接?br />  private Vector drivers  = new Vector();//驱动信息<br />  private Hashtable pools=new Hashtable();//q接?br />  <br />  /**<br />   * 实例化管理类<br />   */<br />  public DBConnectionManager() {<br />   // TODO Auto-generated constructor stub<br />   this.init();<br />  }<br />  /**<br />   * 得到唯一实例理c?br />   * @return<br />   */<br />  static synchronized public DBConnectionManager getInstance()<br />  {<br />   if(instance==null)<br />   {<br />    instance=new DBConnectionManager();<br />   }<br />   return instance;<br />   <br />  }<br />  /**<br />   * 释放q接<br />   * @param name<br />   * @param con<br />   */<br />  public void freeConnection(String name, Connection con)<br />  {<br />   DBConnectionPool pool=(DBConnectionPool)pools.get(name);//Ҏ关键名字得到q接?br />   if(pool!=null)<br />   pool.freeConnection(con);//释放q接 <br />  }<br />  /**<br />   * 得到一个连接根据连接池的名字name<br />   * @param name<br />   * @return<br />   */<br />  public Connection getConnection(String name)<br />  {<br />   DBConnectionPool pool=null;<br />   Connection con=null;<br />   pool=(DBConnectionPool)pools.get(name);//从名字中获取q接?br />   con=pool.getConnection();//从选定的连接池中获得连?br />   if(con!=null)<br />   System.out.println("得到q接。。?);<br />   return con;<br />  }<br />  /**<br />   * 得到一个连接,Ҏq接池的名字和等待时?br />   * @param name<br />   * @param time<br />   * @return<br />   */<br />  public Connection getConnection(String name, long timeout)<br />  {<br />   DBConnectionPool pool=null;<br />   Connection con=null;<br />   pool=(DBConnectionPool)pools.get(name);//从名字中获取q接?br />   con=pool.getConnection(timeout);//从选定的连接池中获得连?br />   System.out.println("得到q接。。?);<br />   return con;<br />  }<br />  /**<br />   * 释放所有连?br />   */<br />  public synchronized void release()<br />  {<br />   Enumeration allpools=pools.elements();<br />   while(allpools.hasMoreElements())<br />   {<br />    DBConnectionPool pool=(DBConnectionPool)allpools.nextElement();<br />    if(pool!=null)pool.release();<br />   }<br />   pools.clear();<br />  }</div> <div align="left"> /**<br />   * 创徏q接?br />   * @param props<br />   */<br />  private void createPools(DSConfigBean dsb)<br />  {<br />   DBConnectionPool dbpool=new DBConnectionPool();<br />   dbpool.setName(dsb.getName());<br />   dbpool.setDriver(dsb.getDriver());<br />   dbpool.setUrl(dsb.getUrl());<br />   dbpool.setUser(dsb.getUsername());<br />   dbpool.setPassword(dsb.getPassword());<br />   dbpool.setMaxConn(dsb.getMaxconn());<br />   System.out.println("ioio:"+dsb.getMaxconn());<br />   pools.put(dsb.getName(), dbpool);<br />  }<br />  /**<br />   * 初始化连接池的参?br />   */<br />  private void init()<br />  {<br />   //加蝲驱动E序<br />   this.loadDrivers();<br />   //创徏q接?br />   Iterator alldriver=drivers.iterator();<br />   while(alldriver.hasNext())<br />   {<br />    this.createPools((DSConfigBean)alldriver.next());<br />    System.out.println("创徏q接池。。?);<br />    <br />   }<br />   System.out.println("创徏q接池完毕。。?);<br />  }</div> <div align="left"> /**<br />   * 加蝲驱动E序<br />   * @param props<br />   */<br />  private void loadDrivers()<br />  {<br />   ParseDSConfig pd=new ParseDSConfig();<br />  //d数据库配|文?br />   drivers=pd.readConfigInfo("ds.config.xml");<br />   System.out.println("加蝲驱动E序。。?);<br />  }<br />  /**<br />   * @param args<br />   */<br />  public static void main(String[] args) {<br />   // TODO Auto-generated method stub</div> <div align="left"> }</div> <div align="left">}<br /> ----------------------------------------<br /> DSConfigBean.java<br /> ----------------------------------------<br /> /**<br />  * 配置文gBeanc?br />  */<br /> package <a ><font color="#000000"><u>com.chunkyo.db</u></font></a>;</div> <div align="left">/**<br />  * @author chenyanlin<br />  *<br />  */<br /> public class DSConfigBean {</div> <div align="left"> private String type     =""; //数据库类?br />  private String name     =""; //q接池名?br />  private String driver   =""; //数据库驱?br />  private String url      =""; //数据库url<br />  private String username =""; //用户?br />  private String password =""; //密码<br />  private int maxconn  =0; //最大连接数<br />  /**<br />   * <br />   */<br />  public DSConfigBean() {<br />   // TODO Auto-generated constructor stub<br />  }</div> <div align="left"> /**<br />   * @param args<br />   */<br />  public static void main(String[] args) {<br />   // TODO Auto-generated method stub</div> <div align="left"> }</div> <div align="left"> /**<br />   * @return the driver<br />   */<br />  public String getDriver() {<br />   return driver;<br />  }</div> <div align="left"> /**<br />   * @param driver the driver to set<br />   */<br />  public void setDriver(String driver) {<br />   this.driver = driver;<br />  }</div> <div align="left"> /**<br />   * @return the maxconn<br />   */<br />  public int getMaxconn() {<br />   return maxconn;<br />  }</div> <div align="left"> /**<br />   * @param maxconn the maxconn to set<br />   */<br />  public void setMaxconn(int maxconn) {<br />   this.maxconn = maxconn;<br />  }</div> <div align="left"> /**<br />   * @return the name<br />   */<br />  public String getName() {<br />   return name;<br />  }</div> <div align="left"> /**<br />   * @param name the name to set<br />   */<br />  public void setName(String name) {<br />   this.name = name;<br />  }</div> <div align="left"> /**<br />   * @return the password<br />   */<br />  public String getPassword() {<br />   return password;<br />  }</div> <div align="left"> /**<br />   * @param password the password to set<br />   */<br />  public void setPassword(String password) {<br />   this.password = password;<br />  }</div> <div align="left"> /**<br />   * @return the type<br />   */<br />  public String getType() {<br />   return type;<br />  }</div> <div align="left"> /**<br />   * @param type the type to set<br />   */<br />  public void setType(String type) {<br />   this.type = type;<br />  }</div> <div align="left"> /**<br />   * @return the url<br />   */<br />  public String getUrl() {<br />   return url;<br />  }</div> <div align="left"> /**<br />   * @param url the url to set<br />   */<br />  public void setUrl(String url) {<br />   this.url = url;<br />  }</div> <div align="left"> /**<br />   * @return the username<br />   */<br />  public String getUsername() {<br />   return username;<br />  }</div> <div align="left"> /**<br />   * @param username the username to set<br />   */<br />  public void setUsername(String username) {<br />   this.username = username;<br />  }</div> <div align="left">}<br /> -----------------------------------------------------<br /> ParseDSConfig.java<br /> -----------------------------------------------------<br /> /**<br />  * 操作配置文gc??nbsp; ?修改 删除{操?<br />  */<br /> package <a ><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 />  * @author chenyanlin<br />  *<br />  */<br /> public class ParseDSConfig {</div> <div align="left"> /**<br />   * 构造函?br />   */<br />  public ParseDSConfig() {<br />   // TODO Auto-generated constructor stub<br />  }<br />  /**<br />   * dxml配置文g<br />   * @param path<br />   * @return<br />   */<br />  public Vector readConfigInfo(String path)<br />  {<br />   String rpath=this.getClass().getResource("").getPath().substring(1)+path;<br />   Vector dsConfig=null;<br />   FileInputStream fi = null;<br />   try<br />   {<br />    fi=new FileInputStream(rpath);//d路径文g<br />    dsConfig=new Vector();<br />    SAXBuilder sb=new SAXBuilder();<br />    Document doc=sb.build(fi);<br />    Element root=doc.getRootElement();<br />    List pools=root.getChildren();<br />    Element pool=null;<br />    Iterator allPool=pools.iterator();<br />    while(allPool.hasNext())<br />    {<br />     pool=(Element)allPool.next();<br />     DSConfigBean dscBean=new DSConfigBean();<br />     dscBean.setType(pool.getChild("type").getText());<br />     dscBean.setName(pool.getChild("name").getText());<br />     System.out.println(dscBean.getName());<br />     dscBean.setDriver(pool.getChild("driver").getText());<br />     dscBean.setUrl(pool.getChild("url").getText());<br />     dscBean.setUsername(pool.getChild("username").getText());<br />     dscBean.setPassword(pool.getChild("password").getText());<br />     dscBean.setMaxconn(Integer.parseInt(pool.getChild("maxconn").getText()));<br />     dsConfig.add(dscBean);<br />    }<br />    <br />   } catch (FileNotFoundException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />   } catch (JDOMException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />   } catch (IOException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />   }<br />   <br />   finally<br />   {<br />    try {<br />     fi.close();<br />    } catch (IOException e) {<br />     // TODO Auto-generated catch block<br />     e.printStackTrace();<br />    }<br />   }<br />   <br />   return dsConfig;<br />  }<br /> </div> <div align="left">/**<br />  *修改配置文g 没时间写 q段旉再脓上去 其实一L <br />  */<br />  public void modifyConfigInfo(String path,DSConfigBean dsb) throws Exception<br />  {<br />   String rpath=this.getClass().getResource("").getPath().substring(1)+path;<br />   FileInputStream fi=null; //d<br />   FileOutputStream fo=null; //写入<br />   <br />  }<br /> /**<br />  *增加配置文g<br />  *<br />  */<br />  public void addConfigInfo(String path,DSConfigBean dsb) <br />  {<br />   String rpath=this.getClass().getResource("").getPath().substring(1)+path;<br />   FileInputStream fi=null;<br />   FileOutputStream fo=null;<br />   try<br />   {<br />    fi=new FileInputStream(rpath);//dxml?br />    <br />    SAXBuilder sb=new SAXBuilder();<br />    <br />    Document doc=sb.build(fi); //得到xml<br />    Element root=doc.getRootElement();<br />    List pools=root.getChildren();//得到xml子树<br />    <br />    Element newpool=new Element("pool"); //创徏新连接池<br />    <br />    Element pooltype=new Element("type"); //讄q接池类?br />    pooltype.setText(dsb.getType());<br />    newpool.addContent(pooltype);<br />    <br />    Element poolname=new Element("name");//讄q接池名?br />    poolname.setText(dsb.getName());<br />    newpool.addContent(poolname);<br />    <br />    Element pooldriver=new Element("driver"); //讄q接池驱?br />    pooldriver.addContent(dsb.getDriver());<br />    newpool.addContent(pooldriver);<br />    <br />    Element poolurl=new Element("url");//讄q接池url<br />    poolurl.setText(dsb.getUrl());<br />    newpool.addContent(poolurl);<br />    <br />    Element poolusername=new Element("username");//讄q接池用户名<br />    poolusername.setText(dsb.getUsername());<br />    newpool.addContent(poolusername);<br />    <br />    Element poolpassword=new Element("password");//讄q接池密?br />    poolpassword.setText(dsb.getPassword());<br />    newpool.addContent(poolpassword);<br />    <br />    Element poolmaxconn=new Element("maxconn");//讄q接池最大连?br />    poolmaxconn.setText(String.valueOf(dsb.getMaxconn()));<br />    newpool.addContent(poolmaxconn);<br />    pools.add(newpool);//childd到root<br />    Format format = Format.getPrettyFormat();<br />       format.setIndent("");<br />       format.setEncoding("utf-8");<br />       XMLOutputter outp = new XMLOutputter(format);<br />       fo = new FileOutputStream(rpath);<br />       outp.output(doc, fo);<br />   } catch (FileNotFoundException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />   } catch (JDOMException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />   } catch (IOException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />   }<br />   finally<br />   {<br />    <br />   }<br />  }<br />  /**<br />   *删除配置文g<br />   */<br />  public void delConfigInfo(String path,String name)<br />  {<br />   String rpath=this.getClass().getResource("").getPath().substring(1)+path;<br />   FileInputStream fi = null;<br />   FileOutputStream fo=null;<br />   try<br />   {<br />    fi=new FileInputStream(rpath);//d路径文g<br />    SAXBuilder sb=new SAXBuilder();<br />    Document doc=sb.build(fi);<br />    Element root=doc.getRootElement();<br />    List pools=root.getChildren();<br />    Element pool=null;<br />    Iterator allPool=pools.iterator();<br />    while(allPool.hasNext())<br />    {<br />     pool=(Element)allPool.next();<br />     if(pool.getChild("name").getText().equals(name))<br />     {<br />      pools.remove(pool);<br />      break;<br />     }<br />    }<br />    Format format = Format.getPrettyFormat();<br />       format.setIndent("");<br />       format.setEncoding("utf-8");<br />       XMLOutputter outp = new XMLOutputter(format);<br />       fo = new FileOutputStream(rpath);<br />       outp.output(doc, fo);</div> <div align="left">   <br />   } catch (FileNotFoundException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />   } catch (JDOMException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />   } catch (IOException e) {<br />    // TODO Auto-generated catch block<br />    e.printStackTrace();<br />   }<br />   <br />   finally<br />   {<br />    try {<br />     fi.close();<br />    } catch (IOException e) {<br />     // TODO Auto-generated catch block<br />     e.printStackTrace();<br />    }<br />   }<br />  }<br />  /**<br />   * @param args<br />   * @throws Exception <br />   */<br />  public static void main(String[] args) throws Exception {<br />   // TODO Auto-generated method stub</div> <div align="left">  ParseDSConfig pd=new ParseDSConfig();<br />   String path="ds.config.xml";<br />   pd.readConfigInfo(path);<br />   //pd.delConfigInfo(path, "tj012006");<br />   DSConfigBean dsb=new DSConfigBean();<br />   dsb.setType("oracle");<br />   dsb.setName("yyy004");<br />   dsb.setDriver("org.oracle.jdbc");<br />   dsb.setUrl("jdbc:oracle://localhost");<br />   dsb.setUsername("sa");<br />   dsb.setPassword("");<br />   dsb.setMaxconn(1000);<br />   pd.addConfigInfo(path, dsb);<br />   pd.delConfigInfo(path, "yyy001");<br />  }</div> <div align="left">}<br /> <br /> --------------------------------------<br /> ds.config.xml   配置文g<br /> --------------------------------------<br /> <br /> <br /> <ds-config><br /> <pool><br /> <type>mysql</type><br /> <name>user</name><br /> <driver>com.mysql.jdbc.driver</driver><br /> <url>jdbc:mysql://localhost:3306/user</url><br /> <username>sa</username><br /> <password>123456</password><br /> <maxconn>100</maxconn><br /> </pool><br /> <pool><br /> <type>mysql</type><br /> <name>user2</name><br /> <driver>com.mysql.jdbc.driver</driver><br /> <url>jdbc:mysql://localhost:3306/user2</url><br /> <username>sa</username><br /> <password>1234</password><br /> <maxconn>10</maxconn><br /> </pool><br /> <pool><br /> <type>sql2000</type><br /> <name>books</name><br /> <driver>com.microsoft.sqlserver.driver</driver><br /> <url>jdbc:sqlserver://localhost:1433/books:databasename=books</url><br /> <username>sa</username><br /> <password></password><br /> <maxconn>100</maxconn><br /> </pool><br /> </ds-config><br /> <br /> <br /> 3. q接池的使用<br />   1。Connection的获得和释放<br />   DBConnectionManager   connectionMan=DBConnectionManager .getInstance();//得到唯一实例<br />    //得到q接<br />    String name="mysql";//从上下文得到你要讉K的数据库的名?br />    Connection  con=connectionMan.getConnection(name);<br />   //使用<br />   。。。。。。?br />   // 使用完毕<br />  connectionMan.freeConnection(name,con);//释放Q但q未断开q接<br />  2。数据库q接的动态增加和q接池的动态增?br />       1。调用xml操作增加c?br /> <br />       2。重新实例华q接池管理池c?br /> <br /> <?gt;<br /> </div> <img src ="http://www.tkk7.com/zzs/aggbug/258022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zzs/" target="_blank">ID刀</a> 2009-03-05 16:06 <a href="http://www.tkk7.com/zzs/articles/258022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>上下?/title><link>http://www.tkk7.com/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.tkk7.com/zzs/articles/257365.html</guid><wfw:comment>http://www.tkk7.com/zzs/comments/257365.html</wfw:comment><comments>http://www.tkk7.com/zzs/articles/257365.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zzs/comments/commentRss/257365.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/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>中的出现是如此频J,但其中文译“上下?#8221;又是如此诡异拗口Q因此导致很多h不是很了解Context的具体含义是指什么,所以很有必要来q一下这词的含义?br /> <br /> 先来丑և个JAVA中用到Context的例?br /> <br /> Q?QJNDI的一个类javax.naming.InitialContextQ它dJNDI的一些配|信息,q内含对象和其在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">q是一DJBoss中获取MBean的远E调用类的代码。在q里面通过InitialContext中JNDI注册的名U?#8220;jmx/invoker/RMIAdaptor”来获得RMIAdaptor<br /> 对象。这和JAVA集合中的MAP有点象,有一个String的keyQkeyҎ着它的对象?br /> <br /> Q?Q再来看看下面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配置文g的信息,使得可以通过getBean用名U得到相应的注册对象</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">从上面的代码Q我很能体会到Context所代表的意义:公用信息、环境、容?...。所以我觉得Context译成上下文q不直观Q按照语a使用的环境,译?#8220;环境”?#8220;容器”可能更好?nbsp;                                                                       (?<br /> </span></p> <img src ="http://www.tkk7.com/zzs/aggbug/257365.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zzs/" target="_blank">ID刀</a> 2009-03-02 17:07 <a href="http://www.tkk7.com/zzs/articles/257365.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WEB试(?http://www.tkk7.com/zzs/articles/257328.htmlID刀ID刀Mon, 02 Mar 2009 05:33:00 GMThttp://www.tkk7.com/zzs/articles/257328.htmlhttp://www.tkk7.com/zzs/comments/257328.htmlhttp://www.tkk7.com/zzs/articles/257328.html#Feedback0http://www.tkk7.com/zzs/comments/commentRss/257328.htmlhttp://www.tkk7.com/zzs/services/trackbacks/257328.html 

1. 概述
   
随着web应用的增多,新的模式解决Ҏ中以web为核心的应用也越来越多, 很多公司各种应用的架构都?span lang="EN-US">B/S?span lang="EN-US">web应用ZQ但是有?span lang="EN-US">WEB试斚w的内容ƈ没有相应的ȝQ所以我在这里对web的测试方法和采用的测试技术进行ȝQ便于内部交?/font>
   
试Ҏ量늛webE序的各个方面,试技术方面在l承传统试技术的技术上l合web应用的特炏V?/font>
   
相关的测试和实现技术也有着很大的关p,׃本公怋?span lang="EN-US">J2EE体系Q也怾子中只有JAVAq_可以使用Q?span lang="EN-US">.NETq_试技术暂时不涉及Q如果你有请与我联系?/font>
2.
试Ҏ

说明Q测试方法的选择取决你的试{略?/font>
   
一般的web试和以往的应用程序的试的侧重点不完全相同,基本包括以下几个斚w?/font>
   
当然圆满的完成测试还要有好的团体和流E等的方斚w面的支持Q你同样应该对这些方面进行注意?/font>
   
有些试Ҏ设计C程Q哪些应该在你的试团队中徏立?

2.1 界面试
   
现在一般h都有使用览器浏览网늚l历Q用戯然不是专业h员但是对界面效果的印象是很重要的。如果你注重q方面的试Q那么验证应用程序是否易于用就非常重要了。很多h认ؓq是试中最不重要的部分Q但是恰恰相反界面对不懂技术的客户来说那相当关键,慢慢体会你会明白的?/font>
   
Ҏ上可以根据设计文档,如果够专业的话可以专业美工h员,来确定整体风格页面风|然后Ҏq个可以面人员可以生成静态的HTMLQ?span lang="EN-US">CSS{甚至生成几套不用的Ҏ来讨论,或者交l客戯审,最后Ş成统一的风格的面/框架。注意不要靠E序员的术素养形成你的web风格Q那样可能会很糟p?/font>
主要包括以下几个斚w的内容:

站点地图和导航条 位置、是否合理、是否可以导航等内容布局 布局是否合理Q滚动条{简介说?说明文字是否合理Q位|,是否正确

背景/色调 是否正确、美观,是否W合用户需求;

面在窗口中的显C是否正、美观(在调整浏览器H口大小Ӟ屏幕h是否正确Q表单样?大小Q格式,是否Ҏ交数据进行验证(如果在页面部分进行验证的话){?/font>
q接 q接的Ş式,位置Q是否易于理解等

   web
试的主要页面元?/font>
面元素的容错性列表(如输入框、时间列表或日历Q?/font>
面元素清单Qؓ实现功能Q是否将所需要的元素全部都列出来了,如按钮、单选框、复选框、列表框、超q接、输入框{等Q?/font>
面元素的容错性是否存?/font>
面元素的容错性是否正?/font>
面元素基本功能是否实现Q如文字Ҏ、动ȝ效、按钮、超q接Q?/font>
面元素的外形、摆放位|(如按钮、列表框、核选框、输入框、超q接{)

面元素是否昄正确Q主要针Ҏ字、图形、签章)

元素是否昄Q元素是否存在)

面元素清单Qؓ实现功能Q是否将所需要的元素全部都列出来了,如按钮、单选框、复选框、列表框、超q接、输入框{等Q?/font>
   
试技?/font>
    
通过面走查Q浏览确定用的面是否W合需求。可以结合兼Ҏ测试对不用分L率下面昄效果Q如果有影响应该交给设计人员提出解决Ҏ?/font> 
    
可以l合数据定义文档查看表单的内容Q长度等信息?/font>
    
对于动态生成的面最好也能进行浏览查看。如Servelet部分可以l合~码规范Q进行代码走查。是否支持中文,如果数据?span lang="EN-US">XM  装要做的工作会多一点等{?

   界面试要素:
W合标准和规?span lang="EN-US">,灉|?span lang="EN-US">,正确?span lang="EN-US">,直观?span lang="EN-US">,舒适?span lang="EN-US">,实用?span lang="EN-US">,一致?/font>
   1.
直观?/font>:
   
用户界面是否z净,不唐H?span lang="EN-US">,不拥?span lang="EN-US">.界面不应该ؓ用户刉障?span lang="EN-US">.所需功能或者期待的响应应该明显,q在预期出现的地?/font>.
   
界面l织和布局合理?span lang="EN-US">  是否允许用户LC一个功能{到另一个功?span lang="EN-US">  下一步做什么明昑֐  M时刻都可以决定放弃或者退?span lang="EN-US">,退出吗  输入得到承认了吗  菜单或者窗口是否深藏不?/font>   
   
有多余功能吗  软g整体抑或局部是否做得太?span lang="EN-US">  是否有太多特性把工作复杂化了  是否感到信息太庞?/font>   
   
如果其他所有努力失?span lang="EN-US">,帮助pȝ真能帮忙?/font>   

   2.
一致?/font>
   
快速键和菜单选项.?span lang="EN-US">Windows 中按F1键L得到帮助信息

   
术语和命?span lang="EN-US">.整个软g使用同样的术语吗  Ҏ命名一致吗  例如,Find是否一直叫Find,而不是有时叫
Search   
   
软g是否一直面向同一U别用户  带有花哨用户界面的趣呌卡程序不应该昄泄露技术机密的错误提示信息
.
   
按钮位置和等L按键.大家是否注意到对话框?span lang="EN-US">OK按钮?span lang="EN-US">Canc  e按钮?span lang="EN-US">,OK按钮L在上Ҏ者左?span lang="EN-US">,?span lang="EN-US">Canc  e按钮L在下Ҏx  同样原因,Canc  e按钮的等h键通常?span lang="EN-US">Esc,而选中按钮的等h钮通常?span lang="EN-US">Enter.保持一?/font>.

   3.
灉|?/font>
   
状态蟩?span lang="EN-US">.灉|的Y件实现同一d有多U选择方式
.
   
状态终止和跌,h定w处理能力
.
   
数据输入和输?span lang="EN-US">.用户希望有多U方法输入数据和查看l果.例如,在写字板插入文字可用键盘输入,_脓,?span lang="EN-US">6U文件格式读?span lang="EN-US">,作ؓ对象插入,或者用鼠标从其他程序拖?/font>.
   4.
舒适?/font>
   
恰当.软g外观和感觉应该与所做的工作和用者相W?/font>.
   
错误处理.E序应该在用h行严重错误的操作之前提出警告,q允许用h复由于错误操作导致丢q数据.如大家认?span lang="EN-US">undo /redo是当然的
.
   
性能.快不见得是好?span lang="EN-US">.要让用户看得清程序在做什?span lang="EN-US">,它是有反应的.

2.2 功能试
   
对功能测试是试中的重点

主要包括一下几个方面的内容

   
q接q个q接和界面测试中的连接不同那里注重的是连接方式和位置Q如是图像还是文字放|的位置{,q是其他的方式。这里的q接注重功能。如是否有连接,q接的是否是说明的位|等?/font>
   
表单提交应当模拟用户提交Q验证是否完成功能,如注册信息,要测试这些程序,需要验证服务器能正保存这些数据,而且后台q行的程序能正确解释和用这些信息。还有数据正性验证,异常处理{,最好结合易用性要求等?span lang="EN-US">B/Sl构实现的功能可能主要的在q里Q提交数据,处理数据{如果有固定的操作流E可以考虑自动化测试工L录制功能Q编写可重复使用的脚本代码,可以在测试、回归测试时q行以便减轻试人员工作量?/font>
   Cookies
验证 如果pȝ使用?span lang="EN-US">cookieQ测试h员需要对它们q行。如果在 cookies 中保存了注册信息Q请认?span lang="EN-US"> cookie能够正常工作而且已对q些信息已经加密。如果?span lang="EN-US"> cookie 来统计次敎ͼ需要验证次数篏计正。关?span lang="EN-US">cookie的用可以参考浏览器的帮助信息。如果?span lang="EN-US">B/Sl构cookies中存攄信息更多。功能易用性测?完成了功能测试可以对应用性进行了解,最好听听客L反映Q在可以的情况下对程序进行改q是很有必要的,和客户保持互动对pȝ满意度也是很有帮助的?/font>
   
试技术功能测试的试技术可是很多的Q我们可以结合实际环境选择使用

   
白盒试技?span lang="EN-US">(White Box Testing) 深入C码一U的试Q用这U技术发现问题最早,效果也是最好的。该技术主要的特征是测试对象进入了代码内部,Ҏ开发h员对代码和对E序的熟悉程?span lang="EN-US">,Ҏ需要的部分q行在Y件编码阶D,开发h员根据自己对代码的理解和接触所q行的Y件测试叫做白盒测试。这一阶段试以Y件开发h员ؓ主,?span lang="EN-US">JAVAq_使用Xunitpd工具q行试Q?span lang="EN-US">Xunit试工具是类一U的试工具Ҏ一个类和该cȝҎq行试?/font>
   
黑盒试技术(Black Box TestingQ黑盒测试的内容主要有以下几个方面,但是主要q是功能部分。主要是覆盖全部的功能,可以l合兼容Q性能试{方面进行,Ҏ软g需求,设计文档Q模拟客户场景随pȝq行实际的测试,q种试技术是使用最多的试技术涵盖了试的方斚w面,可以考虑以下斚w

     
正确?span lang="EN-US"> (Correctness)Q计结果,命名{方?/font>
     
可用?span lang="EN-US"> (Usability)Q是否可以满Y件的需求说明?/font>
     
边界条g (Boundary Condition)输入部分的边界?span lang="EN-US">,是使用一般书中说的等L划分,试试最大最和非法数据{等
.
     
性能 (Performance) 正常使用的时间内pȝ完成一个Q务需要的旉,多h同时使用的时候响应时?span lang="EN-US">,在可以接受范围内.J2EE技术实现的pȝ在性能斚w更是需要照儡,一般原则是3U以下接?span lang="EN-US">,3-5U可以接?span lang="EN-US">,5U以上就影响易用性了. 如果在测试过E中发现性能问题Q修复v来是非常艰难的,因ؓq常常意味着

E序的算法不好,l构不好Q或者设计有问题。因此在产品开发的开始阶D,p考虑到Y件的性能问题

     
压力试 (Stress) 多用h?可以考虑使用压力试工具,压力和性能试l合hq行.如果有负载^衡的话还要在服务器端打开监测工具,查看服务?span lang="EN-US">CPU使用?span lang="EN-US">,内存占用情况,如果有必要可以模拟大量数据输?span lang="EN-US">,对硬盘的影响{等信息.如果有必要的话必进行性能优化(软硬仉可以).q里的压力测试针对的是某几项功能
,.
     
错误恢复 (Error Recovery) 错误处理Q页面数据验?span lang="EN-US">,包括H然间断?span lang="EN-US">,输入脏数据等
.
安全性测?span lang="EN-US">(Security)q个领域正在研究?span lang="EN-US">,不过防火?span lang="EN-US">,补丁?span lang="EN-US">.杀毒Y件等的就不必说了,不过可以考虑破坏性测试时L.看了一些资料后得知,q里面设计到的知?span lang="EN-US">\内容可以写本书了,不是一两句可以说清?span lang="EN-US">,特别是一些商务网?span lang="EN-US">,或者跟钱有?span lang="EN-US">,或者和公司U密有关?span lang="EN-US">web更是,需要这斚w的测?span lang="EN-US">,在外国有一U专门干q一行的人叫安全N,可以审核代码,提出安全,出现紧急事件是的处理办法等,在国内没有听说哪里有专门搞安全技术测试的内容
.
     
兼容?span lang="EN-US"> (Compatibility) 不同览器,不同应用E序版本在实现功能时的表?span lang="EN-US">,不同的上|方?span lang="EN-US">,如果你测试的是一个公q站的?/font>.
   
兼容性测试内容详q?/font>
   
gq_

   
览器Y件和版本:览器插?span lang="EN-US">,览器选项,视频分L率和色深.文字大小,调制解调器速率
.
     
软g配置 (Configuration) ?span lang="EN-US">IE览器的不用选项-安全讑֮最?span lang="EN-US">,用脚本E序,{等,你们的程序在各种不用的设|下表现如何.

单元试技?/font>(Unit Test):
2.2.1
下面是对白盒试和单元测试的区别的论q?/font>:
   
单元试和白盒测试是不同?span lang="EN-US">,虽然单元试和白盒测试都是关注功能虽然他们都需要代码支?span lang="EN-US">,但是U别不同,白盒试x的是cM一个方法的功能是更的单位,但是完成一个单元测试可能需?span lang="EN-US">N多类,所以说作单元测试需要什么写驱动和稳定桩,比如查询单元是一个查询包?span lang="EN-US">N多的试c?span lang="EN-US">,试数据,q行他需要提供数据的部分,输入参数和发出命令的驱动{等.是比cd的一个整体进行的
.
   
另一个明昄区别是白盒测试不会关注类接口,但是单元试主要的内容就是类接口试
.
   
不过很多时候是很少区分?span lang="EN-US">,因ؓq两U技术实现v来有很多怺兌的部?span lang="EN-US">.不过要看你对质量的关注程度来军_
.
2.2.2
功能试边界试\界试技术详q?/font>
   
边界条g

边界条g是指软g计划的操作界限所在的边缘条g
.
如果软g试问题包含定的边?span lang="EN-US">,那么数据cd可能?/font>:
数?速度 字符 地址 位置 寸 数量

同时,考虑q些cd的下q特?/font>:
W一?span lang="EN-US">/最后一?最?span lang="EN-US">/最大?/font>
开?span lang="EN-US">/完成 过/在内

I?span lang="EN-US">/?最?span lang="EN-US">/最?/font>
最?span lang="EN-US">/最?最?span lang="EN-US">/最q?/font>
最?span lang="EN-US">/最?最?span lang="EN-US">/最?/font>
盔R/最q?/font>
   
界试

通常是简单加1或者很的?span lang="EN-US">(对于最大?span lang="EN-US">)和减?span lang="EN-US">1或者很的?span lang="EN-US">(对于最?span lang="EN-US">),例如
:
W一个减1/最后一个加
1
开始减1/完成?/font>1
IZ再减/满了再加

慢上加慢/快上加快

最大数?span lang="EN-US">1/最数?/font>1
最值减1/最大值加
1
刚好过/刚好在内

短了再短/长了再长

早了更早/晚了更晚

最高加1/最低减
1
   
另一些该注意的输?span lang="EN-US">:默认,I白,I?span lang="EN-US">,零值和?span lang="EN-US">;非法,错误,不正和垃圾数据
.
2.2.3
状态测试技?/font>

   
软g可能q入的每一U独立状?/font>;
   
从一U状态{入另一U状态所需的输入和条g
;
   
q入或退出某U状态时的设|条件及输入l果
.

   
具体试Ҏ可以参考如?/font>:
   
每种状态至访问一?/font>;
   
试看v来最常见最普遍的状态{?/font>;
   
试状态之间最不常用的分支

   
试所有错误状态及其返回?/font>
   
试随机状态{?/font>
2.2.4
竞争条g试技?/font>
   
竞争条g典型情Ş参考如?/font>:
   
两个不同的程序同时保存或打开同一个文?/font>
   
׃n同一台打印机,通信端口或者其他外围设?/font>
   
当Y件处于读取或者修改状态时按键或者单击鼠?/font>
   
同时关闭或者启动Y件的多个实例

   
同时使用不同的程序访问一个共同数据库

2.3 负蝲\压力试(StressTest)
   
在这里的负蝲\压力和功能测试中的不?span lang="EN-US">,他是pȝ试的内?span lang="EN-US">,是基本功能已l通过后进行的.可以在集成测试阶D?span lang="EN-US">,亦可以在pȝ试阶段q行
.
   
使用负蝲试工具q行,虚拟一定数量的用户看一看系l的表现,是否满定义中的指标
.
   
负蝲试一般用工具完成,  oadrunnerQ?span lang="EN-US">web  oadQ?span lang="EN-US">wasQ?span lang="EN-US">ew  Q?span lang="EN-US">e-test{,主要的内定w是编写出试脚本Q脚本中一般包括用户一般常用的功能Q然后运行,得出报告。所以负载测试包括的主要内容׃介绍了?/font>
   
负蝲试技术在各种极限情况下对产品q行试 (如很多h同时使用该YӞ或者反复运行该软g)Q以查品的长期E_性。例如,使用压力试工具?span lang="EN-US">web服务器进行压力测?span lang="EN-US">. 本项试可以帮助扑ֈ一些大型的问题Q如L、崩损、内存泄漏等Q因为有些存在内存泄漏问题的E序Q在q行一两次时可能不会出现问题,但是如果q行了成千上万次Q内存泄漏得来多Q就会导致系l崩滑。用J2EE实现的系l很但是ƈ不是没有内存问题
.
   
无论什么工具基本的技术都是利用线E技术模仿和虚拟用户Q在q里主要的难点在与测试脚本的~写Q每U工具用的脚本都不一P但是大多数工具都提供录制功能q是不会编码的试人员同样可以试?/font>
   
对负载工L延使用可以q行pȝE_性测试,pȝ极限试Q如使用100?span lang="EN-US">  oad Sizeq箋使用24时Q微软定义的通过准则是通过72时试的程序一般不会出现稳定性的问题?

2.4 回归试 (Regression Test)
   
q一D|间以后,再回q头来对以前修复q的Bug重新q行试Q看?span lang="EN-US">Bug 是否会重新出现?/font>
   
回归试技术可以在试的各个阶D出玎ͼ无论是单元测试还是集成测试还是系l测试。是对以前问题进行验证的q程?/font>
   
回归试的目的就是保证以前已l修复的Bug不会再出现。实际上Q许?span lang="EN-US">Bug都是在回归测试时发现的,在此阶段Q我们首先要查以前找到的Bug 是否已经更正了。值得注意的是Q已l更正的Bug 也可能又回来了,有的Bug l过修改之后可能又生了新的Bug。所以,回归试可保证已更正?span lang="EN-US">Bug不再重现Q不产生新的Bug?/font>
2.5 A  pha
?span lang="EN-US">Beta 试
(A  pha and Beta Test):
   
在正式发布品之前往往要先发布一些测试版Q让用户能够反馈出相关信息,或者找到存在的BugQ以便在正式版中得到解决?/font>
   
特别是在有客户参加的情况下,对系l进行测试可能会出现一些我们没有考虑的情况,q可以解决一些客户实际关心的问题

不同的测试技术区?/font>
3.1
覆盖试技?/font>
说明:试覆盖率可以看出测试的完成?span lang="EN-US">,在测试分析报告中可以作ؓ量化指标的依据,试覆盖率越高效果越好?/font>
   
覆盖试可以是程序代码的执行路径覆盖Q亦可以是功能实现的步骤覆盖Q可以理解成程囄路径覆盖Q?/font>
   
该技术可以用在Q何测试阶D,包括单元坏歅R集成测试、系l测试?/font>
   
使用该技术时可以使用以上的Q何测试方法和试技术?/font>
3.2
白盒试和黑盒测试技?/font>
   
白盒试技?span lang="EN-US"> (White Box Testing)该技术主要的特征是测试对象进入了代码内部,Ҏ开发h员对代码和对E序的熟悉程?span lang="EN-US">,Ҏ需要的部分q行在Y件编码阶D,开发h员根据自己对代码的理解和接触所q行的Y件测试叫做白盒测试。这一阶段试以Y件开发h员ؓ主,使用Xunitpd工具q行试Q可以包括很多方面如功能性能{?/font>
   
黑盒试 (Black Box Testing)试的主体部分黑盒测试的内容主要有以下几个方面,但是主要q是功能部分。主要是覆盖全部的功能,可以l合兼容Q性能试{方面进?span lang="EN-US">,包括的不同测试类型请参考以上内宏V?/font>
3.3
手工试和自动化试

   
手工试Q?span lang="EN-US">Manual  TestingQ:即依靠h力来查找Bug。方法可以参考上边的试Q也可以Ҏ对实现技术及l验{进行不同的试?/font>
   
自动试Q?span lang="EN-US">Automation TestingQ用有针对工具实行。可以作动化试的计?span lang="EN-US">,对可以进行自动化试的部分编写或者录制相应的脚本,可以加入功能,定w,表单提交{?span lang="EN-US">,可以参?span lang="EN-US">MI,Rationa  或者其他类试工具说明
.
   
Ҏ权威的Y件测试经验,手工试q是主要的测试方法,自动试不够灉|Q在q里不再详述。微软的试q程80Q还是手工完成?/font>
   
自动试永远也代替不了手工测试,但是手工试的工作量很大是不争的事实?/font>
3.4
ҎRUP标准按阶D区分测?/font>
   
单元试在上Ҏ详细的叙qͼq有针对单元试和集成测试的Q请参考?/font>
   
集成试分ؓ功能集成试和系l集成测试,怺有调用的功能集成Q在pȝ环境下功能相互调用的影响{,使用Ҏ可以L选用上面的内宏V注重功能方面?/font>
   
pȝ试在功能实现的基础上,可以加入兼容性,易用性,性能{等

   
验收试可以包括Alpha?span lang="EN-US">Beta试Q在q里׃再详q?

4. 存在风险及解x?/font>
说明Q测试不能找出所有的问题Q只是尽量将问题在开发阶D解军_多数的问题而已?/font>
试风险如下Q?/font>
   
软硬件的试环境提供上也Ҏ试结果有很大的媄响?/font>
   
试团队的水qIl验Q合作效果等

   
整个开发流E对试的重视程度,试的进入时间等

   
׃试环境操作pȝQ网l环境,带宽{情况可能生的试l果可能不同q是需要经验以及对试环境的保护等斚w下一些功夫?/font>
5.
软g~陷的原?/font>
   
软g~陷区别于Y?span lang="EN-US">bug,它是在测试过E中出现的对pȝ有媄响的,但是在设计中没有的或者对修改后的bug试和开发h员有不同意见{?/font>
   
软g未达C品说明书标明的功能?/font>
   
软g出现了品说明书指明不会出现的错误?/font>
   
软g功能出产品说明书指明范围?/font>
   
软g未达C品说明书虽未指出但应辑ֈ的目标?/font>
   
软g试员认Y仉以理解、不易用、运行速度~慢Q或者最l用戯Z好?

6. 文档试
   
产品说明书属性检查清?/font>
   
完整.是否有遗漏和丢失  完全?span lang="EN-US">  单独使用是否包含全部内容
   
   
准确.既定解决Ҏ正确?span lang="EN-US">  目标明确?span lang="EN-US">  有没有错?/font>   
   
_,不含p?span lang="EN-US">,清晰.描述是否一清二?span lang="EN-US">  q是自说自话  Ҏ看懂和理解吗
   
   
一?span lang="EN-US">.产品功能能描q是否自相矛?span lang="EN-US">,与其他功能有没有冲突
   
   
贴切.描述功能的陈q是否必?span lang="EN-US">  有没有多余信?span lang="EN-US">  功能是否原来的客戯?/font>   
   
合理.在特定的预算和进度下,以现有h?span lang="EN-US">,物力和资源能否实?/font>   
   
代码无关.是否坚持定义产品,而不是定义其所信赖的Y件设?span lang="EN-US">,架构和代?/font>   
   
可测试?span lang="EN-US">.Ҏ能否测?span lang="EN-US">  试员徏立验证操作的试E序是否提供_的信?/font>   

   
产品说明书用语检查清?/font>
说明 寚w题的描述通常表现为粉饰没有仔l考虑的功?span lang="EN-US">----可归l于前文所q的属?span lang="EN-US">.从品说明书上找L用语,仔细审视它们在文中是怎样使用?span lang="EN-US">.产品说明书可能会为其掩饰和开?span lang="EN-US">,也可能含p其?span lang="EN-US">----无论是哪一U情况都可视Y件缺?/font>.
   
L,每一U?span lang="EN-US">,所?span lang="EN-US">,没有,从不.如果看到此类l对或肯定的,切实认定的叙q?span lang="EN-US">,软g试员就可以着手设计针锋相对的案例
.
   
当然,因此,明显,,必然.q些话意图诱使接受假定情?span lang="EN-US">.不要中了圈套
.
   
某些,有时,常常,通常,惯常,l常,大多,几乎.q些话太q模p?span lang="EN-US">."有时"发生作用的功能无法测?/font>.
   
{等,诸如此类,依此cL.以这L词结束的功能清单无法试.功能清单要绝Ҏ者解释明?span lang="EN-US">,以免让hqh,不知如何推论
.
   
良好,q?span lang="EN-US">,廉h,高效,?span lang="EN-US">,E_.q些是不定的说?span lang="EN-US">,不可试.如果在品说明书中出?span lang="EN-US">,必进一步指明含?/font>.
   
已处?span lang="EN-US">,已拒l?span lang="EN-US">,已忽?span lang="EN-US">,已消?span lang="EN-US">.q些廉洁可能会隐藏大量需要说明的功能
.
   
如果...那么...(没有否则).扑և?span lang="EN-US">"如果...那么..."而缺配套的"否则"l构的陈q?span lang="EN-US">.想一?span lang="EN-US">"如果"没有发生会怎样.

 



ID刀 2009-03-02 13:33 发表评论
]]>
annotation的作用(转)http://www.tkk7.com/zzs/articles/257071.htmlID刀ID刀Fri, 27 Feb 2009 09:23:00 GMThttp://www.tkk7.com/zzs/articles/257071.htmlhttp://www.tkk7.com/zzs/comments/257071.htmlhttp://www.tkk7.com/zzs/articles/257071.html#Feedback0http://www.tkk7.com/zzs/comments/commentRss/257071.htmlhttp://www.tkk7.com/zzs/services/trackbacks/257071.html 1Q?nbsp;   ~译工具或其他工具可以根据被附加在代码里的annotation信息自动生成配置文g或文档等外部文g?br /> 比如Qsun公司提供了aptQAnnotation Processing ToolQ?/a>工具Qapt工具是一个可以处理annotation的命令行工具Qapt提供了在~译期针Ҏ代码U别的解析,q可以在解析时生成新的源代码和其他文Ӟ同时q可以对生成的源代码q行~译?br /> 2Q?nbsp;   其他E序可以在运行时动态解析将要被执行的程序里的annotation信息QƈҎ被附加的annotation信息来执行不同的操作?br /> 比如QEJB3规范比较广泛地使用了annotationҎ。比如只要在POJO为class注明@Stateless注释QEJB容器便会Ҏ此annotation把该POJO注册为无状态的Session Bean。EJB3使用了annotation大大地简化了EJB的开发和配置q程。我们会在其他文章里专门介绍EJB Annotation的原理与使用ҎQ这里不做详q?br />
本文通过一个简单地例子来说明怎么在运行期动态解析annotation。Apt工具的用我们会在近期其他文章里对其加以介绍?br />
比如Q我们定义了MyAnnotation3注释Q?br />  MyAnnotation3.java
package com.test.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation3 {
    public String value();
    public String[] multiValues();
    int number() default 0;
}
上面定义了一个名为MyAnnotation3的注释?br />
我们再定义一个GetMyAnnotationc,该类使用了MyAnnotation3注释Q?br /> GetMyAnnotation.javaQ?br />
package com.test.annotation.test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import javax.ejb.EJB;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.test.annotation.MyAnnotation3;

// 为GetMyAnnotationc附加MyAnnotation3 注释
@MyAnnotation3(value = "Class GetMyAnnotation", multiValues = {"1","2"})
public class GetMyAnnotation {
    // 为testField1属性附加MyAnnotation3 注释
    @MyAnnotation3(value = "call testField1", multiValues={"1"}, number = 1)
    private String testField1;

    // 为testMethod1Ҏ附加MyAnnotation3 注释
    @MyAnnotation3(value = "call testMethod1", multiValues={"1", "2"}, number = 1)
    public void testMethod1() {

    }

    @Deprecated
    @MyAnnotation3(value = "call testMethod2", multiValues={"3", "4", "5"})
    public void testMethod2() {

    }
}
上面的例子GetMyAnnotation非常单,里面没有M功能Q但是分别ؓc(classQ,属性(fieldQ,ҎQmethodQ申明(附加Q了MyAnnotation3 注释?br />
下面我们用程序TestMyAnnotation3对GetMyAnnotation里MyAnnotation3注释q行解析?br />
q行时解析annotation
TestMyAnnotation3.java
public class TestMyAnnotation3 {

    public static void main(String[] args) {
        System.out.println("--Class Annotations--");
        if (GetMyAnnotation.class.isAnnotationPresent(MyAnnotation3.class)) {
            System.out.println("[GetMyAnnotation].annotation:");
            MyAnnotation3 classAnnotation = GetMyAnnotation.class.getAnnotation(MyAnnotation3.class);
            printMyAnnotation3(classAnnotation);
        }
        
        
        System.out.println("--Fields Annotations--");
        Field [] fields = GetMyAnnotation.class.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(MyAnnotation3.class)) {
                System.out.println("[GetMyAnnotation." + field.getName() + "].annotation:");
                MyAnnotation3 fieldAnnotation = field.getAnnotation(MyAnnotation3.class);
                printMyAnnotation3(fieldAnnotation);
            }
        }
        
        System.out.println("--Methods Annotations--");
        Method[] methods = GetMyAnnotation.class.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("[GetMyAnnotation." + method.getName() + "].annotation:");
            if (method.isAnnotationPresent(MyAnnotation3.class)) {
                MyAnnotation3 methodAnnotation = method.getAnnotation(MyAnnotation3.class);
                printMyAnnotation3(methodAnnotation);  
            }
        }
    }
    
    private static void printMyAnnotation3(MyAnnotation3 annotation3) {
        if (annotation3 == null) {
            return;
        }
        
        System.out.println("{value=" + annotation3.value());
        
        String multiValues = "";
        for (String value: annotation3.multiValues()) {
            multiValues += "," + value;
        }
        
        System.out.println("multiValues=" + multiValues);
        
        System.out.println("number=" + annotation3.number() + "}");
    }
}

输出Q?br />
--Class Annotations--
[GetMyAnnotation].annotation:
{value=Class GetMyAnnotation
multiValues=,1,2
number=0}
--Fields Annotations--
[GetMyAnnotation.testField1].annotation:
{value=call testField1
multiValues=,1
number=1}
--Methods Annotations--
[GetMyAnnotation.testMethod1].annotation:
{value=call testMethod1
multiValues=,1,2
number=1}
[GetMyAnnotation.testMethod2].annotation:
{value=call testMethod2
multiValues=,3,4,5
number=0}


JDK1.5以后的版本提供的跟annotation有关的接口:
interface java.lang.reflect.AnnotatedElement {
    boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
    <T extends Annotation> T getAnnotation(Class<T> annotationClass);
    Annotation[] getAnnotations();
    Annotation[] getDeclaredAnnotations();
}
该接口主要用来取得附加在c(classQ,构造方法(constructorQ,属性(fieldQ,ҎQmethodQ,包(packageQ上的annotation信息?br />
JDK1.5与此有关的几个类都实CAnnotatedElement接口Q?br />
java.lang.reflect.AccessibleObject,
java.lang.reflect.Class,
java.lang.reflect.Constructor,
java.lang.reflect.Field,
java.lang.reflect.Method,
java.lang.reflect.Package
所以可以利用反(reflectionQ功能在E序里动态解析附加的annotation信息?br />

ȝQ?/strong>
本文通过举例单地说明了怎么动态解析annotationQ大家可以D一反三Q利用Java的annotationҎ,完成更复杂功能等?nbsp;   

ID刀 2009-02-27 17:23 发表评论
]]>
自定?Java Annotation(?http://www.tkk7.com/zzs/articles/257070.htmlID刀ID刀Fri, 27 Feb 2009 09:21:00 GMThttp://www.tkk7.com/zzs/articles/257070.htmlhttp://www.tkk7.com/zzs/comments/257070.htmlhttp://www.tkk7.com/zzs/articles/257070.html#Feedback0http://www.tkk7.com/zzs/comments/commentRss/257070.htmlhttp://www.tkk7.com/zzs/services/trackbacks/257070.htmlAnnotation是一U特D的interface。所以可以在annotation里定义方法,属性;也可以让某个cMannotationl承QimplementsQ?br />
下面从简单地范例开始,让我们一步步加深对annotation的了解?br />
无Q何方?属性Annotation范例Q?/div>

MyAnnotation0.java

package com.test.annotation;

public @interface MyAnnotation0 {
    
}

MyAnnotation0Z个无MҎ和属性的annotation?br />
使用MyAnnotation0Q?br />

TestMyAnnotation0.java
@MyAnnotation0
public class TestMyAnnotation0 {
    @MyAnnotation0
    public void testMethod() {

    }
}



 h一个valueҎAnnotation范例Q?/p>

MyAnnotation1.java

public @interface MyAnnotation1 {
    
    /**
     * value method
     * @return value
     */

    public String value();
}

MyAnnotation1h一个名为value的方法?br />
MyAnnotation1使用Q?br /> TestMyAnnotation1.java

@MyAnnotation1("hello")
public class TestMyAnnotation1 {
    @MyAnnotation1(value="world")
    public void testMethod() {
    }
}

可以通过@Annotation?Ҏ?=?, Ҏ?=?, …)的Ş式给annotation赋倹{只有一个方法的时候,可以直接省略为:@Annotation??) 的赋值Ş式。当Ҏq回一个数l时Q可以用 Ҏ?{?, ?, …}l其赋倹{?br />

h一个valueҎ和一个属性Annotation范例Q?/div>

如果必要Q还可以在annotation里ؓ其定义属性。如下:
MyAnnotation2.java

@interface MyAnnotation2 {
    public String value();
    public String myProperty = "hello world";
}

其中QmyProperty只能x为public或无public修饰Q无public修饰时也默认为publicQؓstatic, final属性(即不写也默认ؓstatic, finalQ?br />
使用例:
TestMyAnnotation2

class TestMyAnnotation2 {
    public static void main(String[] args) {
        System.out.println(MyAnnotation2.myProperty);
    }

    @MyAnnotation2("")
    public void testMethod1() {
    }
}

上例会打印出Q?/p>

hello world



 

复杂型annotation的定义与使用

本节介绍较ؓ复杂的annotation定义与用?br /> 先看代码Q?br /> MyAnnotation3.java

public @interface MyAnnotation3 {
    public String value();
    public String[] multiValues();
    int number() default 0;
}

MyAnnotation3h一个返回String的valueҎQ返回String[]的multiValues ҎQ还有一个返回int 的numberҎ。其中numberҎh默认??br />
使用例:
TestMyAnnotation3.java

class TestMyAnnotation3 {
    @MyAnnotation3(value = "call testMethod1", multiValues={"1", "2"}, number = 1)
    public void testMethod1() {

    }

    @MyAnnotation3(value = "call testMethod2", multiValues={"1", "2"})
    public void testMethod2() {

    }
}

numberh默认|所以标注时可以不ؓ其赋倹{其余方法则必须通过上面介绍的方法赋倹{multiValuesq回一个String[]数组Q所以可以通过multiValues={"1", "2"}为其赋倹{?br />

 



ID刀 2009-02-27 17:21 发表评论
]]>Java Annotation注释语法Q{Q?/title><link>http://www.tkk7.com/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.tkk7.com/zzs/articles/257069.html</guid><wfw:comment>http://www.tkk7.com/zzs/comments/257069.html</wfw:comment><comments>http://www.tkk7.com/zzs/articles/257069.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zzs/comments/commentRss/257069.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zzs/services/trackbacks/257069.html</trackback:ping><description><![CDATA[<br /> JAVA从J2SE5开始提供名为annotationQ注释,标注Q的功能。Java的annotationQ可以附加在package, class, method, field{上面,相当于给它们d了额外的辅助信息。附加在package, class, method, field{上的AnnotationQ如果没有外部解析工L对其加以解析和处理的情况Q本w不会对Java的源代码或class{生Q何媄响,也不会对它们的执行生Q何媄响?br /> <br /> 但借助外部工具Q比如javacQEJB容器{,可以寚w加在package, class, method, field的annotationq行解析Q可以根据annotation而做出相应的处理Q比如运行时改变对象/Ҏ的行为?br /> <br /> <br /> <div id="z99prhn" class="tf_edit_html_title1" id="tf_edit_html_title1">Java标准Annotation</div> @Deprecated 相当于Javadoc的@deprecatedQ被@Deprecated标注的对象class, method{被注明Z推荐使用。主要用于javac{编译工兗?br /> @Override 注明对象method重蝲了父cȝҎ。javac{编译工L译时会根据此Annotation判断重蝲Ҏ是否正确?br /> @SuppressWarnings 告诉javac{编译器忽略所指定的特定的警告信息?br /> @Target 被定义的annotation可以附加在那些对象上?br /> @Retention annotation的作用期间?br /> <div id="h339bjj" class="tf_edit_html_title1" id="tf_edit_html_title1">Java标准Annotation的?/div> @DeprecatedQ?br /> <div id="l9nlp9h" 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 />     …<br /> }<br /> </div> @SuppressWarnings<br /> <div id="113j3bb" 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 />     …<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 />     …<br /> }</div> <br /> @Override <br /> <div id="xhlvhpf" class="tf_edit_html_code" id="tf_edit_html_code">@Override<br /> <span style="font-weight: bold; color: #7f0055">public</span> String doSth() {<br />     …<br /> }<br /> </div> <br /> <br /> <div id="v9hxrrz" class="tf_edit_html_title1" id="tf_edit_html_title1">Annotation的定?/div> 定义ҎQ?br /> @interface Annotation?{定义体}<br /> <br /> 定义?Q?br /> <div id="rln3x99" 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> 该例定义了一个无M属?Ҏ的Annotation?br /> <br /> 定义?Q?br /> <div id="htvhtbb" 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 />     <span style="font-weight: bold; color: #7f0055">public</span> String value();<br /> }<br /> </div> 该例定义了只有一个方法ؓvalue()的Annotation。一般来_只有一个方法的AnnotationQ方法名一定定义ؓvalue?br /> <br /> 定义?Q?br /> <div id="x9jnr9x" 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 />     <span style="font-weight: bold; color: #7f0055">public</span> String value();<br />     <span style="font-weight: bold; color: #7f0055">public</span> String [] multiValues();<br />     <span style="font-weight: bold; color: #7f0055">int</span> number() <span style="font-weight: bold; color: #7f0055">default</span> 0;<br />     <br /> }<br /> </div> 该例定义了一个具有多Ҏ的Annotation。ƈ讄其中一个方法number的默认gؓ0。multiValues Ҏ定义为数l类型。Annotation定义可以用MetaAnnotationQ元注释Q修饰。MetaAnnotation有以?个:<br /> @Retention<br /> @Target<br /> <br /> 我们在以下对@Retention与@Target加以说明?br /> <br /> <br /> <div id="19htnd9" class="tf_edit_html_title1" id="tf_edit_html_title1">@Retention</div> @Retention 可以讄为RetentionPolicycd的倹{?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文g中,但执行时不会在VM装蝲。也是说不能在执行时动态取得annotation信息。未讄@Retention时这是默认讄倹{?</td> </tr> <tr class="altEventRow"> <td>RetentionPolicy.RUNTIME</td> <td>annotation信息被~译器编译时保存在class文g中,执行时也会被VM装蝲?</td> </tr> <tr class="eventRow"> <td>RetentionPolicy.SOURCE</td> <td>annotation信息被~译器编译时舍弃掉?</td> </tr> </tbody> </table> <br /> <br /> <div id="93f99p9" class="tf_edit_html_title1" id="tf_edit_html_title1">@Target</div> @Target表明Annotation可以附加在哪UJAVA元素之上Q可以设|ؓjava.lang.annotation.ElementType数组cd的倹{?br /> 使用?Q?br /> <div id="9rr93tv" class="tf_edit_html_code" id="tf_edit_html_code">@Target(ElementType.METHOD)<br /> </div> <br /> 使用?Q?br /> <div id="lfjdpx9" 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>c,接口或者枚丑֣?/td> </tr> </tbody> </table> <br /> <br /> <br /> <br /> <br /> <img src ="http://www.tkk7.com/zzs/aggbug/257069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zzs/" target="_blank">ID刀</a> 2009-02-27 17:16 <a href="http://www.tkk7.com/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.tkk7.com/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.tkk7.com/zzs/articles/257037.html</guid><wfw:comment>http://www.tkk7.com/zzs/comments/257037.html</wfw:comment><comments>http://www.tkk7.com/zzs/articles/257037.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zzs/comments/commentRss/257037.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zzs/services/trackbacks/257037.html</trackback:ping><description><![CDATA[<p align="left">来源Q?a style="color: #339966" >http://java.chinaitlab.com/EJB/743927.html</a><br /> <br /> </p> <a class="channel_keylink" target="_blank">Java</a>企业U版本,或者说<a class="channel_keylink" target="_blank">Java</a> EE(以前叫J2EE),对于开?a class="channel_keylink" target="_blank">服务?/a>端的应用来说是一个强大的但却又过于复杂的的^台。从它诞生之日vQ过于复杂一直是对用Java EE犹U不决的一个重要因素。在JavaWorld的以前的一文?#8221;化之?#8221;中,我指Z那些让Java EE应用变复杂的因素Q其中很多都是与当前的EJB 2.1规范有关?<br />   在过ȝ三年中,Java开放源代码C֌QJavaC֌q程(JCP)以及主要的Java EE供应商,一直致力于让Java EE更简单。D例来?新的设计范例Q比如POJO服务Q服务拦截器和依赖注入,已经可以在实际应用中用来化Java EE的开发了。还有,新的工具和框Ӟ比如Hibernate, AOP(aspect-oriented programmingQ面向方面编E?QStruts,Xdoclet和Spring, 也已l被q泛用于同一目的? <p>  <strong>化不是功能的减少</strong></p> <p>  化一个编E模型ƈ没有减少它的功能。简化只是把复杂的逻辑隐藏C框架代码或可重用的组件中M。根本上Q它是把复杂的东西从需要应用开发者直接管理的地方转移C大多数开发者看不到的地斏V?/p> <p>  上述的模板和工具让初学者更Ҏ上手Q同时也提高了有l验的Java开发者的生力,现在它们正在被JCP合ƈC一代的Java EE标准?比如:EJB 3.0)。由Java开发h员Raghu Kodali最q所做的研究昄:Java EE的示例程序RosterApp从EJB 2.1转到EJB 3.0可以减少癑ֈ之五十以上的代码?/p> <p>  Java注释是EJB3.0背后的关键,它将POJO服务QPOJO持久化和依赖注入一L定ؓ一个完整的企业U中间g解决Ҏ。这文章中Q我使用了一个示例应?JBoss EJB 3.0 TrailBlazerQ来演示使用注释开发轻量的EJB 3.0 POJO应用。TrailBlazer的应用用EJB 3.0中不同的工具和API重复实现了一个投资计器。示例程序完全可以在JBoss 应用<a class="channel_keylink" target="_blank">服务?/a>4.0.3版本中运行,q且与最新的EJB 3.0标准完全兼容(完成??/p> <p>  让我们来开始体验一下注释驱动编E模型的好处吧?/p> <p>  EJB 3.0的注释驱动编E模?/p> <p>  从开发者的观点来看QEJB 3.0q泛C用了Java 注释.注释有两个关键优?它们取代了过多的XML配置文gq且消除了严格组件模型需求?/p> <p>  <strong>注释 vs XML</strong></p> <p>  ZXML的布|描q和注释一起都可以用来在Java EE应用中配|服务的相关属性。它们的区别在于:XML文档是与代码分开处理的,特别是在q行时刻Q而注释是与代码编译在一Lq被~译器检查的。对于开发者来说这有了一些重要的含义Q正如我下面所列出?</p> <p>  冗长:XML配置文g是出了名的冗长的。ؓ了配|代码,XML文g必须复制许多信息:比如代码中类名字和方法名字。Java注释则不同,它是代码的一部分Q不需要额外的引用可以指明配|信息?/p> <p>  强壮?在XML文g中重复的代码信息引入了多处龃淼目赡堋Q热?如果你写错了Ҏ的名字,那应用直到运行时L会出错垮掉。也是_XML配置文g的强壮性就不如注释Q注释是被编译器查的Qƈ和其它代码一赯处理的?/p> <p>  灉|?既然XML文g是在代码之外被单独处理的Q那也就是说ZXML的配|信息不?#8220;编?#8221;的,是可以以后修改的。部|的灉|性对pȝ理员来说是非常非常重要的特性?/p> <p>  注释是简单易用的Q已证明对大多数应用来说_了。XML文g更复杂,但能被用来处理更高的问题。EJB 3.0允许你通过注释来配|大多数的应用。EJB 3.0也支持用XML文g来覆盖默认的注释Q及配置像数据库联接q样的外部资源?/p> <p>  除了替换和简化XML描述W,注释也允许我们废除困扰EJB 1.x, EJB 2.x的严格组件模型?/p> <p>  <strong>POJO vs 严格lg</strong></p> <p>  EJB lg是容器管?container-managed)的对象。容器在q行时刻操作Bean的状态和行ؓ。ؓ了让行ؓ发生QEJB 2.1规范定义了一个Bean必须遵守的严格的lg模型。每一个EJBcdM某一U抽象类中承,qؓ容器提供了回调的钩子。既然Java只支持单l承Q严格组件模型就限制了开发者用EJBlg创徏一个复杂对象结构的能力。当把复杂的应用数据映射到实?Bean中的时候,正如我们在第二部分中看到的,q会成ؓ一个很大的问题?/p> <p>  在EJB 3.0中,所有的容器服务都可以通过使用注释的POJO应用来配|和交付。大多数情况下,q不需要特D的lgcR让我们通过JBoss EJB 3.0 TrailBlazerCZ看一下如何在EJB 3.0中用注释?/p> <p>  <strong>开发藕合松散的服务对象</strong></p> <p>  像Java EEq样的企业中间件的一个最重要的好处是允许开发者用藕合松散的lg来开发应用。这些组件仅仅通过他们自己发布的商业接口来藕合。因此这些组件的实现cd以在不改变应用其余部分的情况下改变自q实现。这会使应用更加强壮,更容易测试,更易UL。EJB 3.0使得在POJO中创合松散的商业lg变得更简单了?/p> <p>  <strong>Session bean</strong></p> <p>  在EJB 3.0应用中,藕合松散的服务组件的典型应用是Session Bean。一个Session Bean臛_有一个接?也就?商业接口)Q其它应用组仉过它获得服务。下面的代码为我们的投资计算器服务提供了商业接口。它只有一个方法,Ҏl定的v始年龄,l止q龄Q增长率Q月存金额,计算出L资额?/p> <p>public interface Calculator {<br />   public double calculate (int start, int end, <br />                 double growthrate, double saving);<br /> }</p> <p>  Session beancȝ单地实现了商业接口。你必须通过使用Stateless或Stateful注释来告诉EJB 3.0容器q个POJOcL一个Session Bean。有状?Stateful)的session bean在不同的服务h间维护着客户的状态。相反地Q对于无状?Stateless)的session beanQ每ơ的h都是被随机挑选的session bean实例处理的。这些行为是与EJB 2.1规范中的有状态和无状态session bean的定义是一致的。EJB 3.0容器出何时实例化Bean对象Qƈ通过商业接口让其可用。下面是session bean实现cȝ代码:<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 />   public double calculate (int start, int end, <br />                     double growthrate, double saving) {<br />     double tmp = Math.pow(1. + growthrate / 12., <br />                           12. * (end - start) + 1);<br />     return saving * 12. * (tmp - 1) / growthrate;<br />   }<br /> }</td> </tr> </tbody> </table> </p> <p>  你也可以Z个session bean指明多个接口-一个ؓ本地客户服务Q一个ؓq程客户服务。只要用@Local和@Remote注释来区分。下面的代码片断昄了同时实C本地和远E接口的CalculatorBean。如果你没有@Local和@Remote注释Qsession 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>  public double calculate (int start, int end, <br />                            double growthrate, double saving) {<br />     double tmp = Math.pow(1. + growthrate / 12., 12. * (end - start) + 1);<br />     return saving * 12. * (tmp - 1) / growthrate;<br />   }</p> <p>  public String getServerInfo () {<br />     return "This is the JBoss EJB 3.0 TrailBlazer";<br />   }<br /> }</p> </td> </tr> </tbody> </table> </p> <p>  Session bean用户通过JNDI得到bean的一个存?Stub)对象。容器所提供的存根对象实Csession bean的商业接口。所有针对存根的调用都被引向了容器,由容器调用相应的实现cM的接口。对于有状态的的session beanQ你必须自己在客L~存存根对象Q这样在每次的后l调用时Q容器才知道要提供相同的的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>  到藕合松散的目的Q应用把session bean实例的创建、缓存、销毁全部交lEJB 3.0容器(也就是,反向控制设计模式)。应用只和bean的商业接口打交道?/p> <p>  但如果应用需要对session对象更好的控制呢?比如_应用可能需要在创徏session bean的时候初始化数据库联接,而在销毁bean时关闭外部的联接。上q这些,你都可能通过在beancM定义生命周期的回调方法来实现。这些方法将会被容器在生命周期的不同阶段调用(?创徏或销毁时)。通过使有下面所列的注释QEJB 3.0允许你将MҎ指定为回调方法。这不同于EJB 2.1QEJB 2.1中,所有的回调Ҏ必须实现Q即使这是空的。EJB 3.0中,bean可以有Q意数量,L名字的回调方法?/p> <p>  @PostConstruct:当bean对象完成实例化后Q用了q个注释的方法会被立卌用。这个注释同旉用于有状态和无状态的session bean?/p> <p>  @PreDestroy:使用q个注释的方法会在容器从它的对象池中销毁一个无用的或者过期的bean实例q前调用。同旉用于有状态和无状态的session bean.</p> <p>  @PrePassivate:当一个有状态的session bean实例I闲q长的时_容器会钝化它,q把它的状态保存下来。用这个注释的Ҏ会在容器钝化bean实例之前调用。适用于有状态session bean?/p> <p>  @PostActivate:当客L再次使用已经被钝化的的有状态session beanӞ新的实例被创建,状态被恢复。用此注释的session bean会在bean的激zd成时调用?/p> <p>  @Init:q个注释指定了有状态session bean初始化的Ҏ。它区别于@PostConstruct注释在于:多个@Init注释Ҏ可以同时存在于有状态session bean 中,但每个bean实例只会有一个@Init注释的方法会被调用。这取决于bean是如何创建的(l节LEJB 3.0规范)。@PostConstruct在@Init之后被调用?/p> <p>  另一个有用的生命周期Ҏ注释是@RemoveQ特别是对于有状态session bean。当应用通过存根对象调用使用了@Remove注释的方法时Q容器就知道在该Ҏ执行完毕后,要把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>    // ... ...<br />     <br />     @PostConstruct<br />     public void initialize () {<br />         // Initializes the history records and load<br />         // necessary data from database etc.<br /> // 初始化历史记录,q从数据库中装入必需的数据?br />     }  <br />     <br />     @PreDestroy<br />     public void exit () {<br />         // Save history records into database if necessary.<br /> // 如有必要则将历史记录保存x据库?br />     }   <br />     <br />     @Remove<br />     public void stopSession () {<br />         // Call to this method signals the container<br />         // to remove this bean instance and terminates<br />         // the session. The method body can be empty.<br /> // 调用q个Ҏ来通知容器bean实例U除q中止session.<br /> // q个Ҏ可以为空?br />     }<br />     <br />     // ... ...<br /> }</p> </td> </tr> </tbody> </table> </p> <p>   <strong>消息驱动bean</strong></p> <p>  Session bean服务提供了同步调用的Ҏ。另一个重要的藕合松散服务cd是一U通过q入的消息来触发的异步服?比如:email或Java消息服务产生的消?。EJB 3.0的消息驱动bean(MDB)是设计用来专门处理基于消息请求的lg?/p> <p>  一个MDBcdd现MessageListener接口。当容器到bean守候的队列一条消息时Q就调用onMessage()ҎQ将消息作ؓ参数传入。MDB在OnMessage()中决定如何处理该消息。你可以用注释来配置MDB侦听哪一条队列。当MDB部vӞ容器会用到其中的注释信息。在下面的例子中QCalculatorBean MDB会在JMS队列queue/mdb有消息进入时调用。MDB解析消息QƈҎ消息内容计算投资?br /> <br /> <table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt=""> <tbody> <tr> <td> @MessageDriven(activateConfig =<br /> {<br />   @ActivationConfigProperty(propertyName="destinationType",<br />     propertyValue="javax.jms.Queue"),<br />   @ActivationConfigProperty(propertyName="destination",<br />     propertyValue="queue/mdb")<br /> })<br /> public class CalculatorBean implements MessageListener { <p>  public void onMessage (Message msg) {<br />     try {<br />       TextMessage tmsg = (TextMessage) msg;<br />       Timestamp sent =<br />           new Timestamp(tmsg.getLongProperty("sent"));<br />       StringTokenizer st =<br />           new StringTokenizer(tmsg.getText(), ",");</p> <p>      int start = Integer.parseInt(st.nextToken());<br />       int end = Integer.parseInt(st.nextToken());<br />       double growthrate = Double.parseDouble(st.nextToken());<br />       double saving = Double.parseDouble(st.nextToken());</p> <p>      double result =<br />           calculate (start, end, growthrate, saving);<br />       RecordManager.addRecord (sent, result);</p> <p>    } catch (Exception e) {<br />       e.printStackTrace ();<br />     }<br />   }</p> <p>  // ... ...<br /> }</p> </td> </tr> </tbody> </table> </p> <p>  依赖注入</p> 在上一节中Q你学到了如何开发藕合松散的服务lg。但是,Z存取那些服务对象Q你需要通过服务器的JNDI来查扑֭根对?session bean)或消息队?MDB)。JNDI查找是把客户端与实际的服务端实现解藕的关键步骤。但是,直接使用一个字W串来进行JNDI查找q不优雅。有q样几个原因: <p>  客户端与服务端必L一致的Z字符串的名字。它没有在编译时得到认证或在布v时得到检查?/p> <p>  从JNDIq回的服务对象的cd没有在编译时q行查,有可能在q行时出现{?casting)错误?/p> <p>  冗长的查找代码,有着自己的try-catch代码块,在应用之间是重复的和杂ؕ?/p> <p> EJB 3.0Q对MPOJO,提供了一个简单的和优雅的Ҏ来解藕服务对象和资源。用@EJB注释Q你可以EJB存根对象注入CQ何EJB 3.0容器理的POJO中。如果注释用在一个属性变量上Q容器将会在它被W一ơ访问之前赋值给它正的倹{下面的例了演示了怎样把CalculatorBean无状态session bean的存Ҏ入到CalculatorMDB MDBcM?/p> <p>public class CalculatorMDB implements MessageListener {</p> <p>  @EJB Calculator cal;<br />   <br />   // Use the cal variable<br />   // ... ...<br /> }</p> <p>  注释如果被用在JavaBean风格的setterҎ上时Q容器会在属性第一ơ用之前,自动地用正确的参数调用bean的setterҎ。下面的片断演示了这是如何做?<br /> <br /> <table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt=""> <tbody> <tr> <td> public class CalculatorMDB implements MessageListener { <p>  Calculator cal;<br />   <br />   @EJB<br />   public void setCal (Calculator cal) {<br />     this.cal = cal;<br />   }<br />   <br />   // Use the cal variable<br /> // 使用cal变量<br />   // ... ...<br /> }</p> </td> </tr> </tbody> </table> </p> <p>  除@EJB注释之外QEJB 3.0也支持@Resource注释来注入来自JNDI的Q何资源。下面的例子中,我演CZ如何注入服务器端默入的TimerService和SessionContext对象Q也演示了如何注入来自JNDI的命名数据库和JMS资源?br /> <br /> <table bordercolor="#cccccc" cellspacing="0" cellpadding="1" width="80%" align="center" bgcolor="#ffffff" border="1" heihgt=""> <tbody> <tr> <td> @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>  此外Q你也可以把一个容器管理的持久化管理器(也就是,EntityManager-cM于Hibernate session对象)注入到EJB 3.0 POJO中?/p> <p>  把容器服务交lPOJO</p> <p>  除了理生命周期和访问藕合松散的服务对象外,EJB 3.0通过单的注释也ؓPOJO提供了运行时L务?/p> <p>  <strong>事务</strong></p> <p>  最有用的容器服务可能就是事务管理服务,当应用出现失败或异常Ӟ它保证了数据库的完整性。你可以单地ؓ一个POJOҎx它的事务属性。这样容器就可以在合适的上下文中q行q个Ҏ。D例来_下面的代码申明了容器在运行updateExchangeRate()时必dZ个新的事务。当q个Ҏ退出时提交事务。实际上Q所有在updateExchangeRate()中被调用的方法都在此事务中运行,除非有特别申明。在updateExchangeRate()中的数据库操作要么全部成功,要么全部p|?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>  // ... ...</p> <p>  @TransactionAttribute(TransactionAttributeType.REQUIRED)<br />   public void updateExchangeRate (double newrate) throws Exception {<br />     // Update the database in a loop.<br /> // 在@环中更新数据?br />     // ... ...<br />     // The operations in the loop must all be successful or<br />     // the database is not updated at all.<br /> // 循环中的操作必须全部成功或者根本不更新?br />   }<br /> }</p> </td> </tr> </tbody> </table> </p> <p>  <strong><a class="channel_keylink" target="_blank">安全</a></strong></p> <p>  容器也提供了<a class="channel_keylink" target="_blank">安全</a>服务来进行用戯证和Ҏ用户规则来限制对POJO的访问。对每一个POJO来说Q你可以通过使用@SecurityDomain注释为它指定一个安全域, 安全域告诉容器到哪里L密码和用戯色列表。JBoss中的other域表明文件是classpath中的users.propertes和roles.properties。这PҎ一个方法来_我们可以使用一个安全限制注释来指定谁可以运行这个方法。比如,下面的例子,容器Ҏ有试图调用addFund()的用戯行认证,只允许拥有AdminUser角色的用户实际运行它。如果你没有d或者没有以理员的w䆾dQ一个安全意外将会抛出?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>  @RolesAllowed()<br />   public void addFund (String name, double growthrate) {<br />     // ... ...<br />   }</p> <p>  @RolesAllowed()<br />   public void addInvestor (String name, int start, int end) {<br />     // ... ...<br />   }</p> <p>  @PermitAll<br />   public Collection <Fund> getFunds () {<br />     // ... ...<br />   }<br />   <br />   // ... ...</p> <p>  @RolesAllowed()<br />   public double calculate (int fundId, int investorId, <br />                                        double saving) {<br />     // ... ...<br />   }<br /> }</p> </td> </tr> </tbody> </table> </p> <p>  通用拦截?/p> <p>  事务和安全服务都可以被看作是容器理的运行时L截器。容器拦截了对EJB存根的调用,q在其上应用事务上下文或q行安全限制?/p> <p>  在EJB 3.0中,你可以自己写拦截器来扩展容器服务。用@AroundInvoke注释Q你可以Q意beanҎ作ؓ拦截器方法在LbeanҎ之前和之后运行。下面的例子中,log()Ҏ是一个拦截器Q它计算和记录了其它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>  // Bean methods that are to be intercepted by "log()"<br />   // beanҎ被log()Ҏ拦截<br /> // <br />   // ... ...<br />   <br />   @AroundInvoke<br />   public Object log (InvocationContext ctx)<br />                             throws Exception {</p> <p>    String className = ctx.getBean().getClass().getName();<br />     String methodName = ctx.getMethod().getName();<br />     String target = className + "." + methodName + "()";</p> <p>    long start = System.currentTimeMillis();<br />     System.out.println ("Invoking " + target);<br />     try {<br />       return ctx.proceed();<br />     } catch(Exception e) {<br />       throw e;<br />     } finally {<br />       System.out.println("Exiting " + target);</p> <p>      cal.setTrace(cal.getTrace() + "<br /> " +<br />                    "Exiting " + target);<br />       long time = System.currentTimeMillis() - start;<br />       System.out.println("This method takes " +<br />                           time + "ms to execute");<br />     }<br />   }</p> </td> </tr> </tbody> </table> </p> <img src ="http://www.tkk7.com/zzs/aggbug/257037.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zzs/" target="_blank">ID刀</a> 2009-02-27 15:09 <a href="http://www.tkk7.com/zzs/articles/257037.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>E序员应用EJB 3.0必要的准?http://www.tkk7.com/zzs/articles/257025.htmlID刀ID刀Fri, 27 Feb 2009 06:49:00 GMThttp://www.tkk7.com/zzs/articles/257025.htmlhttp://www.tkk7.com/zzs/comments/257025.htmlhttp://www.tkk7.com/zzs/articles/257025.html#Feedback0http://www.tkk7.com/zzs/comments/commentRss/257025.htmlhttp://www.tkk7.com/zzs/services/trackbacks/257025.htmlhttp://java.chinaitlab.com/EJB/356292.html

EJB 3.0极其重视开发的易性,q调整了模型。这l非巧合Q因范的主要设计者:Linda DeMichiel选择了广泛听取外界的意见Qƈ借鉴TopLink{品所取得的经验。这样一来,q项规范可以沿着已经由流行、得到公认的技术开辟出来的道\前进Q而这些道路实际上成了业内事实上的最佛_c?

  那么Q作为程序员的你Q面Ҏ的规范,该做哪些准备呢?

  处理好架构问?/strong>

  首先要确保你的架构可以利用持久性方面的标准及认可的设计模式。实际上Q这可能需要改动你的应用程序,不过如果你期望应用程序能l得h间的考验Q那么进行这U投入是值得的。用会话外观、数据访问对象(DAOQ层或者服务层L好主意,不过在这里它们都臛_重要。如果你的应用程序已l用远E实体构成——虽然这U做法ƈ不常见,那么需要重新设计架构。访问持久性对象之前,应当先部|可q程化服务层。如果要使用实体Q它应当完全是本地实体?

  不过Q用本地实体不是目的,因ؓ实体qؓ部v人员提供了ؓ实体声明事务?a class="channel_keylink" target="_blank">安全需求的功能。EJB 3.0不允怓Q何这些属性在实体层面q行讑֮。相反,实体的运行环境将p用者来定Q所以所需的Q何事务或?a class="channel_keylink" target="_blank">安全环境由负责闭的J2EElg来安装或者声明?

  CMP应用E序

  如果你已l是容器理持久性(CMPQ用P那么你可能迫不及待地惌得新Ҏ,希望抛弃无关的接口、不必要的bean代码以及J琐的XML部v描述W,q些是与以前的实体bean开发相关的一些烦人问题。分别要扩展EJBObject和EJBLocalObject的远E和本地接口再也不需要了Q现在实体只要实现普?a class="channel_keylink" target="_blank">Java接口QPOJIQ即可,如果它们选择q么做的话?

  其次Q你可能在想如何更容易地在容器中部vEJBQ或者甚x本不用部|Ԍ而是在独立环境中的容器外面进行测试。因为实体是具体的普?a class="channel_keylink" target="_blank">Java对象QPOJOQ,你就可以像一直以来创建Java对象的方式那P即用new()来创建?

  POJO应用E序

  可以通过实体理器(EntityManagerQ访问大部分新的持久性API。实体管理器可以注入C话bean里面Q或者用Java命名和目录接口(JNDIQ进行查询。实体管理器代表事务的持久性上下文。一旦发现操作单元或者实体管理器理的对象在事务l束?#8220;很脏”Q就会被写到外面的数?a class="channel_keylink" target="_blank">存储区?

  应用E序可以通过抽取含有操作单元/会话工gQartifactQ的代码Q让自己不受全面变化的媄响。这样一来,可以通过可插入方式来获得所用的实际会话。定义会话、然后允许包围层把它与外界隔d来,q类似EJB 3.0容器所采用的依赖注入范例(dependency injection paradigmQ。应用程序中使用的所有资源应当采用这U模式。在EJB 3.0中,标准资源由应用E序声明Q随后在q行时被注入到bean里面?

  采用标准Ҏ?/strong>

  EJB 3.0的许多特性可以在TopLink存在已久的特性当中找到媄子。只要用这些特性,你就能够拥有EJB 3.0的功能,虽然APIq没有完成?

  查询是q样一个方面,你现在可以开始用EJB 3.0的特性。EJB 3.0查询可以从实体管理器获得Qƈ且可以在上面执行。可以在你需要直接查询SLQ、ƈ通过查询q回对象的少数情况下Q创建本地SQL查询?

  查询语言往往是造成q移问题的根源,因ؓ不编写实质性或者穷举性的转换分析工具Q就很难实现自动转换。EJB查询语言q种合理、有效的Ҏ可对关系查询语言q行抽象处理Q将受益于新增的几项Ҏ。现有的EJB查询语言仍可以适用Q不qEJB查询语言斚w的更多构件和功能进一步改q查询语a。用EJB查询语言~写查询是明智之DQ因为查询语a不会出现重大改变Q除了功能上有所d外?

  l承

  EJB 2.1从来没有指定真正的、自然的l承。实际上Q只有在厂商不设|障的情况下才有可能实现承,不过仍很隑֮义及理。EJB 3.0却不会这栗由于具体的Java对象能够彼此l承Q也用不着定义U束l承范围的方法,所以你能够创徏L深度及广度的实体l承层次?

  目前可以通过TopLink Mapping Workbench或JDeveloper、映Java对象的GUI工具以及用于映射对象的基于Java的APIQ获得同Lq种灉|性。现在你可以创徏域模型(domain modelQ,以遵守适合你应用程序的l承{略Q而不必等规范发布?

  乐观锁定

  TopLink支持的乐观锁定(optimistic lockingQ模型现在将被采用到EJB 3.0模型里面。这U机制对应用E序非常有用Q不仅仅是因为在?写访问比通常?0Q?0的情况下Q它可以大大提高性能Q还因ؓ它有助于获得Cpȝ所需的那U可扩展架构。业界的众多应用E序使用q种主要的锁定范例,来获得Web应用E序所需的可扩展性。只要用简单方法:为每个乐观锁定的对象采用数据库列和对象版本字D,很Ҏ获得可移植性?

  q种锁定带来了另外的好处Q能够用非q接模式的对象。只要把数据重新q入事务、然后通过乐观锁值验证已改动的对象是不是失效副本Q就很容易支持在ȝ状态下改动数据和关pȝ功能?

  对象Q关pL?/strong>

  想编写面向对象的JavaE序Q却把数据保存在关系数据库里面,q在以前是困扰应用程序开发的一个重大问题?

  军_把用于对象关pL的标准化元数据和语义添加到EJB 3.0内,q向实现下列功能q出了一大步Q让应用E序能够灉|地把应用E序攑֜不同数据库上面运行,甚至可以使用不同的持久性框架来q行q行。对象-关系映射标准的第一个阶D将包括如今Z用来映射域模型的几种最行的映方法,譬如数据转换和一对一及多对多关系{。随后还会添?#8220;高”映射Ҏ?/p>

ID刀 2009-02-27 14:49 发表评论
]]>
EJB 3.0的三大类型详?http://www.tkk7.com/zzs/articles/257021.htmlID刀ID刀Fri, 27 Feb 2009 06:35:00 GMThttp://www.tkk7.com/zzs/articles/257021.htmlhttp://www.tkk7.com/zzs/comments/257021.htmlhttp://www.tkk7.com/zzs/articles/257021.html#Feedback0http://www.tkk7.com/zzs/comments/commentRss/257021.htmlhttp://www.tkk7.com/zzs/services/trackbacks/257021.htmlhttp://java.chinaitlab.com/EJB/356299.html

无论你唇╞ean会话是ؓ了执行特定Q务,q是把表映射到实体bean以更新数据,都可以用普通的Java对象和接口来完成q些工作Qƈ且可以通过在业务方法中使用注释Q把Ҏ提供l客L?

  Enterprise JavaBean (EJB) 是可重用的、可UL?J2EE lg。EJB 由封装业务逻辑的方法组成。譬如说QEJB 可能有这L业务逻辑Q包含了更新数据库中客户数据的方法。众多远E和本地客户端可以调用该Ҏ。另外,EJB 在容器里面运行,q样开发h员只要关注bean里面的业务逻辑Q不必担心复杂、容易出错的问题Q譬如事务支持?a class="channel_keylink" target="_blank">安全性和q程对象讉K{。EJB 作ؓ普通Java对象QPOJOQ的形式来开发,开发h员可以用元数据注释Qmetadata annotationsQ来指定容器如何理q些bean?

  EJB 包括三种主要cdQ会?bean、实?bean和消息驱动的bean。会话bean执行独立的、解除耦合的Q务,譬如查客L信用记录。实体bean是一个复杂的业务实体Q它代表数据库中存在的业务对象。消息驱动的bean用于接收异步JMS 消息。下面,让我们进一步研IEJB 3.0规范中的q些cd?

  一、会话bean

  会话bean通常代表业务程里面的操作,譬如“处理订单”。可Ҏ对话状态的保持性,x状态和无状态对会话beanq行分类?

  无状态的会话 bean没有内部状态。它们不跟踪记录从一个方法调用传递到另一个方法调用的信息。因此,每次调用无状态的业务Ҏ都独立于前一ơ调用,譬如计算E款或者运贏V用某个应税D用计税ƄҎӞ对税ƑրD行计ƈq回l调用方法,而不必保存调用者的内部状态供以后调用。因些beanq不保持状态,所以容器对它们q行理很单。客Lh无状态的bean实例Ӟ可以从容器保持的无状态的会话bean 实例池当中接收一个实例。另外,因ؓ无状态的会话 bean可以׃nQ所以容器可保持数量较少的实例ؓ许多客户端提供服务。想指定Java Bean作ؓ无状态的会话bean加以部v及管理,只需要ؓ该beand注释@Stateless?

  有状态的会话 bean在方法调用时可保持对话状态,譬如客户的网上购物R。客户开始网上购物时Q可以从数据库中索客L详细信息。客户往购物车里面添加商品或者从里面删除商品、下订单{时调用的其他方法也可以使用q些详细信息。不q,有状态的会话bean是暂时性的Q因为出C话终止、系l崩溃或者网l故障后Q状态不复存在。客Lh有状态的会话bean实例Ӟ׃ؓ该客L分配一个有状态的实例Qƈ客户端保持该lg的状态。要指定容器在某个方法完成后删除有状态的会话bean实例Q只要ؓ该方法添加注释@Remove?

  会话 beanCZ如下Q?

import javax.ejb.Stateless.*;

/*A simple stateless session bean implementing the incrementValue() method of the * CalculateEJB interface.*/

@Stateless(name="CalculateEJB")

public class CalculateEJBBean

implements CalculateEJB

{

int value = 0;

public String incrementValue()

{

value++;

return "value incremented by 1";

}

}

  二、实体bean

  实体bean是管理持久性数据的一个对象,有可能用几个相关的Java对象Qƈ可以通过主键实现惟一性。通过d@Entity注释Q可以把某类指定为实体bean。实体bean代表数据库中的持久性数据,如客戯中的一行或者员工表中的一条员工记录。实体beanq可以在多个客户端之间共享。譬如说Q某个员工实体bean可以由多个客L用于计算某员工的q薪或者更新员工地址。实体bean对象的特定字D可以成为持久性字Dc实体bean中没有被@Transient注释标记的所有字D都被视为持久性字DcEJB 3.0的一个主要特性就是,能够使用元数据注释来创徏包含对象/关系映射的实体bean。譬如说Q想指定把实体bean的empId字段映射?Employees表中的EMPNO属性,p使用@Table(name="Employees") 来注释表名,使用 @Column(name="EMPNO") 来注释字D,如下面的例子所C。另外,EJB 3.0 的一个特性是Q在开发期间可以方便地试实体beanQ因为现在?Oracle 应用服务?/a>实体试工具Q就可以在容器外面运行实体bean?

  实体 beanCZ如下Q?

import javax.persistence.*;

import java.util.ArrayList;

import java.util.Collection;

@Entity

@Table(name = "EMPLOYEES")

public class Employee implements java.io.Serializable

{

 private int empId;

 private String eName;

 private double sal;

 @Id

 @Column(name="EMPNO", primaryKey=true)

 public int getEmpId()

{ return empId;}

 public void setEmpId(int empId)

{ this.empId = empId; }

 public String getEname()

{ return eName; }

 public void setEname(String eName)

{ this.eName = eName; }

 public double getSal()

{ return sal; }

 public void setSal(double sal)

{ this.sal = sal; }

 public String toString()

{StringBuffer buf = new StringBuffer();

buf.append("Class:")

.append(this.getClass().getName()).append(" ::") .append(" empId:").append(getEmpId()).append(" ename:") .append(getEname()).append("sal:").append(getSal());

return buf.toString();}

}

  三、消息驱动的bean

  消息驱动的beanQMDBQؓ实现异步通信提供了一U比使用直接的Java消息服务QJMSQ更单的Ҏ。MDB用于接收异步JMS消息。容器处理JMS队列和主题所需的大部分讄q程。它把所有消息发送给相关的MDB。MDB允许J2EE应用E序发送异步消息,随后q些消息由应用程序来处理。要把bean指定为MDBQ需要实现javax.jms.MessageListener接口Qƈ且用@MessageDriven注释该bean?

  消息驱动的beanCZ如下Q?

import javax.ejb.MessageDriven;

import javax.ejb.ActivationConfigProperty;

import javax.ejb.Inject;

import javax.jms.*;

import java.util.*;

import javax.ejb.TimedObject;

import javax.ejb.Timer;

import javax.ejb.TimerService;

@MessageDriven(

activationConfig = {

@ActivationConfigProperty(propertyName="connectionFactoryJndiName",

 propertyValue="jms/TopicConnectionFactory"),

@ActivationConfigProperty(propertyName= "destinationName", propertyValue="jms/myTopic"),

@ActivationConfigProperty(propertyName= "destinationType", propertyValue="javax.jms.Topic"),

@ActivationConfigProperty(propertyName= "messageSelector", propertyValue="RECIPIENT = 'MDB'") } )

/** 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

* prints the contents of the message. */

public class MessageLogger implements MessageListener, TimedObject

{

 @Inject javax.ejb.MessageDrivenContext mc;

 public void onMessage(Message message)

 { System.out.println("onMessage() - " + message);

 try

 {

 String subject = message.getStringProperty("subject");

 String inmessage = message.getStringProperty("message");

 System.out.println("Message received\n\tDate:" + new java.util.Date() + "\n\tSubject:" + subject + "\n\tMessage:" + inmessage + "\n");

 System.out.println("Creating Timer a single event timer");

 TimerService ts = mc.getTimerService();

 Timer timer = ts.createTimer(30000, subject);

 System.out.println("Timer created by MDB at:" + new Date(System.currentTimeMillis()) +" with info:"+subject); }

 catch (Throwable ex)

 { ex.printStackTrace(); }

}

 public void ejbTimeout(Timer timer)

 { System.out.println("EJB 3.0:Timer with MDB");

 System.out.println("ejbTimeout() called at:" + new Date(System.currentTimeMillis()));

 return; }

}

  四、?EJB 3.0

  EJB客户端是讉Kbean的应用程序。它不必位于客户端层上,但可以是独立的应用程序、Java服务?/a>面QJSPQ、服务器程序或者另一个EJB。客L通过bean的远E或本地接口来用EJB的方法,q程q是本地取决于客L是在同一个JVM里面q是不同的JVM里面。这些接口定义了bean的方法,而beanc负责实际实现这些方法。客L讉KbeancȝҎӞ容器׃为bean生成一个代理,名ؓq程或者本地对象。远E或者本地对象接收请求后Q交l相应的bean实例Qƈ结果返回给客户端。想调用bean的方法,客户端需要通过使用EJB部v描述W(deployment descriptorQ里面定义的bean名称来找到该bean。在以下的示例中Q客L使用Context对象扑ֈ名ؓ“Statelessejb”的bean?

  EJB 客户端示例如下:

import javax.naming.Context;

import javax.naming.InitialContext;

/* A simple bean client which calls methods on a stateless session bean.*/

public class CalculateejbClient

{

public static void main(String [] args)

{

 Context context = new InitialContext();

 CalculateEJB myejb =(CalculateEJB)context.lookup ("java:comp/env/ejb/CalculateEJB");

myejb.incrementValue(); }

}



ID刀 2009-02-27 14:35 发表评论
]]>
EJB 3.0学习W记一:开发环境搭?http://www.tkk7.com/zzs/articles/257009.htmlID刀ID刀Fri, 27 Feb 2009 06:04:00 GMThttp://www.tkk7.com/zzs/articles/257009.htmlhttp://www.tkk7.com/zzs/comments/257009.htmlhttp://www.tkk7.com/zzs/articles/257009.html#Feedback0http://www.tkk7.com/zzs/comments/commentRss/257009.htmlhttp://www.tkk7.com/zzs/services/trackbacks/257009.html来源Q?a style="color: #339966" >http://java.chinaitlab.com/EJB/757956.html

一、开发环境选择


    IDEQNetBeans IDE 6.0.1
    SERVER:Sun Application Server(9.0)

二、安装NetBeans


    我用的是NetBeans IDE 6.0.1Q大家可以从sum公司|站下蝲。安装过E很单,只需要点“下一?#8221;?nbsp;OK了,需要注意的是在选择要安装的应用服务?/a>的时候,选择GlassFish V2 URLQ这是Sun公司在NetBeans里集成的一个应?a class="channel_keylink" target="_blank">服务?/a>Q其实也是QSun Application Server.
                    

        安装完成后启动NetBeans IDE 6.0.1,不知道是什么原?当一启动IDE和应用服务器后电脑暴?q程java.exe占用内存?20M之大,不知道那位朋友可有什么好的解x?知道的文章下面留a告诉?谢谢.
                      

三、徏立EJBcd


    新徏一cdEJB3.0,开发EJB所需要的jar包导入便OK。详l步骤如下:菜单中的“工具”选项里选择“?#8221;Q在弹出的窗体中建立新库q命名ؓEJB3.0, 然后EJB所需要的 jar?所有的jar包都可以在GlassFish的安装目录下的lib目录?导入到此cd里便OK?br />              

四、启动应用服务器


      启动服务器很单,在菜单里选择“H口”里面?#8220;服务”选项Q在弹出的窗体里选中“服务?#8221;Q点开子节点,里面有个GlassFish V2的选项Q右?->启动?br />                                                  

        OKQ到q里我们的准备工作算是告一D落了,我们来测试下服务器是否可以正常启动?nbsp;打开览器,在地址栏里输入Qhttp://localhost:4848,看是不是出来如下d界面?nbsp; 
               

     输入用户名和密码登陆试试?br />      User Name:admin 
     Passwrod:adminadminQ成功登录后的控制界面如下所C:


       EJB开发的环境搭徏基本上就搭徏好了Q本文就此结?/p>

ID刀 2009-02-27 14:04 发表评论
]]>
վ֩ģ壺 ޳ߵӰɫ| ԻȫƵ߹ۿ| վС˵| ĻӰѹۿ| ɫ߳Ƶ| ߾ƷaaaƬ| ߹ۿһ| avһ| þþƷav| ޾Ʒ߹ۿ̬ͼ| avһ| èwww˳| ŷɫƵ߹ۿ| Ƶ߹ۿ| Ƶ߹ۿ| ҹѹۿ| ŷaԴ| ass**ëpics| ӰԺ߲| ޸߹ۿ| AV뾫ƷһٶӰԺ| 츾þþ| Ƶ| ұͨӰƬ߲| Ѵվ߿| һɫëƬ| ޹ƷۺϾþ| aëƬѧѹۿ | ޾Ʒþþþϼ| ֳִִˬƵ| ѵӰ| ѹھƷþþþӰԺ| պ޾Ʒ| ޾ƷƬ߹ۿ| 4338ȫɫվ| þþƷA㽶 | һƵѹۿ| ˹ѳƵ| պAVһl| þþþŮʦһ| յӰ߲Ѱ|