源代碼目錄
src
src/javactest/pa/A.java
src/javactest/pb/B.java
其中A引用B
類目錄
classes
src 和classes目錄同級(jí),假設(shè)父目錄為test
(一)關(guān)于javac
(1)先編譯B再編譯A
cd test
javac -d classes src/javactest/pb/B.java
javac -cp classes src/javactest/pa/A.java
(2)使用sourcepath編譯A,如果java有變更,會(huì)重新編譯
cd test
javac -d classes -sourcepath src src/javactest/pa/A.java
或
javac -d classes -sourcepath src -cp classes src/javactest/pa/A.java
(二)關(guān)于jar
(1)創(chuàng)建jar
i)
cd classes
jar cvf javactest.jar .
則jar包生成在classes目錄下
ii)
cd test
jar cvf javactest.jar –C classes .
則jar包生成在test目錄下
注意-C classes相當(dāng)于把當(dāng)前路徑改為classes,jar包中不會(huì)出現(xiàn)classes目錄。
如果:
cd test
jar cvf javactest.jar classes
這里有問題,jar中會(huì)將classes目錄加入
iii) 以自己的manifest.mf來創(chuàng)建jar,在test目錄下創(chuàng)建manifest.mf文件
cd test
jar cvfm javactest.jar manifest.mf –C classes .
(2)列出jar中內(nèi)容
cd test
jar tvf javactest.jar
(3)提取jar中內(nèi)容
cd test
jar xvf javactest.jar META-INF/MANIFEST.MF
(3)更新jar
cd test
jar –uvf javactest.jar images/icon_button.gif
加入images/icon_button.gif
注意:不能加入META-INF/MANIFEST.MF
(4)更新MANIFEST.MF
修改MANIFEST.MF,加入
Main-Class: javactest.pa.A
注意:Main-Class后的冒號(hào)后必須有空格,并且最后必須換行
cd test
jar uvfm javactest.jar META-INF/MANIFEST.MF
(三)關(guān)于java
java –jar javactest.jar
java -cp javactest.jar javactest.pa.A
參考資料
http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_the_JAR_Utility.pdf
http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html
http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javac.html
http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html
http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html
NamedDispatcher
Returns a RequestDispatcher object that acts as a wrapper for the named servlet.
getNamedDispatcher(String) method takes the name of the Servlet as parameter which is declared via Deployment descriptor.
Example: Deployment Descriptor
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>com.example.ServletExample</servlet-class>
</servlet>
RequestDispatcher dispatch = request.getNamedDispatcher(?FirstServlet??);dispatch.forward(request, response);
Note: A servlet instance can determine its name using servletConfig.getServletName(); This method returns the name of the class that implements the Servlet interface or extends the HttpServlet class.
RequestDispatcher
Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path.
RequestDispatcher dispatch = request.getRequestDispatcher("/tes");
Here "/tes" represents the url-pattern element value of the servlet class.
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/tes</url-pattern>
</servlet-mapping>
It represents the path of the servlet class. Since both the base as well as target servlet are in the same package structure by just specifying the url-pattern element value we will be able to access the target servlet.
We shouldn't specify the entire path like
String str = "/WEB-INF/classes/com/example/posr/Test"
RequestDispatcher dispatch = request.getRequestDispatcher(str);
To forward a request to a JSP page we use
RequestDispatcher dispatch = request.getRequestDispatcher("/TestJspOne.jsp");Here "/TestJspOne.jsp" the slash denotes the Jsp page is at the root of the application.
Is Tomcat an application server?
What's the difference between Tomcat and JBoss/Geronimo?
In the strictest sense, one could say: A web server serves up static HTML pages and nothing else. Tomcat is a Servlet/JSP container, and 'Java application servers' are those which support the full JEE (formerly J2EE) stack.
The distinctions between these terms, however, have always been blurry, and continue to become more so over time, and will vary depending on where and with whom your discussion takes place. To understand this requires a little history lesson.
Tomcat started its life as the JServ module for Apache HTTPD (now known as the Apache web server). It was only a servlet container and was incapable of handling web requests on its own. When combined, HTTPD would handle all web requests, would serve up all the static content on its own and forward any dynamic requests to JServ. Httpd was the web server and JServ was the servlet container.
Eventually, JServ was replaced by the Tomcat application server, and a connector was added that allowed Tomcat to operate as a standalone web/application server. At the time Tomcat alone was not fast enough for use in heavy traffic production environments, and didn't support SSL so it was standard practice to combine Tomcat with the Apache web server; much in the same way that JServ and httpd were used. This is still not uncommon today and there are still valid reasons for wanting to do so.
Over time, both Tomcat and the Java Virtual machine, with its Just In Time compiler, have made huge gains in performance, and in many cases running Tomcat as a standalone application server is just as fast or faster than running it in conjunction with the Apache web server. (Testing your application in both configurations under load is the only way to know for sure). Tomcat also has full support for SSL.
So, as you can see, in the case of Tomcat, the lines between application server and web server have blurred over the years.
The lines are also somewhat blurry when you look at the Apache web server itself. It has been hosting large commercial applications using CGI (Common Gateway Interface) for over a dozen years. In addition, many modules, such as the one that allows the popular PHP scripting language to run natively, have become almost standard in an Apache web server installation.
Another popular web/application server, Microsoft's IIS (Internet Information Server), is also used as both a web server and application server. It too can be configured to pass requests for dynamic content to Tomcat via an ISAPI filter. It can also be configured to support popular scripting languages such as PHP, and has native support for Microsoft's own ASP and ASP.NET platforms. Here also, the distinction between web server and application server is blurry.
In some circles, in order to qualify as a "Java application server" the server must support the entire JEE (formerly known as J2EE) stack. Tomcat does not do this. It does not support EJB (Enterprise Java Beans), amongst other APIs. JBoss and Apache's Geronimo application server do support the entire JEE stack. Their servlet and JSP capabilities come from an embedded version of Tomcat (or some other servlet container).
Since one actually contains and relies on the other, the question "Which is better - Tomcat or JBoss" or the phrase, "Tomcat vs JBoss" is not answerable. They are not legitimate comparisons.
Many large, commercial applications are hosted on Tomcat; both with and without an external HTTP web server and without EJB.
To sum it up, the terms do exist but need to be considered in the context of their use in order to understand what they really mean.![]() |
級(jí)別: 初級(jí) 殷 健, 軟件工程師,IBM CSDL 2006 年 7 月 27 日 Web 應(yīng)用要適應(yīng)多語言的需求。不同國家的用戶應(yīng)該可以輸入本國語言的字符, 同時(shí) Web 應(yīng)用又應(yīng)該可以根據(jù)不同的區(qū)域設(shè)置來用多國語言顯示頁面。 當(dāng)前,不同的語言有不同的編碼方式來顯示對(duì)應(yīng)的語言信息,例如中文可以用 GB2312 編碼來顯示,日文可以用 Shift-JIS 編碼來顯示。但 UTF-8 編碼方式幾乎可以包括了所有的語言字符。用 UTF-8 編碼來處理 Web 應(yīng)用信息的輸入和顯示可以使不同 Web 應(yīng)用之間的信息交互標(biāo)準(zhǔn)化,并且可以簡化應(yīng)用的開發(fā)過程。 UTF-8 編碼是一種被廣泛應(yīng)用的編碼,這種編碼致力于把全球的語言納入一個(gè)統(tǒng)一的編碼,目前已經(jīng)將幾種亞洲語言納入。UTF 代表 UCS Transformation Format. UTF-8 采用變長度字節(jié)來表示字符,理論上最多可以到 6 個(gè)字節(jié)長度。UTF-8 編碼兼容了 ASC II(0-127), 也就是說 UTF-8 對(duì)于 ASC II 字符的編碼是和 ASC II 一樣的。對(duì)于超過一個(gè)字節(jié)長度的字符,才用以下編碼規(guī)范: 左邊第一個(gè)字節(jié)1的個(gè)數(shù)表示這個(gè)字符編碼字節(jié)的位數(shù),例如兩位字節(jié)字符編碼樣式為為:110xxxxx 10xxxxxx; 三位字節(jié)字符的編碼樣式為:1110xxxx 10xxxxxx 10xxxxxx.;以此類推,六位字節(jié)字符的編碼樣式為:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx。 xxx 的值由字符編碼的二進(jìn)制表示的位填入。只用最短的那個(gè)足夠表達(dá)一個(gè)字符編碼的多字節(jié)串。例如: Unicode 字符: 00 A9(版權(quán)符號(hào)) = 1010 1001, UTF-8 編碼為:11000010 10101001 = 0x C2 0xA9; 字符 22 60 (不等于符號(hào)) = 0010 0010 0110 0000, UTF-8 編碼為:11100010 10001001 10100000 = 0xE2 0x89 0xA0
在 HTTP 通訊中,在客戶端發(fā)出的請(qǐng)求報(bào)文中,首先設(shè)置的是方法。方法是用來告訴服務(wù)器客戶端發(fā)起的動(dòng)作請(qǐng)求。在請(qǐng)求的報(bào)文頭部,客戶端還可以同時(shí)發(fā)送附加的信息, 比如客戶端使用的瀏覽器和客戶端可以解釋的內(nèi)容類型等。這些信息可以被服務(wù)器端應(yīng)用程序使用以生成響應(yīng)。下面是一個(gè) HTTP 請(qǐng)求消息的示例: 圖1. HTTP 請(qǐng)求消息頭
這個(gè)請(qǐng)求通過 GET 方法來獲取資源 /intro.htm。User-Agent 提供了客戶端瀏覽器的信息,同時(shí) Accept 提供了客戶端可以接受的媒體類型。Accep-language 指出了客戶端瀏覽器的首選語言, Accept-Charset 提供了瀏覽器的首選字符集,服務(wù)器端程序能夠根據(jù)客戶端的要求來生成需要的響應(yīng)。 用戶可以通過配置瀏覽器來設(shè)置首選語言。以 IE 為示例如下: 圖2. 瀏覽器首選語言設(shè)置 ![]() 當(dāng)瀏覽器發(fā)出請(qǐng)求后,可以通過以下代碼來讀取客戶端瀏覽器的首選語言和國家代碼。 圖3. 服務(wù)器端 Servlet 讀取瀏覽器首選國家和語言
服務(wù)器端的輸出結(jié)果為: 圖4. 服務(wù)器端 Servlet 讀取瀏覽器首選國家和語言結(jié)果
當(dāng)服務(wù)器端收到請(qǐng)求后,會(huì)處理請(qǐng)求并發(fā)回應(yīng)答。服務(wù)器通過應(yīng)答消息的頭部來指明諸如服務(wù)器軟件和相應(yīng)的內(nèi)容類型等信息。以下是一個(gè)應(yīng)答消息頭的示例: 圖5.HTTP 應(yīng)答消息頭
Content-type 表明了應(yīng)答消息的 MIME 類型和應(yīng)答消息體的字符集,瀏覽器會(huì)用相應(yīng)的字符集來顯示消息內(nèi)容。例如,在以上示例中字符集是 UTF-8,瀏覽器會(huì)用 UTF-8 編碼來解析和現(xiàn)實(shí)返回的消息體。同時(shí)頁面輸入也會(huì)被用 UTF-8 編碼。
可以通過以下幾種方式來設(shè)置內(nèi)容類型。 如果被訪問的是一個(gè)靜態(tài)的 HTML 頁面。可以通過以下方式來設(shè)置頁面的編碼方式。 圖6. 設(shè)置頁面編碼的靜態(tài) HTML 文件
標(biāo)記"<META http-equiv="Content-Type" content="text/html; charset=UTF-8">" 將應(yīng)答消息頭中 Content_type 設(shè)置為"text/html; charset=UTF-8". 在 Servlet 中,我們可以通過以下方式來設(shè)置應(yīng)答消息的內(nèi)容類型。 圖7.設(shè)置頁面編碼的 Servlet 片斷
代碼行"resp.setContentType("text/html;charset=UTF-8");"將應(yīng)答消息頭中 Content_type 設(shè)置為"text/html; charset=UTF-8"。 我們通過以下示例說明如何在 JSP 中設(shè)置頁面的編碼格式。 圖8. 設(shè)置業(yè)面編碼的 JSP 頁面指令
在這行的頁面指令中的"text/html; charset=UTF-8"將應(yīng)答消息中的"Content-type" 設(shè)置為"text/html; charset=UTF-8"。 "pageEncoding"只是指明了 JSP 頁面本身的編碼格式,指明了 JSP 是以什么編碼方式保存。容器在讀取文件時(shí)將起轉(zhuǎn)化為內(nèi)部使用的 Unicode. 當(dāng)應(yīng)答發(fā)送回至瀏覽器時(shí),容器會(huì)將內(nèi)部使用的 Unicode 轉(zhuǎn)化為在 Content-type 中指定的字符集。 如果沒有指定 PageEncoding,可以通過使用 Content-type 指定的字符集來解釋 JSP 頁面字節(jié)。 為了能正常顯示 UTF-8 編碼的字符,要滿足以下兩個(gè)條件: 1. 通知瀏覽器應(yīng)答消息使用的字符集。 2. 配置瀏覽器使其能有正常顯示 UTF-8 編碼的字體。
HTML 的表單可以接受非西歐語言字符的輸入。當(dāng)需要?jiǎng)?chuàng)建一個(gè)需要接受非西歐語言字符輸入的表單時(shí),必須通知瀏覽器應(yīng)該為用戶輸入使用哪個(gè)字符集,我們可以通過設(shè)置 page 指令的 contentType 屬性來設(shè)置。 我們需要注意的是,當(dāng)表單被提交后,瀏覽器會(huì)將表單字段值轉(zhuǎn)換為指定字符集對(duì)應(yīng)的字節(jié)值,然后根據(jù) HTTP 標(biāo)準(zhǔn) URL 編碼方案對(duì)結(jié)果字節(jié)進(jìn)行編碼。當(dāng)使用 ISO-8859-1 編碼時(shí),任何 a 到 z, A 到 Z 和 0 到 9 之外的字符都會(huì)被轉(zhuǎn)化為十六進(jìn)制格式的字節(jié)值,并在前面加上一個(gè)百分號(hào)(%).例如,如果表單的字符集被設(shè)為 UTF-8, 字符"中文"被傳遞的編碼格式為:"%E4%B8%AD%E6%96%87"。為了對(duì)輸入的信息進(jìn)行處理,容器必須知道瀏覽器是使用什么字符集對(duì)輸入進(jìn)行 編碼的。問題是當(dāng)今多數(shù)的瀏覽器并不提供這種信息,因此你必須自己提供這種信息,并告訴容器用哪個(gè)字符集對(duì)輸入進(jìn)行解碼。 在本文第3部分中說明了如何設(shè)置頁面的顯示編碼,在設(shè)置頁面編碼的同時(shí),也就指定了頁面的輸入方式。如果頁面的顯示被設(shè)置為UTF-8,那么用戶所有的頁面輸入都會(huì)按照 UTF-8 編碼。 服務(wù)器端程序在讀取表單輸入之前要設(shè)定輸入編碼。我們可以看一下示例。 以下是一個(gè)用來提示用戶輸入的 JSP 頁面: 圖9. 用以界面輸入的 JSP 頁面
頁面指令元素的屬性 Content-type 值為"text/html; charset=UTF-8",這會(huì)向?yàn)g覽器指明頁面是按照 UTF-8 編碼的,并且所有用戶通過頁面的輸入也會(huì)按照 UTF-8 編碼。被 Action 所觸發(fā)的 Servlet 如下例所示。 圖10. 用以按 UTF-8 讀取輸入并輸出的 Servlet
通過表單頁面輸入"中文"并提交表單,得到的結(jié)果為: 圖11.正確顯示結(jié)果的頁面 ![]() 如果我們注釋掉語句:resp.setContentType("text/html;charset=UTF-8"), 如下例: 圖12. 用以按非 UTF-8 讀取輸入并輸出的 Servlet
輸入"中文"并提交表單,得到的結(jié)果為: 圖13. 錯(cuò)誤顯示輸入結(jié)果的頁面 ![]() 頁面不能正確顯示 UTF-8 編碼的字符。 在被觸發(fā)的 Servlet 中通過設(shè)置 resp.setContentType("text/html;charset=UTF-8") 來向?yàn)g覽器指明輸出的編碼字符集為 UTF-8,瀏覽器會(huì)用正確的字符集來顯示輸出。如果 Servlet 中沒有顯示的調(diào)用 resp.setContentType("text/html;charset=UTF-8") 來設(shè)定輸出字符集,瀏覽器將不能正確的解碼和顯示輸出。
本文給出了一些在 Web 應(yīng)用開發(fā)中如何顯示和輸入 UTF-8 編碼字符的方法。便于讀者在開發(fā)實(shí)踐中參考。
|
Unicode
是Unicode.org制定的編碼標(biāo)準(zhǔn),目前得到了絕大部分操作系統(tǒng)和編程語言的支持。Unicode.org官方對(duì)Unicode的定義是:
Unicode provides a unique number for every
character。可見,Unicode所做的是為每個(gè)字符定義了一個(gè)相應(yīng)的數(shù)字表示。比如,“a“的Unicode值是0x0061,“一”的
Unicde值是0x4E00,這是最簡單的情況,每個(gè)字符用2個(gè)字節(jié)表示。
Unicode.org定義了百萬個(gè)以上的
字符,如果將所有的字符用統(tǒng)一的格式表示,需要的是4個(gè)字節(jié)。“a“的Unicode表示就會(huì)變成0x00000061,而“一“的Unicode值是
0x00004E00。實(shí)際上,這就是UTF32,Linux操作系統(tǒng)上所使用的Unicode方案。
但是,仔細(xì)分析可
以發(fā)現(xiàn),其實(shí)絕大部分字符只使用2個(gè)字節(jié)就可以表示了。英文的Unicode范圍是0x0000-0x007F,中文的Unicode范圍是0x4E00
-0x9F**,真正需要擴(kuò)展到4個(gè)字節(jié)來表示的字符少之又少,所以有些系統(tǒng)直接使用2個(gè)字節(jié)來表示Unicode。比如Windows系統(tǒng)上,
Unicode就是兩個(gè)字節(jié)的。對(duì)于那些需要4個(gè)字節(jié)才能表示的字符,使用一種代理的手法來擴(kuò)展(其實(shí)就是在低兩個(gè)字節(jié)上做一個(gè)標(biāo)記,表示這是一個(gè)代理,
需要連接上隨后的兩個(gè)字節(jié),才能組成一個(gè)字符)。這樣的好處是大量的節(jié)約了存取空間,也提高了處理的速度。這種Unicode表示方法就是UTF16。一
般在Windows平臺(tái)上,提到Unicode,那就是指UTF16了。
至于UTF16-LE和
UTF16-BE,與計(jì)算機(jī)的CPU構(gòu)架有關(guān)。LE指Little Endian,而BE指Big
Endian。關(guān)于這方面的信息,網(wǎng)上有很多相關(guān)的帖子。我們一般的X86系統(tǒng)都是Little
Endian的,可以認(rèn)為UTF16=UTF16-LE.
由于對(duì)于歐洲和北美,實(shí)際上使用的編碼范圍在0x0000-
0x00FF之間,只需要一個(gè)字符就可以表示所有的字符。即使是使用UTF16來作為內(nèi)存的存取方式,還是會(huì)帶來巨大的空間浪費(fèi),因此就有了UTF8的編
碼方式。這是一種很靈活的編碼,對(duì)于只需要1個(gè)字節(jié)的字符,就使用一個(gè)字節(jié),對(duì)于中日韓等原本需要兩個(gè)字節(jié)才能表示的字符,則通過一個(gè)UTF16-
UTF8的算法實(shí)現(xiàn)相互之間的轉(zhuǎn)換(一般需要3個(gè)字節(jié)才能表示),而對(duì)于需要4個(gè)字節(jié)才能表示的字符,UTF8可以擴(kuò)展到6個(gè)字節(jié)每個(gè)字符。UTF8使用
的算法很有意思,大致映射關(guān)系如下:
UTF-32 UTF8
0x00000000 - 0x0000007F 0xxxxxxx
0x00000080 - 0x000007FF 110xxxxx 10xxxxxx
0x00000800 - 0x0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
0x00010000 - 0x001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0x00200000 - 0x03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0x04000000 - 0x7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
可以發(fā)現(xiàn)這和IP的分址算法很是相像。
由于UTF8可以方便的轉(zhuǎn)換為UTF16和UTF32(不需要碼表,轉(zhuǎn)換算法可以在Unicode.org上找到C代碼)。而且UTF8在每個(gè)操作系統(tǒng)平臺(tái)上的實(shí)現(xiàn)都是一樣的,也不存在跨平臺(tái)的問題,所以UTF8成為跨平臺(tái)的Unicode很好的解決方案。當(dāng)然,對(duì)于中文來說,由于每個(gè)字符需要3個(gè)字節(jié)才能表示,還是有點(diǎn)浪費(fèi)的。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=160958
■DriverManager 類 DriverManager 類是 JDBC 的管理層,作用于用戶和驅(qū)動(dòng)程序之間。它跟蹤可用的驅(qū)動(dòng)程序,并在數(shù)據(jù)庫和相應(yīng)驅(qū)動(dòng)程序之間建立連接。另外,DriverManager 類也處理諸如驅(qū)動(dòng)程序登錄時(shí)間限制及登錄和跟蹤消息的顯示等事務(wù)。 對(duì)于簡單的應(yīng)用程序,一般程序員需要在此類中直接使用的唯一方法是 DriverManager.getConnection。正如名稱所示,該方法將建立與數(shù)據(jù)庫的連接。JDBC 允許用戶調(diào)用 DriverManager 的方法 getDriver、getDrivers 和 registerDriver 及 Driver 的方法 connect。但多數(shù)情況下,讓 DriverManager 類管理建立連接的細(xì)節(jié)為上策。 ■跟蹤可用驅(qū)動(dòng)程序 DriverManager 類包含一列 Driver 類,它們已通過調(diào)用方法 DriverManager.registerDriver 對(duì)自己進(jìn)行了注冊(cè)。所有 Driver 類都必須包含有一個(gè)靜態(tài)部分。它創(chuàng)建該類的實(shí)例,然后在加載該實(shí)例時(shí) DriverManager 類進(jìn)行注冊(cè)。這樣,用戶正常情況下將不會(huì)直接調(diào)用 DriverManager.registerDriver;而是在加載驅(qū)動(dòng)程序時(shí)由驅(qū)動(dòng)程序自動(dòng)調(diào)用。加載 Driver 類,然后自動(dòng)在 DriverManager 中注冊(cè)的方式有兩種: 通過調(diào)用方法 Class.forName。這將顯式地加載驅(qū)動(dòng)程序類。由于這與外部設(shè)置無關(guān),因此推薦使用這種加載驅(qū)動(dòng)程序的方法。以下代碼加載類 acme.db.Driver: Class.forName("acme.db.Driver"); 如果將 acme.db.Driver 編寫為加載時(shí)創(chuàng)建實(shí)例,并調(diào)用以該實(shí)例為參數(shù)的 DriverManager.registerDriver(本該如此),則它在 DriverManager 的驅(qū)動(dòng)程序列表中,并可用于創(chuàng)建連接。 通過將驅(qū)動(dòng)程序添加到 java.lang.System 的屬性 jdbc.drivers 中。這是一個(gè)由 DriverManager 類加載的驅(qū)動(dòng)程序類名的列表,由冒號(hào)分隔:初始化 DriverManager 類時(shí),它搜索系統(tǒng)屬性 jdbc.drivers,如果用戶已輸入了一個(gè)或多個(gè)驅(qū)動(dòng)程序,則 DriverManager 類將試圖加載它們。以下代碼說明程序員如何在 ~/.hotjava/properties 中輸入三個(gè)驅(qū)動(dòng)程序類(啟動(dòng)時(shí),HotJava 將把它加載到系統(tǒng)屬性列表中): jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.test.ourDriver; 對(duì) DriverManager 方法的第一次調(diào)用將自動(dòng)加載這些驅(qū)動(dòng)程序類。 注意:加載驅(qū)動(dòng)程序的第二種方法需要持久的預(yù)設(shè)環(huán)境。如果對(duì)這一點(diǎn)不能保證,則調(diào)用方法 Class.forName 顯式地加載每個(gè)驅(qū)動(dòng)程序就顯得更為安全。這也是引入特定驅(qū)動(dòng)程序的方法,因?yàn)橐坏?DriverManager 類被初始化,它將不再檢查 jdbc.drivers 屬性列表。 在以上兩種情況中,新加載的 Driver 類都要通過調(diào)用 DriverManager.registerDriver 類進(jìn)行自我注冊(cè)。如上所述,加載類時(shí)將自動(dòng)執(zhí)行這一過程。 由于安全方面的原因,JDBC 管理層將跟蹤哪個(gè)類加載器提供哪個(gè)驅(qū)動(dòng)程序。這樣,當(dāng) DriverManager 類打開連接時(shí),它僅使用本地文件系統(tǒng)或與發(fā)出連接請(qǐng)求的代碼相同的類加載器提供的驅(qū)動(dòng)程序。 ■建立連接 加載 Driver 類并在 DriverManager 類中注冊(cè)后,它們即可用來與數(shù)據(jù)庫建立連接。當(dāng)調(diào)用 DriverManager.getConnection 方法發(fā)出連接請(qǐng)求時(shí),DriverManager 將檢查每個(gè)驅(qū)動(dòng)程序,查看它是否可以建立連接。 有時(shí)可能有多個(gè) JDBC 驅(qū)動(dòng)程序可以與給定的 URL 連接。例如,與給定遠(yuǎn)程數(shù)據(jù)庫連接時(shí),可以使用 JDBC-ODBC 橋驅(qū)動(dòng)程序、JDBC 到通用網(wǎng)絡(luò)協(xié)議驅(qū)動(dòng)程序或數(shù)據(jù)庫廠商提供的驅(qū)動(dòng)程序。在這種情況下,測試驅(qū)動(dòng)程序的順序至關(guān)重要,因?yàn)?DriverManager 將使用它所找到的第一個(gè)可以成功連接到給定 URL 的驅(qū)動(dòng)程序。 DriverManager 試圖按注冊(cè)的順序使用每個(gè)驅(qū)動(dòng)程序(jdbc.drivers 中列出的驅(qū)動(dòng)程序總是先注冊(cè))。它將跳過代碼不可信任的驅(qū)動(dòng)程序,除非加載它們的源與試圖打開連接的代碼的源相同。它通過輪流在每個(gè)驅(qū)動(dòng)程序上調(diào)用方法 Driver.connect,并向它們傳遞用戶開始傳遞給方法 DriverManager.getConnection 的 URL 來對(duì)驅(qū)動(dòng)程序進(jìn)行測試,然后連接第一個(gè)認(rèn)出該 URL 的驅(qū)動(dòng)程序。這種方法初看起來效率不高,但由于不可能同時(shí)加載數(shù)十個(gè)驅(qū)動(dòng)程序,因此每次連接實(shí)際只需幾個(gè)過程調(diào)用和字符串比較。以下代碼是通常情況下用驅(qū) 動(dòng)程序(例如 JDBC-ODBC 橋驅(qū)動(dòng)程序)建立連接所需所有步驟的示例: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加載驅(qū)動(dòng)程序 String url = "jdbc:odbc:fred"; DriverManager.getConnection(url, "userID", "passwd"); 8.語句 ■Statement 對(duì)象概述 Statement 對(duì)象用于將 SQL 語句發(fā)送到數(shù)據(jù)庫中。實(shí)際上有三種 Statement 對(duì)象,它們都作為在給定連接上執(zhí)行 SQL 語句的包容器:Statement、PreparedStatement(它從 Statement 繼承而來)和 CallableStatement(它從 PreparedStatement 繼承而來)。它們都專用于發(fā)送特定類型的 SQL 語句: Statement 對(duì)象用于執(zhí)行不帶參數(shù)的簡單 SQL 語句;PreparedStatement 對(duì)象用于執(zhí)行帶或不帶 IN 參數(shù)的預(yù)編譯 SQL 語句;CallableStatement 對(duì)象用于執(zhí)行對(duì)數(shù)據(jù)庫已存儲(chǔ)過程的調(diào)用。 Statement 接口提供了執(zhí)行語句和獲取結(jié)果的基本方法。PreparedStatement 接口添加了處理 IN 參數(shù)的方法;而 CallableStatement 添加了處理 OUT 參數(shù)的方法。 ■創(chuàng)建 Statement 對(duì)象 建立了到特定數(shù)據(jù)庫的連接之后,就可用該連接發(fā)送 SQL 語句。Statement 對(duì)象用 Connection 的方法 createStatement 創(chuàng)建,如下列代碼段中所示: Connection con = DriverManager.getConnection(url, "sunny", ""); Statement stmt = con.createStatement(); 為了執(zhí)行 Statement 對(duì)象,被發(fā)送到數(shù)據(jù)庫的 SQL 語句將被作為參數(shù)提供給 Statement 的方法: ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table2"); ■使用 Statement 對(duì)象執(zhí)行語句 Statement 接口提供了三種執(zhí)行 SQL 語句的方法:executeQuery、executeUpdate 和 execute。使用哪一個(gè)方法由 SQL 語句所產(chǎn)生的內(nèi)容決定。 方法 executeQuery 用于產(chǎn)生單個(gè)結(jié)果集的語句,例如 SELECT 語句。 方法 executeUpdate 用于執(zhí)行 INSERT、UPDATE 或 DELETE 語句以及 SQL DDL(數(shù)據(jù)定義語言)語句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 語句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一個(gè)整數(shù),指示受影響的行數(shù)(即更新計(jì)數(shù))。對(duì)于 CREATE TABLE 或 DROP TABLE 等不操作行的語句,executeUpdate 的返回值總為零。 方法 execute 用于執(zhí)行返回多個(gè)結(jié)果集、多個(gè)更新計(jì)數(shù)或二者組合的語句。 執(zhí)行語句的所有方法都將關(guān)閉所調(diào)用的 Statement 對(duì)象的當(dāng)前打開結(jié)果集(如果存在)。這意味著在重新執(zhí)行 Statement 對(duì)象之前,需要完成對(duì)當(dāng)前 ResultSet 對(duì)象的處理。 應(yīng)注意,繼承了 Statement 接口中所有方法的 PreparedStatement 接口都有自己的 executeQuery、executeUpdate 和 execute 方法。Statement 對(duì)象本身不包含 SQL 語句,因而必須給 Statement.execute 方法提供 SQL 語句作為參數(shù)。PreparedStatement 對(duì)象并不將 SQL 語句作為參數(shù)提供給這些方法,因?yàn)樗鼈円呀?jīng)包含預(yù)編譯 SQL 語句。CallableStatement 對(duì)象繼承這些方法的 PreparedStatement 形式。對(duì)于這些方法的 PreparedStatement 或 CallableStatement 版本,使用查詢參數(shù)將拋出 SQLException。 ■語句完成 當(dāng)連接處于自動(dòng)提交模式時(shí),其中所執(zhí) 行的語句在完成時(shí)將自動(dòng)提交或還原。語句在已執(zhí)行且所有結(jié)果返回時(shí),即認(rèn)為已完成。對(duì)于返回一個(gè)結(jié)果集的 executeQuery 方法,在檢索完 ResultSet 對(duì)象的所有行時(shí)該語句完成。對(duì)于方法 executeUpdate,當(dāng)它執(zhí)行時(shí)語句即完成。但在少數(shù)調(diào)用方法 execute 的情況中,在檢索所有結(jié)果集或它生成的更新計(jì)數(shù)之后語句才完成。 有些 DBMS 將已存儲(chǔ)過程中的每條語句視為獨(dú)立的語句;而另外一些則將整個(gè)過程視為一個(gè)復(fù)合語句。在啟用自動(dòng)提交時(shí),這種差別就變得非常重要,因?yàn)樗绊懯裁磿r(shí)候調(diào)用 commit 方法。在前一種情況中,每條語句單獨(dú)提交;在后一種情況中,所有語句同時(shí)提交。 ■關(guān)閉 Statement 對(duì)象 Statement 對(duì)象將由 Java 垃圾收集程序自動(dòng)關(guān)閉。而作為一種好的編程風(fēng)格,應(yīng)在不需要 Statement 對(duì)象時(shí)顯式地關(guān)閉它們。這將立即釋放 DBMS 資源,有助于避免潛在的內(nèi)存問題。 9.結(jié)果設(shè)置 ■概述 ResultSet 包含符合 SQL 語句中條件的所有行,并且它通過一套 get 方法(這些 get 方法可以訪問當(dāng)前行中的不同列)提供了對(duì)這些行中數(shù)據(jù)的訪問。ResultSet.next 方法用于移動(dòng)到 ResultSet 中的下一行,使下一行成為當(dāng)前行。 ■行和光標(biāo) ResultSet 維護(hù)指向其當(dāng)前數(shù)據(jù)行的光標(biāo)。每調(diào)用一次 next 方法,光標(biāo)向下移動(dòng)一行。最初它位于第一行之前,因此第一次調(diào)用 next 將把光標(biāo)置于第一行上,使它成為當(dāng)前行。隨著每次調(diào)用 next 導(dǎo)致光標(biāo)向下移動(dòng)一行,按照從上至下的次序獲取 ResultSet 行。在 ResultSet 對(duì)象或其父輩 Statement 對(duì)象關(guān)閉之前,光標(biāo)一直保持有效。在 SQL 中,結(jié)果表的光標(biāo)是有名字的。如果數(shù)據(jù)庫允許定位更新或定位刪除,則需要將光標(biāo)的名字作為參數(shù)提供給更新或刪除命令。可通過調(diào)用方法 getCursorName 獲得光標(biāo)名。 注意:不是所有 DBMS支持定位更新和刪除。可使用 DatabaseMetaData.supportsPositionedDelete 和 supportsPositionedUpdate 方法來檢查特定連接是否支持這些操作。當(dāng)支持這些操作時(shí),DBMS/驅(qū)動(dòng)程序必須確保適當(dāng)鎖定選定行,以使定位更新不會(huì)導(dǎo)致更新異常或其它并發(fā)問題。 ■列 方法 getXXX 提供了獲取當(dāng)前行中某列值的途徑。在每一行內(nèi),可按任何次序獲取列值。但為了保證可移植性,應(yīng)該從左至右獲取列值,并且一次性地讀取列值。列名或列號(hào)可用 于標(biāo)識(shí)要從中獲取數(shù)據(jù)的列。例如,如果 ResultSet 對(duì)象 rs 的第二列名為“title”,并將值存儲(chǔ)為字符串,則下列任一代碼將獲取存儲(chǔ)在該列中的值: String s = rs.getString("title"); String s = rs.getString(2); 注意列是從左至右編號(hào)的,并且從列 1 開始。同時(shí),用作 getXXX 方法的輸入的列名不區(qū)分大小寫。 提供使用列名這個(gè)選項(xiàng)的目的是為了讓在查詢中指定列名的用戶可使用相同的名字作為 getXXX 方法的參數(shù)。另一方面,如果 select 語句未指定列名(例如在“select * from table1”中或列是導(dǎo)出的時(shí)),則應(yīng)該使用列號(hào)。這些情況下,用戶將無法確切知道列名。 有些情況下,SQL 查詢返回的結(jié)果集中可能有多個(gè)列具有相同的名字。如果列名用作 getXXX 方法的參數(shù),則 getXXX 將返回第一個(gè)匹配列名的值。因而,如果多個(gè)列具有相同的名字,則需要使用列索引來確保檢索了正確的列值。這時(shí),使用列號(hào)效率要稍微高一些。 ■數(shù)據(jù)類型和轉(zhuǎn)換 對(duì)于 getXXX 方法,JDBC 驅(qū)動(dòng)程序試圖將基本數(shù)據(jù)轉(zhuǎn)換成指定 Java 類型,然后返回適合的 Java 值。例如,如果 getXXX 方法為 getString,而基本數(shù)據(jù)庫中數(shù)據(jù)類型為 VARCHAR,則 JDBC 驅(qū)動(dòng)程序?qū)?VARCHAR 轉(zhuǎn)換成 Java String。getString 的返回值將為 Java String 對(duì)象。可使用 ResultSet.getXXX 方法獲取常見的 JDBC 數(shù)據(jù)類型。 準(zhǔn)備語句 ■概述 該 PreparedStatement 接口繼承 Statement,并與之在兩方面有所不同: PreparedStatement 實(shí)例包含已編譯的 SQL 語句。這就是使語句“準(zhǔn)備好”。 包含于 PreparedStatement 對(duì)象中的 SQL 語句可具有一個(gè)或多個(gè) IN 參數(shù)。IN 參數(shù)的值在 SQL 語句創(chuàng)建時(shí)未被指定。相反的,該語句為每個(gè) IN 參數(shù)保留一個(gè)問號(hào)(“?”)作為占位符。每個(gè)問號(hào)的值必須在該語句執(zhí)行之前,通過適當(dāng)?shù)? setXXX 方法來提供。 由于 PreparedStatement 對(duì)象已預(yù)編譯過,所以其執(zhí)行速度要快于 Statement 對(duì)象。因此,多次執(zhí)行的 SQL 語句經(jīng)常創(chuàng)建為 PreparedStatement 對(duì)象,以提高效率。 作為 Statement 的子類,PreparedStatement 繼承了 Statement 的所有功能。另外它還添加了一整套方法,用于設(shè)置發(fā)送給數(shù)據(jù)庫以取代 IN 參數(shù)占位符的值。同時(shí),三種方法 execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要參數(shù)。這些方法的 Statement 形式(接受 SQL 語句參數(shù)的形式)不應(yīng)該用于 PreparedStatement 對(duì)象。 ■創(chuàng)建 PreparedStatement 對(duì)象 以下的代碼段(其中 con 是 Connection 對(duì)象)創(chuàng)建包含帶兩個(gè) IN 參數(shù)占位符的 SQL 語句的 PreparedStatement 對(duì)象: PreparedStatement pstmt = con.prepareStatement( "UPDATE table4 SET m = ? WHERE x = ?"); pstmt 對(duì)象包含語句 "UPDATE table4 SET m = ? WHERE x = ?",它已發(fā)送給 DBMS,并為執(zhí)行作好了準(zhǔn)備。 ■傳遞 IN 參數(shù) 在執(zhí)行 PreparedStatement 對(duì)象之前,必須設(shè)置每個(gè) ? 參數(shù)的值。這可通過調(diào)用 setXXX 方法來完成,其中 XXX 是與該參數(shù)相應(yīng)的類型。例如,如果參數(shù)具有 Java 類型 long,則使用的方法就是 setLong。setXXX 方法的第一個(gè)參數(shù)是要設(shè)置的參數(shù)的序數(shù)位置,第二個(gè)參數(shù)是設(shè)置給該參數(shù)的值。例如,以下代碼將第一個(gè)參數(shù)設(shè)為 123456789,第二個(gè)參數(shù)設(shè)為 100000000: pstmt.setLong(1, 123456789); pstmt.setLong(2, 100000000); 一旦設(shè)置了給定語句的參數(shù)值,就可用它多次執(zhí)行該語句,直到調(diào)用 clearParameters 方法清除它為止。 在連接的缺省模式下(啟用自動(dòng)提交),當(dāng)語句完成時(shí)將自動(dòng)提交或還原該語句。 如果基本數(shù)據(jù)庫和驅(qū)動(dòng)程序在語句提交之后仍保持這些語句的打開狀態(tài),則同一個(gè) PreparedStatement 可執(zhí)行多次。如果這一點(diǎn)不成立,那么試圖通過使用 PreparedStatement 對(duì)象代替 Statement 對(duì)象來提高性能是沒有意義的。 利用 pstmt(前面創(chuàng)建的 PreparedStatement 對(duì)象),以下代碼例示了如何設(shè)置兩個(gè)參數(shù)占位符的值并執(zhí)行 pstmt 10 次。如上所述,為做到這一點(diǎn),數(shù)據(jù)庫不能關(guān)閉 pstmt。在該示例中,第一個(gè)參數(shù)被設(shè)置為 "Hi"并保持為常數(shù)。在 for 循環(huán)中,每次都將第二個(gè)參數(shù)設(shè)置為不同的值:從 0 開始,到 9 結(jié)束。 pstmt.setString(1, "Hi"); for (int i = 0; i < 10; i++) { pstmt.setInt(2, i); int rowCount = pstmt.executeUpdate(); } ■IN 參數(shù)中數(shù)據(jù)類型的一致性 setXXX 方法中的 XXX 是 Java 類型。它是一種隱含的 JDBC 類型(一般 SQL 類型),因?yàn)轵?qū)動(dòng)程序?qū)?Java 類型映射為相應(yīng)的 JDBC 類型(遵循該 JDBC Guide中§8.6.2 “映射 Java 和 JDBC 類型”表中所指定的映射),并將該 JDBC 類型發(fā)送給數(shù)據(jù)庫。例如,以下代碼段將 PreparedStatement 對(duì)象 pstmt 的第二個(gè)參數(shù)設(shè)置為 44,Java 類型為 short: pstmt.setShort(2, 44); 驅(qū)動(dòng)程序?qū)?44 作為 JDBC SMALLINT 發(fā)送給數(shù)據(jù)庫,它是 Java short 類型的標(biāo)準(zhǔn)映射。 程序員的責(zé)任是確保將每個(gè) IN 參數(shù)的 Java 類型映射為與數(shù)據(jù)庫所需的 JDBC 數(shù)據(jù)類型兼容的 JDBC 類型。不妨考慮數(shù)據(jù)庫需要 JDBC SMALLINT 的情況。如果使用方法 setByte ,則驅(qū)動(dòng)程序?qū)?JDBC TINYINT 發(fā)送給數(shù)據(jù)庫。這是可行的,因?yàn)樵S多數(shù)據(jù)庫可從一種相關(guān)的類型轉(zhuǎn)換為另一種類型,并且通常 TINYINT 可用于 SMALLINT 適用的任何地方。然而,對(duì)于要適用于盡可能多的數(shù)據(jù)庫的應(yīng)用程序,最好使用與數(shù)據(jù)庫所需的確切的 JDBC 類型相應(yīng)的 Java 類型。如果所需的 JDBC 類型是 SMALLINT,則使用 setShort 代替 setByte 將使應(yīng)用程序的可移植性更好。 ■ JDBC URL JDBC URL 提供了一種標(biāo)識(shí)數(shù)據(jù)庫的方法,可以使相應(yīng)的驅(qū)動(dòng)程序能識(shí)別該數(shù)據(jù)庫并與之建立連接。實(shí)際上,驅(qū)動(dòng)程序編程員將決定用什么 JDBC URL 來標(biāo)識(shí)特定的驅(qū)動(dòng)程序。用戶不必關(guān)心如何來形成 JDBC URL;他們只須使用與所用的驅(qū)動(dòng)程序一起提供的 URL 即可。JDBC 的作用是提供某些約定,驅(qū)動(dòng)程序編程員在構(gòu)造他們的 JDBC URL 時(shí)應(yīng)該遵循這些約定。 (1) 由于 JDBC URL 要與各種不同的驅(qū)動(dòng)程序一起使用,因此這些約定應(yīng)非常靈活。它們應(yīng)允許不同的驅(qū)動(dòng)程序使用不同的方案來命名數(shù)據(jù)庫。例如, odbc 子協(xié)議允許(但并不是要求) URL 含有屬性值。 (2) JDBC URL 應(yīng)允許驅(qū)動(dòng)程序編程員將一切所需的信息編入其中。這樣就可以讓要與給定數(shù)據(jù)庫對(duì)話的 applet 打開數(shù)據(jù)庫連接,而無須要求用戶去做任何系統(tǒng)管理工作。 (3) JDBC URL 應(yīng)允許某種程度的間接性。也就是說,JDBC URL 可指向邏輯主機(jī)或數(shù)據(jù)庫名,而這種邏輯主機(jī)或數(shù)據(jù)庫名將由網(wǎng)絡(luò)命名系統(tǒng)動(dòng)態(tài)地轉(zhuǎn)換為實(shí)際的名稱。這可以使系統(tǒng)管理員不必將特定主機(jī)聲明為 JDBC 名稱的一部份。網(wǎng)絡(luò)命名服務(wù)(例如 DNS、 NIS 和 DCE )有多種,而對(duì)于使用哪種命名服務(wù)并無限制。 JDBC URL 的標(biāo)準(zhǔn)語法如下所示。 它由三部分組成,各部分間用冒號(hào)分隔:jdbc:< 子協(xié)議 >:< 子名稱 > JDBC URL 的三個(gè)部分可分解如下: jdbc ─ 協(xié)議。JDBC URL 中的協(xié)議總是 jdbc。 <子協(xié)議> ─ 驅(qū)動(dòng)程序名或數(shù)據(jù)庫連接機(jī)制(這種機(jī)制可由一個(gè)或多個(gè)驅(qū)動(dòng)程序支持)的名稱。子協(xié)議名的典型示例是 "odbc",該名稱是為用于指定 ODBC 風(fēng)格的數(shù)據(jù)資源名稱的 URL 專門保留的。例如,為了通過 JDBC-ODBC 橋來訪問某個(gè)數(shù)據(jù)庫,可以用如下所示的 URL: jdbc:odbc:fred 本例中,子協(xié)議為 "odbc",子名稱 "fred" 是本地 ODBC 數(shù)據(jù)資源。 如果要用網(wǎng)絡(luò)命名服務(wù)(這樣 JDBC URL 中的數(shù)據(jù)庫名稱不必是實(shí)際名稱),則命名服務(wù)可以作為子協(xié)議。例如,可用如下所示的 URL : jdbc:dcenaming:accounts-payable 本例中,該 URL 指定了本地 DCE 命名服務(wù)應(yīng)該將 數(shù)據(jù)庫名稱 "accounts-payable" 解析為更為具體的 可用于連接真實(shí)數(shù)據(jù)庫的名稱。 <子名稱> ─ 一種標(biāo)識(shí)數(shù)據(jù)庫的方法。子名稱可以依不同的子協(xié)議而變化。它還可以有子名稱的子名稱(含有驅(qū)動(dòng)程序編程員所選的任何內(nèi)部語法)。使用子名稱的目的是為定位 數(shù)據(jù)庫提供足夠的信息。前例中,因?yàn)?ODBC 將提供其余部份的信息,因此用 "fred" 就已足夠。然而,位于遠(yuǎn)程服務(wù)器上的數(shù)據(jù)庫需要更多的信息。例如,如果數(shù)據(jù)庫是通過 Internet 來訪問的,則在 JDBC URL 中應(yīng)將網(wǎng)絡(luò)地址作為子名稱的一部份包括進(jìn)去,且必須遵循如下所示的標(biāo)準(zhǔn) URL 命名約定: //主機(jī)名:端口/子協(xié)議 假設(shè) "dbnet" 是個(gè)用于將某個(gè)主機(jī)連接到 Internet 上的協(xié)議,則 JDBC URL 類似: jdbc:dbnet://wombat:356/fred ■ "odbc" 子協(xié)議 子協(xié)議 odbc 是一種特殊情況。它是為用于指定 ODBC 風(fēng)格的數(shù)據(jù)資源名稱的 URL 而保留的,并具有下列特性:允許在子名稱(數(shù)據(jù)資源名稱)后面指定任意多個(gè)屬性值。odbc 子協(xié)議的完整語法為: jdbc:odbc:< 數(shù)據(jù)資源名稱 >[;< 屬性名 >=< 屬性值 >]* 因此,以下都是合法的 jdbc:odbc 名稱: jdbc:odbc:qeor7 jdbc:odbc:wombat jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER jdbc:odbc:qeora;UID=kgh;PWD=fooey ■注冊(cè)子協(xié)議 驅(qū)動(dòng)程序編程員可保留某個(gè)名稱以將之用作 JDBC URL 的子協(xié)議名。當(dāng) DriverManager 類將此名稱加到已注冊(cè)的驅(qū)動(dòng)程序清單中時(shí),為之保留該名稱的驅(qū)動(dòng)程序應(yīng)能識(shí)別該名稱并與它所標(biāo)識(shí)的數(shù)據(jù)庫建立連接。例如,odbc 是為 JDBC- ODBC 橋而保留的。示例之二,假設(shè)有個(gè) Miracle 公司,它可能會(huì)將 "miracle" 注冊(cè)為連接到其 Miracle DBMS 上的 JDBC 驅(qū)動(dòng)程序的子協(xié)議,從而使其他人都無法使用這個(gè)名稱。 |
1 |
public interface HogeIF { |
1 |
public class Hoge implements |
1 |
HogeIF hoge = new Hoge(); |
1 |
public class HogeProxy |
1 |
before |
1 |
import |
1 |
HogeIF hoge = (HogeIF)DynamicHogeProxy |
1 |
|
1 |
HogeIF hoge = (HogeIF)DynamicHogeProxy |