国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

不需要應(yīng)用服務(wù)器的J2EE

2019-11-18 12:43:57
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  例子:消息驅(qū)動(dòng)Bank

  為了闡述我們的觀點(diǎn),我們將開(kāi)發(fā)和安裝一個(gè)完整的樣板應(yīng)用程序:一個(gè)消息驅(qū)動(dòng)的銀行系統(tǒng). 通過(guò)(幸虧有SPRing)改進(jìn)的基于POJOs的編程模型和保留相同的事務(wù),我們可以不需要EJB或者一個(gè)應(yīng)用服務(wù)器來(lái)實(shí)現(xiàn)這個(gè)系統(tǒng)。在下一個(gè)部分,我們將從消息驅(qū)動(dòng)架構(gòu)產(chǎn)生到另一個(gè)架構(gòu).就像基于WEB的架構(gòu)一樣.圖1展示我們的樣本應(yīng)用程序的架構(gòu).  

不需要應(yīng)用服務(wù)器的J2EE(圖一)


  Figure 1. Architecture of the message-driven bank

  在我們的例子中,我們將處理來(lái)自java消息服務(wù)隊(duì)列的銀行定單.一張定單的處理包括通過(guò)JDBC來(lái)更新當(dāng)前帳戶的數(shù)據(jù)庫(kù).為了避免信息的丟失和重復(fù),我們將使用JTA和JTA/XA事務(wù)來(lái)配合更新:處理信息和更新數(shù)據(jù)庫(kù)將發(fā)生在一個(gè)原子事務(wù)里.資源部分可得到JTA/XA的更多信息.

  編寫(xiě)應(yīng)用程序代碼

  該應(yīng)用程序?qū)⒂蓛蓚€(gè)JAVA類(lèi)組成: Bank(一個(gè)DAO)和MessageDrivenBank.如圖2.

不需要應(yīng)用服務(wù)器的J2EE(圖二)


  Figure 2. Classes for the message-driven bank

  Bank是一個(gè)數(shù)據(jù)訪問(wèn)對(duì)象,這個(gè)對(duì)象封裝數(shù)據(jù)庫(kù)訪問(wèn)。MessageDrivenBank是一個(gè)消息驅(qū)動(dòng)façade并且是DAO的委托.與典型的J2EE方法不同,這個(gè)應(yīng)用程序不包括EJB類(lèi).

  第一步:編寫(xiě)B(tài)ank DAO

  如下, Bank源代碼是很直接和簡(jiǎn)單的JDBC操作.

package jdbc;
import javax.sql.*;
import java.sql.*;
public class Bank
{
  private DataSource dataSource;
  public Bank() {}
  public void setDataSource ( DataSource dataSource )
  {
    this.dataSource = dataSource;
  }

private DataSource getDataSource()
  {
    return this.dataSource;
  }

  private Connection getConnection()
  throws SQLException
  {
    Connection ret = null;
    if ( getDataSource() != null ) {
        ret = getDataSource().
              getConnection();
    }
    return ret;
  }

  private void closeConnection ( Connection c )
  throws SQLException
  {
    if ( c != null ) c.close();
  }
    
  public void checkTables()
  throws SQLException
  {
        
    Connection conn = null;
    try {
      conn = getConnection();
      Statement s = conn.createStatement();
      try {
        s.executeQuery (
        "select * from Accounts" );
      }
      catch ( SQLException ex ) {
        //table not there => create it
        s.executeUpdate (
        "create table Accounts ( " +
        "account VARCHAR ( 20 ), " +
        "owner VARCHAR(300), " +
        "balance DECIMAL (19,0) )" );
        for ( int i = 0; i < 100 ; i++ ){
          s.executeUpdate (
          "insert into Accounts values ( " +
          "'account"+i +"' , 'owner"+i +"', 10000 )"
          );
        }
      }
      s.close();
      }
      finally {
        closeConnection ( conn );

      }

      //That concludes setup
  }

    
  //
  //Business methods are below
  //

  public long getBalance ( int account )
  throws SQLException
  {
        
    long res = -1;
    Connection conn = null;

    try {
      conn = getConnection();
      Statement s = conn.createStatement();
      
      String query =
      "select balance from Accounts where account='"+
      "account" + account +"'";
      
      ResultSet rs = s.executeQuery ( query );
      if ( rs == null !rs.next() )
        throw new SQLException (
        "Account not found: " + account );
      res = rs.getLong ( 1 );
      s.close();
    }
    finally {
        closeConnection ( conn );
    }
    return res;
        
  }

