什么是Java EE 5.0?
“Do more with less work”,這是Java EE 5.0的正式宣言,也是其與J2EE 1.4最顯著的區(qū)別。Java EE 5.0提供了諸多新特性以簡化應用的開發(fā),譬如:
通過Annotation代替舊有的xml配置文件;
重新設計的EJBl 3.0變得輕量與簡單;
基于組件化的JSF Web編程模型;
與JAX-RPC相比更易使用的JAX-WS等Webl Services相關規(guī)范;
擁有了諸如依賴注入、AOP編程等以往開源框架才擁有的功能等等。
圖中藍底白字部分是Java EE 5新的功能,從下圖可以看到,在WEB層加入了JSF這個新的表現(xiàn)層框架。EJB從EJB2.0升級到EJB3.0。Java 5.0還加入了Annotations,通過Annotations引入,降低Java EE開發(fā)成本。
Java EE 5.0架構圖
為什么我們還需要Java EE 5.0?
在談論Java EE 5.0眾多新特性的時候,我們面對這樣一個問題:在J2EE 1.4依然占據(jù)主流開發(fā)地位,并且除官方標準以外,還擁有很多豐富的開源框架可供選擇的今天,為什么我們還需要Java EE 5.0?
首先,作為官方標準的J2EE 1.4,是一種過度理論化的計算模型,無論是開發(fā)效率還是運行期性能,都已經(jīng)日顯老態(tài);其次,在諸多開源框架的沖擊下,J2EE 1.4的功能局限性也日益暴露出來,譬如:與Entity Bean相比,Hibernate提供了更好的OR Mapping解決方案;與Session Bean相比,Spring Framework對Bean的管理更簡單,更高效,功能也更豐富;與單純的JSP/Servlet相比,Struts、WebWork能夠在更高層次上解決Web開發(fā)的復雜度問題。
人們是智慧的,業(yè)界既需要代表現(xiàn)實主義的官方標準和商業(yè)軟件的存在,也同時需要代表理想主義的開源組織和開源軟件的存在。尤其是在Java EE 越來越 Open的今天,我們甚至已經(jīng)忽略了哪些特性是官方標準應該具備的、哪些特性是開源軟件應該具有的。事實上,整個業(yè)界都在迫切等待下一代J2EE規(guī)范的誕生,而一旦該規(guī)范誕生,它將匯集整個業(yè)界的智慧,融合已有開源框架的優(yōu)秀特性,并使商業(yè)軟件或開源軟件迅速向其靠攏。而它,就是Java EE 5.0!
Java EE 5.0新特性介紹
Annotation
Annotation中文意為標注,是JDK 1.5中引入的非常迷人的特性之一,通過在Java代碼加入元信息(Meta Data),影響工具和庫對代碼的處理。在Java EE 5中,增加了在POJO(Plain Old Java Object)中進行Annotation功能。Annotation可以用于:
定義和使用Web Service
開發(fā)EJB組件
映射Java類到XML
映射Java類到DB
指定外部依賴
指定部署信息,包括安全屬性等
下面是Java EE 5中使用Annotation定義Web Service的一個例子:
package endpoint;
import javax.jws.WebService;
@WebService
public class Hello {
public String sayHello(String param) {
return “Hello “ + param;
}
}
一個普通的Java類,通過加入@WebService這一Annotation,服務器就可將此類中的公共方法發(fā)布為Web Service,簡單又方便。
引入Annotations可以大大降低Java EE開發(fā)成本,開發(fā)更適應中小型系統(tǒng)的開發(fā),簡化這部分系統(tǒng)開發(fā)步驟。
EJB3.0
EJB3.0是對重載的EJB2的批判性思考和揚棄。在EJB3.0中,不再需要EJB home接口,也不需要實現(xiàn)javax.ejb.SessionBean接口,一個簡單的POJO對象就足于代表實體對象,并支持繼承和多態(tài)。同時,困擾人們多年的EJB部署描述符變成可選的。EJB的持久變得更加簡化、輕量級,EJB的查找也變得更加簡便,JNDI API不再是必須的。EJB3.0還使用了Interceptor,在業(yè)務方法被調用前進行攔截,因而更加容易實現(xiàn)靈活的AOP編程。
JavaServer Faces 1.2
JavaServer Faces (JSF) 是一種用于構建 Web 應用程序的新標準 Java 框架。它提供了一種以組件為中心來開發(fā) Java Web 用戶界面的方法,從而簡化了開發(fā)。JSF提供了標準的編程接口、豐富可擴展的UI組件庫、事件驅動模型等一套完整的Web應用框架。通過 JSF ,可以在頁面中輕松自如地使用 WEB 組件、捕獲用戶行為所產(chǎn)生的事件、執(zhí)行驗證、建立頁面導航等。JSF1.2支持
托管Bean中的依賴注入
簡單易用,功能強大,支持擴展的表達式語言
大量的JSF組件
支持AJAX
JAX-WS2.0, JAXB2.0:更簡單、更廣泛的Web Service支持
Java EE 5提供了更簡單、更廣泛的Web Service支持,包括:
JSR 224, Java API for XML-Based Web Services (JAX-WS) 2.0
JSR 222, Java Architecture for XML Binding (JAXB) 2.0
JSR 181, Web Services Metadata for the Java Platform 2.0
SOAP with Attachments API for Java (SAAJ) 1.3
JAX-WS 2.0繼承自JAX-RPC 1.1,實現(xiàn)更簡單的編程模型并集成JAXB 2.0,支持可擴展的傳輸協(xié)議,支持支持異步客戶端,并支持REST應用。
JAXB2.0全面支持XML Schema,能夠綁定Java類到XML Schema,支持更小的內存占用和更快的編組(marshalling)、更靈活的編出(unmarshalling),支持局部綁定 XML文檔到 JAXB 對象。
一個基于JAX-WS 2.0的HelloWorld例子如下:
package endpoint;
import javax.jws.WebService;
import javax.jws.WebMethod;
@WebService()
public class HelloWorld{
//the implementation class must have a default public constructor
public HelloWorld() {};
@WebMethod(operationName="sayHello", action="urn:SayHello")
public String sayHello(String name){
return "Hello "+ name + "!";
}
}
上例中,只需要一個實現(xiàn)類,并通過使用annotations,將自動生成SEI和其他一些文件,開發(fā)人員從此可以將精力集中在業(yè)務邏輯的實現(xiàn)上。
依賴注入
通過依賴注入更容易訪問資源??勺⑷氲馁Y源包括:
SessionContext
DataSources
Other EJB
Web services
message queues等
一個依賴注入的例子:
package com.example;
@Session
public class MyEJB {
@Resource(name = “employeeDatabase”)
private DataSource myDS;
...
}
上述代碼片斷定義了名為MyEJB的Session Bean,并定義了一個名為employeeDatabase的資源,將其注入到一個名為myDS的字段。通過依賴注入,不再需要復雜的部署描述符入口,事情就這么簡單。
輕量級Java持久API模型
Java 持久API(JPA)也是Java EE 5中的一大亮點,這是個輕量級的持久模型。
在JPA中,實體是 POJO對象。實體對象不再是組件,也不再需要位于 EJB 模塊中。另外,對象關系映射的處理方式也得以標準化,可以通過使用標注來指定對象關系映射信息,同時向下兼容 XML 描述符。
在JPA中,支持命名查詢,通過元數(shù)據(jù)表示的靜態(tài)查詢。重用查詢變得非常簡單。
JPA支持簡單的打包規(guī)則。由于實體 Bean 是簡單的 Java 技術類,因此幾乎可以在 Java EE 應用程序中的任意位置將其打包。例如,實體 Bean 可以是 EJB JAR、應用程序客戶端 JAR、WEB-INF/lib、WEB-INF/classes 的一部分。
JPA支持分離的實體。由于實體 Bean 是 POJO,因此可以對它們執(zhí)行序列化,通過網(wǎng)絡將其發(fā)送到其他地址空間,并在不識別持久性的環(huán)境中使用它們。
JPA提供EntityManager API。可以通過標準 EntityManager API 來執(zhí)行涉及實體的創(chuàng)建、讀取、更新和刪除 (Create Read Update Delete, CRUD) 操作。通過EntityManager API,編程將變得非常簡便。
泛型(Generics)
Jav EE 5之前一個集合可以放任何類型的對象,相應地從集合里面拿對象的時候我們也不得不對他們進行強制得類型轉換。
現(xiàn)在Java EE 5引入了泛型,它允許指定集合里元素的類型,這樣你可以得到強類型在編譯時刻進行類型檢查的好處,發(fā)現(xiàn)類型不符,避免到運行時出現(xiàn)類型轉換錯誤,不再需要顯式的強制轉換(cast)。
舉例如下:
使用泛型前:
ArrayList list = new ArrayList();
list.add(0, new Integer(42));
int total = ((Integer)list.get(0)).intValue();
使用泛型后:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = list.get(0).intValue();
自動裝箱(Autoboxing)和自動拆箱(Auto-Unboxing)
Jav EE 5之前,集合不能存放基本類型,簡單數(shù)據(jù)類型(int,long,float等)和其對應的包裝類型(Integer,Long,F(xiàn)loat等)之間不能自動轉換。
現(xiàn)在自動轉換機制(自動裝箱(Autoboxing)和自動拆箱(Auto-unboxing))解決了這些問題。自動裝箱(Autoboxing)特性讓Java自動包裝一個簡單數(shù)據(jù)類型(例如int)到對應的包裝類型中(例如Integer)中。自動拆箱(Auto-unboxing)是相反的過程,即將一個包裝類型(例如Integer)自動轉換為它所對應的簡單數(shù)據(jù)類型(例如int)。
舉例如下:
以前:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = (list.get(0)).intValue();
以后(請對照泛型部分使用泛型前的例子代碼):
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, 42);
int total = list.get(0);
枚舉(Enumeration)
Jav EE 5之前,枚舉類型沒有加入到Java中來,導致我們在程序中寫了許多public static final。
現(xiàn)在加入了一個全新類型的“類”-枚舉類型。本質上,一個枚舉是一個命名常量的列表。枚舉類型通過新的關鍵字enum來支持。下面是定義一個枚舉的例子代碼:
publicenumColor
{
Red,
White,
Blue
}
然后可以這樣來使用ColormyColor=Color.Red.
枚舉類型還提供了兩個有用的靜態(tài)方法values()和valueOf(). 我們可以很方便地
使用它們,例如
for(Colorc:Color.values())了System.out.println(c);
增強的for循環(huán)
Java 5.0中添加了“For-Each”形式的循環(huán)。For-Each循環(huán)的加入簡化了集合的遍歷,為大量集合、數(shù)組等的循環(huán)處理提供了便利,并為我們防止數(shù)組越界提供有益的幫助,還避免了原來必需的強制類型轉換(case),讓我們能在編譯時就發(fā)現(xiàn)類型不符,避免到運行時出現(xiàn)類型轉換錯誤。
假設我們要遍歷一個集合對其中的元素進行一些處理。典型的代碼為:
voidprocessAll(Collectionc){
for(Iteratori=c.iterator();i.hasNext();){
MyClassmyObject=(MyClass)i.next();
myObject.process();
}
}
使用For-Each循環(huán),我們可以把代碼改寫成:
voidprocessAll(Collectionc){
for(MyClassmyObject:c)
myObject.process();
}
這段代碼要比上面清晰許多,并且避免了強制類型轉換。
不定參數(shù)(Varargs)
Varargs使程序員可以聲明一個接受可變數(shù)目參數(shù)的方法。在過去,經(jīng)常采用將參數(shù)包裝到一個數(shù)組或者集合中的方式。Varargs讓一個方法可以帶有可變數(shù)目參數(shù)。Varargs的加入使得創(chuàng)建帶有可變數(shù)目參數(shù)的方法變的更加容易。下面是使用不定參數(shù)的例子:
// 方法定義
void argtest(Object ... args) {
for (int i=0;i <args.length; i++) {
}
}
// 調用方式
argtest("test", "data");
靜態(tài)導入(Static Import)
過去使用靜態(tài)成員通常我們需要進行這種形式的調用:YourClassName.staticMember,在每次使用靜態(tài)成員的時候我們都要把這個靜態(tài)成員所屬類的名字寫一遍。現(xiàn)在靜態(tài)導入可以讓我們不必每次都去寫類的名字了,可以直接通過靜態(tài)成員的名字來訪問它們,無需再給出他們的類名。下面是使用靜態(tài)導入的例子:
// 靜態(tài)導入
import static java.awt.BorderLayout.*;
// 調用靜態(tài)成員
getContentPane().add(new JPanel(), CENTER);
元數(shù)據(jù)(Metadata)
新的元數(shù)據(jù)工具更多是為未來考慮而增加的,它讓你能夠在程序中嵌入注解(annotation),這些注解能夠被不同的編程工具處理。例如,工具可以根據(jù)注解(annotation)的要求生成Java源代碼,這樣只要程序員指定一種動作,然后就可以將實際提供代碼的事情留給工具了,從而大大降低了程序員必須手工輸入的重復代碼的數(shù)量。
下面是使用元數(shù)據(jù)前后的代碼對比:
使用前:
public interface PingIF extends Remote {
public void ping() throws RemoteException;
}
public class Ping implements PingIF {
public void ping() {
……
}
}
使用后:
public class Ping {
public @remote void ping() {
……
}
}
其它改變
Java 5在基礎類庫、用戶界面、虛擬機、執(zhí)行效率、垃圾收集等其它方面也進行了大量的升級。