啦啦啦中文在线观看日本,日韩免费一区二区,亚洲午夜久久久久http://www.aygfsteel.com/shypwang/category/25145.htmlzh-cnFri, 21 Mar 2008 17:42:28 GMTFri, 21 Mar 2008 17:42:28 GMT60使用.bat文件在Windows下運行Java程序時怎樣避免DOS窗口 http://www.aygfsteel.com/shypwang/articles/187636.html妖人妖人Fri, 21 Mar 2008 02:17:00 GMThttp://www.aygfsteel.com/shypwang/articles/187636.htmlhttp://www.aygfsteel.com/shypwang/comments/187636.htmlhttp://www.aygfsteel.com/shypwang/articles/187636.html#Feedback0http://www.aygfsteel.com/shypwang/comments/commentRss/187636.htmlhttp://www.aygfsteel.com/shypwang/services/trackbacks/187636.html使用.bat文件在Windows下運行Java程序時怎樣避免DOS窗口 我們在啟動腳本中一般使用類似如下的命令執(zhí)行一個Java程序:
    java xxx.xxx.MailClass.class
或:
    java -jar xxx.jar
這樣在Java程序啟動時,加載的DOS窗口一直出現(xiàn),直到你關閉了Java程序才一起關閉。

很多朋友詢問怎樣才能避免這個DOS窗口,你只需要把.bat中的啟動命名修改為:
    start javaw xxx.xxx.MailClass.class
或:
    start javaw -jar xxx.jar
即可。


注:DOS窗口還是會一閃而過,因為javaw是一個需要dos加載的命令。


妖人 2008-03-21 10:17 發(fā)表評論
]]>
1 java,javac,jar 命令http://www.aygfsteel.com/shypwang/articles/187633.html妖人妖人Fri, 21 Mar 2008 02:07:00 GMThttp://www.aygfsteel.com/shypwang/articles/187633.htmlhttp://www.aygfsteel.com/shypwang/comments/187633.htmlhttp://www.aygfsteel.com/shypwang/articles/187633.html#Feedback0http://www.aygfsteel.com/shypwang/comments/commentRss/187633.htmlhttp://www.aygfsteel.com/shypwang/services/trackbacks/187633.html 

1 java,javac,jar 命令

源代碼目錄

src

src/javactest/pa/A.java

src/javactest/pb/B.java

其中A引用B

類目錄

classes

src classes目錄同級,假設父目錄為test

(一)關于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有變更,會重新編譯

     cd test

     javac -d classes -sourcepath src src/javactest/pa/A.java

    

     javac -d classes -sourcepath src -cp classes src/javactest/pa/A.java

(二)關于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相當于把當前路徑改為classesjar包中不會出現(xiàn)classes目錄。

如果:

cd test

    jar cvf javactest.jar classes

這里有問題,jar中會將classes目錄加入

iii) 以自己的manifest.mf來創(chuàng)建jar,在test目錄下創(chuàng)建manifest.mf文件

cd test

     jar cvfm javactest.jar manifest.mf –C classes .

2)列出jar中內容

   cd test

   jar tvf javactest.jar

3)提取jar中內容

   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后的冒號后必須有空格,并且最后必須換行

cd test

jar uvfm javactest.jar META-INF/MANIFEST.MF

(三)關于java

   java –jar javactest.jar

java -cp javactest.jar javactest.pa.A

參考資料

http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_CLASSPATH_and_SOURCEPATH.html

http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_CLASSPATH_and_Other_APIs.pdf

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

2 jar file specification

http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html

 



妖人 2008-03-21 10:07 發(fā)表評論
]]>
ConnectionPool,Dao,DataSource關系http://www.aygfsteel.com/shypwang/articles/154624.html妖人妖人Sun, 21 Oct 2007 00:29:00 GMThttp://www.aygfsteel.com/shypwang/articles/154624.htmlhttp://www.aygfsteel.com/shypwang/comments/154624.htmlhttp://www.aygfsteel.com/shypwang/articles/154624.html#Feedback0http://www.aygfsteel.com/shypwang/comments/commentRss/154624.htmlhttp://www.aygfsteel.com/shypwang/services/trackbacks/154624.html ConnectionPool 為了管理Connection
Dao 為了將Business logic和Database logic 分離
將ConnectionPool放在naming space 中,是為了可以Globally取得ConnectionPool

在j2ee開發(fā)中,一般用DataSource subsystem取代ConnectionPool,并且注冊在JNDI中,Dao使用DataSource。
DataSource也是用來管理Connection的

妖人 2007-10-21 08:29 發(fā)表評論
]]>
What is the difference between the getRequestDispatcher(String) and getNamedDispatcher(String) methods in the ServletContext Class?http://www.aygfsteel.com/shypwang/articles/154621.html妖人妖人Sun, 21 Oct 2007 00:19:00 GMThttp://www.aygfsteel.com/shypwang/articles/154621.htmlhttp://www.aygfsteel.com/shypwang/comments/154621.htmlhttp://www.aygfsteel.com/shypwang/articles/154621.html#Feedback0http://www.aygfsteel.com/shypwang/comments/commentRss/154621.htmlhttp://www.aygfsteel.com/shypwang/services/trackbacks/154621.htmlWhat is the difference between the getRequestDispatcher(String) and getNamedDispatcher(String) methods in the ServletContext Class?

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.

妖人 2007-10-21 08:19 發(fā)表評論
]]>
Web Vs Application Server http://www.aygfsteel.com/shypwang/articles/154620.html妖人妖人Sun, 21 Oct 2007 00:15:00 GMThttp://www.aygfsteel.com/shypwang/articles/154620.htmlhttp://www.aygfsteel.com/shypwang/comments/154620.htmlhttp://www.aygfsteel.com/shypwang/articles/154620.html#Feedback0http://www.aygfsteel.com/shypwang/comments/commentRss/154620.htmlhttp://www.aygfsteel.com/shypwang/services/trackbacks/154620.html Web Vs Application Server   

What's the difference between a web server, an application server, and a servlet container?

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.