  public void withdraw ( int account , int amount )
  throws Exception
  {
    Connection conn = null;

    try {
      conn = getConnection();
      Statement s = conn.createStatement();

      String sql =
      "update Accounts set balance = balance - "+
      amount + " where account ='account"+
      account+"'";
      
      s.executeUpdate ( sql );
      s.close();
    
    }
    finally {
        closeConnection ( conn );

    }
  }
}


  注重:代碼并沒(méi)有依靠EJB或任何專(zhuān)門(mén)的應(yīng)用程序服務(wù)器.實(shí)際上,這是一個(gè)純JAVA代碼,這個(gè)JAVA代碼是能在任何J2SE環(huán)境下運(yùn)行的.
你同時(shí)應(yīng)注重:我們使用了來(lái)自JDBC的DataSource接口.這意味著我們的類(lèi)是獨(dú)立于目前JDBC供給商提供的類(lèi). 你可能會(huì)迷惑,這怎么能與特定的數(shù)據(jù)治理系統(tǒng)(DBMS)提供商的JDBC實(shí)現(xiàn)緊密結(jié)合呢? 這里就是Spring框架幫你實(shí)現(xiàn)的. 這個(gè)技術(shù)被稱為依靠注入:在我們的應(yīng)用程序的啟動(dòng)期間,通過(guò)調(diào)用setDataSource方法,Spring為我們提供了相應(yīng)的datasource對(duì)象.在后面幾部分我們會(huì)更多地提到Spring.假如我們?cè)谝郧笆褂脩?yīng)用程序服務(wù)器,我們將不得不借助于JAVA命名綁定接口(JNDI)查詢.

  除了直接使用JDBC,我們也可以使用Hibernate或者一個(gè)JDO工具來(lái)實(shí)現(xiàn)我們的持久層.這同樣不需要任何的EJB代碼.

  第二步:配置BankDAO

  我們會(huì)將便用Spring框架來(lái)配置我們的應(yīng)用程序.Spring不是必需的,但是使用Spring的好處是我們將可以簡(jiǎn)單的添加服務(wù),如:我們JAVA對(duì)象的事務(wù)和安全.這類(lèi)似于應(yīng)用服務(wù)器為EJB提供的東西,只是在我們的例子中Spring將變得更輕易.
Spring也答應(yīng)我們把我們的類(lèi)從目前的JDBC驅(qū)動(dòng)實(shí)現(xiàn)中分離出來(lái):Spring能夠配置Driver(基于我們的xml配置數(shù)據(jù))并把它提供給BankDAO對(duì)象(依靠注入原理).這樣可以保持我們的JAVA代碼的清淅和集中.這步的Spring配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>


<beans>

<bean id="datasource"
class="com.atomikos.jdbc.nonxa.NonXADataSourceBean">

    <property name="user">
        <value>sa</value>
    </property>
    <property name="url">
        <value>jdbc:hsqldb:SpringNonXADB
        </value>
    </property>
    <property name="driverClassName">
        <value>org.hsqldb.jdbcDriver</value>
    </property>
    <property name="poolSize">
        <value>1</value>
    </property>
    <property name="connectionTimeout">
        <value>60</value>
    </property>
</bean>

<bean id="bank" class="jdbc.Bank">
        <property name="dataSource">
            <ref bean="datasource"/>
        </property>
</bean>

