Java EE 5 是 Java 企業(yè)級應(yīng)用規(guī)范的最新標準,它在以往版本的基礎(chǔ)上進行了大范圍的改進,吸取了開源領(lǐng)域廣泛使用的技術(shù)(例如 POJO,IoC),降低了 Java EE 的學(xué)習(xí)難度,簡化了企業(yè)級應(yīng)用程序的開發(fā),提高了開發(fā)效率。
以下是 Java EE 5 中引入的五個比較重要的技術(shù):
- Java Annotation 不是 Java EE 5 中的技術(shù),它是 Java 5 的一個新的特性。但是在 Java EE 5 中大量的使用了 Annotation,因為它的使用,極大的簡化了 Java EE 應(yīng)用程序的開發(fā)和維護。
- Java Server Faces (JSF)是對 JSP 技術(shù)的一種擴展和增強,它已經(jīng)存在了一段時間,但并沒有被包含在 J2EE 規(guī)范中,用戶需要在他們的 Web 應(yīng)用中包含 JSF 的 jar 文件來支持 JSF 技術(shù)。Java EE 5 中包含了最新的 JSF 1.2 規(guī)范,從而在 WAS CE v2.1 上開發(fā) JSF的應(yīng)用也變得更加容易。
- Java Persistence API (JPA)是用來代替 J2EE 中 Entity Bean 的一種技術(shù)規(guī)范。在 Java EE 5 中,Entity Bean 規(guī)范沒有進行任何更新,舊的 Entity Bean 在 Java EE 5 中還被支持,但新添加的 JPA 是將來 Java EE 中持久化技術(shù)的方向。使用 JPA 開發(fā)數(shù)據(jù)庫應(yīng)用也變得更加簡單和容易。
- Enterprise Java Bean (EJB) 3.0 是對 EJB 技術(shù)的一次比較大的改動。EJB 3.0 充分利用了 Java Annotation,提供了一個新的 EJB 編程模型,從而簡化了 EJB 應(yīng)用程序的開發(fā)。
- JAX-WS 2.0 是 JAX-RPC 1.1 的一個后繼版本,JAX-RPC 不會再有新的版本,而 JAX-WS 2.0 會成為 Java EE 5 中實現(xiàn) Web Service 的技術(shù)。
本文將通過開發(fā)一個網(wǎng)上商店的具體示例,向您展示如何在 WAS CE 中使用以上技術(shù)。
為了在 WAS CE v2.1 中展示以上所提到的新技術(shù),我們假設(shè)了一個網(wǎng)上商店:Ollivanders (Harry Potter 的魔法世界中最好的魔杖商店),簡稱 OlliShop。OlliShop 提供了簡單的 Web 界面,用戶可以用此 Web 界面注冊、登錄和購買魔杖;另外 OlliShop 向第三方集成商提供了 WebService 接口,可以通過 SOAP 協(xié)議來調(diào)用 OlliShop 的服務(wù)。您可以下載本例的源代碼。
網(wǎng)上商店的架構(gòu)如圖 1 所示:
圖 1. OlliShop 的架構(gòu)圖
OlliShop 由 5 個功能模塊組成:
- ShopWEB 是 OlliShop 的用戶界面,用戶只能通過瀏覽器來訪問此模塊。ShopWEB 模塊使用了 JSF 技術(shù)。
- ShopWS 是 OlliShop 的 Web Service 接口,它提供了其它應(yīng)用程序通過 Web Service 的方式訪問 OlliShop 的服務(wù)。此模塊使用了 JAX-WS 技術(shù)。
- ShopUtil 是一個工具包,包含一些公用的工具類以供其它模塊使用。
- ShopEJB 是業(yè)務(wù)實現(xiàn)模塊,主要包括一個無狀態(tài) Session Bean,供 ShopWEB 和 ShopWS 調(diào)用。此模塊使用了 EJB 3.0 技術(shù)。
- ShopJPA 是數(shù)據(jù)庫訪問模塊,它通過 ORM 機制把對數(shù)據(jù)庫的操作轉(zhuǎn)換成對對象的操作。此模塊使用了 JPA 技術(shù)。
WAS CE 作為一個開源的應(yīng)用服務(wù)器,選擇一個免費且強大的開發(fā)工具是很必要的,Eclipse 就是一個不錯的選擇。WAS CE 提供了一個 Eclipse 插件,可以通過此插件來管理 WAS CE 應(yīng)用服務(wù)器,開發(fā)、部署和調(diào)試 Java EE 的應(yīng)用,再配合 Eclipse 中的 WTP(Web Tools Platform)插件,對于一個小規(guī)模的應(yīng)用,這樣的 IDE 已經(jīng)可以勝任。
本文使用的 Eclipse 環(huán)境如下:
- Eclipse 3.4
- Eclipse WTP 3.0M2
- WAS CE Server adapter 2.1,此插件可以從以下網(wǎng)址下載:http://public.dhe.ibm.com/software/websphere/wasce/updates/
在 Eclipse 的 J2EE 視圖中的 Servers view 處創(chuàng)建 WAS CE 服務(wù)器,如圖 2 所示。
圖2. Eclipse中的WAS CE Server
現(xiàn)在我們開發(fā) Java EE 應(yīng)用程序的環(huán)境已經(jīng)準備好了,可以開始 OlliShop 應(yīng)用的開發(fā)了。OlliShop 包含了多個模塊,是一個典型的 EAR 應(yīng)用程序,整個 OlliShop 的工程視圖如圖 3,它包括 6 個工程。在后面的描述中我們將會具體介紹每一個工程。
圖 3. OlliShop 中包含的工程
通過 Eclipse 中的 "Enterprise Application Project" 向?qū)?chuàng)建一個 EAR 工程。需要注意的是,創(chuàng)建工程時需要選擇上面創(chuàng)建的 IBM WAS CE v2.1 作為 Target Runtime,如圖 4 所示。以下的所有工程除了 ShopUtil 外都需要 IBM WAS CE v2.1 作為 Target Runtime。
圖 4. 創(chuàng)建 ShopEAR 工程
此工程創(chuàng)建后會自動在 EarContent\META-INF\ 目錄下生成 WAS CE 的部署計劃:geronimo-application.xml。雙擊此文件可以打開此部署計劃的編輯界面,通過此編輯界面可以很容易的操作此部署計劃。
通過 Eclipse 中的 ”JPA Project” 向?qū)?chuàng)建 ShopJPA 工程。創(chuàng)建過程中可以把此工程加入到上面創(chuàng)建的 ShopEAR 工程中。此工程創(chuàng)建后,Eclipse 會轉(zhuǎn)換到 JPA 視圖。此時我們需要使用數(shù)據(jù)庫了,因此我們需要先創(chuàng)建數(shù)據(jù)庫。
WAS CE 中默認的內(nèi)置數(shù)據(jù)庫為 Derby,我們的 OlliShop 應(yīng)用就是使用了此數(shù)據(jù)庫。通過J2EE 視圖中的 Servers view,可以啟動 WAS CE。通過 http://localhost:8080/console/
進入 WAS CE 的管理控制臺,默認的用戶名/口令為 system/manager。通過此控制臺可以管理Derby 數(shù)據(jù)庫,單擊左邊菜單欄中的 "DB Manager" 進入數(shù)據(jù)庫管理界面,創(chuàng)建名為 "shop" 的數(shù)據(jù)庫,然后可以使用以下腳本創(chuàng)建所需要的表:
清單 1. 創(chuàng)建數(shù)據(jù)庫腳本
CREATE TABLE Users ( ID INTEGER NOT NULL, UserName VARCHAR(250) NOT NULL, Password VARCHAR(250) NOT NULL ); CREATE TABLE Goods ( ID INTEGER NOT NULL, Name VARCHAR(250) NOT NULL, Price DECIMAL(14, 2) NOT NULL, Quantity DOUBLE NOT NULL ); CREATE INDEX Users_ID ON Users(ID); CREATE INDEX Goods_ID ON Goods(ID); |
JPA 需要通過數(shù)據(jù)源才能訪問到相應(yīng)的數(shù)據(jù)庫,在 WAS CE 中有兩種方式創(chuàng)建數(shù)據(jù)源:通過管理控制臺創(chuàng)建和通過部署計劃創(chuàng)建。在這里我們使用第二種方式,所以需要修改在 ShopEAR 中的部署計劃:geroniom-application.xml。
在 geronimo-application.xml 中添加以下代碼:
清單2. geronimo-application.xml
<ext-module> <connector>ShopDataSource</connector> <external-path xmlns:dep="http://geronimo./xml/ns/deployment-1.2"> <dep:groupId>org.tranql</dep:groupId> <dep:artifactId>tranql-connector-derby-embed-local</dep:artifactId> <dep:type>rar</dep:type> </external-path> <connector xmlns="http://geronimo./xml/ns/j2ee/connector-1.2"> <resourceadapter> <outbound-resourceadapter> <connection-definition> <connectionfactory-interface> javax.sql.DataSource </connectionfactory-interface> <connectiondefinition-instance> <name>jdbc/ShopDataSource</name> <config-property-setting name="UserName"> </config-property-setting> <config-property-setting name="Password"> </config-property-setting> <config-property-setting name="DatabaseName"> shop </config-property-setting> <config-property-setting name="CreateDatabase"> true </config-property-setting> <connectionmanager> <single-pool> <max-size>100</max-size> <min-size>0</min-size> <blocking-timeout-milliseconds> 5000 </blocking-timeout-milliseconds> <idle-timeout-minutes>30</idle-timeout-minutes> <match-one/> </single-pool> </connectionmanager> </connectiondefinition-instance> </connection-definition> </outbound-resourceadapter> </resourceadapter>> </connector> </ext-module> |
從以上代碼可以看出此數(shù)據(jù)源指定的數(shù)據(jù)庫為 shop,創(chuàng)建的數(shù)據(jù)源的 JNDI 的名字為jdbc/ShopDataSource。
Eclipse 提供了一個創(chuàng)建 JPA Entity Bean 的工具,此工具能夠根據(jù)數(shù)據(jù)庫中表的設(shè)置創(chuàng)建出相應(yīng)的 Entity Bean。為了使用此工具,需要先在 Eclipse 中連接到 Derby 數(shù)據(jù)庫,在 JPA 視圖的 Data Source Explorer 中創(chuàng)建到 Derby 的連接。步驟如下:
1. 在 "Database" 的右鍵菜單中選擇 "New …"
2. 選擇 “Generic JDBC Connection”
3. 輸入連接的名字:Derby
4. 選擇 “Derby Client JDBC Driver”,Derby JDBC Driver位于:%WASCE_HOME%\repository\org\apache\derby\derbyclient\10.2.2.0\derbyclient-10.2.2.0.jar
。輸入以下連接屬性:
Database:shop
URL:jdbc:derby://localhost:1527/shop;create=true
User Name:user
Password:app
5. 連接剛創(chuàng)建的 Derby。
現(xiàn)在可以通過 Derby 連接創(chuàng)建相應(yīng)的 Entity Bean 了。在 shop 數(shù)據(jù)庫中只有兩個表:users 和 goods。我們先創(chuàng)建一個類 com.ibm.wasce.shop.entity.User,此時在 JPA 視圖中就可以把此類映射到數(shù)據(jù)庫中的表 users,如圖5所示。
圖 5. User 類映射到表 users
在 User類 中添加 3 個屬性:id、userName、password,然后把它們映射到 users 表中的字段,如圖 6 所示。
圖6. 映射屬性 id 到表 users 中的字段 id
用戶登錄時,需要從數(shù)據(jù)庫中根據(jù)用戶輸入的用戶名查詢該用戶來驗證用戶名和密碼。在傳統(tǒng)的應(yīng)用中,我們需要從數(shù)據(jù)源中得到 Connection,然后執(zhí)行 SQL 語句,從返回的數(shù)據(jù)集中獲得數(shù)據(jù),再生產(chǎn)相應(yīng)的 User 對象。在 EJB 3.0 中,這項工作已經(jīng)大大簡化,主要是因為使用了 Annotation NamedQueries 和 EJB QL。通過 NamedQueries,只需要再聲明一個 EJB QL,就可以得到相應(yīng)的 User 對象,開發(fā)人員不再需要關(guān)心數(shù)據(jù)庫連接和數(shù)據(jù)轉(zhuǎn)換等繁瑣的事情。EJB QL 是和 SQL 很像的一種語言,只是它要操作的不是數(shù)據(jù)庫中的表,而是 JPA Entity Bean。
最終生成的 User 類如下:
清單3. 生成 JPA 實體 Bean
@NamedQueries ( { @NamedQuery ( name = "getUserByName", query = "select u from User u where u.userName= :name" ) }) @Entity @Table(name="USERS", schema = "APP") public class User { @Id @GeneratedValue private Integer id; private String userName; private String password; // 以下的setter/getter方法省略 |
通過以上的方式,我們創(chuàng)建了與表 goods 相對應(yīng)的 JPA Entity Bean。
接下來,我們將通過 Eclipse 中的 “EJB Project” 向?qū)?chuàng)建 ShopEJB 工程,同時把新創(chuàng)建的工程加入到 ShopEAR 中。
此工程中的 EJB 采用 EJB 3.0 的方式開發(fā)。在傳統(tǒng)的EJB編程模型中,每一個Bean需要兩個接口和一個類來組成:Remote(或Local)接口、Home 接口和 Bean 實現(xiàn)類,而且這三個類之間需要通過某種編碼約定來規(guī)范,在部署時再由 EJB 容器生產(chǎn)一些魔術(shù)代碼(Magic Codes)把它們之間的調(diào)用關(guān)系連起來。而在 EJB 3.0 中的實現(xiàn)則顯得更加簡單和直接,一個 EJB 只需要一個接口和一個類:Remote(或 Local)接口和實現(xiàn) Remote(或 Local)接口的類。另外一個區(qū)別是在 EJB 3.0 中部署描述符(ejb-jar.xml)也不再是必須的了,我們可以通過 Annotation 的方式來定義這些元數(shù)據(jù)。
以下是 ShopBean 的 Local 接口,它是一個普通的 Java 接口。如果是 Remote 接口,則需要加上 Annotation @Remote。
清單 4. ShopBean 的 Local 接口
public interface ShopBean { public boolean login( String name, String password ); public List listGoods(); public Good getGoodById( int id ); } |
以下是 ShopBean 的實現(xiàn)類。在此類中,唯一能感覺到它和 EJB 相關(guān)的地方就是 @Stateless
,其它的地方和普通的 Java 類沒有區(qū)別。此類主要用來實現(xiàn)操作在 ShopJPA 中開發(fā)的 Entity Bean。EntityManager 是 JPA 中最重要的一個接口,應(yīng)用程序主要通過它來添加、修改和查詢 Entity Bean。通過 Annotation @PersistenceContext
,WAS CE 中的 EJB 容器會把一個 EntityManager 的實例賦給此類中的em對象,這就是在 EJB 3.0 中被廣泛使用的依賴注入(Dependency Injection)的方法。在這個類中,也用到了在 ShopJPA 中定義的 NamedQuery。
清單 5. ShopBean 的實現(xiàn)
@Stateless public class ShopBeanImpl implements ShopBean { @PersistenceContext private EntityManager em; public Good getGoodById(int id) { Query query = em.createNamedQuery( "getGoodByID" ); query.setParameter("id", id); return (Good)query.getSingleResult(); } public List listGoods() { Query query = em.createNamedQuery( "getAllGoods" ); return query.getResultList(); } public boolean login(String name, String password) { try { Query query = em.createNamedQuery( "getUserByName" ); query.setParameter( "name", name ); User user = (User)query.getSingleResult(); return user != null && user.getPassword().equals( password ); } catch ( Exception e ) { return false; } } |
通過 Eclipse 中的 "Java Project" 向?qū)?chuàng)建 ShopUtil 工程??梢栽?ShopEAR 工程的屬性管理頁面中,把 ShopUtil 工程加入到 ShopEAR 中。
此工程提供了 ShopWEB 和 ShopWS 訪問 EJB 的功能,而不需要在兩個 Web 工程中分別定義。它使用 JNDI 的方式訪問 EJB,如清單 6 所示:
清單 6. 使用 JNDI 訪問 EJB
private EJBLocator() { try { InitialContext rootContext = new InitialContext(); shopbean = (ShopBean)rootContext.lookup( "java:comp/env/ejb/shopbean" ); } catch ( NamingException ne ) { ne.printStackTrace(); } } |
接下來,我們將創(chuàng)建兩個 Web 工程。在創(chuàng)建的兩個 Web 工程中需要進行以下設(shè)置才可以使用:
- 在 Web 工程的屬性中:"Java Build Path" -> "Projects" 中添加 ShopUtil 工程。
- 添加以下一行到 Web 工程的文件:WebContent\META-INF\ MANIFEST.MF;Class-Path: ShopUtil.jar
在創(chuàng)建此工程前,需要先根據(jù) WTP 的文檔來設(shè)置 Java Server Faces,WAS CE v2.1 提供了JSF 所需要的以下兩個 Jar 文件:
- %WASCE_HOME%\repository\org\apache\myfaces\core\myfaces-api\1.2.0\myfaces-api-1.2.0.jar
- %WASCE_HOME%\repository\org\apache\myfaces\core\myfaces-impl\1.2.0\myfaces-impl-1.2.0.jar
設(shè)置完 JSF 后,通過 Eclipse 中的 “Dynamic Web Project” 向?qū)?chuàng)建 ShopWEB 工程,Configurations-> JavaServer Faces v1.2 Project,同時把新創(chuàng)建的工程加入到 ShopEAR 中。
新生成的工程中會包含 JSF 的配置文件:faces-config.xml,雙擊此文件可打開 JSF 配置編輯器,如圖 7 所示。
圖 7. faces-config.xml 的編輯器
通過此編輯器中的 ManageBean 頁面,可以生成 JSF 中的 Managed Bean。在本例中,有兩個Managed Bean:GoodsBean 和 LoginBean。
WST 還提供了一個 JSF 頁面編輯器,可以進行可視化的開發(fā)。在本例中,有兩個頁面:一個登錄頁面和一個顯示商品列表的頁面。其中登錄頁面的編輯如圖 8 所示。
圖 8. JSF 的可視化編輯頁面
本例中的業(yè)務(wù)邏輯是用戶正確登錄后會自動轉(zhuǎn)到商品列表頁面,否則將返回到登錄頁面。這種頁面跳轉(zhuǎn)的邏輯也可以通過可視化的方式來進行設(shè)置,如圖 9 所示。
圖 9. 頁面跳轉(zhuǎn)邏輯編輯頁面
通過 Eclipse 中的 "EJB Project" 向?qū)?chuàng)建 ShopWS 工程,同時把新創(chuàng)建的工程加入到ShopEAR 中。
通過 JAX-WS 的方式來開發(fā) Web Service 簡化了很多工作。在本例中,我們開發(fā)了一個通過商品編號來查詢商品價格的 Web Service。此 Service 只需要使用一個接口和一個實現(xiàn)類,在部署時,WAS CE 會根據(jù)接口和類中的 Annotation 來生成相應(yīng)的 WSDL 文件。
以下是此 Service 的接口,使用了 Annotation @WebService
。
清單 7. ShopService 接口
@WebService(name="ShopServicePortType", targetNamespace = "http://shop.wasce.ibm.com") public interface ShopService { public double getPriceById( int goodsId ); } |
以下是此 Service 的實現(xiàn)類:
清單 8. ShopService 的實現(xiàn)
@WebService(serviceName = "ShopService", portName="ShopServicePort", endpointInterface = "com.ibm.wasce.shop.ws.ShopService", targetNamespace = "http://shop.wasce.ibm.com") public class ShopServiceImpl implements ShopService { public double getPriceById( int goodsId ) { ShopBean shopbean = EJBLocator.getInstance().getShopBean(); Good good = shopbean.getGoodById(goodsId); return 20; } } |
以上定義的 Web Service 需要通過 Servlet 的方式發(fā)布,所以需要在 web.xml 中進行以下配置:
清單 9. 在 web.xml 中配置 ShopService
<servlet> <display-name>ShopService</display-name> <servlet-name>ShopService</servlet-name> <servlet-class> com.ibm.wasce.shop.ws.ShopServiceImpl </servlet-class> </servlet> <servlet-mapping> <servlet-name>ShopService</servlet-name> <url-pattern>/shopservice</url-pattern> </servlet-mapping> |
雖然類 com.ibm.wasce.shop.ws.ShopServiceImpl 不是一個 Servlet,它沒有繼承javax.servlet.http.HttpServlet,但是在部署的時候,WAS CE 的部署程序會對 ShopServiceImpl進行解析,并且生成一個 Servlet 來包裝 ShopServiceImpl,這樣就可以通過地址 /shopservice來訪問到此 Web Service。
也可以通過 JAX-WS 的方式來調(diào)用上面生成的 Web Service,代碼如下:
清單 10. 調(diào)用 ShopService
public static double getPriceById( int goodsId) throws Exception { URL url = new URL("http://localhost:8080/ShopWS/shopservice?wsdl"); QName qname = new QName("http://shop.wasce.ibm.com", "ShopService"); Service service = Service.create(url, qname); ShopService shopservice = (ShopService)service.getPort(ShopService.class); double price = shopservice.getPriceById( goodsId ); return price; } |
在 Eclipse 中開發(fā)完以上模塊后,就可以部署此應(yīng)用。我們可以通過兩種方式來部署:通過Eclipse 部署或者從 Eclipse 中導(dǎo)出 EAR 后通過命令行部署。
第一種方式:通過 Eclipse 部署
- 在 Eclipse 中的 Server 視圖,右擊 WASCE Server,選擇Add and Remove Projects ...
- 添加 ShopEAR 到 Configured projects 列表中
- 點擊 Finish
第二種方式:通過命令行部署
- 右擊 ShopEAR 工程,選擇 Export
- 選擇“Java EE”-> EAR file
- 指定要保存的目錄和文件名,例如 d:\temp\ShopEAR.ear
- 用以下命令部署導(dǎo)出的 ear 文件
%WASCE_HOME%\bin\deploy --username system --password manager deploy d:\temp\ShopEAR.ear
部署此應(yīng)用后,可以通過 http://localhost:8080/ShopWEB/
來訪問 OlliShop 的主頁,默認的用戶名/密碼為 user1/user1
對于 Web Service,可以通過 http://localhost:8080/ShopWS/shopservice?wsdl
來訪問 shopservice的 WSDL 文件,可以通過http://localhost:8080/ShopWS/invokeshopservice.jsp
來調(diào)用此 Web Service。
WAS CE v2.1 作為一款免費的 Java EE 5 應(yīng)用服務(wù)器,結(jié)合 Eclipse 強大的 WST 工具,為廣大開發(fā)人員提供了快速的開發(fā)環(huán)境,也為中小型企業(yè)實踐 Java EE 5 的應(yīng)用提供了一個很好的平臺。
描述 | 名字 | 大小 | 下載方法 |
---|---|---|---|
代碼示例 | OlliShop.zip | 49 KB | HTTP |
學(xué)習(xí)
- WebSphere Application Server Community Edition V2.1 中的新增功能:本文主要講述了 WebSphere Application Server Community Edition V2.1 中的新增功能,包括使用 Gshell 執(zhí)行 Geronimo 命令、在您自己的服務(wù)器集基礎(chǔ)上創(chuàng)建多個服務(wù)器組裝,以及通過專家模式和新的 Monitoring Portlet 完全控制服務(wù)器的能力。
- 從 Apache Tomcat Version 6.0 遷移到 WAS CE V2.1 :本文將逐步地指導(dǎo)您將一個應(yīng)用程序部署到 Tomcat 6.0,然后遷移代碼并將其部署到 WebSphere Application Server Community Edition V2.1。并通過該示例應(yīng)用程序突出說明了這兩種實現(xiàn)之間的一些顯著差異。
- 使用 WAS CE 開發(fā) JPA 應(yīng)用程序:本教程將向您介紹如何用 JPA 開發(fā) WAS CE 目標平臺下的 Java EE 5 應(yīng)用。本教程通過一個示例應(yīng)用程序的開發(fā)過程,將帶您了解如何創(chuàng)建 JPA 項目和持久生成類,如何配置持久單元以及如何部署和運行 Web 應(yīng)用程序。
- WAS CE 產(chǎn)品文檔:本網(wǎng)站向您提供了 WAS CE 不同版本的產(chǎn)品幫助文檔。
- Eclipse 網(wǎng)站:本網(wǎng)站向您提供了 開源開發(fā)工具 Eclipse 最新。
- Geronimo 專題:為您提供了 Apache Geronimo 相關(guān)的技術(shù)文章、教程、下載等資源。
- WAS CE 專欄:為您提供了開源應(yīng)用服務(wù)器 WAS CE 相關(guān)的技術(shù)文章、教程、下載等資源。
獲得產(chǎn)品和技術(shù)