妖人 2007-10-21 08:15 發(fā)表評論
]]>
UTF-8 字符處理在 Web 開發(fā)中的應用http://www.aygfsteel.com/shypwang/articles/153237.html妖人妖人Tue, 16 Oct 2007 05:12:00 GMThttp://www.aygfsteel.com/shypwang/articles/153237.htmlhttp://www.aygfsteel.com/shypwang/comments/153237.htmlhttp://www.aygfsteel.com/shypwang/articles/153237.html#Feedback0http://www.aygfsteel.com/shypwang/comments/commentRss/153237.htmlhttp://www.aygfsteel.com/shypwang/services/trackbacks/153237.html

UTF-8 字符處理在 Web 開發(fā)中的應用

developerWorks
文檔選項

未顯示需要 JavaScript 的文檔選項

將此頁作為電子郵件發(fā)送

將此頁作為電子郵件發(fā)送



級別: 初級

殷 健, 軟件工程師,IBM CSDL

2006 年 7 月 27 日

Web 應用要適應多語言的需求。不同國家的用戶應該可以輸入本國語言的字符, 同時 Web 應用又應該可以根據(jù)不同的區(qū)域設置來用多國語言顯示頁面。 當前,不同的語言有不同的編碼方式來顯示對應的語言信息,例如中文可以用 GB2312 編碼來顯示,日文可以用 Shift-JIS 編碼來顯示。但 UTF-8 編碼方式幾乎可以包括了所有的語言字符。用 UTF-8 編碼來處理 Web 應用信息的輸入和顯示可以使不同 Web 應用之間的信息交互標準化,并且可以簡化應用的開發(fā)過程。

UTF-8 編碼介紹

UTF-8 編碼是一種被廣泛應用的編碼,這種編碼致力于把全球的語言納入一個統(tǒng)一的編碼,目前已經將幾種亞洲語言納入。UTF 代表 UCS Transformation Format.

UTF-8 采用變長度字節(jié)來表示字符,理論上最多可以到 6 個字節(jié)長度。UTF-8 編碼兼容了 ASC II(0-127), 也就是說 UTF-8 對于 ASC II 字符的編碼是和 ASC II 一樣的。對于超過一個字節(jié)長度的字符,才用以下編碼規(guī)范:

左邊第一個字節(jié)1的個數(shù)表示這個字符編碼字節(jié)的位數(shù),例如兩位字節(jié)字符編碼樣式為為:110xxxxx 10xxxxxx; 三位字節(jié)字符的編碼樣式為:1110xxxx 10xxxxxx 10xxxxxx.;以此類推,六位字節(jié)字符的編碼樣式為:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx。 xxx 的值由字符編碼的二進制表示的位填入。只用最短的那個足夠表達一個字符編碼的多字節(jié)串。例如:

Unicode 字符: 00 A9(版權符號) = 1010 1001, UTF-8 編碼為:11000010 10101001 = 0x C2 0xA9; 字符 22 60 (不等于符號) = 0010 0010 0110 0000, UTF-8 編碼為:11100010 10001001 10100000 = 0xE2 0x89 0xA0





回頁首


HTTP 通訊協(xié)議

HTTP 請求

在 HTTP 通訊中,在客戶端發(fā)出的請求報文中,首先設置的是方法。方法是用來告訴服務器客戶端發(fā)起的動作請求。在請求的報文頭部,客戶端還可以同時發(fā)送附加的信息, 比如客戶端使用的瀏覽器和客戶端可以解釋的內容類型等。這些信息可以被服務器端應用程序使用以生成響應。下面是一個 HTTP 請求消息的示例:


圖1. HTTP 請求消息頭
GET /intro.html HTTP/1.0
User-Agent: Mozilla/4.0 (compatible; MSIE 4.0; Windows 95)
Accept: image/gif, image/jpeg, text/*, */*
Accept-language : zh
Accept-Charset: iso-8859-1

這個請求通過 GET 方法來獲取資源 /intro.htm。User-Agent 提供了客戶端瀏覽器的信息,同時 Accept 提供了客戶端可以接受的媒體類型。Accep-language 指出了客戶端瀏覽器的首選語言, Accept-Charset 提供了瀏覽器的首選字符集,服務器端程序能夠根據(jù)客戶端的要求來生成需要的響應。 用戶可以通過配置瀏覽器來設置首選語言。以 IE 為示例如下:


圖2. 瀏覽器首選語言設置
圖2. 瀏覽器首選語言設置

當瀏覽器發(fā)出請求后,可以通過以下代碼來讀取客戶端瀏覽器的首選語言和國家代碼。