</beans>


  這個(gè)XML文件包括兩個(gè)對(duì)象的配置:訪問(wèn)數(shù)據(jù)庫(kù)的DataSource和使用這個(gè)DataSource的Bank對(duì)象.下面是由Spring維護(hù)的一些基本任務(wù).
  ·        創(chuàng)建應(yīng)用程序(例: Bank和DataSource)需要的對(duì)象(“beans”).在XML文件中給出了這些對(duì)象的類(lèi)名,并且在我們的例子中,這些對(duì)象需要有一個(gè)公共的無(wú)參數(shù)constrUCtor (Spring也答應(yīng)參數(shù),但是配置語(yǔ)法上有所不同).這些對(duì)象都被命名(XML中的id屬性),所以我們后面能夠引用這些對(duì)象. id也答應(yīng)我們的應(yīng)用程序找回它需要的已配置對(duì)象.
  ·        這些對(duì)象的初始化是通過(guò)在XML文件中的properties的值實(shí)現(xiàn). 在XML文件中這些properties名 應(yīng)與對(duì)應(yīng)的類(lèi)中的setXXX方法相對(duì)應(yīng).
  ·        將對(duì)象連接在一起 :一個(gè)property可能是另一個(gè)對(duì)象(例如:在我們例子中的數(shù)據(jù)源)的引用,引用可以通過(guò)id創(chuàng)建.

  注重:在我們下一步中, 我們將選擇配置一個(gè)JTA-enabled的數(shù)據(jù)源(由Atomikos Transactions提供,可用于企業(yè)和J2SE的JTA產(chǎn)品,我們將應(yīng)用于我們的應(yīng)用程序). 簡(jiǎn)單起見(jiàn),我們將使用HypersonicSQLDB,這個(gè)DBMS不需要專(zhuān)門(mén)的安裝步驟—它是在.jar文件里,就像JTA和Spring.

  但是,考慮到漸增的可靠性需求,強(qiáng)列推薦你使用XA-capable的DBMS和JDBC驅(qū)動(dòng).沒(méi)有XA的支持, 在crash或重啟之后你的應(yīng)用程序?qū)⒉荒芑謴?fù)原有數(shù)據(jù). 資源部分有鏈接到關(guān)于事務(wù)和XA的信息和一些例子.

  作為一個(gè)練習(xí),你可以試試從HypersonicSQLDB轉(zhuǎn)換到FirstSQL,一個(gè)易安裝XA-compliant的DBMS.換句話說(shuō),任何其他為企業(yè)預(yù)備的和XA-capable的DBMS也會(huì)做得很好.

  第三步:測(cè)試BankDAO

  讓我們來(lái)測(cè)試我們的代碼,(使用極限編程的程序員會(huì)首先寫(xiě)測(cè)試,但因開(kāi)始不是很清淅,所以我們直到現(xiàn)在才開(kāi)始寫(xiě)測(cè)試.)下面是一個(gè)簡(jiǎn)單的單元測(cè)試.這個(gè)測(cè)試可在你的的應(yīng)用程序里運(yùn)行:它通過(guò)Spring獲得一個(gè)BANK對(duì)象來(lái)進(jìn)行測(cè)試(這在setUp方法中實(shí)現(xiàn)).注重:這個(gè)測(cè)試使用清楚的事務(wù)劃分:每一個(gè)測(cè)試開(kāi)始之前開(kāi)始一個(gè)事務(wù),每個(gè)測(cè)試結(jié)束時(shí)強(qiáng)制進(jìn)行事務(wù)回滾.這是通過(guò)手工的方式來(lái)減少測(cè)試對(duì)數(shù)據(jù)庫(kù)數(shù)據(jù)的影響.

package jdbc;
import com.atomikos.icatch.jta.UserTransactionImp;
import junit.framework.TestCase;
import java.io.FileInputStream;
import java.io.InputStream;
import org.springframework.beans.factory.xml.XmlBeanFactory;

public class BankTest extends TestCase
{

    private UserTransactionImp utx;

    private Bank bank;

    public BankTest ( String name )
    {
        super ( name );
        utx = new UserTransactionImp();
        

    }

    protected void setUp()
        throws Exception
    {
        //start a new transaction
        //so we can rollback the
        //effects of each test
        //in teardown!
        utx.begin();
        
        //open bean XML file
        InputStream is =
            new FileInputStream("config.xml");

        //the factory is Spring's entry point
        //for retrieving the configured
        //objects from the XML file

        XmlBeanFactory factory =
            new XmlBeanFactory(is);

        bank = ( Bank ) factory.getBean ( "bank" );
        bank.checkTables();
    }

    protected void tearDown()
        throws Exception
    {
        //rollback all DBMS effects
        //of testing
        utx.rollback();
    }

    public void testBank()
    throws Exception
    {
        int accNo = 10;
        long initialBalance = bank.getBalance ( accNo );
        bank.withdraw ( accNo , 100 );
        long newBalance = bank.getBalance ( accNo );
        if ( ( initialBalance - newBalance ) != 100 )
            fail ( "Wrong balance after withdraw: " +
                   newBalance );
    }
    
}


  我們將需要JTA事務(wù)來(lái)確保JMS和JDBC都是原子操作.一般來(lái)說(shuō),當(dāng)經(jīng)常都是兩個(gè)或多個(gè)連接的時(shí)候,你應(yīng)考慮一下JTA/XA。例如,在我們例子中的JMS和JDBC. Spring本身不提供JTA事務(wù);它需要一個(gè)JTA實(shí)現(xiàn)或者委派一個(gè)應(yīng)用服務(wù)器來(lái)處理這個(gè)事務(wù).在這里,我們使用了一個(gè)JTA實(shí)現(xiàn),這個(gè)實(shí)現(xiàn)可以在任何J2SE平臺(tái)上工作.
最終架構(gòu)如下面圖3.白色方框代表我們的應(yīng)用程序代碼.



發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 英吉沙县| 泰宁县| 来凤县| 白朗县| 江山市| 阳谷县| 航空| 吴堡县| 夏河县| 铜山县| 安福县| 北川| 合作市| 吉首市| 多伦县| 永宁县| 武穴市| 东乡县| 增城市| 营口市| 花垣县| 临潭县| 杂多县| 广丰县| 辽阳县| 武宁县| 临泽县| 嵩明县| 邵武市| 凤翔县| 高邮市| 五指山市| 高台县| 蒲城县| 揭西县| 甘泉县| 新昌县| 虞城县| 西乡县| 清丰县| 金秀|