十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
java控制臺輸出由print( ) 和 println( )來完成最為簡單。這兩種方法由rintStream(System.out引用的對象類型)定義。盡管System.out是一個字節(jié)流,用它作為簡單程序的輸出是可行的。因為PrintStream是從OutputStream派生的輸出流,它同樣實現(xiàn)低級方法write(),write()可用來向控制臺寫數(shù)據(jù)。PrintStream 定義的write( )的最簡單的形式如下:
成都創(chuàng)新互聯(lián)公司一直在為企業(yè)提供服務(wù),多年的磨煉,使我們在創(chuàng)意設(shè)計,成都全網(wǎng)營銷到技術(shù)研發(fā)擁有了開發(fā)經(jīng)驗。我們擅長傾聽企業(yè)需求,挖掘用戶對產(chǎn)品需求服務(wù)價值,為企業(yè)制作有用的創(chuàng)意設(shè)計體驗。核心團(tuán)隊擁有超過10年以上行業(yè)經(jīng)驗,涵蓋創(chuàng)意,策化,開發(fā)等專業(yè)領(lǐng)域,公司涉及領(lǐng)域有基礎(chǔ)互聯(lián)網(wǎng)服務(wù)西部信息服務(wù)器租用、手機(jī)APP定制開發(fā)、手機(jī)移動建站、網(wǎng)頁設(shè)計、網(wǎng)絡(luò)整合營銷。
void write(int byteval)
該方法按照byteval指定的數(shù)目向文件寫字節(jié)。盡管byteval 定義成整數(shù),但只有低位的8個字節(jié)被寫入。下面的短例用 write()向屏幕輸出字符“A”,然后是新的行。
// Demonstrate System.out.write().
class WriteDemo {
public static void main(String args[]) {
int b;
b = 'A';
System.out.write(b);
System.out.write('\n');
}
}
一般不常用write()來完成向控制臺的輸出(盡管這樣做在某些場合非常有用),因為print()和println() 更容易用。
四、PrintWriter類
盡管Java允許用System.out向控制臺寫數(shù)據(jù),但建議僅用在調(diào)試程序時或在例程中。對于實際的程序,Java推薦的向控制臺寫數(shù)據(jù)的方法是用PrintWriter流。PrintWriter是基于字符的類。用基于字符類向控制臺寫數(shù)據(jù)使程序更為國際化。PrintWriter定義了多個構(gòu)造函數(shù),這里所用到的一個如下:
PrintWriter(OutputStream outputStream, boolean flushOnNewline)
outputStream是OutputStream類的對象,flushOnNewline控制Java是否在println()方法被調(diào)用時刷新輸出流。如果flushOnNewline為true,刷新自動發(fā)生,若為false,則不發(fā)生。
PrintWriter支持所有類型(包括Object)的print( )和println( )方法,這樣,就可以像用ystem.out那樣用這些方法。如果遇到不同類型的情況,PrintWriter方法調(diào)用對象的toString()方法并打印結(jié)果。用PrintWriter向外設(shè)寫數(shù)據(jù),指定輸出流為System.out并在每一新行后刷新流。例如這行代碼創(chuàng)建了與控制臺輸出相連的PrintWriter類。
PrintWriter pw = new PrintWriter(System.out, true);
下面的應(yīng)用程序說明了用PrintWriter處理控制臺輸出的方法:
// Demonstrate PrintWriter
import java.io.*;
public class PrintWriterDemo {
public static void main(String args[]) {
PrintWriter pw = new PrintWriter(System.out, true);
pw.println("This is a string");
int i = -7;
pw.println(i);
double d = 4.5e-7;
pw.println(d);
}
}
該程序的輸出如下:
This is a string
-7
4.5E-7
io包支持Java的基本I/O(輸入/輸出)系統(tǒng),包括文件的輸入/輸出。對輸入/輸出的支持是來源于Java的內(nèi)核API庫,而不是語言關(guān)鍵字。
一、輸入/輸出基礎(chǔ)
很多實際的Java應(yīng)用程序不是基于文本的控制臺程序。盡管基于文本的程序作為教學(xué)實例是很出色的,它們無法勝任JAVA在實際中的重要應(yīng)用。Java對外設(shè)輸入/輸出的支持也是有限的,并且用起來有些笨拙——甚至是在簡單的例子程序中?;谖谋镜目刂婆_輸入/輸出對于Java程序并不是十分重要。
Java 提供了與文件和網(wǎng)絡(luò)相關(guān)的強(qiáng)大的和靈活的輸入/輸出支持,Java的輸入/輸出系統(tǒng)是緊密相連并且是具有一致性的。
1.1 流的概念
Java程序通過流來完成輸入/輸出。流是生產(chǎn)或消費(fèi)信息的抽象。流通過Java的輸入/輸出系統(tǒng)與物理設(shè)備鏈接。盡管與它們鏈接的物理設(shè)備不盡相同,所有流的行為具有同樣的方式。這樣,相同的輸入/輸出類和方法適用于所有類型的外部設(shè)備。這意味著一個輸入流能夠抽象多種不同類型的輸入:從磁盤文件,從鍵盤或從網(wǎng)絡(luò)套接字。同樣,一個輸出流可以輸出到控制臺,磁盤文件或相連的網(wǎng)絡(luò)。流是處理輸入/輸出的一個潔凈的方法,例如它不需要代碼理解鍵盤和網(wǎng)絡(luò)的不同。Java中流的實現(xiàn)是在java.io包定義的類層次結(jié)構(gòu)內(nèi)部的。
1.2 字節(jié)流和字符流
要使用流類,必須導(dǎo)入Java.io包。Java 2 定義了兩種類型的流:字節(jié)類和字符類。字節(jié)流(byte stream)為處理字節(jié)的輸入和輸出提供了方便的方法。例如使用字節(jié)流讀取或書寫二進(jìn)制數(shù)據(jù)。字符流(character stream)為字符的輸入和輸出處理提供了方便。它們采用了統(tǒng)一的編碼標(biāo)準(zhǔn),因而可以國際化。在某些場合,字符流比字節(jié)流更有效。在最底層,所有的輸入/輸出都是字節(jié)形式的?;谧址牧髦粸樘幚碜址峁┓奖阌行У姆椒?。下面是對字節(jié)流和字符流的概述。
1.2.1 字節(jié)流類
字節(jié)流由兩個類層次結(jié)構(gòu)定義。在頂層有兩個抽象類:InputStream 和 OutputStream。每個抽象類都有多個具體的子類,這些子類對不同的外設(shè)進(jìn)行處理,例如磁盤文件,網(wǎng)絡(luò)連接,甚至是內(nèi)存緩沖區(qū)。字節(jié)流類顯示于表1-1中。
表1-1 字節(jié)流類
流類 含義
BufferedInputStream緩沖輸入流
BufferedOutputStream緩沖輸出流
ByteArrayInputStream從字節(jié)數(shù)組讀取的輸入流
ByteArrayOutputStream向字節(jié)數(shù)組寫入的輸出流
DataInputStream包含讀取Java標(biāo)準(zhǔn)數(shù)據(jù)類型方法的輸入流
DataOutputStream包含編寫Java標(biāo)準(zhǔn)數(shù)據(jù)類型方法的輸出流
FileInputStream讀取文件的輸入流
FileOutputStream寫文件的輸出流
FilterInputStream實現(xiàn)InputStream
FilterOutputStream實現(xiàn)OutputStream
InputStream描述流輸入的抽象類
OutputStream描述流輸出的抽象類
PipedInputStream輸入管道
PipedOutputStream輸出管道
PrintStream包含print()和println()的輸出流
PushbackInputStream 支持向輸入流返回一個字節(jié)的單字節(jié)的“unget”的輸入流
RandomAccessFile支持隨機(jī)文件輸入/輸出
SequenceInputStream兩個或兩個以上順序讀取的輸入流組成的輸入流
抽象類InputStream 和 OutputStream定義了實現(xiàn)其他流類的關(guān)鍵方法。最重要的兩種方法是read()和write(),它們分別對數(shù)據(jù)的字節(jié)進(jìn)行讀寫。兩種方法都在InputStream 和OutputStream中被定義為抽象方法。它們被派生的流類重載。
1.2.2 字符流類
字符流類由兩個類層次結(jié)構(gòu)定義。頂層有兩個抽象類:Reader和Writer。這些抽象類處理統(tǒng)一編碼的字符流。Java中這些類含有多個具體的子類。字符流類如表1-2所示。
表1-2 字符流的輸入/輸出類
抽象類Reader和Writer定義了幾個實現(xiàn)其他流類的關(guān)鍵方法。其中兩個最重要的是read()和write(),它們分別進(jìn)行字符數(shù)據(jù)的讀和寫。這些方法被派生流類重載。
1.3 預(yù)定義流
所有的Java程序自動導(dǎo)入java.lang包。該包定義了一個名為System的類,該類封裝了運(yùn)行時環(huán)境的多個方面。System 同時包含三個預(yù)定義的流變量,in,out和err。這些成員在System中是被定義成public 和static型的,這意味著它們可以不引用特定的System對象而被用于程序的其他部分。
System.out是標(biāo)準(zhǔn)的輸出流。默認(rèn)情況下,它是一個控制臺。System.in是標(biāo)準(zhǔn)輸入,默認(rèn)情況下,它指的是鍵盤。System.err指的是標(biāo)準(zhǔn)錯誤流,它默認(rèn)是控制臺。然而,這些流可以重定向到任何兼容的輸入/輸出設(shè)備。System.in 是inputStream的對象;System.out和System.err是PrintStream的對象。它們都是字節(jié)流,盡管它們用來讀寫外設(shè)的字符。但可以用基于字符的流來包裝它們。
二、讀取控制臺輸入
在Java 1.0中,完成控制臺輸入的惟一途徑是字節(jié)流,使用該方法的老代碼依然存在。今天,運(yùn)用字節(jié)流讀取控制臺輸入在技術(shù)上仍是可行的,但這樣做需要用到不被贊成的方法,這種做法不值得推薦。Java 2中讀取控制臺輸入的首選方法是字符流,它使程序容易符合國際標(biāo)準(zhǔn)并且易于維護(hù)。
Java沒有像標(biāo)準(zhǔn)C的函數(shù)scanf()或C++輸入操作符那樣的統(tǒng)一的控制臺輸入方法。Java中,控制臺輸入由從System.in讀取數(shù)據(jù)來完成。為獲得屬于控制臺的字符流,在BufferedReader對象中包裝System.in。BufferedReader 支持緩沖輸入流查看批注。它最常見的構(gòu)造函數(shù)如下:
BufferedReader(Reader inputReader)
這里,inputReader是鏈接被創(chuàng)建的BufferedReader實例的流。Reader是一個抽象類。它的一個具體的子類是InputStreamReader,該子類把字節(jié)轉(zhuǎn)換成字符查看批注。為獲得鏈接System.in的一個InputStreamReader的對象,用下面的構(gòu)造函數(shù):
InputStreamReader(InputStream inputStream)
因為System .in引用了InputStream 類型的對象,它可以用于inputStream。綜上所述,下面的一行代碼創(chuàng)建了與鍵盤相連的BufferedReader對象。
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
當(dāng)該語句執(zhí)行后,br是通過System.in生成的鏈接控制臺的字符流。
2.1 讀取字符
從BufferedReader讀取字符,用read()。這里所用的read()版本如下:
int read( ) throws IOException
該方法每次執(zhí)行都從輸入流讀取一個字符然后以整型返回。當(dāng)遇到流的末尾時它返回-1??梢钥吹?,它要引發(fā)一個IOException異常。下面的例程演示了read()方法,從控制臺讀取字符直到用戶鍵入“q”:
// Use a BufferedReader to read characters from the console.
import java.io.*;
class BRRead {
public static void main(String args[])
throws IOException
{
char c;
BufferedReader br = new
BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter characters, 'q' to quit.");
// read characters
do {
c = (char) br.read();
System.out.println(c);
} while(c != 'q');
}
}
下面是程序運(yùn)行:
Enter characters, 'q' to quit.
123abcq
1
2
3
a
b
c
q
2.2 讀取字符串
從鍵盤讀取字符串,使用readLine()。它是BufferedReader 類的成員。它的通常形式如下:
String readLine( ) throws IOException
它返回一個String對象。下面的例子闡述了BufferedReader類和readLine()方法;程序讀取和顯示文本的行直到鍵入“stop”:
// Read a string from console using a BufferedReader.
import java.io.*;
class BRReadLines {
public static void main(String args[])
throws IOException
{
// create a BufferedReader using System.in
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
String str;
System.out.println("Enter lines of text.");
System.out.println("Enter 'stop' to quit.");
do {
str = br.readLine();
System.out.println(str);
} while(!str.equals("stop"));
}
}
下面的例程生成了一個小文本編輯器。它創(chuàng)建了一個String對象的數(shù)組,然后依行讀取文本,把文本每一行存入數(shù)組。它將讀取到100行或直到按“stop”才停止。該例運(yùn)用一個BufferedReader類來從控制臺讀取數(shù)據(jù)。
// A tiny editor.
import java.io.*;
class TinyEdit {
public static void main(String args[])
throws IOException
{
// create a BufferedReader using System.in
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
String str[] = new String[100];
System.out.println("Enter lines of text.");
System.out.println("Enter 'stop' to quit.");
for(int i=0; i100; i++) {
str[i] = br.readLine();
if(str[i].equals("stop")) break;
}
System.out.println("\nHere is your file:");
// display the lines
for(int i=0; i100; i++) {
if(str[i].equals("stop")) break;
System.out.println(str[i]);
}
}
}
下面是輸出部分:
Enter lines of text.
Enter ‘stop’ to quit.
This is line one.
This is line two.
Java makes working with strings easy.
Just create String objects.
stop
Here is your file:
This is line one.
This is line two.
Java makes working with strings easy.
Just create String objects.
操作簡單,要求硬件配置低。
量級主要是看容器的依賴性所決定的,依賴性越小,越輕量,
Jim Rivera是 BEA 公司的一位技術(shù)主管,負(fù)責(zé)通過技術(shù)傳播推廣BEA 產(chǎn)品的應(yīng)用。Jim 于1999 年加入BEA,擔(dān)任 BEA WebLogic Server 6、7 和8 版本的技術(shù)產(chǎn)品經(jīng)理。在這個崗位上,Jim 負(fù)責(zé)各種服務(wù)器組件的策略和路線圖,包括 EJB、Web services、XML 和集群。Jim 在dev2dev 上有一個blog。dev2dev 通過電子郵件采訪了 Jim,獲得他對輕量級Java、應(yīng)用程序框架和持久性框架,以及它們與應(yīng)用服務(wù)器上企業(yè)計算的關(guān)系的看法。
輕量級Java
dev2dev: 您是如何定義“輕量級Java”的?
Jim: 我認(rèn)為,在Java 應(yīng)用程序開發(fā)環(huán)境中,“輕量級Java”主要是指兩個東西:簡化的編程模型和更具響應(yīng)能力的容器。輕量級Java 旨在消除與傳統(tǒng) J2EE API 有關(guān)的不必要的復(fù)雜性和限制。它也將縮短應(yīng)用程序的部署時間,這對于支持開發(fā)最佳實踐(比如頻繁單元測試)非常重要。
dev2dev: 對您來說哪種輕量級技術(shù)是最重要的,輕量級Java 對終端用戶有什么幫助?
Jim: 很顯然,控制反轉(zhuǎn) (IoC)模式在這個領(lǐng)域有著重大的影響。使用IoC,開發(fā)人員不需要編寫復(fù)雜的代碼來執(zhí)行查詢、處理基礎(chǔ)架構(gòu)異?;蚬芾磉B接,就能夠解決對象依賴性問題。這有助于簡化代碼、將業(yè)務(wù)邏輯與基礎(chǔ)架構(gòu)分離,從而使應(yīng)用程序更易于維護(hù)。
輕量級Java 的另一個關(guān)鍵特征是,它不會強(qiáng)迫業(yè)務(wù)對象遵循平臺特定接口。這允許開發(fā)人員在普通舊式Java 對象(POJO)中實現(xiàn)業(yè)務(wù)邏輯,從而提高生產(chǎn)率。
與具體的類相反,當(dāng)把開發(fā)的最佳實踐與界面相結(jié)合時,這些特性也使得對代碼進(jìn)行單元測試容易得多。由于業(yè)務(wù)邏輯實現(xiàn)在 POJO中,所以不再需要將對象部署到重量級容器中以在單元測試中練習(xí)它。因此,將對象宿主在諸如 JUnit 之類的簡單測試環(huán)境中和為快速迭代單元測試“模擬”外部依賴性就變得微不足道了。
dev2dev: 作為一個技術(shù)傳播者,您一定目睹了許多新的和已部署的技術(shù)。您是否看到了轉(zhuǎn)向輕量級技術(shù)的趨勢?
Jim: 當(dāng)然。在早期的采用者當(dāng)中,明確地存在轉(zhuǎn)向諸如 Spring、Hibernate 和Beehive 之類框架的趨勢。它在應(yīng)用程序的構(gòu)建方式上有了明顯的不同,對未來 J2EE技術(shù)的方向有著積極的影響。例如,EJB 3.0就基本上是以使得輕量級Java盛行的概念為基礎(chǔ)的。
重量級
dev2dev:人們在想起應(yīng)用服務(wù)器供應(yīng)商時,通常把它們置于“重量級陣營”。我想您正在努力改變這種狀況,對吧?換言之,許多人認(rèn)為應(yīng)用程序供應(yīng)商已經(jīng)在實現(xiàn)重量級組件(比如 EJB 2.0)上付出了很大的代價,它們不愿意輕易放棄這些成果。
Jim: 首先,我認(rèn)為沒有理由放棄在 EJB 上的現(xiàn)有投資,因為在某些場景中它仍然是最好的技術(shù),例如當(dāng)您希望通過 RMI遠(yuǎn)程公開業(yè)務(wù)服務(wù)時。當(dāng)然,諸如 EJB 之類的開放標(biāo)準(zhǔn)在保護(hù)客戶投資方面的價值也不能低估。
已經(jīng)說過,我覺得人們經(jīng)常過分強(qiáng)調(diào) EJB在應(yīng)用服務(wù)器中的實際價值。盡管這一點(diǎn)未必對所有的應(yīng)用服務(wù)器供應(yīng)商都適用,但是 BEA 只投入了相對較少的一部分開發(fā)資源來支持 J2EE API。我們工作最主要的目標(biāo)是為宿主應(yīng)用程序構(gòu)建最可靠、可伸縮和容錯的內(nèi)核。這些品質(zhì)以及分布式事務(wù)服務(wù)、高速消息傳遞、遺留系統(tǒng)集成、高級 Web 服務(wù)、配置管理、診斷和故障排除和高級安全性,代表了 WebLogic Server 的真正價值,而且對總體擁有成本(TCO)有著巨大的影響。幸運(yùn)的是,這些附加值對基于Spring 或Beehive 的應(yīng)用程序的相關(guān)性和適用性與采用EJB 構(gòu)建的應(yīng)用程序是一樣的。雖然輕量級Java 技術(shù)使得應(yīng)用程序的開發(fā)和維護(hù)更容易,但是它們不會代替真正高端應(yīng)用服務(wù)器的品質(zhì)。實際上,我們認(rèn)為輕量級Java 與WebLogic Server 是一致的。
dev2dev: BEA 有沒有一個輕量級 Java 策略?BEA 實現(xiàn)輕量級 Java 的方法是什么?
Jim: 我們的策略是接納所有有利于提高開發(fā)人員生產(chǎn)率、在市場上為部署這些技術(shù)提供最佳平臺的技術(shù)。輕量級 Java有助于降低開發(fā)成本,WebLogic Server 則有助于降低運(yùn)營成本,它們是一個非常強(qiáng)大的組合。
應(yīng)用程序框架
dev2dev:由BEA贊助的Beehive項目顯然是一個輕量級 Java組件模型。您能否談?wù)勱P(guān)于 Beehive 的情況,以及它在你們的整個策略中的地位?
Jim: Beehive是一個應(yīng)用程序框架,致力于使J2EE 應(yīng)用程序和基于SOA 的應(yīng)用程序的開發(fā)更容易,它基于我們發(fā)布WebLogic Workshop 的經(jīng)驗。它基于 POJO 和用于配置依賴性、服務(wù)質(zhì)量等的元數(shù)據(jù)提供一個編程模型。元數(shù)據(jù)以 J2SE 5.0 代碼注解和外部 XML文件的形式獲得支持。存在一些用于訪問 J2EE資源、定義業(yè)務(wù)和 Web 服務(wù)以及基于 MVC模式開發(fā) Web 應(yīng)用程序的組件。在我們努力提高開發(fā)人員生產(chǎn)率、鞏固 Java 整體市場的過程中,Beehive 是非常關(guān)鍵的一部分。
dev2dev: Beehive 可以被認(rèn)為是一個“應(yīng)用程序框架”。在Spring Framework中提供了一種非常流行的輕量級 Java 方法。Spring(以及其他類似的框架)對于 BEA 有多重要?
Jim: 任何能夠幫助我們的客戶提高生產(chǎn)率的東西都對我們非常重要。我們歡迎并且接納這些技術(shù),在適當(dāng)?shù)臅r候也可以在技術(shù)層面上集成或者共享這些技術(shù)。
dev2dev: 你們考慮過明確支持這些框架嗎?
Jim: 就像我原來說過的,WebLogic Server具有很多方面的特性,能夠提供基于輕量級 Java 技術(shù)的應(yīng)用程序。許多都是隱含的,然而在某些情況下,最小量的集成工作就能為輕量級 Java 開發(fā)人員提供重要的價值。舉個例子,當(dāng)今存在的一些適配器允許 Spring 應(yīng)用程序使用 WebLogic Server 的分布式事務(wù)能力,無需改變?nèi)魏螒?yīng)用程序代碼。我們正在調(diào)查許多其他的機(jī)會,當(dāng)然也一直在傾聽客戶的需求。
dev2dev: 我們已經(jīng)看到輕量級框架對EJB 3 的一些影響。您認(rèn)為這會擴(kuò)展到J2EE的其他方面嗎?
Jim: 是的。我認(rèn)為 JSR 175(即Java元數(shù)據(jù))對于簡化 J2EE 編程模型是一種關(guān)鍵的支持技術(shù)。EJB 3.0使用了它,而且它也是 JSR 181(即Web Services 元數(shù)據(jù),一個BEA 倡導(dǎo)的規(guī)范)的基礎(chǔ)。沒有理由相信它會就此停止。
輕量級持久性
dev2dev: IoC 容器看起來是輕量級 Java 的中心。另外的一個關(guān)鍵因素是POJO 和輕量級持久性。您能針對這個問題談?wù)効捶▎幔?/p>
Jim: 同樣,共同的主題是簡化編程模型。沒有比POJO更簡單的了。當(dāng)然,企業(yè)開發(fā)要求我們有能力應(yīng)用附加的品質(zhì),比如持久性規(guī)則、事務(wù)語義和 POJO 的安全約束。盛行很廣的方式是在元數(shù)據(jù)中定義這些品質(zhì),要么作為代碼注解,要么放在外部文件中。
dev2dev: 您是否覺得因為有多種方法用于完成持久性這樣的事情而存在一些危險?比如,我們很快將會有EJB 2、EJB 3、JDO、Hibernate,等等。
Jim: 我認(rèn)為這只是成熟領(lǐng)域的一個實際情況。多年來,J2EE 規(guī)范沒有完全涵蓋這個特定的領(lǐng)域,自然就會導(dǎo)致其他規(guī)范的出現(xiàn)。就我所知道的在 JCP中發(fā)生的事情,我們似乎正在走向統(tǒng)一。這對于整個行業(yè)來說是一件好事。
未來
dev2dev: 您能預(yù)見一下輕量級 Java和 BEA 的未來嗎?
Jim: 我們將會繼續(xù)活躍于這個領(lǐng)域中,既通過諸如 Apache Beehive、XMLBeans、Eclipse和JCP 之類的渠道推動創(chuàng)新,又吸收諸如 Spring 這樣的其他領(lǐng)先技術(shù),并且為了客戶的利益而展開協(xié)作。
艾伯特.愛因斯坦曾經(jīng)說過:“一切都應(yīng)該盡可能地簡單,但是不能更簡單?!贝_實如此,簡化一門理論的基本假設(shè),使我們可以專注于真正關(guān)鍵的地方,這正是一直以來對科學(xué)真理的追求。企業(yè)軟件開發(fā)同樣如此。
提供一個將復(fù)雜的事物(例如,事務(wù)、安全或持久性)對開發(fā)者進(jìn)行隱藏的應(yīng)用框架是簡化企業(yè)軟件開發(fā)的關(guān)鍵。一個設(shè)計良好的框架可以提高代碼重用率、開發(fā)者的生產(chǎn)力及軟件的質(zhì)量。然而,現(xiàn)有J2EE1.4的EJB2.1框架被普遍認(rèn)為設(shè)計差,且過于復(fù)雜。不滿于EJB2.1的框架結(jié)構(gòu),Java開發(fā)者嘗試了各種各樣的中間件服務(wù)傳遞方法。最引人注目的是,以下兩個框架引起了開發(fā)者極大興趣并得到了大量正面的反饋。他們以未來企業(yè)Java應(yīng)用所選框架的姿態(tài)展現(xiàn)。
Spring框架雖然很流行但并不是一個標(biāo)準(zhǔn)的開源框架。它主要由Interface21 Inc開發(fā)和控制。Spring框架結(jié)構(gòu)是基于依賴注入(Dependency Injection (DI))的設(shè)計模式。它可以獨(dú)立或在現(xiàn)有的應(yīng)用服務(wù)器上運(yùn)行,而且大量地使用了xml配置文件
EJB3.0是由Java Community Process (JCP)制訂的標(biāo)準(zhǔn)框架,為所有主要的J2EE廠商支持。JBoss已經(jīng)提供了試用版EJB3.0標(biāo)準(zhǔn)的開源或商業(yè)性質(zhì)實現(xiàn)。EJB3.0充分利用了Java的注釋
這兩個框架結(jié)構(gòu)都有一個共同核心設(shè)計理念:將中間件服務(wù)傳遞給耦合松散的POJOS (Plain Old Java Objects, 簡單潔凈Java對象)。 這樣的框架利用截取執(zhí)行上下文或在運(yùn)行時將服務(wù)對象注入POJO來把應(yīng)用服務(wù)“纏繞”到POJO。POJO本身并不關(guān)心這種“纏繞”,對這種框架結(jié)構(gòu)也沒有什么依賴。因此,開發(fā)者可專注于業(yè)務(wù)邏輯和脫離框架的POJO單元測試。除此之外, 由于POJO并不須要繼承框架的類或?qū)崿F(xiàn)其接口,開發(fā)者能夠極其靈活地搭建繼承結(jié)構(gòu)和建造應(yīng)用。
然而,在擁有同一理念的同時,兩個框架結(jié)構(gòu)使用不同的方式來傳遞POJO服務(wù)。許多書籍或文章都將Spring 或EJB3.0和EJB2.1做了比較,但是對Spring 和EJB3.0的比較并沒有仔細(xì)研究過。在本文中,我將對Srping和EJB3.0框架背后的關(guān)鍵不同處進(jìn)行考察,并討論其優(yōu)缺點(diǎn)。本文的觀點(diǎn)也適用于其它更少為人知的框架,因為他們都是對“耦合松散的POJO”的設(shè)計。希望這篇文章可以幫助你選擇適合你需求的最好框架。
廠商無關(guān)性
開發(fā)者選擇Java平臺其中最引人注目的理由之一:廠商無關(guān)性。EJB3.0正是一套設(shè)計為廠商無關(guān)的開放性標(biāo)準(zhǔn)。EJB3.0標(biāo)準(zhǔn)為所有企業(yè)Java社團(tuán)里開源或商業(yè)性質(zhì)廠商所開發(fā)和支持。它將開發(fā)者與應(yīng)用服務(wù)器實現(xiàn)完全隔離。例如,JBoss的 EJB3.0實現(xiàn)基于Hibernate,Oracle的基于TopLink,但是開發(fā)者并不須要學(xué)習(xí)Hibernate- 或TopLink的具體API來使應(yīng)用可在Jboss或Oracle上運(yùn)行。廠商無關(guān)性使EJB3.0與現(xiàn)今其它POJO中間件框架區(qū)別開來。
但是,正如許多EJB3.0評論家迅速所指出的,在本文撰寫時EJB3.0標(biāo)準(zhǔn)還沒有到達(dá)一個最終版本。大概還有一到兩年的時間EJB3.0才能廣泛地為所有主要J2EE廠商所支持。即使你的應(yīng)用服務(wù)器本身不支持EJB3.0,你仍然可以通過下載安裝”內(nèi)嵌的”EJB3.0產(chǎn)品來運(yùn)行EJB3.0的應(yīng)用。例如,JBoss的內(nèi)嵌EjB3.0是開源產(chǎn)品且可以在任何J2SE5.0兼容的環(huán)境運(yùn)行(例如, 在任何Java服務(wù)器上),此產(chǎn)品正處于軟件測試階段。其它廠商不久也將發(fā)布自己的內(nèi)嵌EJB3.0產(chǎn)品,特別是針對標(biāo)準(zhǔn)中關(guān)于數(shù)據(jù)持久性的部分。
另一方面,Spring一直以來都是非標(biāo)準(zhǔn)的技術(shù),在未來可預(yù)知的一段時間內(nèi)這種情況將持續(xù)下去。雖然你可以在任何應(yīng)用服務(wù)器上使用Spring框架,Spring應(yīng)用會被鎖入在Spring本身和你選擇整合進(jìn)Spring的具體服務(wù)中。
Spring框架是一個開源項目,但同時它有一個XML格式的配置文件和編程接口。當(dāng)然任何一個非標(biāo)準(zhǔn)的產(chǎn)品都會有這種“鎖入”(lock-in)的情況,并不是Spring特有的。但Spring應(yīng)用的長期生存能力仍然還得托Spring這個項目的福(或者是Interface21公司,它雇傭了大部分Spring核心開發(fā)人員)。除此之外,假如你用到任何一個具體的Spring服務(wù),例如,Spring事務(wù)管理器或則Spring MVC,你也會被鎖入到這些API里。
Spring的應(yīng)用對終端用戶是不可知的。例如,對數(shù)據(jù)持久服務(wù),Spring框架兼容不同的DAO和JDBC的模版幫助類,如Hibernate, iBatis, 和 JDO。所以假如你需要為spring應(yīng)用切換在數(shù)據(jù)持久化服務(wù)(例如從JBDC到Hibernate),你需要修改你的代碼以適合新的模版幫助類。
服務(wù)整合
從一個很高的角度上看,Spring框架處于應(yīng)用服務(wù)器和服務(wù)庫的上方。服務(wù)整合的代碼(如,數(shù)據(jù)訪問模板和幫助類)屬于框架,并暴露于應(yīng)用開發(fā)者。相反,EJB3.0框架與應(yīng)用服務(wù)器高度整合,服務(wù)整合代碼也包裝在一個標(biāo)準(zhǔn)接口后面。
因此,實現(xiàn)EJB3.0的廠商可以大大地優(yōu)化整體性能和提升開發(fā)者的體驗。例如,在JBoss EJB3.0的實現(xiàn)中,當(dāng)你在用EntityManager持久化一個Entity Bean時,后臺的Hibernate會話事務(wù)已經(jīng)自動地幫定到調(diào)用方法的JTA 的事務(wù)上,在JTA 事務(wù)提交的同時Hibernate會話事務(wù)也提交了。你甚至可以使用一個簡單的 @PersistenceContext 注釋(稍候例子演示)將EntityManager和它后臺的Hibernate事務(wù)綁定到一個stateful session bean的應(yīng)用事務(wù)中。在一個會話中應(yīng)用事務(wù)橫跨多個線程,這在事務(wù)性網(wǎng)頁應(yīng)用很有用,例如,多頁面的購物車。
由于高度整合的EJB3.0的框架,使簡單、集成的編程接口成為可能。Oracle EJB3.0框架和其后臺的Toplink持久化服務(wù)也同樣程度地整合。
另一個EJB3.0整合服務(wù)的絕好例子就是集群支持。假如你在一個服務(wù)器集群上部署了一個EJB3.0的應(yīng)用,所有容錯(fail-over)、負(fù)載均衡、分布式緩沖和狀態(tài)復(fù)制都已經(jīng)自動為應(yīng)用所獲得可用。后臺的集群支持被隱藏在EJB3.0的框架后面,對EJB3.0開發(fā)者來說這些都是完全透明不可見的。
在Spring里,很難優(yōu)化框架和服務(wù)之間的通訊。例如,為了使用Spring里的聲明事務(wù)服務(wù)來管理Hibernate事務(wù),你必須顯示地在XML文件中配置Spring TransactionManager和Hibernate SessionFactory對象。Spring必須電顯示地管理橫跨多個HTTP請求的事務(wù)。除此之外,沒有別的方法均衡Spring應(yīng)用里的集群。
服務(wù)組合的彈性
由于Spring的服務(wù)整合代碼作為編程接口的一部份暴露在外,應(yīng)用開發(fā)者有按自己需求裝配服務(wù)的彈性。這個特點(diǎn)使你能夠組合自己的輕量級應(yīng)用服務(wù)器。Spring的一個普遍用法就是將Tomcat和Hibernate組合在一起支持?jǐn)?shù)據(jù)庫驅(qū)動的web應(yīng)用。在這種情況,Spring本身提供事務(wù)服務(wù),Hibernat提供持久化服務(wù)——這種設(shè)置創(chuàng)建了一個袖珍型的應(yīng)用服務(wù)器。
EJB3.0應(yīng)用服務(wù)器典型地不提供這種根據(jù)需求任你挑撿服務(wù)的彈性空間。大多數(shù)時間,你得到的只是一系列包裝好的特性,其中一些你可能根本就不需要。但是如果應(yīng)用服務(wù)器像JBoss一樣提供一個模塊性的內(nèi)部設(shè)計,那么你可以只取其中一部分,而把不必要的部分剝?nèi)ァT谌魏吻闆r,去自定義一個功能強(qiáng)大的應(yīng)用服務(wù)器是沒有什么價值的。
當(dāng)然,假如應(yīng)用已經(jīng)超過單個點(diǎn),那么你應(yīng)該加入常用服務(wù)器上的服務(wù),例如,資源池(resource pooling),消息隊列(message queuing)和集群(clustering)。就總體的資源消耗而言,Spring解決方法和其他EJB3.0解決方法一樣是重量級的。
在Spring框架里,具有彈性的服務(wù)裝配使得將虛擬對象而不是真正的業(yè)務(wù)對象綁定到應(yīng)用中做脫離容器的單元測試更簡單。在EJB3.0應(yīng)用中,大多數(shù)組件都是簡單POJO,他們可以很容易地在容器外被測試。但是對于與容器服務(wù)相關(guān)的對象(例如持久化實實體管理器EntityManager)建議用容器內(nèi)測試。因為這樣會比虛擬對象測試方法更簡單,強(qiáng)壯及準(zhǔn)確。
XML Vs.注解
從應(yīng)用開發(fā)者的觀點(diǎn)上來看,Spring的編程開發(fā)接口主要基于XML配置文件而EJB3.0廣泛地應(yīng)用Java注解。XML可以表達(dá)復(fù)雜的關(guān)系,但是它也冗長且不夠健壯;注解簡單明了,但是很難在注解里表達(dá)復(fù)雜或繼承性的關(guān)系。
Spring選擇XML或EJB3.0選擇注解都是有他們兩者框架后的體系結(jié)構(gòu)決定的。因為注解只能容納很少的配置信息,只有整合前的框架(重頭戲都在框架里)才可以把廣泛地使用注解作為配置選擇。正如我們所討論過的,EJB3.0剛好符合這個要求,而Spring作為一個普通的DI框架并不符合。
當(dāng)然,EJB3.0和Spring都相互取長補(bǔ)短,在某種程度上他們都支持XML和注解。例如,在EJB3.0中,XML配置文件作為一個可選的重載機(jī)制來改變注解的默認(rèn)行為。注解也可以配置一些Spring服務(wù)。
通過例子是學(xué)習(xí)XML和注解方式之間差異的最好方法。在下面幾個環(huán)節(jié)里,讓我們來看看Spring和EJB3.0是怎樣提供關(guān)鍵服務(wù)給應(yīng)用的。
聲明性服務(wù)
Spring和EJB3.0都將運(yùn)行時服務(wù)(例如,事務(wù)、安全、日志和配置服務(wù))綁定到應(yīng)用。因為這些服務(wù)于應(yīng)用的業(yè)務(wù)邏輯是沒有直接聯(lián)系,他們只是由應(yīng)用本身管理。換句話說,這些服務(wù)在運(yùn)行時由容器透明地應(yīng)用到應(yīng)用中。開發(fā)者或是管理者配置容器,準(zhǔn)確地告訴它什么時候怎樣應(yīng)用這些服務(wù)。
EJB3.0運(yùn)用Java注解來配置聲明性服務(wù),而Sring使用XML配置文件。在大多數(shù)情況下,EJB3.0注解方式對于這種服務(wù)更簡單明了。這里有一個在EJB3.0中將事務(wù)服務(wù)運(yùn)用到POJO的例子。
public class Foo }
你也可以為一個代碼段聲明多個屬性,應(yīng)用多個服務(wù)。這是一個在EJB3.0里同時應(yīng)用事務(wù)和安全服務(wù)到POJO的例子
1.下載JAVA程序,電腦上下載的JAVA分兩種,1.rar壓縮包,rar壓縮包解壓后包含2個文件:JAR和JAD .2.JAR壓縮包。rar壓縮包比較簡單解壓就可以了,至于JAR就要生成JAD文件了,怎么生成呢!下載JAD生成器,迅雷搜一下一大把,懶得下或下不到的就到“手機(jī)樂園“在線生成(網(wǎng)址就不發(fā)了,百度搜索下)。
2.把JAR和JAD文件一起傳入手機(jī)內(nèi)存卡,方法 4種,1數(shù)據(jù)線,2讀卡器,3藍(lán)牙,4紅外線。常用的是1和2,3和4我家電腦不支持我不懂,講下數(shù)據(jù)線,三星手機(jī)要連接USB要下載安裝PC套件,沒有的買個碟子安裝或網(wǎng)上下載,有讀卡器的就讀卡器,把下載好了的JAR和JAD文件通過USB傳到手機(jī)內(nèi)存卡 Other files文件夾里,沒有的就建一個。傳好后就把卡放回手機(jī)。
3.啟動JAVA安裝,待機(jī)狀態(tài)下輸入*#9998*4678255# .手機(jī)顯示已啟動即可。
4.進(jìn)入手機(jī)內(nèi)存卡的“Other files”夾里,選中JAD后按選項,手機(jī)提示是否安裝,選擇OK .
5.安裝完的游戲自動儲存在JAVA世界 .其他文件夾中的JAR和JAD即可刪除了.留著也行以備不小心刪了軟件可以重新安裝。
安裝方法就是這樣的,根據(jù)多次安裝失敗經(jīng)歷,把安裝JAVA失敗的狀況做了一下總結(jié):
1.一定要用英文字符或數(shù)字為JAR和JAD文件命名,而且命名長度不要太長,越短越好。如果用中文字符起名的話可是安不進(jìn)去文件的.
2.JAVA程序的JAR文件大小,不要超過手機(jī)所限制的大小,否則也是安裝不了.
3.如果前2個條件都滿足,安裝JAVA還是發(fā)生錯誤,則只保留JAR文件,刪除JAD文件.下載JAD生成器重新生成jad文件,再安裝試試.
4.還有一些安裝時候容易搞錯的地方,JAR和JAD文件記得一定是傳入手機(jī)內(nèi)存卡的"Other files",待機(jī)狀態(tài)下輸入指令的時候,手機(jī)會提示"已啟動",這時候是開啟JAVA安裝,再次輸入指令,提示"未啟動",JAVA安裝也就關(guān)閉了.
5.如果條件滿足以上所述,還安裝不起JAVA,就是手機(jī)不支持該JAVA程序了.