圖3. 服務器端 Servlet 讀取瀏覽器首選國家和語言
protected void insertproc(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
Locale reqLocal = req.getLocale();
System.out.println("The country is :" + reqLocal.getCountry());
System.out.println("The language is :" + reqLocal.getLanguage());

服務器端的輸出結果為:


圖4. 服務器端 Servlet 讀取瀏覽器首選國家和語言結果
[06-3-10 14:56:32:516 CST] 6ce078f9 SystemOut     O The country is :CN
[06-3-10 14:56:32:516 CST] 6ce078f9 SystemOut O The language is :zh

HTTP 響應

當服務器端收到請求后,會處理請求并發(fā)回應答。服務器通過應答消息的頭部來指明諸如服務器軟件和相應的內容類型等信息。以下是一個應答消息頭的示例:


圖5.HTTP 應答消息頭
Date: Saturday, 23-May-98 03:25:12 GMT
Server: JavaWebServer/1.1.1
MIME-version: 1.0
Content-type: text/html; charset=UTF-8
Content-length: 1029
Last-modified: Thursday, 7-May-98 12:15:35 GMT

Content-type 表明了應答消息的 MIME 類型和應答消息體的字符集,瀏覽器會用相應的字符集來顯示消息內容。例如,在以上示例中字符集是 UTF-8,瀏覽器會用 UTF-8 編碼來解析和現(xiàn)實返回的消息體。同時頁面輸入也會被用 UTF-8 編碼。





回頁首


Web 頁面顯示編碼

可以通過以下幾種方式來設置內容類型。

在 HTML 中設置頁面的編碼方式

如果被訪問的是一個靜態(tài)的 HTML 頁面。可以通過以下方式來設置頁面的編碼方式。


圖6. 設置頁面編碼的靜態(tài) HTML 文件
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<TITLE>example.html</TITLE>
</HEAD>
<BODY>
</BODY>
</HTML>

標記"<META http-equiv="Content-Type" content="text/html; charset=UTF-8">" 將應答消息頭中 Content_type 設置為"text/html; charset=UTF-8".

在 Servlet 中設置頁面顯示編碼方式

在 Servlet 中,我們可以通過以下方式來設置應答消息的內容類型。


圖7.設置頁面編碼的 Servlet 片斷
protected void insertproc(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
resp.setContentType("text/html;charset=UTF-8");

代碼行"resp.setContentType("text/html;charset=UTF-8");"將應答消息頭中 Content_type 設置為"text/html; charset=UTF-8"。

在 JSP 中設置頁面顯示編碼方式

我們通過以下示例說明如何在 JSP 中設置頁面的編碼格式。


圖8. 設置業(yè)面編碼的 JSP 頁面指令
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

在這行的頁面指令中的"text/html; charset=UTF-8"將應答消息中的"Content-type" 設置為"text/html; charset=UTF-8"。

"pageEncoding"只是指明了 JSP 頁面本身的編碼格式,指明了 JSP 是以什么編碼方式保存。容器在讀取文件時將起轉化為內部使用的 Unicode. 當應答發(fā)送回至瀏覽器時,容器會將內部使用的 Unicode 轉化為在 Content-type 中指定的字符集。

如果沒有指定 PageEncoding,可以通過使用 Content-type 指定的字符集來解釋 JSP 頁面字節(jié)。

為了能正常顯示 UTF-8 編碼的字符,要滿足以下兩個條件:

1. 通知瀏覽器應答消息使用的字符集。

2. 配置瀏覽器使其能有正常顯示 UTF-8 編碼的字體。





回頁首


Web 頁面輸入編碼

HTML 的表單可以接受非西歐語言字符的輸入。當需要創(chuàng)建一個需要接受非西歐語言字符輸入的表單時,必須通知瀏覽器應該為用戶輸入使用哪個字符集,我們可以通過設置 page 指令的 contentType 屬性來設置。

我們需要注意的是,當表單被提交后,瀏覽器會將表單字段值轉換為指定字符集對應的字節(jié)值,然后根據(jù) HTTP 標準 URL 編碼方案對結果字節(jié)進行編碼。當使用 ISO-8859-1 編碼時,任何 a 到 z, A 到 Z 和 0 到 9 之外的字符都會被轉化為十六進制格式的字節(jié)值,并在前面加上一個百分號(%).例如,如果表單的字符集被設為 UTF-8, 字符"中文"被傳遞的編碼格式為:"%E4%B8%AD%E6%96%87"。為了對輸入的信息進行處理,容器必須知道瀏覽器是使用什么字符集對輸入進行 編碼的。問題是當今多數(shù)的瀏覽器并不提供這種信息,因此你必須自己提供這種信息,并告訴容器用哪個字符集對輸入進行解碼。

頁面輸入編碼設定

在本文第3部分中說明了如何設置頁面的顯示編碼,在設置頁面編碼的同時,也就指定了頁面的輸入方式。如果頁面的顯示被設置為UTF-8,那么用戶所有的頁面輸入都會按照 UTF-8 編碼。

頁面輸入輸出過程編碼設置

服務器端程序在讀取表單輸入之前要設定輸入編碼。我們可以看一下示例。

以下是一個用來提示用戶輸入的 JSP 頁面:


圖9. 用以界面輸入的 JSP 頁面
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<HTML>
<HEAD>
<TITLE>insertdb.jsp</TITLE>
</HEAD>
<BODY>
<P>
<FORM METHOD=POST ACTION="./InsertDbProcDs">
<TABLE>
<TR>
<TD>Name:</TD>
<TD><input type="text" name="col2" value=""></TD>
<TR>
<TD><INPUT type="submit" value="submit"></TD>
</TR>
</TR>
</TABLE>
</RORM>
</P>
</BODY>
</HTML>

頁面指令元素的屬性 Content-type 值為"text/html; charset=UTF-8",這會向瀏覽器指明頁面是按照 UTF-8 編碼的,并且所有用戶通過頁面的輸入也會按照 UTF-8 編碼。被 Action 所觸發(fā)的 Servlet 如下例所示。


圖10. 用以按 UTF-8 讀取輸入并輸出的 Servlet
    protected void insertproc(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
String test1 = req.getParameter("col2");
PrintWriter out = resp.getWriter();
resp.setContentType("text/html;charset=UTF-8");
out.println("<HTML>");
out.println("The input is " + test1);
out.println("</HTML>");


通過表單頁面輸入"中文"并提交表單,得到的結果為:


圖11.正確顯示結果的頁面
圖11.正確顯示結果的頁面

如果我們注釋掉語句:resp.setContentType("text/html;charset=UTF-8"), 如下例:


圖12. 用以按非 UTF-8 讀取輸入并輸出的 Servlet
protected void insertproc(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
String test1 = req.getParameter("col2");
PrintWriter out = resp.getWriter();
//resp.setContentType("text/html;charset=UTF-8")
out.println("<HTML>");
out.println("The input is " + test1);
out.println("</HTML>");

輸入"中文"并提交表單,得到的結果為:


圖13. 錯誤顯示輸入結果的頁面
圖13. 錯誤顯示輸入結果的頁面

頁面不能正確顯示 UTF-8 編碼的字符。

在被觸發(fā)的 Servlet 中通過設置 resp.setContentType("text/html;charset=UTF-8") 來向瀏覽器指明輸出的編碼字符集為 UTF-8,瀏覽器會用正確的字符集來顯示輸出。如果 Servlet 中沒有顯示的調用 resp.setContentType("text/html;charset=UTF-8") 來設定輸出字符集,瀏覽器將不能正確的解碼和顯示輸出。





回頁首


結論

本文給出了一些在 Web 應用開發(fā)中如何顯示和輸入 UTF-8 編碼字符的方法。便于讀者在開發(fā)實踐中參考。



參考資料



妖人 2007-10-16 13:12 發(fā)表評論
]]>
關于UTF8,UTF16,UTF32,UTF16-LE,UTF16-BEhttp://www.aygfsteel.com/shypwang/articles/140846.html妖人妖人Wed, 29 Aug 2007 04:32:00 GMThttp://www.aygfsteel.com/shypwang/articles/140846.htmlhttp://www.aygfsteel.com/shypwang/comments/140846.htmlhttp://www.aygfsteel.com/shypwang/articles/140846.html#Feedback0http://www.aygfsteel.com/shypwang/comments/commentRss/140846.htmlhttp://www.aygfsteel.com/shypwang/services/trackbacks/140846.html  關于UTF8,UTF16,UTF32,UTF16-LE,UTF16-BE

        Unicode 是Unicode.org制定的編碼標準,目前得到了絕大部分操作系統(tǒng)和編程語言的支持。Unicode.org官方對Unicode的定義是: Unicode provides a unique number for every character。可見,Unicode所做的是為每個字符定義了一個相應的數(shù)字表示。比如,“a“的Unicode值是0x0061,“一”的 Unicde值是0x4E00,這是最簡單的情況,每個字符用2個字節(jié)表示。

        Unicode.org定義了百萬個以上的 字符,如果將所有的字符用統(tǒng)一的格式表示,需要的是4個字節(jié)。“a“的Unicode表示就會變成0x00000061,而“一“的Unicode值是 0x00004E00。實際上,這就是UTF32,Linux操作系統(tǒng)上所使用的Unicode方案。

        但是,仔細分析可 以發(fā)現(xiàn),其實絕大部分字符只使用2個字節(jié)就可以表示了。英文的Unicode范圍是0x0000-0x007F,中文的Unicode范圍是0x4E00 -0x9F**,真正需要擴展到4個字節(jié)來表示的字符少之又少,所以有些系統(tǒng)直接使用2個字節(jié)來表示Unicode。比如Windows系統(tǒng)上, Unicode就是兩個字節(jié)的。對于那些需要4個字節(jié)才能表示的字符,使用一種代理的手法來擴展(其實就是在低兩個字節(jié)上做一個標記,表示這是一個代理, 需要連接上隨后的兩個字節(jié),才能組成一個字符)。這樣的好處是大量的節(jié)約了存取空間,也提高了處理的速度。這種Unicode表示方法就是UTF16。一 般在Windows平臺上,提到Unicode,那就是指UTF16了。
        
        至于UTF16-LE和 UTF16-BE,與計算機的CPU構架有關。LE指Little Endian,而BE指Big Endian。關于這方面的信息,網上有很多相關的帖子。我們一般的X86系統(tǒng)都是Little Endian的,可以認為UTF16=UTF16-LE.

        由于對于歐洲和北美,實際上使用的編碼范圍在0x0000- 0x00FF之間,只需要一個字符就可以表示所有的字符。即使是使用UTF16來作為內存的存取方式,還是會帶來巨大的空間浪費,因此就有了UTF8的編 碼方式。這是一種很靈活的編碼,對于只需要1個字節(jié)的字符,就使用一個字節(jié),對于中日韓等原本需要兩個字節(jié)才能表示的字符,則通過一個UTF16- UTF8的算法實現(xiàn)相互之間的轉換(一般需要3個字節(jié)才能表示),而對于需要4個字節(jié)才能表示的字符,UTF8可以擴展到6個字節(jié)每個字符。UTF8使用 的算法很有意思,大致映射關系如下:
        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可以方便的轉換為UTF16和UTF32(不需要碼表,轉換算法可以在Unicode.org上找到C代碼)。而且UTF8在每個操作系統(tǒng)平臺上的實現(xiàn)都是一樣的,也不存在跨平臺的問題,所以UTF8成為跨平臺的Unicode很好的解決方案。當然,對于中文來說,由于每個字符需要3個字節(jié)才能表示,還是有點浪費的。
        
            
        



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=160958



妖人 2007-08-29 12:32 發(fā)表評論
]]>
Java數(shù)據(jù)庫連接:JDBC應用說明http://www.aygfsteel.com/shypwang/articles/139365.html妖人妖人Sun, 26 Aug 2007 01:09:00 GMThttp://www.aygfsteel.com/shypwang/articles/139365.htmlhttp://www.aygfsteel.com/shypwang/comments/139365.htmlhttp://www.aygfsteel.com/shypwang/articles/139365.html#Feedback0http://www.aygfsteel.com/shypwang/comments/commentRss/139365.htmlhttp://www.aygfsteel.com/shypwang/services/trackbacks/139365.html
Java數(shù)據(jù)庫連接:JDBC應用說明
ChinaITLab收集整理     2005-11-9   保存本文   推薦給好友   QQ上看本站 收藏本站
 

