
2006年3月20日
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
摘要:
閱讀全文
出處:http://www.aygfsteel.com/xmatthew/archive/2008/04/14/192450.html
(轉(zhuǎn))設(shè)計(jì)一個(gè)Tomcat訪問日志分析工具
常使用web服務(wù)器的朋友大都了解,一般的web server有兩部分日志:
一是運(yùn)行中的日志,它主要記錄運(yùn)行的一些信息,尤其是一些異常錯(cuò)誤日志信息
二是訪問日志信息,它記錄的訪問的時(shí)間,IP,訪問的資料等相關(guān)信息。
現(xiàn)在我來和大家介紹一下利用tomcat產(chǎn)生的訪問日志數(shù)據(jù),我們能做哪些有效的分析數(shù)據(jù)?
首先是配置tomcat訪問日志數(shù)據(jù),默認(rèn)情況下訪問日志沒有打開,配置的方式如下:
編輯 ${catalina}/conf/server.xml文件.注:${catalina}是tomcat的安裝目錄
把以下的注釋(<!-- -->)去掉即可。
<!--
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" prefix="localhost_access_log." suffix=".txt"
pattern="common" resolveHosts="false"/>
-->
其中 directory是產(chǎn)生的目錄 tomcat安裝${catalina}作為當(dāng)前目錄
pattern表示日志生產(chǎn)的格式,common是tomcat提供的一個(gè)標(biāo)準(zhǔn)設(shè)置格式。其具體的表達(dá)式為 %h %l %u %t "%r" %s %b
但本人建議采用以下具體的配置,因?yàn)闃?biāo)準(zhǔn)配置有一些重要的日志數(shù)據(jù)無法生。
%h %l %u %t "%r" %s %b %T
具體的日志產(chǎn)生樣式說明如下(從官方文檔中摘錄):
* %a - Remote IP address
* %A - Local IP address
* %b - Bytes sent, excluding HTTP headers, or '-' if zero
* %B - Bytes sent, excluding HTTP headers
* %h - Remote host name (or IP address if resolveHosts is false)
* %H - Request protocol
* %l - Remote logical username from identd (always returns '-')
* %m - Request method (GET, POST, etc.)
* %p - Local port on which this request was received
* %q - Query string (prepended with a '?' if it exists)
* %r - First line of the request (method and request URI)
* %s - HTTP status code of the response
* %S - User session ID
* %t - Date and time, in Common Log Format
* %u - Remote user that was authenticated (if any), else '-'
* %U - Requested URL path
* %v - Local server name
* %D - Time taken to process the request, in millis
* %T - Time taken to process the request, in seconds
There is also support to write information from the cookie, incoming header, the Session or something else in the ServletRequest. It is modeled after the apache syntax:
* %{xxx}i for incoming headers
* %{xxx}c for a specific cookie
* %{xxx}r xxx is an attribute in the ServletRequest
* %{xxx}s xxx is an attribute in the HttpSession
現(xiàn)在我們回頭再來看一下下面這個(gè)配置 %h %l %u %t "%r" %s %b %T 生產(chǎn)的訪問日志數(shù)據(jù),我們可以做哪些事?
先看一下,我們能得到的數(shù)據(jù)有:
* %h 訪問的用戶IP地址
* %l 訪問邏輯用戶名,通常返回'-'
* %u 訪問驗(yàn)證用戶名,通常返回'-'
* %t 訪問日時(shí)
* %r 訪問的方式(post或者是get),訪問的資源和使用的http協(xié)議版本
* %s 訪問返回的http狀態(tài)
* %b 訪問資源返回的流量
* %T 訪問所使用的時(shí)間
有了這些數(shù)據(jù),我們可以根據(jù)時(shí)間段做以下的分析處理(圖片使用jfreechart工具動(dòng)態(tài)生成):
* 獨(dú)立IP數(shù)統(tǒng)計(jì)
* 訪問請(qǐng)求數(shù)統(tǒng)計(jì)
* 訪問資料文件數(shù)統(tǒng)計(jì)
* 訪問流量統(tǒng)計(jì)
* 訪問處理響應(yīng)時(shí)間統(tǒng)計(jì)
* 統(tǒng)計(jì)所有404錯(cuò)誤頁(yè)面
* 統(tǒng)計(jì)所有500錯(cuò)誤的頁(yè)面
* 統(tǒng)計(jì)訪問最頻繁頁(yè)面
* 統(tǒng)計(jì)訪問處理時(shí)間最久頁(yè)面
* 統(tǒng)計(jì)并發(fā)訪問頻率最高的頁(yè)面
分析工具包括兩大部分,一個(gè)是后臺(tái)解釋程序,每天執(zhí)行一次對(duì)后臺(tái)日志數(shù)據(jù)進(jìn)行解析后保存到數(shù)據(jù)庫(kù)中。
第二個(gè)是顯示程序,從數(shù)據(jù)庫(kù)中查詢數(shù)據(jù)并生成相應(yīng)的圖表信息。
摘要:
閱讀全文
摘要:
閱讀全文
如果你覺得你的Eclipse在啟動(dòng)的時(shí)候很慢(比如說超過20秒鐘),也許你要調(diào)整一下你的Eclipse啟動(dòng)參數(shù)了,以下是一些``小貼士'':
1. 檢查啟動(dòng)Eclipse的JVM設(shè)置。 在Help\About Eclipse SDK\Configuration Detail里面,你可以看到啟動(dòng)Eclipse的JVM。 這個(gè)JVM和你在Eclipse中設(shè)置的Installed JDK是兩回事情。 如果啟動(dòng)Eclipse的JVM還是JDK 1.4的話,那最好改為JDK 5,因?yàn)镴DK 5的性能比1.4更好。
C:\eclipse\eclipse.exe -vm "C:\Program Files\Java\jdk1.5.0_08\ bin\javaw.exe"
2. 檢查Eclipse所使用的heap的大小。 在C:\eclipse目錄下有一個(gè)配置文件eclipse.ini,其中配置了Eclipse啟動(dòng)的默認(rèn)heap大小
-vmargs
-Xms40M
-Xmx256M
所以你可以把默認(rèn)值改為:
-vmargs
-Xms256M
-Xmx512M
當(dāng)然,也可以這樣做,把堆的大小改為256 - 512。
C:\eclipse\eclipse.exe -vm "C:\Program Files\Java\jdk1.5.0_08\ bin\javaw.exe" -vmargs -Xms256M -Xmx512M
3. 其他的啟動(dòng)參數(shù)。 如果你有一個(gè)雙核的CPU,也許可以嘗試這個(gè)參數(shù):
-XX:+UseParallelGC
讓GC可以更快的執(zhí)行。(只是JDK 5里對(duì)GC新增加的參數(shù))
Java對(duì)多線程的支持與同步機(jī)制深受大家的喜愛,似乎看起來使用了synchronized關(guān)鍵字就可以輕松地解決多線程共享數(shù)據(jù)同步問題。到底如何?――還得對(duì)synchronized關(guān)鍵字的作用進(jìn)行深入了解才可定論。
總的說來,synchronized關(guān)鍵字可以作為函數(shù)的修飾符,也可作為函數(shù)內(nèi)的語(yǔ)句,也就是平時(shí)說的同步方法和同步語(yǔ)句塊。如果再細(xì)的分類,synchronized可作用于instance變量、object reference(對(duì)象引用)、static函數(shù)和class literals(類名稱字面常量)身上。
在進(jìn)一步闡述之前,我們需要明確幾點(diǎn):
A.無論synchronized關(guān)鍵字加在方法上還是對(duì)象上,它取得的鎖都是對(duì)象,而不是把一段代碼或函數(shù)當(dāng)作鎖――而且同步方法很可能還會(huì)被其他線程的對(duì)象訪問。
B.每個(gè)對(duì)象只有一個(gè)鎖(lock)與之相關(guān)聯(lián)。
C.實(shí)現(xiàn)同步是要很大的系統(tǒng)開銷作為代價(jià)的,甚至可能造成死鎖,所以盡量避免無謂的同步控制。
接著來討論synchronized用到不同地方對(duì)代碼產(chǎn)生的影響:
假設(shè)P1、P2是同一個(gè)類的不同對(duì)象,這個(gè)類中定義了以下幾種情況的同步塊或同步方法,P1、P2就都可以調(diào)用它們。
1. 把synchronized當(dāng)作函數(shù)修飾符時(shí),示例代碼如下:
Public synchronized void methodAAA()
{
//….
}
這也就是同步方法,那這時(shí)synchronized鎖定的是哪個(gè)對(duì)象呢?它鎖定的是調(diào)用這個(gè)同步方法對(duì)象。也就是說,當(dāng)一個(gè)對(duì)象P1在不同的線程中執(zhí)行這個(gè)同步方法時(shí),它們之間會(huì)形成互斥,達(dá)到同步的效果。但是這個(gè)對(duì)象所屬的Class所產(chǎn)生的另一對(duì)象P2卻可以任意調(diào)用這個(gè)被加了synchronized關(guān)鍵字的方法。
上邊的示例代碼等同于如下代碼:
public void methodAAA()
{
synchronized (this) // (1)
{
//…..
}
}
(1)處的this指的是什么呢?它指的就是調(diào)用這個(gè)方法的對(duì)象,如P1。可見同步方法實(shí)質(zhì)是將synchronized作用于object reference。――那個(gè)拿到了P1對(duì)象鎖的線程,才可以調(diào)用P1的同步方法,而對(duì)P2而言,P1這個(gè)鎖與它毫不相干,程序也可能在這種情形下擺脫同步機(jī)制的控制,造成數(shù)據(jù)混亂:(
2.同步塊,示例代碼如下:
public void method3(SomeObject so)
{
synchronized(so)
{
//…..
}
}
這時(shí),鎖就是so這個(gè)對(duì)象,誰(shuí)拿到這個(gè)鎖誰(shuí)就可以運(yùn)行它所控制的那段代碼。當(dāng)有一個(gè)明確的對(duì)象作為鎖時(shí),就可以這樣寫程序,但當(dāng)沒有明確的對(duì)象作為鎖,只是想讓一段代碼同步時(shí),可以創(chuàng)建一個(gè)特殊的instance變量(它得是一個(gè)對(duì)象)來充當(dāng)鎖:
class Foo implements Runnable
{
private byte[] lock = new byte[0]; // 特殊的instance變量
Public void methodA()
{
synchronized(lock) { //… }
}
//…..
}
注:零長(zhǎng)度的byte數(shù)組對(duì)象創(chuàng)建起來將比任何對(duì)象都經(jīng)濟(jì)――查看編譯后的字節(jié)碼:生成零長(zhǎng)度的byte[]對(duì)象只需3條操作碼,而Object lock = new Object()則需要7行操作碼。
3.將synchronized作用于static 函數(shù),示例代碼如下:
Class Foo
{
public synchronized static void methodAAA() // 同步的static 函數(shù)
{
//….
}
public void methodBBB()
{
synchronized(Foo.class) // class literal(類名稱字面常量)
}
}
代碼中的methodBBB()方法是把class literal作為鎖的情況,它和同步的static函數(shù)產(chǎn)生的效果是一樣的,取得的鎖很特別,是當(dāng)前調(diào)用這個(gè)方法的對(duì)象所屬的類(Class,而不再是由這個(gè)Class產(chǎn)生的某個(gè)具體對(duì)象了)。
記得在《Effective Java》一書中看到過將 Foo.class和 P1.getClass()用于作同步鎖還不一樣,不能用P1.getClass()來達(dá)到鎖這個(gè)Class的目的。P1指的是由Foo類產(chǎn)生的對(duì)象。
可以推斷:如果一個(gè)類中定義了一個(gè)synchronized的static函數(shù)A,也定義了一個(gè)synchronized 的instance函數(shù)B,那么這個(gè)類的同一對(duì)象Obj在多線程中分別訪問A和B兩個(gè)方法時(shí),不會(huì)構(gòu)成同步,因?yàn)樗鼈兊逆i都不一樣。A方法的鎖是Obj這個(gè)對(duì)象,而B的鎖是Obj所屬的那個(gè)Class。
小結(jié)如下:
搞清楚synchronized鎖定的是哪個(gè)對(duì)象,就能幫助我們?cè)O(shè)計(jì)更安全的多線程程序。
還有一些技巧可以讓我們對(duì)共享資源的同步訪問更加安全:
1. 定義private 的instance變量+它的 get方法,而不要定義public/protected的instance變量。如果將變量定義為public,對(duì)象在外界可以繞過同步方法的控制而直接取得它,并改動(dòng)它。這也是JavaBean的標(biāo)準(zhǔn)實(shí)現(xiàn)方式之一。
2. 如果instance變量是一個(gè)對(duì)象,如數(shù)組或ArrayList什么的,那上述方法仍然不安全,因?yàn)楫?dāng)外界對(duì)象通過get方法拿到這個(gè)instance對(duì)象的引用后,又將其指向另一個(gè)對(duì)象,那么這個(gè)private變量也就變了,豈不是很危險(xiǎn)。這個(gè)時(shí)候就需要將get方法也加上synchronized同步,并且,只返回這個(gè)private對(duì)象的clone()――這樣,調(diào)用端得到的就是對(duì)象副本的引用了。
摘要:
閱讀全文
這幾個(gè)學(xué)習(xí)材料非常短小精悍,可清晰快捷的掌握以下幾個(gè)概念,方便更深入學(xué)習(xí)
XML tutorial:
http://www.w3schools.com/xml/default.asp
SOAP tutorial:
http://www.w3schools.com/soap/default.asp
WSDL tutorial:
http://www.w3schools.com/wsdl/default.asp
WEB Service tutorial:
http://www.w3schools.com/webservices/default.asp
類-->對(duì)象-->實(shí)例
人類是類
某個(gè)人是對(duì)象
你是實(shí)例
實(shí)例本身也是對(duì)象。
表現(xiàn)出來是這樣的
String 類
String str str是對(duì)象
String str = "abc"; "abc"是實(shí)例,也是對(duì)象.
這樣也能解釋instance of object這種說法 str的實(shí)例是"abc"
1.?概述?
本文主要包括以下幾個(gè)方面:編碼基本知識(shí),java,系統(tǒng)軟件,url,工具軟件等。?
在下面的描述中,將以"中文"兩個(gè)字為例,經(jīng)查表可以知道其GB2312編碼是"d6d0?cec4",Unicode編碼為"4e2d?6587",UTF編碼就是"e4b8ad?e69687"。注意,這兩個(gè)字沒有iso8859-1編碼,但可以用iso8859-1編碼來"表示"。?
2.?編碼基本知識(shí)?
最早的編碼是iso8859-1,和ascii編碼相似。但為了方便表示各種各樣的語(yǔ)言,逐漸出現(xiàn)了很多標(biāo)準(zhǔn)編碼,重要的有如下幾個(gè)。?
2.1.?iso8859-1?
屬于單字節(jié)編碼,最多能表示的字符范圍是0-255,應(yīng)用于英文系列。比如,字母'a'的編碼為0x61=97。?
很明顯,iso8859-1編碼表示的字符范圍很窄,無法表示中文字符。但是,由于是單字節(jié)編碼,和計(jì)算機(jī)最基礎(chǔ)的表示單位一致,所以很多時(shí)候,仍舊使用iso8859-1編碼來表示。而且在很多協(xié)議上,默認(rèn)使用該編碼。比如,雖然"中文"兩個(gè)字不存在iso8859-1編碼,以gb2312編碼為例,應(yīng)該是"d6d0?cec4"兩個(gè)字符,使用iso8859-1編碼的時(shí)候則將它拆開為4個(gè)字節(jié)來表示:"d6?d0?ce?c4"(事實(shí)上,在進(jìn)行存儲(chǔ)的時(shí)候,也是以字節(jié)為單位處理的)。而如果是UTF編碼,則是6個(gè)字節(jié)"e4?b8?ad?e6?96?87"。很明顯,這種表示方法還需要以另一種編碼為基礎(chǔ)。?
2.2.?GB2312/GBK?
這就是漢子的國(guó)標(biāo)碼,專門用來表示漢字,是雙字節(jié)編碼,而英文字母和iso8859-1一致(兼容iso8859-1編碼)。其中g(shù)bk編碼能夠用來同時(shí)表示繁體字和簡(jiǎn)體字,而gb2312只能表示簡(jiǎn)體字,gbk是兼容gb2312編碼的。?
2.3.?unicode?
這是最統(tǒng)一的編碼,可以用來表示所有語(yǔ)言的字符,而且是定長(zhǎng)雙字節(jié)(也有四字節(jié)的)編碼,包括英文字母在內(nèi)。所以可以說它是不兼容iso8859-1編碼的,也不兼容任何編碼。不過,相對(duì)于iso8859-1編碼來說,uniocode編碼只是在前面增加了一個(gè)0字節(jié),比如字母'a'為"00?61"。?
需要說明的是,定長(zhǎng)編碼便于計(jì)算機(jī)處理(注意GB2312/GBK不是定長(zhǎng)編碼),而unicode又可以用來表示所有字符,所以在很多軟件內(nèi)部是使用unicode編碼來處理的,比如java。?
2.4.?UTF?
考慮到unicode編碼不兼容iso8859-1編碼,而且容易占用更多的空間:因?yàn)閷?duì)于英文字母,unicode也需要兩個(gè)字節(jié)來表示。所以u(píng)nicode不便于傳輸和存儲(chǔ)。因此而產(chǎn)生了utf編碼,utf編碼兼容iso8859-1編碼,同時(shí)也可以用來表示所有語(yǔ)言的字符,不過,utf編碼是不定長(zhǎng)編碼,每一個(gè)字符的長(zhǎng)度從1-6個(gè)字節(jié)不等。另外,utf編碼自帶簡(jiǎn)單的校驗(yàn)功能。一般來講,英文字母都是用一個(gè)字節(jié)表示,而漢字使用三個(gè)字節(jié)。?
注意,雖然說utf是為了使用更少的空間而使用的,但那只是相對(duì)于unicode編碼來說,如果已經(jīng)知道是漢字,則使用GB2312/GBK無疑是最節(jié)省的。不過另一方面,值得說明的是,雖然utf編碼對(duì)漢字使用3個(gè)字節(jié),但即使對(duì)于漢字網(wǎng)頁(yè),utf編碼也會(huì)比unicode編碼節(jié)省,因?yàn)榫W(wǎng)頁(yè)中包含了很多的英文字符。?
3.?java對(duì)字符的處理?
在java應(yīng)用軟件中,會(huì)有多處涉及到字符集編碼,有些地方需要進(jìn)行正確的設(shè)置,有些地方需要進(jìn)行一定程度的處理。?
3.1.?getBytes(charset)?
這是java字符串處理的一個(gè)標(biāo)準(zhǔn)函數(shù),其作用是將字符串所表示的字符按照charset編碼,并以字節(jié)方式表示。注意字符串在java內(nèi)存中總是按unicode編碼存儲(chǔ)的。比如"中文",正常情況下(即沒有錯(cuò)誤的時(shí)候)存儲(chǔ)為"4e2d?6587",如果charset為"gbk",則被編碼為"d6d0?cec4",然后返回字節(jié)"d6?d0?ce?c4"。如果charset為"utf8"則最后是"e4?b8?ad?e6?96?87"。如果是"iso8859-1",則由于無法編碼,最后返回?"3f?3f"(兩個(gè)問號(hào))。?
3.2.?new?String(charset)?
這是java字符串處理的另一個(gè)標(biāo)準(zhǔn)函數(shù),和上一個(gè)函數(shù)的作用相反,將字節(jié)數(shù)組按照charset編碼進(jìn)行組合識(shí)別,最后轉(zhuǎn)換為unicode存儲(chǔ)。參考上述getBytes的例子,"gbk"?和"utf8"都可以得出正確的結(jié)果"4e2d?6587",但iso8859-1最后變成了"003f?003f"(兩個(gè)問號(hào))。?
因?yàn)閡tf8可以用來表示/編碼所有字符,所以new?String(?str.getBytes(?"utf8"?),?"utf8"?)?===?str,即完全可逆。?
3.3.?setCharacterEncoding()?
該函數(shù)用來設(shè)置http請(qǐng)求或者相應(yīng)的編碼。?
對(duì)于request,是指提交內(nèi)容的編碼,指定后可以通過getParameter()則直接獲得正確的字符串,如果不指定,則默認(rèn)使用iso8859-1編碼,需要進(jìn)一步處理。參見下述"表單輸入"。值得注意的是在執(zhí)行setCharacterEncoding()之前,不能執(zhí)行任何getParameter()。java?doc上說明:This?method?must?be?called?prior?to?reading?request?parameters?or?reading?input?using?getReader()。而且,該指定只對(duì)POST方法有效,對(duì)GET方法無效。分析原因,應(yīng)該是在執(zhí)行第一個(gè)getParameter()的時(shí)候,java將會(huì)按照編碼分析所有的提交內(nèi)容,而后續(xù)的getParameter()不再進(jìn)行分析,所以setCharacterEncoding()無效。而對(duì)于GET方法提交表單是,提交的內(nèi)容在URL中,一開始就已經(jīng)按照編碼分析所有的提交內(nèi)容,setCharacterEncoding()自然就無效。?
對(duì)于response,則是指定輸出內(nèi)容的編碼,同時(shí),該設(shè)置會(huì)傳遞給瀏覽器,告訴瀏覽器輸出內(nèi)容所采用的編碼。?
3.4.?處理過程?
下面分析兩個(gè)有代表性的例子,說明java對(duì)編碼有關(guān)問題的處理方法。?
3.4.1.?表單輸入?
User?input??*(gbk:d6d0?cec4)??browser??*(gbk:d6d0?cec4)??web?server??iso8859-1(00d6?00d?000ce?00c4)??class,需要在class中進(jìn)行處理:getbytes("iso8859-1")為d6?d0?ce?c4,new?String("gbk")為d6d0?cec4,內(nèi)存中以u(píng)nicode編碼則為4e2d?6587。?
l?用戶輸入的編碼方式和頁(yè)面指定的編碼有關(guān),也和用戶的操作系統(tǒng)有關(guān),所以是不確定的,上例以gbk為例。?
l?從browser到web?server,可以在表單中指定提交內(nèi)容時(shí)使用的字符集,否則會(huì)使用頁(yè)面指定的編碼。而如果在url中直接用?的方式輸入?yún)?shù),則其編碼往往是操作系統(tǒng)本身的編碼,因?yàn)檫@時(shí)和頁(yè)面無關(guān)。上述仍舊以gbk編碼為例。?
l?Web?server接收到的是字節(jié)流,默認(rèn)時(shí)(getParameter)會(huì)以iso8859-1編碼處理之,結(jié)果是不正確的,所以需要進(jìn)行處理。但如果預(yù)先設(shè)置了編碼(通過request.?setCharacterEncoding?()),則能夠直接獲取到正確的結(jié)果。?
l?在頁(yè)面中指定編碼是個(gè)好習(xí)慣,否則可能失去控制,無法指定正確的編碼。?
3.4.2.?文件編譯?
假設(shè)文件是gbk編碼保存的,而編譯有兩種編碼選擇:gbk或者iso8859-1,前者是中文windows的默認(rèn)編碼,后者是linux的默認(rèn)編碼,當(dāng)然也可以在編譯時(shí)指定編碼。?
Jsp??*(gbk:d6d0?cec4)??java?file??*(gbk:d6d0?cec4)??compiler?read??uincode(gbk:?4e2d?6587;?iso8859-1:?00d6?00d?000ce?00c4)??compiler?write??utf(gbk:?e4b8ad?e69687;?iso8859-1:?*)??compiled?file??unicode(gbk:?4e2d?6587;?iso8859-1:?00d6?00d?000ce?00c4)??class。所以用gbk編碼保存,而用iso8859-1編譯的結(jié)果是不正確的。?
class??unicode(4e2d?6587)??system.out?/?jsp.out??gbk(d6d0?cec4)??os?console?/?browser。?
l?文件可以以多種編碼方式保存,中文windows下,默認(rèn)為ansi/gbk。?
l?編譯器讀取文件時(shí),需要得到文件的編碼,如果未指定,則使用系統(tǒng)默認(rèn)編碼。一般class文件,是以系統(tǒng)默認(rèn)編碼保存的,所以編譯不會(huì)出問題,但對(duì)于jsp文件,如果在中文windows下編輯保存,而部署在英文linux下運(yùn)行/編譯,則會(huì)出現(xiàn)問題。所以需要在jsp文件中用pageEncoding指定編碼。?
l?Java編譯的時(shí)候會(huì)轉(zhuǎn)換成統(tǒng)一的unicode編碼處理,最后保存的時(shí)候再轉(zhuǎn)換為utf編碼。?
l?當(dāng)系統(tǒng)輸出字符的時(shí)候,會(huì)按指定編碼輸出,對(duì)于中文windows下,System.out將使用gbk編碼,而對(duì)于response(瀏覽器),則使用jsp文件頭指定的contentType,或者可以直接為response指定編碼。同時(shí),會(huì)告訴browser網(wǎng)頁(yè)的編碼。如果未指定,則會(huì)使用iso8859-1編碼。對(duì)于中文,應(yīng)該為browser指定輸出字符串的編碼。?
l?browser顯示網(wǎng)頁(yè)的時(shí)候,首先使用response中指定的編碼(jsp文件頭指定的contentType最終也反映在response上),如果未指定,則會(huì)使用網(wǎng)頁(yè)中meta項(xiàng)指定中的contentType。?
3.5.?幾處設(shè)置?
對(duì)于web應(yīng)用程序,和編碼有關(guān)的設(shè)置或者函數(shù)如下。?
3.5.1.?jsp編譯?
指定文件的存儲(chǔ)編碼,很明顯,該設(shè)置應(yīng)該置于文件的開頭。例如:<%@page?pageEncoding="GBK"%>。另外,對(duì)于一般class文件,可以在編譯的時(shí)候指定編碼。?
3.5.2.?jsp輸出?
指定文件輸出到browser是使用的編碼,該設(shè)置也應(yīng)該置于文件的開頭。例如:<%@?page?contentType="text/html;?charset=?GBK"?%>。該設(shè)置和response.setCharacterEncoding("GBK")等效。?
3.5.3.?meta設(shè)置?
指定網(wǎng)頁(yè)使用的編碼,該設(shè)置對(duì)靜態(tài)網(wǎng)頁(yè)尤其有作用。因?yàn)殪o態(tài)網(wǎng)頁(yè)無法采用jsp的設(shè)置,而且也無法執(zhí)行response.setCharacterEncoding()。例如:<META?http-equiv="Content-Type"?content="text/html;?charset=GBK"?/>?
如果同時(shí)采用了jsp輸出和meta設(shè)置兩種編碼指定方式,則jsp指定的優(yōu)先。因?yàn)閖sp指定的直接體現(xiàn)在response中。?
需要注意的是,apache有一個(gè)設(shè)置可以給無編碼指定的網(wǎng)頁(yè)指定編碼,該指定等同于jsp的編碼指定方式,所以會(huì)覆蓋靜態(tài)網(wǎng)頁(yè)中的meta指定。所以有人建議關(guān)閉該設(shè)置。?
3.5.4.?form設(shè)置?
當(dāng)瀏覽器提交表單的時(shí)候,可以指定相應(yīng)的編碼。例如:<form?accept-charset=?"gb2312">。一般不必不使用該設(shè)置,瀏覽器會(huì)直接使用網(wǎng)頁(yè)的編碼。?
4.?系統(tǒng)軟件?
下面討論幾個(gè)相關(guān)的系統(tǒng)軟件。?
4.1.?mysql數(shù)據(jù)庫(kù)?
很明顯,要支持多語(yǔ)言,應(yīng)該將數(shù)據(jù)庫(kù)的編碼設(shè)置成utf或者unicode,而utf更適合與存儲(chǔ)。但是,如果中文數(shù)據(jù)中包含的英文字母很少,其實(shí)unicode更為適合。?
數(shù)據(jù)庫(kù)的編碼可以通過mysql的配置文件設(shè)置,例如default-character-set=utf8。還可以在數(shù)據(jù)庫(kù)鏈接URL中設(shè)置,例如:?useUnicode=true&characterEncoding=UTF-8。注意這兩者應(yīng)該保持一致,在新的sql版本里,在數(shù)據(jù)庫(kù)鏈接URL里可以不進(jìn)行設(shè)置,但也不能是錯(cuò)誤的設(shè)置。?
4.2.?apache?
appache和編碼有關(guān)的配置在httpd.conf中,例如AddDefaultCharset?UTF-8。如前所述,該功能會(huì)將所有靜態(tài)頁(yè)面的編碼設(shè)置為UTF-8,最好關(guān)閉該功能。?
另外,apache還有單獨(dú)的模塊來處理網(wǎng)頁(yè)響應(yīng)頭,其中也可能對(duì)編碼進(jìn)行設(shè)置。?
4.3.?linux默認(rèn)編碼?
這里所說的linux默認(rèn)編碼,是指運(yùn)行時(shí)的環(huán)境變量。兩個(gè)重要的環(huán)境變量是LC_ALL和LANG,默認(rèn)編碼會(huì)影響到j(luò)ava?URLEncode的行為,下面有描述。?
建議都設(shè)置為"zh_CN.UTF-8"。?
4.4.?其它?
為了支持中文文件名,linux在加載磁盤時(shí)應(yīng)該指定字符集,例如:mount?/dev/hda5?/mnt/hda5/?-t?ntfs?-o?iocharset=gb2312。?
另外,如前所述,使用GET方法提交的信息不支持request.setCharacterEncoding(),但可以通過tomcat的配置文件指定字符集,在tomcat的server.xml文件中,形如:<Connector?...?URIEncoding="GBK"/>。這種方法將統(tǒng)一設(shè)置所有請(qǐng)求,而不能針對(duì)具體頁(yè)面進(jìn)行設(shè)置,也不一定和browser使用的編碼相同,所以有時(shí)候并不是所期望的。?
5.?URL地址?
URL地址中含有中文字符是很麻煩的,前面描述過使用GET方法提交表單的情況,使用GET方法時(shí),參數(shù)就是包含在URL中。?
5.1.?URL編碼?
對(duì)于URL中的一些特殊字符,瀏覽器會(huì)自動(dòng)進(jìn)行編碼。這些字符除了"/?&"等外,還包括unicode字符,比如漢子。這時(shí)的編碼比較特殊。?
IE有一個(gè)選項(xiàng)"總是使用UTF-8發(fā)送URL",當(dāng)該選項(xiàng)有效時(shí),IE將會(huì)對(duì)特殊字符進(jìn)行UTF-8編碼,同時(shí)進(jìn)行URL編碼。如果改選項(xiàng)無效,則使用默認(rèn)編碼"GBK",并且不進(jìn)行URL編碼。但是,對(duì)于URL后面的參數(shù),則總是不進(jìn)行編碼,相當(dāng)于UTF-8選項(xiàng)無效。比如"中文.html?a=中文",當(dāng)UTF-8選項(xiàng)有效時(shí),將發(fā)送鏈接"%e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87";而UTF-8選項(xiàng)無效時(shí),將發(fā)送鏈接"\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87"。注意后者前面的"中文"兩個(gè)字只有4個(gè)字節(jié),而前者卻有18個(gè)字節(jié),這主要時(shí)URL編碼的原因。?
當(dāng)web?server(tomcat)接收到該鏈接時(shí),將會(huì)進(jìn)行URL解碼,即去掉"%",同時(shí)按照ISO8859-1編碼(上面已經(jīng)描述,可以使用URLEncoding來設(shè)置成其它編碼)識(shí)別。上述例子的結(jié)果分別是"\ue4\ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87"和"\u4e\u2d\u65\u87.html?a=\u4e\u2d\u65\u87",注意前者前面的"中文"兩個(gè)字恢復(fù)成了6個(gè)字符。這里用"\u",表示是unicode。?
所以,由于客戶端設(shè)置的不同,相同的鏈接,在服務(wù)器上得到了不同結(jié)果。這個(gè)問題不少人都遇到,卻沒有很好的解決辦法。所以有的網(wǎng)站會(huì)建議用戶嘗試關(guān)閉UTF-8選項(xiàng)。不過,下面會(huì)描述一個(gè)更好的處理辦法。?
5.2.?rewrite?
熟悉的人都知道,apache有一個(gè)功能強(qiáng)大的rewrite模塊,這里不描述其功能。需要說明的是該模塊會(huì)自動(dòng)將URL解碼(去除%),即完成上述web?server(tomcat)的部分功能。有相關(guān)文檔介紹說可以使用[NE]參數(shù)來關(guān)閉該功能,但我試驗(yàn)并未成功,可能是因?yàn)榘姹荆ㄎ沂褂玫氖莂pache?2.0.54)問題。另外,當(dāng)參數(shù)中含有"?&?"等符號(hào)的時(shí)候,該功能將導(dǎo)致系統(tǒng)得不到正常結(jié)果。?
rewrite本身似乎完全是采用字節(jié)處理的方式,而不考慮字符串的編碼,所以不會(huì)帶來編碼問題。?
5.3.?URLEncode.encode()?
這是Java本身提供對(duì)的URL編碼函數(shù),完成的工作和上述UTF-8選項(xiàng)有效時(shí)瀏覽器所做的工作相似。值得說明的是,java已經(jīng)不贊成不指定編碼來使用該方法(deprecated)。應(yīng)該在使用的時(shí)候增加編碼指定。?
當(dāng)不指定編碼的時(shí)候,該方法使用系統(tǒng)默認(rèn)編碼,這會(huì)導(dǎo)致軟件運(yùn)行結(jié)果得不確定。比如對(duì)于"中文",當(dāng)系統(tǒng)默認(rèn)編碼為"gb2312"時(shí),結(jié)果是"%4e%2d%65%87",而默認(rèn)編碼為"UTF-8",結(jié)果卻是"%e4%b8%ad%e6%96%87",后續(xù)程序?qū)㈦y以處理。另外,這兒說的系統(tǒng)默認(rèn)編碼是由運(yùn)行tomcat時(shí)的環(huán)境變量LC_ALL和LANG等決定的,曾經(jīng)出現(xiàn)過tomcat重啟后就出現(xiàn)亂碼的問題,最后才郁悶的發(fā)現(xiàn)是因?yàn)樾薷男薷牧诉@兩個(gè)環(huán)境變量。?
建議統(tǒng)一指定為"UTF-8"編碼,可能需要修改相應(yīng)的程序。?
5.4.?一個(gè)解決方案?
上面說起過,因?yàn)闉g覽器設(shè)置的不同,對(duì)于同一個(gè)鏈接,web?server收到的是不同內(nèi)容,而軟件系統(tǒng)有無法知道這中間的區(qū)別,所以這一協(xié)議目前還存在缺陷。?
針對(duì)具體問題,不應(yīng)該僥幸認(rèn)為所有客戶的IE設(shè)置都是UTF-8有效的,也不應(yīng)該粗暴的建議用戶修改IE設(shè)置,要知道,用戶不可能去記住每一個(gè)web?server的設(shè)置。所以,接下來的解決辦法就只能是讓自己的程序多一點(diǎn)智能:根據(jù)內(nèi)容來分析編碼是否UTF-8。?
比較幸運(yùn)的是UTF-8編碼相當(dāng)有規(guī)律,所以可以通過分析傳輸過來的鏈接內(nèi)容,來判斷是否是正確的UTF-8字符,如果是,則以UTF-8處理之,如果不是,則使用客戶默認(rèn)編碼(比如"GBK"),下面是一個(gè)判斷是否UTF-8的例子,如果你了解相應(yīng)規(guī)律,就容易理解。?
public?static?boolean?isValidUtf8(byte[]?b,int?aMaxCount){?
???????int?lLen=b.length,lCharCount=0;?
???????for(int?i=0;i<lLen?&&?lCharCount<aMaxCount;++lCharCount){?
??????????????byte?lByte=b[i++];//to?fast?operation,?++?now,?ready?for?the?following?for(;;)?
??????????????if(lByte>=0)?continue;//>=0?is?normal?ascii?
??????????????if(lByte<(byte)0xc0?||?lByte>(byte)0xfd)?return?false;?
??????????????int?lCount=lByte>(byte)0xfc?5:lByte>(byte)0xf8?4?
?????????????????????:lByte>(byte)0xf0?3:lByte>(byte)0xe0?2:1;?
??????????????if(i+lCount>lLen)?return?false;?
??????????????for(int?j=0;j<lCount;++j,++i)?if(b[i]>=(byte)0xc0)?return?false;?
???????}?
???????return?true;?
}?
相應(yīng)地,一個(gè)使用上述方法的例子如下:?
public?static?String?getUrlParam(String?aStr,String?aDefaultCharset)?
throws?UnsupportedEncodingException{?
???????if(aStr==null)?return?null;?
???????byte[]?lBytes=aStr.getBytes("ISO-8859-1");?
???????return?new?String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset);?
}?
不過,該方法也存在缺陷,如下兩方面:?
l?沒有包括對(duì)用戶默認(rèn)編碼的識(shí)別,這可以根據(jù)請(qǐng)求信息的語(yǔ)言來判斷,但不一定正確,因?yàn)槲覀冇袝r(shí)候也會(huì)輸入一些韓文,或者其他文字。?
l?可能會(huì)錯(cuò)誤判斷UTF-8字符,一個(gè)例子是"學(xué)習(xí)"兩個(gè)字,其GBK編碼是"?\xd1\xa7\xcf\xb0",如果使用上述isValidUtf8方法判斷,將返回true。可以考慮使用更嚴(yán)格的判斷方法,不過估計(jì)效果不大。?
有一個(gè)例子可以證明google也遇到了上述問題,而且也采用了和上述相似的處理方法,比如,如果在地址欄中輸入"http://www.google.com/search?hl=zh-CN&newwindow=1&q=學(xué)習(xí)",google將無法正確識(shí)別,而其他漢字一般能夠正常識(shí)別。?
最后,應(yīng)該補(bǔ)充說明一下,如果不使用rewrite規(guī)則,或者通過表單提交數(shù)據(jù),其實(shí)并不一定會(huì)遇到上述問題,因?yàn)檫@時(shí)可以在提交數(shù)據(jù)時(shí)指定希望的編碼。另外,中文文件名確實(shí)會(huì)帶來問題,應(yīng)該謹(jǐn)慎使用。?
6.?其它?
下面描述一些和編碼有關(guān)的其他問題。?
6.1.?SecureCRT?
除了瀏覽器和控制臺(tái)與編碼有關(guān)外,一些客戶端也很有關(guān)系。比如在使用SecureCRT連接linux時(shí),應(yīng)該讓SecureCRT的顯示編碼(不同的session,可以有不同的編碼設(shè)置)和linux的編碼環(huán)境變量保持一致。否則看到的一些幫助信息,就可能是亂碼。?
另外,mysql有自己的編碼設(shè)置,也應(yīng)該保持和SecureCRT的顯示編碼一致。否則通過SecureCRT執(zhí)行sql語(yǔ)句的時(shí)候,可能無法處理中文字符,查詢結(jié)果也會(huì)出現(xiàn)亂碼。?
對(duì)于Utf-8文件,很多編輯器(比如記事本)會(huì)在文件開頭增加三個(gè)不可見的標(biāo)志字節(jié),如果作為mysql的輸入文件,則必須要去掉這三個(gè)字符。(用linux的vi保存可以去掉這三個(gè)字符)。一個(gè)有趣的現(xiàn)象是,在中文windows下,創(chuàng)建一個(gè)新txt文件,用記事本打開,輸入"連通"兩個(gè)字,保存,再打開,你會(huì)發(fā)現(xiàn)兩個(gè)字沒了,只留下一個(gè)小黑點(diǎn)。?
6.2.?過濾器?
如果需要統(tǒng)一設(shè)置編碼,則通過filter進(jìn)行設(shè)置是個(gè)不錯(cuò)的選擇。在filter?class中,可以統(tǒng)一為需要的請(qǐng)求或者回應(yīng)設(shè)置編碼。參加上述setCharacterEncoding()。這個(gè)類apache已經(jīng)給出了可以直接使用的例子SetCharacterEncodingFilter。?
6.3.?POST和GET?
很明顯,以POST提交信息時(shí),URL有更好的可讀性,而且可以方便的使用setCharacterEncoding()來處理字符集問題。但GET方法形成的URL能夠更容易表達(dá)網(wǎng)頁(yè)的實(shí)際內(nèi)容,也能夠用于收藏。?
從統(tǒng)一的角度考慮問題,建議采用GET方法,這要求在程序中獲得參數(shù)是進(jìn)行特殊處理,而無法使用setCharacterEncoding()的便利,如果不考慮rewrite,就不存在IE的UTF-8問題,可以考慮通過設(shè)置URIEncoding來方便獲取URL中的參數(shù)。?
6.4.?簡(jiǎn)繁體編碼轉(zhuǎn)換?
GBK同時(shí)包含簡(jiǎn)體和繁體編碼,也就是說同一個(gè)字,由于編碼不同,在GBK編碼下屬于兩個(gè)字。有時(shí)候,為了正確取得完整的結(jié)果,應(yīng)該將繁體和簡(jiǎn)體進(jìn)行統(tǒng)一。可以考慮將UTF、GBK中的所有繁體字,轉(zhuǎn)換為相應(yīng)的簡(jiǎn)體字,BIG5編碼的數(shù)據(jù),也應(yīng)該轉(zhuǎn)化成相應(yīng)的簡(jiǎn)體字。當(dāng)然,仍舊以UTF編碼存儲(chǔ)。?
例如,對(duì)于"語(yǔ)言??言",用UTF表示為"\xE8\xAF\xAD\xE8\xA8\x80?\xE8\xAA\x9E\xE8\xA8\x80",進(jìn)行簡(jiǎn)繁體編碼轉(zhuǎn)換后應(yīng)該是兩個(gè)相同的?"\xE8\xAF\xAD\xE8\xA8\x80>"。?
?
http://sz.eeju.com/show_rent_99461.htm
http://sz.eeju.com/show_rent_98823.htm
http://sz.eeju.com/show_rent_96082.htm
http://sz.eeju.com/show_rent_99193.htm
http://sz.eeju.com/show_rent_99461.htm
http://sz.eeju.com/show_rent_99181.htm
http://rent.sz.soufun.com/cz/CZ_MLS_17845812.htm
http://rent.sz.soufun.com/cz/CZ_MLS_17940110.htm
http://rent.sz.soufun.com/cz/CZ_MLS_17852140.htm?***
|
|
插入排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil; /** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class InsertSort implements SortUtil.Sort{
??? /* (non-Javadoc) ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) ???? */ ??? public void sort(int[] data) { ??????? int temp; ??????? for(int i=1;i<data.length;i++){ ??????????? for(int j=i;(j>0)&&(data[j]<data[j-1]);j--){ ??????????????? SortUtil.swap(data,j,j-1); ??????????? } ??????? }??????? ??? }
} 冒泡排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class BubbleSort implements SortUtil.Sort{
??? /* (non-Javadoc) ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) ???? */ ??? public void sort(int[] data) { ??????? int temp; ??????? for(int i=0;i<data.length;i++){ ??????????? for(int j=data.length-1;j>i;j--){ ??????????????? if(data[j]<data[j-1]){ ??????????????????? SortUtil.swap(data,j,j-1); ??????????????? } ??????????? } ??????? } ??? }
}
選擇排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class SelectionSort implements SortUtil.Sort {
??? /* ???? * (non-Javadoc) ???? * ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) ???? */ ??? public void sort(int[] data) { ??????? int temp; ??????? for (int i = 0; i < data.length; i++) { ??????????? int lowIndex = i; ??????????? for (int j = data.length - 1; j > i; j--) { ??????????????? if (data[j] < data[lowIndex]) { ??????????????????? lowIndex = j; ??????????????? } ??????????? } ??????????? SortUtil.swap(data,i,lowIndex); ??????? } ??? }
}
Shell排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class ShellSort implements SortUtil.Sort{
??? /* (non-Javadoc) ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) ???? */ ??? public void sort(int[] data) { ??????? for(int i=data.length/2;i>2;i/=2){ ??????????? for(int j=0;j<i;j++){ ??????????????? insertSort(data,j,i); ??????????? } ??????? } ??????? insertSort(data,0,1); ??? }
??? /** ???? * @param data ???? * @param j ???? * @param i ???? */ ??? private void insertSort(int[] data, int start, int inc) { ??????? int temp; ??????? for(int i=start+inc;i<data.length;i+=inc){ ??????????? for(int j=i;(j>=inc)&&(data[j]<data[j-inc]);j-=inc){ ??????????????? SortUtil.swap(data,j,j-inc); ??????????? } ??????? } ??? }
}
快速排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class QuickSort implements SortUtil.Sort{
??? /* (non-Javadoc) ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) ???? */ ??? public void sort(int[] data) { ??????? quickSort(data,0,data.length-1);??????? ??? } ??? private void quickSort(int[] data,int i,int j){ ??????? int pivotIndex=(i+j)/2; ??????? //swap ??????? SortUtil.swap(data,pivotIndex,j); ??????? ??????? int k=partition(data,i-1,j,data[j]); ??????? SortUtil.swap(data,k,j); ??????? if((k-i)>1) quickSort(data,i,k-1); ??????? if((j-k)>1) quickSort(data,k+1,j); ??????? ??? } ??? /** ???? * @param data ???? * @param i ???? * @param j ???? * @return ???? */ ??? private int partition(int[] data, int l, int r,int pivot) { ??????? do{ ?????????? while(data[++l]<pivot); ?????????? while((r!=0)&&data[--r]>pivot); ?????????? SortUtil.swap(data,l,r); ??????? } ??????? while(l<r); ??????? SortUtil.swap(data,l,r);??????? ??????? return l; ??? }
} 改進(jìn)后的快速排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class ImprovedQuickSort implements SortUtil.Sort {
??? private static int MAX_STACK_SIZE=4096; ??? private static int THRESHOLD=10; ??? /* (non-Javadoc) ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) ???? */ ??? public void sort(int[] data) { ??????? int[] stack=new int[MAX_STACK_SIZE]; ??????? ??????? int top=-1; ??????? int pivot; ??????? int pivotIndex,l,r; ??????? ??????? stack[++top]=0; ??????? stack[++top]=data.length-1; ??????? ??????? while(top>0){ ??????????? int j=stack[top--]; ??????????? int i=stack[top--]; ??????????? ??????????? pivotIndex=(i+j)/2; ??????????? pivot=data[pivotIndex]; ??????????? ??????????? SortUtil.swap(data,pivotIndex,j); ??????????? ??????????? //partition ??????????? l=i-1; ??????????? r=j; ??????????? do{ ??????????????? while(data[++l]<pivot); ??????????????? while((r!=0)&&(data[--r]>pivot)); ??????????????? SortUtil.swap(data,l,r); ??????????? } ??????????? while(l<r); ??????????? SortUtil.swap(data,l,r); ??????????? SortUtil.swap(data,l,j); ??????????? ??????????? if((l-i)>THRESHOLD){ ??????????????? stack[++top]=i; ??????????????? stack[++top]=l-1; ??????????? } ??????????? if((j-l)>THRESHOLD){ ??????????????? stack[++top]=l+1; ??????????????? stack[++top]=j; ??????????? } ??????????? ??????? } ??????? //new InsertSort().sort(data); ??????? insertSort(data); ??? } ??? /** ???? * @param data ???? */ ??? private void insertSort(int[] data) { ??????? int temp; ??????? for(int i=1;i<data.length;i++){ ??????????? for(int j=i;(j>0)&&(data[j]<data[j-1]);j--){ ??????????????? SortUtil.swap(data,j,j-1); ??????????? } ??????? }?????? ??? }
}
歸并排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class MergeSort implements SortUtil.Sort{
??? /* (non-Javadoc) ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) ???? */ ??? public void sort(int[] data) { ??????? int[] temp=new int[data.length]; ??????? mergeSort(data,temp,0,data.length-1); ??? } ??? ??? private void mergeSort(int[] data,int[] temp,int l,int r){ ??????? int mid=(l+r)/2; ??????? if(l==r) return ; ??????? mergeSort(data,temp,l,mid); ??????? mergeSort(data,temp,mid+1,r); ??????? for(int i=l;i<=r;i++){ ??????????? temp[i]=data[i]; ??????? } ??????? int i1=l; ??????? int i2=mid+1; ??????? for(int cur=l;cur<=r;cur++){ ??????????? if(i1==mid+1) ??????????????? data[cur]=temp[i2++]; ??????????? else if(i2>r) ??????????????? data[cur]=temp[i1++]; ??????????? else if(temp[i1]<temp[i2]) ??????????????? data[cur]=temp[i1++]; ??????????? else ??????????????? data[cur]=temp[i2++];??????????? ??????? } ??? }
}
改進(jìn)后的歸并排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class ImprovedMergeSort implements SortUtil.Sort {
??? private static final int THRESHOLD = 10;
??? /* ???? * (non-Javadoc) ???? * ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) ???? */ ??? public void sort(int[] data) { ??????? int[] temp=new int[data.length]; ??????? mergeSort(data,temp,0,data.length-1); ??? }
??? private void mergeSort(int[] data, int[] temp, int l, int r) { ??????? int i, j, k; ??????? int mid = (l + r) / 2; ??????? if (l == r) ??????????? return; ??????? if ((mid - l) >= THRESHOLD) ??????????? mergeSort(data, temp, l, mid); ??????? else ??????????? insertSort(data, l, mid - l + 1); ??????? if ((r - mid) > THRESHOLD) ??????????? mergeSort(data, temp, mid + 1, r); ??????? else ??????????? insertSort(data, mid + 1, r - mid);
??????? for (i = l; i <= mid; i++) { ??????????? temp[i] = data[i]; ??????? } ??????? for (j = 1; j <= r - mid; j++) { ??????????? temp[r - j + 1] = data[j + mid]; ??????? } ??????? int a = temp[l]; ??????? int b = temp[r]; ??????? for (i = l, j = r, k = l; k <= r; k++) { ??????????? if (a < b) { ??????????????? data[k] = temp[i++]; ??????????????? a = temp[i]; ??????????? } else { ??????????????? data[k] = temp[j--]; ??????????????? b = temp[j]; ??????????? } ??????? } ??? }
??? /** ???? * @param data ???? * @param l ???? * @param i ???? */ ??? private void insertSort(int[] data, int start, int len) { ??????? for(int i=start+1;i<start+len;i++){ ??????????? for(int j=i;(j>start) && data[j]<data[j-1];j--){ ??????????????? SortUtil.swap(data,j,j-1); ??????????? } ??????? } ??? }
} 堆排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class HeapSort implements SortUtil.Sort{
??? /* (non-Javadoc) ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) ???? */ ??? public void sort(int[] data) { ??????? MaxHeap h=new MaxHeap(); ??????? h.init(data); ??????? for(int i=0;i<data.length;i++) ??????????? h.remove(); ??????? System.arraycopy(h.queue,1,data,0,data.length); ??? }
???? private static class MaxHeap{ ???????? ??????? ??????? void init(int[] data){ ??????????? this.queue=new int[data.length+1]; ??????????? for(int i=0;i<data.length;i++){ ??????????????? queue[++size]=data[i]; ??????????????? fixUp(size); ??????????? } ??????? } ???????? ??????? private int size=0;
??????? private int[] queue; ??????????????? ??????? public int get() { ??????????? return queue[1]; ??????? }
??????? public void remove() { ??????????? SortUtil.swap(queue,1,size--); ??????????? fixDown(1); ??????? } ??????? //fixdown ??????? private void fixDown(int k) { ??????????? int j; ??????????? while ((j = k << 1) <= size) { ??????????????? if (j < size && queue[j]<queue[j+1]) ??????????????????? j++; ??????????????? if (queue[k]>queue[j]) //不用交換 ??????????????????? break; ??????????????? SortUtil.swap(queue,j,k); ??????????????? k = j; ??????????? } ??????? } ??????? private void fixUp(int k) { ??????????? while (k > 1) { ??????????????? int j = k >> 1; ??????????????? if (queue[j]>queue[k]) ??????????????????? break; ??????????????? SortUtil.swap(queue,j,k); ??????????????? k = j; ??????????? } ??????? }
??? }
}
?
SortUtil:
package org.rut.util.algorithm;
import org.rut.util.algorithm.support.BubbleSort; import org.rut.util.algorithm.support.HeapSort; import org.rut.util.algorithm.support.ImprovedMergeSort; import org.rut.util.algorithm.support.ImprovedQuickSort; import org.rut.util.algorithm.support.InsertSort; import org.rut.util.algorithm.support.MergeSort; import org.rut.util.algorithm.support.QuickSort; import org.rut.util.algorithm.support.SelectionSort; import org.rut.util.algorithm.support.ShellSort;
/** ?* @author treeroot ?* @since 2006-2-2 ?* @version 1.0 ?*/ public class SortUtil { ??? public final static int INSERT = 1;
??? public final static int BUBBLE = 2;
??? public final static int SELECTION = 3;
??? public final static int SHELL = 4;
??? public final static int QUICK = 5;
??? public final static int IMPROVED_QUICK = 6;
??? public final static int MERGE = 7;
??? public final static int IMPROVED_MERGE = 8;
??? public final static int HEAP = 9;
??? public static void sort(int[] data) { ??????? sort(data, IMPROVED_QUICK); ??? } ??? private static String[] name={ ??????????? "insert","bubble","selection","shell","quick","improved_quick","merge","improved_merge","heap" ??? }; ??? ??? private static Sort[] impl=new Sort[]{ ??????????? new InsertSort(), ??????????? new BubbleSort(), ??????????? new SelectionSort(), ??????????? new ShellSort(), ??????????? new QuickSort(), ??????????? new ImprovedQuickSort(), ??????????? new MergeSort(), ??????????? new ImprovedMergeSort(), ??????????? new HeapSort() ??? };
??? public static String toString(int algorithm){ ??????? return name[algorithm-1]; ??? } ??? ??? public static void sort(int[] data, int algorithm) { ??????? impl[algorithm-1].sort(data); ??? }
??? public static interface Sort { ??????? public void sort(int[] data); ??? }
??? public static void swap(int[] data, int i, int j) { ??????? int temp = data[i]; ??????? data[i] = data[j]; ??????? data[j] = temp; ??? } }
|
Unicode解決方案
Unicode:寬字節(jié)字符集(摘自windows核心編程)
Unicode是Apple和Xerox公司于1988年建立的一個(gè)技術(shù)標(biāo)準(zhǔn)。1991年,成立了一個(gè)集團(tuán)機(jī)構(gòu)負(fù)責(zé)Unicode的開發(fā)和推廣應(yīng)用。該集團(tuán)由Apple、Compaq、IBM、Microsoft、Oracle、Silicon ? Graphics, ? Inc.、Sybase、Unisys和Xerox等公司組成。該集團(tuán)負(fù)責(zé)維護(hù)Unicode標(biāo)準(zhǔn)。
Unicode提供了一種簡(jiǎn)單而又一致的表示字符串的方法。Unicode字符串中的所有字符都是16位的(兩個(gè)字節(jié))。它沒有專門的字節(jié)來指明下一個(gè)字節(jié)是屬于同一個(gè)字符的組成部分,還是一個(gè)新字符。這意味著你只需要對(duì)指針進(jìn)行遞增或遞減,就可以遍歷字符串中的各個(gè)字符,不再需要調(diào)用CharNext之類的函數(shù)。由于Unicode用一個(gè)16位的值來表示每個(gè)字符,因此總共可以得到65000個(gè)字符,這樣,它就能夠?qū)κ澜绺鲊?guó)的書面文字中的所有字符進(jìn)行編碼,遠(yuǎn)遠(yuǎn)超過了單字節(jié)字符集的256個(gè)字符的數(shù)目。
我們面臨的基本問題是世界上的書寫語(yǔ)言不能簡(jiǎn)單地用256個(gè)8位代碼表示。以前的解決方案包括代碼頁(yè)和DBCS已被證明是不能滿足需要的,而且也是笨拙的。那什么才是真正的解決方案呢?
身為程序編寫者,我們經(jīng)歷過這類問題。如果事情太多,用8位數(shù)值已經(jīng)不能表示,那么我們就試更寬的值,例如16位值。而且這很有趣的,正是Unicode被制定的原因。與混亂的256個(gè)字符代碼映像,以及含有一些1字節(jié)代碼和一些2字節(jié)代碼的雙字節(jié)字符集不同,Unicode是統(tǒng)一的16位系統(tǒng),這樣就允許表示65,536個(gè)字符。這對(duì)表示所有字符及世界上使用象形文字的語(yǔ)言,包括一系列的數(shù)學(xué)、符號(hào)和貨幣單位符號(hào)的集合來說是充裕的。
明白Unicode和DBCS之間的區(qū)別很重要。Unicode使用(特別在C程序設(shè)計(jì)語(yǔ)言環(huán)境里)“寬字符集”。“Unicode中的每個(gè)字符都是16位寬而不是8位寬。”在Unicode中,沒有單單使用8位數(shù)值的意義存在。相比之下,在雙字節(jié)字符集中我們?nèi)匀惶幚?位數(shù)值。有些字節(jié)自身定義字符,而某些字節(jié)則顯示需要和另一個(gè)字節(jié)共同定義一個(gè)字符。
處理DBCS字符串非常雜亂,但是處理Unicode文字則像處理有秩序的文字。您也許會(huì)高興地知道前128個(gè)Unicode字符(16位代碼從0x0000到0x007F)就是ASCII字符,而接下來的128個(gè)Unicode字符(代碼從0x0080到0x00FF)是ISO ? 8859-1對(duì)ASCII的擴(kuò)展。Unicode中不同部分的字符都同樣基于現(xiàn)有的標(biāo)準(zhǔn)。這是為了便于轉(zhuǎn)換。希臘字母表使用從0x0370到0x03FF的代碼,斯拉夫語(yǔ)使用從0x0400到0x04FF的代碼,美國(guó)使用從0x0530到0x058F的代碼,希伯來語(yǔ)使用從0x0590到0x05FF的代碼。中國(guó)、日本和韓國(guó)的象形文字(總稱為CJK)占用了從0x3000到0x9FFF的代碼。
Unicode的最大好處是這里只有一個(gè)字符集,沒有一點(diǎn)含糊。Unicode實(shí)際上是個(gè)人計(jì)算機(jī)行業(yè)中幾乎每個(gè)重要公司共同合作的結(jié)果,并且它與ISO ? 10646-1標(biāo)準(zhǔn)中的代碼是一一對(duì)應(yīng)的。Unicode的重要參考文獻(xiàn)是《The ? Unicode ? Standard,Version ? 2.0》(Addison-Wesley出版社,1996年)。這是一本特別的書,它以其它文件少有的方式顯示了世界上書寫語(yǔ)言的豐富性和多樣性。此外,該書還提供了開發(fā)Unicode的基本原理和細(xì)節(jié)。
Unicode有缺點(diǎn)嗎?當(dāng)然有。Unicode字符串占用的內(nèi)存是ASCII字符串的兩倍。(然而壓縮文件有助于極大地減少文件所占的磁盤空間。)但也許最糟的缺點(diǎn)是:人們相對(duì)來說還不習(xí)慣使用Unicode。身為程序編寫者,這就是我們的工作
插件下載地址:
http://www.delphibbs.com/keylife/images/u88173/csdnkantie.rar
下載后解壓到myIE的plugin目錄即可。
例如我的解壓后的目錄:
D:\programs\Maxthon\Plugin\csdnkantie\
效果圖:
http://blog.csdn.net/images/blog_csdn_net/pigo/36738/o_casdnkanite001.gif
http://blog.csdn.net/images/blog_csdn_net/pigo/36738/o_casdnkanite001.gif
pop-ent.21cn.com
@shareinfo.com.cn
在Connection上調(diào)用close方法會(huì)關(guān)閉Statement和ResultSet嗎?
級(jí)聯(lián)的關(guān)閉這聽起來好像很有道理,而且在很多地方這樣做也是正確的,通常這樣寫
Connection con = getConnection();//getConnection is your method
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
……
///rs.close();
///ps.close();
con.close();? // NO!
這樣做的問題在于Connection是個(gè)接口,它的close實(shí)現(xiàn)可能是多種多樣的。在普通情況下,你用 DriverManager.getConnection()得到一個(gè)Connection實(shí)例,調(diào)用它的close方法會(huì)關(guān)閉Statement和 ResultSet。但是在很多時(shí)候,你需要使用數(shù)據(jù)庫(kù)連接池,在連接池中的得到的Connection上調(diào)用close方法的時(shí)候,Connection可能并沒有被釋放,而是回到了連接池中。它以后可能被其它代碼取出來用。如果沒有釋放Statement和ResultSet,那么在Connection上沒有關(guān)閉的Statement和ResultSet可能會(huì)越來越多,那么……
相反,我看到過這樣的說法,有人把Connection關(guān)閉了,卻繼續(xù)使用ResultSet,認(rèn)為這樣是可以的,引發(fā)了激烈的討論,到底是怎么回事就不用我多說了吧。
所以我們必須很小心的釋放數(shù)據(jù)庫(kù)資源,下面的代碼片斷展示了這個(gè)過程
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
??? con = getConnection();//getConnection is your method
??? ps = con.prepareStatement(sql);
??? rs = ps.executeQuery();
??? ///...........
}
catch (SQLException ex) {
??? ///錯(cuò)誤處理
}
finally{
??? try {
??????? if(ps!=null)
??????????? ps.close();
??? }
??? catch (SQLException ex) {
??????? ///錯(cuò)誤處理
??? }
??? try{
??????? if(con!=null)
??????????? con.close();
??? }
??? catch (SQLException ex) {
??????? ///錯(cuò)誤處理
??? }
}
?
1. Open:? Internet Options --> Content --> AutoComplete
2. Click button: ?'Clear Forms' and 'Clear Passwords'
public class TranCharset {
??? private static final String PRE_FIX_UTF = "&#x";
??? private static final String POS_FIX_UTF = ";";
??? public TranCharset() {
??? }
??? /**
???? * Translate charset encoding to unicode
???? *
???? * @param sTemp charset encoding is gb2312
???? * @return charset encoding is unicode
???? */
??? public static String XmlFormalize(String sTemp) {
??????? StringBuffer sb = new StringBuffer();
??????? if (sTemp == null || sTemp.equals("")) {
??????????? return "";
??????? }
??????? String s = TranCharset.TranEncodeTOGB(sTemp);
??????? for (int i = 0; i < s.length(); i++) {
??????????? char cChar = s.charAt(i);
??????????? if (TranCharset.isGB2312(cChar)) {
??????????????? sb.append(PRE_FIX_UTF);
??????????????? sb.append(Integer.toHexString(cChar));
??????????????? sb.append(POS_FIX_UTF);
??????????? } else {
??????????????? switch ((int) cChar) {
??????????????????? case 32:
??????????????????????? sb.append(" ");
??????????????????????? break;
??????????????????? case 34:
??????????????????????? sb.append(""");
??????????????????????? break;
??????????????????? case 38:
??????????????????????? sb.append("&");
??????????????????????? break;
??????????????????? case 60:
??????????????????????? sb.append("<");
??????????????????????? break;
??????????????????? case 62:
??????????????????????? sb.append(">");
??????????????????????? break;
??????????????????? default:
??????????????????????? sb.append(cChar);
??????????????? }
??????????? }
??????? }
??????? return sb.toString();
??? }
??? /**
???? * 將字符串編碼格式轉(zhuǎn)成GB2312
???? *
???? * @param str
???? * @return
???? */
??? public static String TranEncodeTOGB(String str) {
??????? try {
??????????? String strEncode = TranCharset.getEncoding(str);
??????????? String temp = new String(str.getBytes(strEncode), "GB2312");
??????????? return temp;
??????? } catch (java.io.IOException ex) {
??????????? return null;
??????? }
??? }
??? /**
???? * 判斷輸入字符是否為gb2312的編碼格式
???? *
???? * @param c 輸入字符
???? * @return 如果是gb2312返回真,否則返回假
???? */
??? public static boolean isGB2312(char c) {
??????? Character ch = new Character(c);
??????? String sCh = ch.toString();
??????? try {
??????????? byte[] bb = sCh.getBytes("gb2312");
??????????? if (bb.length > 1) {
??????????????? return true;
??????????? }
??????? } catch (java.io.UnsupportedEncodingException ex) {
??????????? return false;
??????? }
??????? return false;
??? }
??? /**
???? * 判斷字符串的編碼
???? *
???? * @param str
???? * @return
???? */
??? public static String getEncoding(String str) {
??????? String encode = "GB2312";
??????? try {
??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
??????????????? String s = encode;
??????????????? return s;
??????????? }
??????? } catch (Exception exception) {
??????? }
??????? encode = "ISO-8859-1";
??????? try {
??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
??????????????? String s1 = encode;
??????????????? return s1;
??????????? }
??????? } catch (Exception exception1) {
??????? }
??????? encode = "UTF-8";
??????? try {
??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
??????????????? String s2 = encode;
??????????????? return s2;
??????????? }
??????? } catch (Exception exception2) {
??????? }
??????? encode = "GBK";
??????? try {
??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
??????????????? String s3 = encode;
??????????????? return s3;
??????????? }
??????? } catch (Exception exception3) {
??????? }
??????? encode = "BIG5";
??????? try {
??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
??????????????? String s4 = encode;
??????????????? return s4;
??????????? }
??????? } catch (Exception exception3) {
??????? }
??????? return "";
??? }
??? public static void main(String args[]) {
??????? System.out.println(XmlFormalize("下載"));
??? }
}
問題:
如何在文本框中只允許輸入漢字,字母數(shù)字或者其他符號(hào)文字都不可以呢?
處理:
//javascript
var?? re=/[^\x00-\xff]/g;
if(re.test(你要測(cè)試的值))
{
????? //是漢字
}
注:用ascII碼控制。好像漢字都是負(fù)數(shù)
System.out.println(Pattern.compile("[\u4e00-\u9fa5]").matcher("a").find());
//[\u4e00-\u9fa5] 中文的正則表達(dá)式
//"a" 你想判斷的字符
問題:
在ArrayList 應(yīng)用中有這樣的代碼:
ArrayList a=new ArrayList();
a.add(...);
Iterator i=a.iterator();
理解:Iterator i=a.iterator();
Iterator 是一個(gè)接口,在上面a.iterator()方法的作用是返回一個(gè)接口
hasmore(),next()是怎么被實(shí)現(xiàn)的?
處理:
迭代模式
ArrayList內(nèi)部有一個(gè)實(shí)現(xiàn)了Iterator 接口的類,a.iterator就是返回它內(nèi)部類的一個(gè)實(shí)例,即返回一個(gè)實(shí)現(xiàn)了的iterator接口的類。
接口是一個(gè)類型,相當(dāng)于一個(gè)父類型(supertype),可以用一個(gè)接口引用一個(gè)實(shí)現(xiàn)了此接口的類的實(shí)例。這樣只能用接口提供的方法來訪問此對(duì)象,可以限制訪問,隱藏具體實(shí)現(xiàn)。
我想遍歷所有key為username的值,比如:
每一個(gè)登陸用戶都有一個(gè)username的session,我如何判斷有多少個(gè)這樣的session及其值呢?
處理:
HttpSessionBindingListener進(jìn)行監(jiān)聽,維護(hù)一個(gè)全局變量
首先明確一下,樓主的問題應(yīng)該是比較 JDK 和 JRE (而不是 JVM,因?yàn)?JDK 和 JRE 里面都包含 JVM)。
顧名思義,JDK 比 JRE 多出來的東西,就是在開發(fā)過程中要用到的一些東西,比如 javac、javadoc、keytool 等工具,還有其它的一些東西(比如 API 文檔)。一般來說,這些東西在軟件開發(fā)完成交付運(yùn)行之后就用不到了。不過也有例外,比如要在 Tomcat 里跑 JSP 的話,就需要 javac。
public:公有的,說明該類成員可被所有的對(duì)象使用
protected:保護(hù)的,說明該類成員能被同一類中的其他成員,或其子類成員,或同一包中的其他類訪問,不能被其他包的非子類訪問
無:默認(rèn)的.當(dāng)修飾符默認(rèn)時(shí),說明該類成員能被同一類中的其他成員,或同一包中的其他類訪問,不能被其他包的類訪問
private:私有的,說明該類成員只能被同一類中的其他成員訪問,不能被其他類的成員訪問,也不能被子類成員訪問.
1. 有一個(gè)ArrayList,里面包含N個(gè)Integer,其中的Integer都是由1至N+1的數(shù)字構(gòu)成,并且不重復(fù),但是有一個(gè)1至N+1的數(shù)字對(duì)應(yīng)的Integer
不存在ArrayList中,求該數(shù)。
public static void main(String[] args){
ArrayList list= new ArrayList();
list.add(Integet(7));
list.add(Integet(8));
list.add(Integet(1));
list.add(Integet(2));
list.add(Integet(3));
list.add(Integet(4));
list.add(Integet(5));
}
public int getMissing(ArrayList list){
int len = list.size();
for (int i = 1; i <= len; i++) {
int j = 0;
while (j < len) {
Integer Val = (Integer) list.get(j);
int value = Val.intValue();
if (i == value)
break;
j++;
}
if (j == len) {
return j;
}
}
return -1;
}
2. 有一個(gè)二叉樹類如下。然后寫出遍歷二叉樹的方法printTree。
class BinaryTree{
class Node{
? String value;
? Node leftNode;
? Node rightNode;
}
public void printTree(Node root){
? reDo(root,0);
}
public void reDo(Node node,int depth){
? if(node != null) {
??? System.out.println(space()+node.value);
??? reDo(node.leftNode,depth+1);
??? reDo(node.rightNode,depth+1);
? }
?????
}
public String space(int len){
?? StringBuffer bs = new StringBuffer();
?? for(int i=0; i<bs.length();i++){
??? bs.append(" ");
?? }
}
}
3. 有int型數(shù)字如下,123,1234,12345,123456,1234567,12345678,123456789
求一個(gè)方法,輸出123 1,234 12,345 123,456 1,234,567 12,345,678 123,456,789
public String printComma(int input){
StringBuffer bs = new StringBuffer(input + "");
int index = bs.length() - 3;
while (index > 0) {
? bs.insert(index, ",");
? index = index - 3;
}
return bs.toString();
}
4.equals(),hasCode()的作用。
5.Object對(duì)象有哪些方法?
? equals(),clone(),notify(),notifyAll(),wait(),wait(long time),wait(long time,int nanos)
? hasCode(),toString(),getClass()。
6.RuntimeException,非RuntimeException的區(qū)別和例子。
7.Singleton模式
8.共享數(shù)據(jù)在web中的范圍
? page,request,seesion,application
9.Servlet的生命周期。
? servlet有良好的生存期定義,包括加載,實(shí)例化,初始化,處理請(qǐng)求,服務(wù)結(jié)束。由javax.servlet.Servlet接口以下方法表達(dá)
? init(),service(),destroy()。
10.abstract和interface的區(qū)別。
? abstract中可以有自己方法的定義和說明,interface只是存在變量和方法的定義。當(dāng)需要的時(shí)候,我們可以inplements多個(gè)接口,但是只能
extends一個(gè)類。
11.實(shí)現(xiàn)多線程有哪幾種方法。
第一種,class MyThread extends Thread{..}? MyThread t = new MyThread(); t.start();
第二中,class UrThread implements Runnable{...} Thread t = new Thread(new UrThread()); t.start();
12.ArrayList和Vector的區(qū)別。
? Vector中的方法是synchronized的,性能上較ArrayList差點(diǎn)。
? 當(dāng)增長(zhǎng)時(shí),Vector默認(rèn)增長(zhǎng)原來的一倍,ArrayList默認(rèn)增長(zhǎng)原來的一半。
13.java實(shí)現(xiàn)序列化的方法是實(shí)現(xiàn)serializable接口,具體怎么做。
??
14.String a = "test"; String b = new String("test"); a==b (false)
?? String c = "te"+"st"; a==c (true)
15.
public synchronized void aMethod1(){
}
public void b aMethod(){
synchronized("test"){
?
}
}
A a1 = new A();
A a2 = new A();
a1.aMethod1();
a2.aMethod1();//不需要等待
a1.aMethod2();
a2.aMethod2();//需要等待
16.編程性能方法的討論,ArrayList,HashMap,StringBuffer。
17.Struts的DispatchAction,Action的區(qū)別。RequestProcessor的作用。
? 問題一:
? 有int型數(shù)字如下,123,1234,12345,123456,1234567,12345678,123456789
? 求一個(gè)方法,輸出123 1,234 12,345 123,456 1,234,567 12,345,678 123,456,789
??處理:
? public void testPrint(int num) {
??? DecimalFormat format = new DecimalFormat("#,###");
??? System.out.println(format.format(num));
? }
?問題二、
double類型如何正確的轉(zhuǎn)換為字符串類型
處理:
?double d = 0.001;
??? DecimalFormat df1 = new DecimalFormat("#.####");
??? String result = df1.format(d);
??? System.out.println(result);
Singleton模式主要作用是保證在Java應(yīng)用程序中,一個(gè)類只有一個(gè)實(shí)例存在。解釋下面的代碼是怎么保證只有一個(gè)實(shí)例的?
public class Singleton {
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
處理:
因?yàn)闃?gòu)造函數(shù)是私有的,用戶不能自己實(shí)例對(duì)象 private Singleton(){}
而且指向這個(gè)唯一的對(duì)象的引用也是私有,只能通過getInstance方法返回對(duì)象的引用
getInstance方法正實(shí)現(xiàn)了保證唯一對(duì)象的功能
上一周的周一和周日
Calendar cl = Calendar.getInstance();
??cl.getTime();
??cl.add(cl.DAY_OF_YEAR, -cl.get(cl.DAY_OF_WEEK)+1);//get previous Sunday
??System.out.println(cl.get(cl.YEAR) + "-" + (cl.get(cl.MONTH)+1) + "-"
??+ cl.get(cl.DAY_OF_MONTH) +"week:"+(cl.get(cl.DAY_OF_WEEK)-1));
??
??cl.add(cl.DAY_OF_YEAR, -6 );?//get previous Monday
??System.out.println(cl.get(cl.YEAR) + "-" + (cl.get(cl.MONTH)+1) + "-"
??+ cl.get(cl.DAY_OF_MONTH) +"week:"+(cl.get(cl.DAY_OF_WEEK)-1));
用戶登陸,登陸成功后將用戶名和密碼保存到session中,然后轉(zhuǎn)到登陸成功后的頁(yè)面。
現(xiàn)在有一個(gè)問題,如果有人看到了某一個(gè)頁(yè)面的url,可以直接在地址欄直接輸入url進(jìn)去,由于session中有用戶名和密碼,所以系統(tǒng)認(rèn)為他也是合法的用戶,如何解決?
處理:
一、 session是存在服務(wù)器上面的?
session有兩種方式一個(gè)是cookies一個(gè)就是url重寫
但是不管是哪種 都是向服務(wù)器傳達(dá)的是session的ID
所以解決的方法就是?
???? 為session設(shè)置一個(gè)存活期:session.setMaxInactiveInterval(10);
二、讓瀏覽器不再緩存
<%
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
%>
<%@ taglib uri="<%
try{
session.invalidate();
}catch(Exception e){}
String scope = "application";
if (request.getParameter("scope") != null)
{
?scope = request.getParameter("scope");
}
boolean refresh = false;
if (request.getParameter("refresh") != null)
{
?refresh = true;
}
boolean forceCacheUse = false;
if (request.getParameter("forceCacheUse") != null)
{
?forceCacheUse = true ;
}
%>
<oscache:cache?? duration="40s" refresh="<%= request.getParameter("refresh") == null ? false : true %>" scope="<%= scope %>">
// *****************************頁(yè)面部分*********************************//
</oscache:cache>
如interface A{..}
這是你提供個(gè)某個(gè)部分的一個(gè)接口,然后
public class B implements A{...}
B是實(shí)現(xiàn)接口的一個(gè)類
A a=new B();
對(duì)象a的形式類型為A,實(shí)際指向一個(gè)B,可是你只能使用接口中已經(jīng)規(guī)定的方法,以后你無論怎么修改B,都不會(huì)影響到其他部分對(duì)對(duì)象a的使用
這樣可以實(shí)現(xiàn)多態(tài),如果B和C都實(shí)現(xiàn)了接口A,那么我可以聲明一個(gè)A的對(duì)象變量,而實(shí)際的實(shí)例可能是B也可能是C
多態(tài)----對(duì)同一個(gè)方法的調(diào)用,不同的實(shí)現(xiàn)類,有不同的響應(yīng)結(jié)果
new String(str.getBytes("gbk"),"utf-8")
java中的字符串都是用unicode編碼來表示的,GBK編碼的漢字應(yīng)該是從程序外面獲得的(如數(shù)據(jù)庫(kù)中,或文本文件中), 例如從本地文本文件1.txt以字節(jié)流方式讀取,得到的字節(jié)數(shù)組buf就是以GBK編碼的字節(jié)數(shù)組,然后用GBK解碼成Unicode字符串str = new String(buf,"GBK"); 然后再編碼成
UTF-8的字節(jié)數(shù)組str.getBytes("UTF-8"),這樣才算真正的轉(zhuǎn)換
問題:
<iframe name="I1" src="cs7.jsp" height="300" width="200"></iframe><br>
<iframe name="I2" id="I2" src="cs8.jsp" height="300" width="200">iframe>
如何把I1的值傳到I2里的一個(gè)input里?
處理:
document.getElementById("I2").src="cs8.jsp?param=p"
然后再cs8.jsp中接受param值放到input中
問題:
A.JSP如下:
……
<iframe src="B.jsp" id="B" frameborder="0" border="0"></iframe>
……
B.JSP如下,里面有一個(gè)C的JS方法
……
<script type="text/javascript">
function C()
{
}
</script>
……
請(qǐng)問如何在A.jsp里調(diào)用該C方法?
處理:
用b.document.script.c()
跨域腳本訪問可能造成嚴(yán)重的安全問題。一些用戶禁用了跨域腳本訪問。
問題:<html>
<iframe frameborder=0 width=600 height=50 marginheight=0 marginwidth=0 scrolling=no src="applytest.jsp" id="applytest"></iframe>
<FORM? name="form1" METHOD="POST" ACTION="customer.do?command=addapplystudent"? onsubmit="return check_data()">
<table>
? <tr>
??? <TD align="left">姓名 </TD>
??????? <td><input? type="text" name="cname">
????????? <font color="#FF0000">*</font>
??? </td>
? </tr>
</table>
</html>
///////////////////////////////////////////////////////////
現(xiàn)在在Action里取到的學(xué)生所在地區(qū)的id總是空,我現(xiàn)在請(qǐng)教各位------怎么取到iframe中的某個(gè)參數(shù)的值?
處理:
可以通過iframe的id="applytest"來訪問其頁(yè)面的標(biāo)簽,如document.all.applytest.all.xxx來訪問其中的名為xxx的標(biāo)簽.通過再在主頁(yè)面設(shè)置hidden將其值拷貝一下就行.
問題一、
<table width="99%"? border="0" align="center" cellpadding="0" cellspacing="0">
? <tr>
??? <td colspan="2"><iframe frameborder=no?
???????????? marginheight=0 marginwidth=0 name=schistory scrolling=no
??????????? src="frame2.htm"? width=100%> </iframe></td>
? </tr>
</table>
現(xiàn)在的問題是當(dāng)frame2.htm顯示的內(nèi)容很長(zhǎng)時(shí),有些內(nèi)容看不到;如何做到該網(wǎng)頁(yè)隨iframe中嵌入的網(wǎng)頁(yè)內(nèi)容長(zhǎng)度自動(dòng)出現(xiàn)滾動(dòng)條,并且這滾動(dòng)條不是出現(xiàn)在iframe中
處理:
你這個(gè)屬于讓iframe的子頁(yè)面決定父頁(yè)面的高度。
寫javascript吧。
<script language="Javascript">
function window.onload()
{
parent.document.all("mainFrame").style.height=document.body.scrollHeight+670;
}
</script>
寫在iframe調(diào)用的子頁(yè)面里面
后面的670是父頁(yè)面比子頁(yè)面高的高度
問題二、如何動(dòng)態(tài)控制IFrame的長(zhǎng)和寬
主頁(yè)面要放置一個(gè)IFrame用于嵌套顯示子頁(yè)面的信息,但是子頁(yè)面的數(shù)據(jù)多少不一,導(dǎo)致子頁(yè)面可能會(huì)很長(zhǎng)或很短,要?jiǎng)討B(tài)控制IFrame的高低隨子頁(yè)面的長(zhǎng)短而變化。
主頁(yè)面如下:
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
</HEAD>
<BODY >
<TABLE>
??? <TR>
?<TD>
?? <iframe id="frmTest" height="100px" name="frmTest" src="in.html"></iframe>
?</TD>
</TR>
</TABLE>
</BODY>
</HTML>
子頁(yè)面只需要做如下處理即可:
在頁(yè)面的最下端添加如下JS腳本:
<script language=javascript>
?window.parent.document.all("frmTest").style.height = document.body.scrollHeight + 10;
</script>
其中frmTest即為Main頁(yè)面的IFrame的ID。