■DriverManager 類

DriverManager 類是 JDBC 的管理層,作用于用戶和驅動程序之間。它跟蹤可用的驅動程序,并在數(shù)據(jù)庫和相應驅動程序之間建立連接。另外,DriverManager 類也處理諸如驅動程序登錄時間限制及登錄和跟蹤消息的顯示等事務。

對于簡單的應用程序,一般程序員需要在此類中直接使用的唯一方法是 DriverManager.getConnection。正如名稱所示,該方法將建立與數(shù)據(jù)庫的連接。JDBC 允許用戶調用 DriverManager 的方法 getDriver、getDrivers 和 registerDriver 及 Driver 的方法 connect。但多數(shù)情況下,讓 DriverManager 類管理建立連接的細節(jié)為上策。

■跟蹤可用驅動程序

DriverManager 類包含一列 Driver 類,它們已通過調用方法 DriverManager.registerDriver 對自己進行了注冊。所有 Driver 類都必須包含有一個靜態(tài)部分。它創(chuàng)建該類的實例,然后在加載該實例時 DriverManager 類進行注冊。這樣,用戶正常情況下將不會直接調用 DriverManager.registerDriver;而是在加載驅動程序時由驅動程序自動調用。加載 Driver 類,然后自動在 DriverManager 中注冊的方式有兩種:

通過調用方法 Class.forName。這將顯式地加載驅動程序類。由于這與外部設置無關,因此推薦使用這種加載驅動程序的方法。以下代碼加載類 acme.db.Driver:

Class.forName("acme.db.Driver");

如果將 acme.db.Driver 編寫為加載時創(chuàng)建實例,并調用以該實例為參數(shù)的 DriverManager.registerDriver(本該如此),則它在 DriverManager 的驅動程序列表中,并可用于創(chuàng)建連接。

通過將驅動程序添加到 java.lang.System 的屬性 jdbc.drivers 中。這是一個由 DriverManager 類加載的驅動程序類名的列表,由冒號分隔:初始化 DriverManager 類時,它搜索系統(tǒng)屬性 jdbc.drivers,如果用戶已輸入了一個或多個驅動程序,則 DriverManager 類將試圖加載它們。以下代碼說明程序員如何在 ~/.hotjava/properties 中輸入三個驅動程序類(啟動時,HotJava 將把它加載到系統(tǒng)屬性列表中):

jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.test.ourDriver;

對 DriverManager 方法的第一次調用將自動加載這些驅動程序類。

注意:加載驅動程序的第二種方法需要持久的預設環(huán)境。如果對這一點不能保證,則調用方法 Class.forName 顯式地加載每個驅動程序就顯得更為安全。這也是引入特定驅動程序的方法,因為一旦 DriverManager 類被初始化,它將不再檢查 jdbc.drivers 屬性列表。

在以上兩種情況中,新加載的 Driver 類都要通過調用 DriverManager.registerDriver 類進行自我注冊。如上所述,加載類時將自動執(zhí)行這一過程。

由于安全方面的原因,JDBC 管理層將跟蹤哪個類加載器提供哪個驅動程序。這樣,當 DriverManager 類打開連接時,它僅使用本地文件系統(tǒng)或與發(fā)出連接請求的代碼相同的類加載器提供的驅動程序。

■建立連接

加載 Driver 類并在 DriverManager 類中注冊后,它們即可用來與數(shù)據(jù)庫建立連接。當調用 DriverManager.getConnection 方法發(fā)出連接請求時,DriverManager 將檢查每個驅動程序,查看它是否可以建立連接。

有時可能有多個 JDBC 驅動程序可以與給定的 URL 連接。例如,與給定遠程數(shù)據(jù)庫連接時,可以使用 JDBC-ODBC 橋驅動程序、JDBC 到通用網絡協(xié)議驅動程序或數(shù)據(jù)庫廠商提供的驅動程序。在這種情況下,測試驅動程序的順序至關重要,因為 DriverManager 將使用它所找到的第一個可以成功連接到給定 URL 的驅動程序。 DriverManager 試圖按注冊的順序使用每個驅動程序(jdbc.drivers 中列出的驅動程序總是先注冊)。它將跳過代碼不可信任的驅動程序,除非加載它們的源與試圖打開連接的代碼的源相同。它通過輪流在每個驅動程序上調用方法 Driver.connect,并向它們傳遞用戶開始傳遞給方法 DriverManager.getConnection 的 URL 來對驅動程序進行測試,然后連接第一個認出該 URL 的驅動程序。這種方法初看起來效率不高,但由于不可能同時加載數(shù)十個驅動程序,因此每次連接實際只需幾個過程調用和字符串比較。以下代碼是通常情況下用驅 動程序(例如 JDBC-ODBC 橋驅動程序)建立連接所需所有步驟的示例:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加載驅動程序
String url = "jdbc:odbc:fred";
DriverManager.getConnection(url, "userID", "passwd");

8.語句

■Statement 對象概述

Statement 對象用于將 SQL 語句發(fā)送到數(shù)據(jù)庫中。實際上有三種 Statement 對象,它們都作為在給定連接上執(zhí)行 SQL 語句的包容器:Statement、PreparedStatement(它從 Statement 繼承而來)和 CallableStatement(它從 PreparedStatement 繼承而來)。它們都專用于發(fā)送特定類型的 SQL 語句: Statement 對象用于執(zhí)行不帶參數(shù)的簡單 SQL 語句;PreparedStatement 對象用于執(zhí)行帶或不帶 IN 參數(shù)的預編譯 SQL 語句;CallableStatement 對象用于執(zhí)行對數(shù)據(jù)庫已存儲過程的調用。

Statement 接口提供了執(zhí)行語句和獲取結果的基本方法。PreparedStatement 接口添加了處理 IN 參數(shù)的方法;而 CallableStatement 添加了處理 OUT 參數(shù)的方法。

■創(chuàng)建 Statement 對象

建立了到特定數(shù)據(jù)庫的連接之后,就可用該連接發(fā)送 SQL 語句。Statement 對象用 Connection 的方法 createStatement 創(chuàng)建,如下列代碼段中所示:

Connection con = DriverManager.getConnection(url, "sunny", "");
Statement stmt = con.createStatement();

為了執(zhí)行 Statement 對象,被發(fā)送到數(shù)據(jù)庫的 SQL 語句將被作為參數(shù)提供給 Statement 的方法:

ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table2");

■使用 Statement 對象執(zhí)行語句

Statement 接口提供了三種執(zhí)行 SQL 語句的方法:executeQuery、executeUpdate 和 execute。使用哪一個方法由 SQL 語句所產生的內容決定。

方法 executeQuery 用于產生單個結果集的語句,例如 SELECT 語句。

方法 executeUpdate 用于執(zhí)行 INSERT、UPDATE 或 DELETE 語句以及 SQL DDL(數(shù)據(jù)定義語言)語句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 語句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一個整數(shù),指示受影響的行數(shù)(即更新計數(shù))。對于 CREATE TABLE 或 DROP TABLE 等不操作行的語句,executeUpdate 的返回值總為零。

方法 execute 用于執(zhí)行返回多個結果集、多個更新計數(shù)或二者組合的語句。

執(zhí)行語句的所有方法都將關閉所調用的 Statement 對象的當前打開結果集(如果存在)。這意味著在重新執(zhí)行 Statement 對象之前,需要完成對當前 ResultSet 對象的處理。

應注意,繼承了 Statement 接口中所有方法的 PreparedStatement 接口都有自己的 executeQuery、executeUpdate 和 execute 方法。Statement 對象本身不包含 SQL 語句,因而必須給 Statement.execute 方法提供 SQL 語句作為參數(shù)。PreparedStatement 對象并不將 SQL 語句作為參數(shù)提供給這些方法,因為它們已經包含預編譯 SQL 語句。CallableStatement 對象繼承這些方法的 PreparedStatement 形式。對于這些方法的 PreparedStatement 或 CallableStatement 版本,使用查詢參數(shù)將拋出 SQLException。

■語句完成

當連接處于自動提交模式時,其中所執(zhí) 行的語句在完成時將自動提交或還原。語句在已執(zhí)行且所有結果返回時,即認為已完成。對于返回一個結果集的 executeQuery 方法,在檢索完 ResultSet 對象的所有行時該語句完成。對于方法 executeUpdate,當它執(zhí)行時語句即完成。但在少數(shù)調用方法 execute 的情況中,在檢索所有結果集或它生成的更新計數(shù)之后語句才完成。

有些 DBMS 將已存儲過程中的每條語句視為獨立的語句;而另外一些則將整個過程視為一個復合語句。在啟用自動提交時,這種差別就變得非常重要,因為它影響什么時候調用 commit 方法。在前一種情況中,每條語句單獨提交;在后一種情況中,所有語句同時提交。

■關閉 Statement 對象

Statement 對象將由 Java 垃圾收集程序自動關閉。而作為一種好的編程風格,應在不需要 Statement 對象時顯式地關閉它們。這將立即釋放 DBMS 資源,有助于避免潛在的內存問題。

9.結果設置

■概述

ResultSet 包含符合 SQL 語句中條件的所有行,并且它通過一套 get 方法(這些 get 方法可以訪問當前行中的不同列)提供了對這些行中數(shù)據(jù)的訪問。ResultSet.next 方法用于移動到 ResultSet 中的下一行,使下一行成為當前行。

■行和光標

ResultSet 維護指向其當前數(shù)據(jù)行的光標。每調用一次 next 方法,光標向下移動一行。最初它位于第一行之前,因此第一次調用 next 將把光標置于第一行上,使它成為當前行。隨著每次調用 next 導致光標向下移動一行,按照從上至下的次序獲取 ResultSet 行。在 ResultSet 對象或其父輩 Statement 對象關閉之前,光標一直保持有效。在 SQL 中,結果表的光標是有名字的。如果數(shù)據(jù)庫允許定位更新或定位刪除,則需要將光標的名字作為參數(shù)提供給更新或刪除命令。可通過調用方法 getCursorName 獲得光標名。 注意:不是所有 DBMS支持定位更新和刪除。可使用 DatabaseMetaData.supportsPositionedDelete 和 supportsPositionedUpdate 方法來檢查特定連接是否支持這些操作。當支持這些操作時,DBMS/驅動程序必須確保適當鎖定選定行,以使定位更新不會導致更新異常或其它并發(fā)問題。

■列

方法 getXXX 提供了獲取當前行中某列值的途徑。在每一行內,可按任何次序獲取列值。但為了保證可移植性,應該從左至右獲取列值,并且一次性地讀取列值。列名或列號可用 于標識要從中獲取數(shù)據(jù)的列。例如,如果 ResultSet 對象 rs 的第二列名為“title”,并將值存儲為字符串,則下列任一代碼將獲取存儲在該列中的值:

String s = rs.getString("title");
String s = rs.getString(2);

注意列是從左至右編號的,并且從列 1 開始。同時,用作 getXXX 方法的輸入的列名不區(qū)分大小寫。

提供使用列名這個選項的目的是為了讓在查詢中指定列名的用戶可使用相同的名字作為 getXXX 方法的參數(shù)。另一方面,如果 select 語句未指定列名(例如在“select * from table1”中或列是導出的時),則應該使用列號。這些情況下,用戶將無法確切知道列名。

有些情況下,SQL 查詢返回的結果集中可能有多個列具有相同的名字。如果列名用作 getXXX 方法的參數(shù),則 getXXX 將返回第一個匹配列名的值。因而,如果多個列具有相同的名字,則需要使用列索引來確保檢索了正確的列值。這時,使用列號效率要稍微高一些。

■數(shù)據(jù)類型和轉換

對于 getXXX 方法,JDBC 驅動程序試圖將基本數(shù)據(jù)轉換成指定 Java 類型,然后返回適合的 Java 值。例如,如果 getXXX 方法為 getString,而基本數(shù)據(jù)庫中數(shù)據(jù)類型為 VARCHAR,則 JDBC 驅動程序將把 VARCHAR 轉換成 Java String。getString 的返回值將為 Java String 對象。可使用 ResultSet.getXXX 方法獲取常見的 JDBC 數(shù)據(jù)類型。

準備語句

■概述

該 PreparedStatement 接口繼承 Statement,并與之在兩方面有所不同:

PreparedStatement 實例包含已編譯的 SQL 語句。這就是使語句“準備好”。

包含于 PreparedStatement 對象中的 SQL 語句可具有一個或多個 IN 參數(shù)。IN 參數(shù)的值在 SQL 語句創(chuàng)建時未被指定。相反的,該語句為每個 IN 參數(shù)保留一個問號(“?”)作為占位符。每個問號的值必須在該語句執(zhí)行之前,通過適當?shù)? setXXX 方法來提供。

由于 PreparedStatement 對象已預編譯過,所以其執(zhí)行速度要快于 Statement 對象。因此,多次執(zhí)行的 SQL 語句經常創(chuàng)建為 PreparedStatement 對象,以提高效率。

作為 Statement 的子類,PreparedStatement 繼承了 Statement 的所有功能。另外它還添加了一整套方法,用于設置發(fā)送給數(shù)據(jù)庫以取代 IN 參數(shù)占位符的值。同時,三種方法 execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要參數(shù)。這些方法的 Statement 形式(接受 SQL 語句參數(shù)的形式)不應該用于 PreparedStatement 對象。

■創(chuàng)建 PreparedStatement 對象

以下的代碼段(其中 con 是 Connection 對象)創(chuàng)建包含帶兩個 IN 參數(shù)占位符的 SQL 語句的 PreparedStatement 對象:

PreparedStatement pstmt = con.prepareStatement(
"UPDATE table4 SET m = ? WHERE x = ?");

pstmt 對象包含語句 "UPDATE table4 SET m = ? WHERE x = ?",它已發(fā)送給 DBMS,并為執(zhí)行作好了準備。

■傳遞 IN 參數(shù)

在執(zhí)行 PreparedStatement 對象之前,必須設置每個 ? 參數(shù)的值。這可通過調用 setXXX 方法來完成,其中 XXX 是與該參數(shù)相應的類型。例如,如果參數(shù)具有 Java 類型 long,則使用的方法就是 setLong。setXXX 方法的第一個參數(shù)是要設置的參數(shù)的序數(shù)位置,第二個參數(shù)是設置給該參數(shù)的值。例如,以下代碼將第一個參數(shù)設為 123456789,第二個參數(shù)設為 100000000:

pstmt.setLong(1, 123456789);
pstmt.setLong(2, 100000000);

一旦設置了給定語句的參數(shù)值,就可用它多次執(zhí)行該語句,直到調用 clearParameters 方法清除它為止。

在連接的缺省模式下(啟用自動提交),當語句完成時將自動提交或還原該語句。

如果基本數(shù)據(jù)庫和驅動程序在語句提交之后仍保持這些語句的打開狀態(tài),則同一個 PreparedStatement 可執(zhí)行多次。如果這一點不成立,那么試圖通過使用 PreparedStatement 對象代替 Statement 對象來提高性能是沒有意義的。

利用 pstmt(前面創(chuàng)建的 PreparedStatement 對象),以下代碼例示了如何設置兩個參數(shù)占位符的值并執(zhí)行 pstmt 10 次。如上所述,為做到這一點,數(shù)據(jù)庫不能關閉 pstmt。在該示例中,第一個參數(shù)被設置為 "Hi"并保持為常數(shù)。在 for 循環(huán)中,每次都將第二個參數(shù)設置為不同的值:從 0 開始,到 9 結束。

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 類型),因為驅動程序將把 Java 類型映射為相應的 JDBC 類型(遵循該 JDBC Guide中§8.6.2 “映射 Java 和 JDBC 類型”表中所指定的映射),并將該 JDBC 類型發(fā)送給數(shù)據(jù)庫。例如,以下代碼段將 PreparedStatement 對象 pstmt 的第二個參數(shù)設置為 44,Java 類型為 short:

pstmt.setShort(2, 44);

驅動程序將 44 作為 JDBC SMALLINT 發(fā)送給數(shù)據(jù)庫,它是 Java short 類型的標準映射。

程序員的責任是確保將每個 IN 參數(shù)的 Java 類型映射為與數(shù)據(jù)庫所需的 JDBC 數(shù)據(jù)類型兼容的 JDBC 類型。不妨考慮數(shù)據(jù)庫需要 JDBC SMALLINT 的情況。如果使用方法 setByte ,則驅動程序將 JDBC TINYINT 發(fā)送給數(shù)據(jù)庫。這是可行的,因為許多數(shù)據(jù)庫可從一種相關的類型轉換為另一種類型,并且通常 TINYINT 可用于 SMALLINT 適用的任何地方。然而,對于要適用于盡可能多的數(shù)據(jù)庫的應用程序,最好使用與數(shù)據(jù)庫所需的確切的 JDBC 類型相應的 Java 類型。如果所需的 JDBC 類型是 SMALLINT,則使用 setShort 代替 setByte 將使應用程序的可移植性更好。

■ JDBC URL

JDBC URL 提供了一種標識數(shù)據(jù)庫的方法,可以使相應的驅動程序能識別該數(shù)據(jù)庫并與之建立連接。實際上,驅動程序編程員將決定用什么 JDBC URL 來標識特定的驅動程序。用戶不必關心如何來形成 JDBC URL;他們只須使用與所用的驅動程序一起提供的 URL 即可。JDBC 的作用是提供某些約定,驅動程序編程員在構造他們的 JDBC URL 時應該遵循這些約定。

(1) 由于 JDBC URL 要與各種不同的驅動程序一起使用,因此這些約定應非常靈活。它們應允許不同的驅動程序使用不同的方案來命名數(shù)據(jù)庫。例如, odbc 子協(xié)議允許(但并不是要求) URL 含有屬性值。

(2) JDBC URL 應允許驅動程序編程員將一切所需的信息編入其中。這樣就可以讓要與給定數(shù)據(jù)庫對話的 applet 打開數(shù)據(jù)庫連接,而無須要求用戶去做任何系統(tǒng)管理工作。

(3) JDBC URL 應允許某種程度的間接性。也就是說,JDBC URL 可指向邏輯主機或數(shù)據(jù)庫名,而這種邏輯主機或數(shù)據(jù)庫名將由網絡命名系統(tǒng)動態(tài)地轉換為實際的名稱。這可以使系統(tǒng)管理員不必將特定主機聲明為 JDBC 名稱的一部份。網絡命名服務(例如 DNS、 NIS 和 DCE )有多種,而對于使用哪種命名服務并無限制。

JDBC URL 的標準語法如下所示。

它由三部分組成,各部分間用冒號分隔:jdbc:< 子協(xié)議 >:< 子名稱 >

JDBC URL 的三個部分可分解如下:

jdbc ─ 協(xié)議。JDBC URL 中的協(xié)議總是 jdbc。

<子協(xié)議> ─ 驅動程序名或數(shù)據(jù)庫連接機制(這種機制可由一個或多個驅動程序支持)的名稱。子協(xié)議名的典型示例是 "odbc",該名稱是為用于指定 ODBC 風格的數(shù)據(jù)資源名稱的 URL 專門保留的。例如,為了通過 JDBC-ODBC 橋來訪問某個數(shù)據(jù)庫,可以用如下所示的 URL:
jdbc:odbc:fred

本例中,子協(xié)議為 "odbc",子名稱 "fred" 是本地 ODBC 數(shù)據(jù)資源。 如果要用網絡命名服務(這樣 JDBC URL 中的數(shù)據(jù)庫名稱不必是實際名稱),則命名服務可以作為子協(xié)議。例如,可用如下所示的 URL :

jdbc:dcenaming:accounts-payable

本例中,該 URL 指定了本地 DCE 命名服務應該將 數(shù)據(jù)庫名稱 "accounts-payable" 解析為更為具體的 可用于連接真實數(shù)據(jù)庫的名稱。

<子名稱> ─ 一種標識數(shù)據(jù)庫的方法。子名稱可以依不同的子協(xié)議而變化。它還可以有子名稱的子名稱(含有驅動程序編程員所選的任何內部語法)。使用子名稱的目的是為定位 數(shù)據(jù)庫提供足夠的信息。前例中,因為 ODBC 將提供其余部份的信息,因此用 "fred" 就已足夠。然而,位于遠程服務器上的數(shù)據(jù)庫需要更多的信息。例如,如果數(shù)據(jù)庫是通過 Internet 來訪問的,則在 JDBC URL 中應將網絡地址作為子名稱的一部份包括進去,且必須遵循如下所示的標準 URL 命名約定:

//主機名:端口/子協(xié)議

假設 "dbnet" 是個用于將某個主機連接到 Internet 上的協(xié)議,則 JDBC URL 類似:

jdbc:dbnet://wombat:356/fred

■ "odbc" 子協(xié)議

子協(xié)議 odbc 是一種特殊情況。它是為用于指定 ODBC 風格的數(shù)據(jù)資源名稱的 URL 而保留的,并具有下列特性:允許在子名稱(數(shù)據(jù)資源名稱)后面指定任意多個屬性值。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

■注冊子協(xié)議

驅動程序編程員可保留某個名稱以將之用作 JDBC URL 的子協(xié)議名。當 DriverManager 類將此名稱加到已注冊的驅動程序清單中時,為之保留該名稱的驅動程序應能識別該名稱并與它所標識的數(shù)據(jù)庫建立連接。例如,odbc 是為 JDBC- ODBC 橋而保留的。示例之二,假設有個 Miracle 公司,它可能會將 "miracle" 注冊為連接到其 Miracle DBMS 上的 JDBC 驅動程序的子協(xié)議,從而使其他人都無法使用這個名稱。


妖人 2007-08-26 09:09 發(fā)表評論
]]>
DynamicProxy [精華]http://www.aygfsteel.com/shypwang/articles/138590.html妖人妖人Wed, 22 Aug 2007 05:22:00 GMThttp://www.aygfsteel.com/shypwang/articles/138590.htmlhttp://www.aygfsteel.com/shypwang/comments/138590.htmlhttp://www.aygfsteel.com/shypwang/articles/138590.html#Feedback0http://www.aygfsteel.com/shypwang/comments/commentRss/138590.htmlhttp://www.aygfsteel.com/shypwang/services/trackbacks/138590.html 最近在寫學校案子用到hibernate,正巧以前打工的地方學習到一個方法,
在javaworld@tw也有人提到過,因此整理一下.
Hibernate + Struts 學習筆記提到過的使用dynamic proxy的做法,
來避免巢狀呼叫,也可以讓service delegate不會跟hibernate綁的死死的.
首先dynamic proxy會利用到java.lang.reflect.Proxy跟java.lang.reflect.InvocationHandler. 直接看以下程式碼
HogeIF.java
1
2
3
public interface HogeIF {
public
void
printMessage(String message);
}

Hoge.java
1
2
3
4
5
public class Hoge implements
HogeIF{
public void printMessage(String message) {

System.out.println(message);
}
}

執(zhí)行時必須寫成
1
2
HogeIF hoge = new Hoge();
hoge.printMessage("hogehoge");

如果想對此方法做點前後置處理,那就寫個proxy
HogeProxy.java
1
2
3
4
5
6
7
8

9
10
11
public class HogeProxy 
implements
HogeIF{
private HogeIF hoge;
public HogeProxy(HogeIF hoge)
{
this.hoge = hoge;
}
public void printMessage(String message)
{
System.out.println("before");
hoge.printMessage(message);
System.out.println("after"
);
}
}

這樣就會變成
1
2
3
before
hogehoge
after

如果每個method都需要加工,需要加工的class都implement不同interface,或者每個class有不同method,那麼........就要寫非常多的proxy來用... 在這邊改個方法使用dynamic proxy...
DynamicHogeProxy.java
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import
java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method
;
public class DynamicHogeProxy implements InvocationHandler
{

private Object obj;
public static Object newInstance(Object obj)
{
return java.lang.reflect.Proxy.newProxyInstance(obj.getClass()
.getClassLoader(), obj.getClass().getInterfaces(),

new DynamicHogeProxy(obj));
}
private DynamicHogeProxy(Object obj)
{

this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args)

throws
Throwable {
Object result;
try {
System.out.println(
"before"
);
result = m.invoke(obj, args);
System.out.println("after");
return result;

} catch (InvocationTargetException e) {
throw
e.getTargetException();
}finally {
}

}

}

執(zhí)行時寫成
1
2
HogeIF hoge = (HogeIF)DynamicHogeProxy.newInstance(new Hoge());
hoge.printMessage("hogehoge");

這樣就可以達到跟上一個例子一樣的效果了. 回到本篇正題,最近用hibernate希望他自動關閉session,但是又不希望在dao的每個method都開開關關,也不希望service delegate裡面去做開關,因此我把每個service delegate都使用dynamic proxy來invoke...這樣就可以做到整個呼叫過程,session的開關只有一次,也就不用擔心巢狀呼叫了. 因此我在每個dao的每個操作的method的開頭加上ThreadLocalSession.currentSession(); 然後每個service delegate都使用dynamic proxy 去invoke. dynamic proxy的內容如下

            
            1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

import
java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method
;
import java.lang.reflect.Proxy;
 
public class DynamicHogeProxy
implements
InvocationHandler{
private Object obj;
private DynamicHogeProxy(Object obj)
{
this.obj = obj;
}
public static Object newInstance(Object obj)
{
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new
DynamicHogeProxy(
obj));
}
public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {
Object result = null;
if
(obj != null) {
try {
result =
method.invoke(obj, args);
} catch (InvocationTargetException e) {

throw
e.getCause();
} finally {
ThreadLocalSession.closeSession();

}
}
return result;
}
}


這種寫法缺點是一定得撰寫interface才可以,不然會發(fā)生ClassCastException.
1
2
HogeIF hoge = (HogeIF)DynamicHogeProxy.newInstance(new Hoge()); //ok!!!
Hoge hoge = (Hoge)DynamicHogeProxy.newInstance(
new
Hoge()); //ClassCastException

而且一開始產生proxy時效能會稍微差一點. 另外,要達到上述功能現(xiàn)在也可以用AspectJ來做...恩...

妖人 2007-08-22 13:22 發(fā)表評論
]]>
主站蜘蛛池模板: 鹰潭市| 萝北县| 石林| 门头沟区| 达尔| 南开区| 临高县| 大渡口区| 额尔古纳市| 昌邑市| 巴林左旗| 达州市| 荥经县| 嘉义市| 卢龙县| 凤台县| 额济纳旗| 建湖县| 阳城县| 车险| 综艺| 廉江市| 伊金霍洛旗| 临洮县| 镇远县| 东阳市| 永嘉县| 侯马市| 晴隆县| 庄河市| 芒康县| 武安市| 洪江市| 双柏县| 安新县| 临邑县| 大关县| 邻水| 佛山市| 中江县| 嘉禾县|