【第一篇】
首先、確定你自己的英語水平。中國大學畢業生的通病是,書面閱讀還可以,口語不行,聽力很差,書寫湊合。但每個人具體情況又都不一樣,有人閱讀專業書一目
十行,但讀報紙很費勁。有人聽新聞可以,聽別的不行。你必須首先了解自己,然后針對你的情況對癥下藥。這種評估工作最好找英語好的人幫你做,如果不方便,
只能自己評自己,就要盡量做到客觀。 其次、確定自己的發音水平。我有個朋友對我說他的發音沒問題,可實際上他說得很多詞我都聽不懂。你學的是英國音還
是美國音都無所謂,反正最終從你嘴里出來的肯定是中國音。最重要的是發音要合理。英語每一個單詞都有自己的念法,你不能憑空想象。比如,有人把
RESUME讀做RE-'SOOM,這樣,別人說RE-SIU-'MAY,你不知道是什么。你念RE-'SOOM,別人也聽不懂。再次、確定自己的英語學
習目標。我這里僅把口語交流做為目標。最后、開始學習。
1、口語學習的關鍵是要模仿人家的說話。這包括語音和語調兩部分。中國英語教學重視語調的很少,盡管很多時候語調可能比語音更重要。
2、買一臺錄音機,找一合磁帶。根據你的水平,可以選擇新概念第二或第三冊,也可以到圖書館借一套有書和磁帶的小故事集。注意:一定要有書,故事篇幅不能太長,生詞量要小,過于簡單沒有關系。我傾向于使用故事,而不是對話或新聞聽力材料。
3、進行跟讀訓練。放磁帶,看著書,搞明白每一個單詞的意思,理解整個故事情節。然后,放一句,暫停,學著人家讀一句,然后,放下一句,暫停,再學一句,繼續。
4、跟讀過程中要注意的幾點:
(1)一定要盡力模仿發音和語調,越象越好。
(2)開始時速度可以比較慢,要逐步使自己跟上人家的速度。
(3)中間可以回倒重放,但我傾向于讓大家完成一小段后再回去重來。
5、同步閱讀。當你對文章發音、語調完全掌握之后,就要在放錄音的同時同步跟讀。爭取讓自己的聲音與他完全重合。注意語調和語音。如果中間有結巴的地方也不要緊,繼續讀下去,然后再回來重讀。
6、關掉錄音機,朗誦課文。注意使用學到的語音語調。帶滾瓜爛熟之后,可以進入下一篇課文。
這樣,一兩個月之后,當你“精讀”過五到十篇約一千字篇幅的文章之后,你會發現你的英語發音和聽力有了明顯的進步。再配合其他學習,如與人聊天,看電視,聽廣播,等等,口語水平會得到顯著提高。
【第二篇】
英語作為一種工具,其實用性愈顯重要。傳統英語教育方法由于過于艱深化,以及盲目的應試模式使大部分的英語學習者學了幾年甚至數十年,卻仍然處于聽不懂開不了口的尷尬境地。那么究竟如何才能在比較短的時間里快速提高口語水平,讓她真正為你所用呢?
西方最新流行一種外語學習理論,即口語提高的最好方式就是采用短期突破法。從下面的公式中,就可以看出,口語短期突破的方法是很有效的。
口語提高速度定律=說英語時間/說中文時間Speed of learning English=Speaking English/Speaking Chinese ( in a period of time)
比如,在給定的一天時間內(16小時),學生A練習英語口語的時間為14小時,說中文的時間為2小時,兩者的比例為7:1;學生B練習口語的時間為2
小時英語,說中文的時間為14小時。比例為1:7。如此一來,學生A比學生B說英語的比例大49倍。
我們認為:這一理論其實就是對語言學習規律一次很好的回歸,語言的核心是使用者能夠隨時隨地地使用它。你用的時間越長,你就越熟練,這里我們說的使用
就是“說”,用嘴巴表達出來,而不是用眼睛和腦子去看和死記。如果你能夠在一段時間內的大部分時間里堅持持續使用英語而不是中文進行表達,把學習英語的任
務轉化成母語似的說話習慣,你就完全可以在很短的時間內有效掌握一口流利的英語口語。
當然現實情況卻是:很多人并沒有這樣的勇氣和能力去堅持使用一個完全不熟悉的語言進行日常的交流!所以選用一套優秀的教材和相應的工具就顯得異常重要了,這種教材應該具備以下特點才能幫助你克服困難:
1、能夠隨時隨地學習,讓你很容易就接觸到英語;
2、能夠讓你脫離書本,完全浸在英語環境里;
3、內容應該精挑細選,具備典型性和代表性,幫助你在短時間內掌握精華內容,從而建立起長期學習的信心和基本能力。
同時你應該注意培養自己的自信,學會勇敢犯錯誤,克服恐懼的心理障礙。其實這種心理障礙是成人自己加給自己的,為什么我們小時候學母語這么自然容易,就是因為那個時候不知道什么是丟臉。所以我們應該象小時候那樣暫時忘卻丟臉,勇敢地去丟臉!
【第三篇】
想提高英語口語水平,首先要在語音上下功夫:)~
下面是些方法,你可以根據自己的學習方式掌握:)~
1.其次,要有大量的閱讀和聽力做基礎。在讀和聽的過程中,積累了詞匯,掌握了句型,熟悉了用英語表達思想的方式,最重要的是培養了語感。
2.同時,學英語口語也需要用多種辦法:如大聲朗讀英語對話和文章,朗讀各種句型的例句和口語中最常用的句子,背誦文章及演講,與會英語的人練口語,當
然,最好與以英語為母語的人練口語。事實上,自言自語亦是練習口語的有效的方法之一。如果你把自己說的英語給錄制下來,聽聽自己的錄音,若有問題,再加以
改正,效果就會更好。
3.說英語還要有膽量。如果你能在說不太出口,或是說不好的情況下,大膽地說。說上一段時間后,突然有一天你會自如、清楚地表達自己的思想。有了大膽說的精神,你才能闖過口語的難關。
4.只會學英語,而不能盡快地去用,那就永遠也學不好英語。在學英語的過程中,要始終尋找機會說英語。比如說,你周圍有幾個喜歡說英語的朋友,大家在一起
就要用英語來交談。這種交談有利于每個人的英語學習,因為大家都有機會運用自己已掌握的英語知識來交流思想,鞏固了已學的知識,并把知識轉化成技能,同
時,還能從別人那兒學到新的東西。要想學好英語口語就要多說。
5.能同以英語為母語的人說英語是最佳方法。在國內學英語缺乏環境,看電影學英語口語是彌補環境不足的好方法。英語電影是一部英語國家的生活、文化、風俗
等一切的百科全書,是最全的英語口語百科全書。大量地看英文電影就是你徹底攻克英語“聽”和“說”的法寶。英語電影把你帶入了一個新的世界中去。你在電影
中,學到了英語口語的語匯、短語、句子結構,以及表達各種內容的說法。你要做的就是把自己想像成電影中的一個角色,在經歷著自己的生活,又在經歷著其他人
的生活。總之,看一部電影比在美國生活一天還好,看電影也能學到地道的英語口語。
【第四篇】
當代社會是個開放社會,信息社會,人們越來越重視交際,而我國改革開放的成功也日益提高了我國在世界上的地位,我們與世界各國交流的領域越來越廣了,沒有出眾的英語口語表達將會寸步難行。
而要提高英語口語表達能力,就要先了解英語口語表達的過程是怎樣發生的。大家知道,語言是思維的外殼。口語表達的過程,實際上是一個復雜的心理和生理過程,是思維借助詞語按一定句式迅速轉換為有聲言語的過程。因此,口語能力的強弱取決于:
1、思維能力的強弱,特別是與口語有關的思維的條理性、敏銳性與靈活性,這是關鍵。
2、準確、迅速地組織言語(選詞、造句、組段、構篇)能力的強弱,這是基礎。
3、運用語言的能力的強弱,這是前提。
根據口語表達循序漸進的一般規律,口語訓練的重點應是培養敏銳的思維和強烈的語感。具體包括:
1、語音。學會科學發聲方法,能用準確、響亮、流暢的英語進行口頭表達。
2、語調。能借助聲音高低升降、抑揚頓挫的變化來表達復雜的感情,掌握停連和輕重、抑揚和明暗、快慢和松緊等一般的朗讀技巧。
3、詞匯。能掌握比較豐富的口語詞匯。
4、語脈。說話能做到有條有理、語言流暢、上下貫通、一脈相承。
5、語境。說話注意目的、對象、場合,合乎規定情景的要求,講禮貌、有針對性。懂得口語修辭。在會話中有隨機應變的能力。
此外,還要懂得口頭言語的輔助手段--表情、姿勢、動作等態勢言語的運用。
由于書面語和口語是相互滲透、相互促進的,為提高口語的表現力,可在說話訓練之前先進行一章朗讀、朗誦訓練。聽和說是一個事物的兩個方面,吸收、表達
兩者不能偏廢,所以口語訓練體系中也應包括。通過以上訓練,掌握一定的朗讀朗誦技巧,培養準確、流利、有感情地朗讀朗誦一般作品的能力,特別注意培養強烈
的語感。
3、聽力訓練
培養聽的注意力、理解力、記憶力和辨析力,提高聽知能力,養成良好的聽的習慣。
4、口語表達基本方式訓練
進行敘述、描述、評述、解說等口語表達基本方式的訓練,培養內部言語向外部言語迅速轉化的能力,結合進行語調、語脈的訓練。
5、會話型言語訓練
言語形式有會話型和獨白型兩類。會話是指兩個以上的人圍繞一個或幾個話題一起說話的形式,如交談、座談、辯論、審訊等。會話時參加者是互為聽、講者
的,因此后面的發言常常受到前面發言的制約。另外,由于當面交談,大量態勢語代替了言語表達,會話者的言語結構往往不嚴謹、不完善,省略句較多。
可進行如下訓練:通過交談和辯論兩種會話言語訓練,了解它們的一般特點、注意事項,結合進行應變能力和禮貌用語的訓練,從而在會話中有效地培養隨機應變的能力。
6、獨白型言語訓練
獨白是指一個人單獨發言而其他人都作為聽眾的言語表達形式,如:講故事、作報告、講課、演講、講解員的解說等。獨白言語一般不在進行過程中跟聽眾問答
交流,因此要求在事先要周密地了解聽眾的要求并系統地組織好發言內容和有關態勢語。獨白是一種高層次的言語形式。
可通過講故事和演講兩種獨白言語的訓練,了解它們的一般特點、注意事項,結合進行運用態勢語的訓練,這類訓練很有利于培養思維的條理性和連貫性。
7、即興小品訓練
即興小品要求表演者按照規定的題目和要求,在規定的時間內,充分發揮自己的想象,不用或少用道具,通過言語和動作的表演,展現社會生活中的某個瞬間或片斷,表達一個簡單的主題。
嚴格地說,小品應該是話劇藝術表演訓練的一種形式,但由于它具有綜合的特點,對訓練思維的創造性、敏捷性、條理性、言語表達的準確性、形象性、流暢
性,以及應變力,乃至姿勢的綜合運用等等,都有很大的好處,所以我們要想英語口語表達能力更上一個層次,這種形式的訓練也要加以采用。
懂得了英語口語表達的規律,并不等于就有了一口流暢的英語表達口才,就好象讀了介紹游泳的書并不等于一定會游泳一樣,關鍵還是要在長期的時實踐中持之
以恒地艱苦磨練。這種訓練不同于我們平時常聽常說的那種日常英語口語訓練。日常的英語口語訓練與之相比簡單得多,所用的詞匯量及話題所涉及的深度都是相當
有限的。而真正高層次的英語口語交際所需達到的流暢性、條理性、敏銳性和靈活性并不是常練一些日常用語就能達到的,其中用到的詞匯量也因話題的深入和多樣
而大大增加了。
所以,要想真正地提高英語口語,說一口流利而又有水平的交際英語,得有對英語口語表達感興趣作為前提,懂得以上的規律,重視運用以上的訓練步驟,加上
長期的艱苦訓練,才會有成效,才會達到目的。聽力訓練,當然,在訓練過程中,聽和說是無法截然分開的。
因此,英語口語訓練體系可按以下順序安排:
1、語音訓練
在學習英語語音知識的基礎上加強語音訓練,進行方音辨正練習。通過學習,打好英語語音知識,有一定的辨音能力,能用英語正確、清楚、響亮地表達。
2、朗讀朗誦訓練
進行呼吸、發聲與共鳴訓練,吐字納音的訓練,以及各種朗讀朗誦技巧的訓練,學會常用文體的朗讀、朗誦,懂得在朗誦中恰當使用態勢語
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/3209946220095109201252
posted @
2009-06-10 09:20 C.B.K 閱讀(93) |
評論 (0) |
編輯 收藏
[關鍵字]:java,design pattern,設計模式,《Java與模式》,Chain of Responsibility,責任鏈模式
[環境]:StarUML5.0 + JDK6
[作者]:Winty (wintys@gmail.com)
[正文]:

package pattern.chainofresponsibility;
/**
* 責任鏈模式:Chain of Responsibility
* @version 2009-5-9
* @author Winty(wintys@gmail.com)
*/
public class ChainOfResponsibilityTest{
public static void main(String[] args){
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
//設置責任鏈
handler3.setSuccessor(handler2);
handler2.setSuccessor(handler1);
//發送命令
handler3.handleRequest();
}
}
/**
*抽象處理者
*/
abstract class Handler{
protected Handler successor;
public Handler getSuccessor(){
return successor;
}
public void setSuccessor(Handler successor){
this.successor = successor;
}
public abstract void handleRequest();
}
/**
*具體處理者
*/
class ConcreteHandler1 extends Handler{
public void handleRequest(){
if(getSuccessor() != null){
System.out.print("Request passed:from class Concrete1");
System.out.println(" to class" + getSuccessor().getClass().getName());
getSuccessor().handleRequest();
}
else{
System.out.println("Request handled in ConcreteHandler1");
}
}
}
/**
*具體處理者
*/
class ConcreteHandler2 extends Handler{
public void handleRequest(){
if(getSuccessor() != null){
System.out.print("Request passed:from class Concrete2");
System.out.println(" to class " + getSuccessor().getClass().getName());
getSuccessor().handleRequest();
}
else{
System.out.println("Request handled in ConcreteHandler2");
}
}
}
/**
*具體處理者
*/
class ConcreteHandler3 extends Handler{
public void handleRequest(){
if(getSuccessor() != null){
System.out.print("Request passed:from class Concrete3");
System.out.println(" to class " + getSuccessor().getClass().getName());
getSuccessor().handleRequest();
}
else{
System.out.println("Request handled in ConcreteHandler3");
}
}
}
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/320994622009410264843
posted @
2009-05-10 14:07 C.B.K 閱讀(88) |
評論 (0) |
編輯 收藏
這么一個需求:同一臺服務器上有兩個應用,如
http://hostA:8080/services和
http://hostA:8080/admin外部訪問時,需要從不同的域名訪問,如
http://services.host.com和
http://admin.host.com一開始給他們這么一個比較簡單的解決方案:
分別把services和admin兩個應用,部署到不同的兩個端口上,如
services ->
http://hostA:8081/admin ->
http://hostA:8082/接著在防火墻配兩個公網IP,然后dns上把services.host.com和admin.host.com配置到這兩個IP上。
當請求到達防火墻時,防火墻根據所訪問的ip轉發到hostA的對應端口上。
前
方用的防火墻是我們公司的Audemon
100,和公司的Audemon系統組的交流后得知,目前的防火墻版本不支持同時配置兩個ip,要到六月底才能出版本支持。!@…%#%…%¥,暈倒,好
像這是很基本的功能來的吧,居然還不支持。沒辦法,此路不通。由于防火墻是不管域名的(因為域名資料是通過應用層傳輸的),那更別指望防火墻根據域名轉發
了。
因此,我們只好提供了軟件級的解決方案,讓前方在Tomcat前加一個Apache 2.2,通過Apache的Virtual Host + AJP實現轉發。
Apache的部分配置如下:
NameVirtualHost *:80
<VirtualHost *:80>
ServerName host1.com
ProxyPass / ajp://host1.com:8009/
ProxyPassReverse / ajp://host1.com:8009/
</VirtualHost>
<VirtualHost *:80>
ServerName host2.com
ProxyPass / ajp://host2.com:8019/
ProxyPassReverse / ajp://host2.com:8019/
</VirtualHost>
Tomcat也需要配置AJP Connector,如host1.com的配置
<Connector port=”8009″ enableLookups=”false” redirectPort=”8443″ protocol=”AJP/1.3″ />
這個方案相對于防火墻的硬件方案,性能上要差一些,但還是不錯的。
另
外還有一種方案是通過iptables的domain module來實現,但這個domain
module好像是國內的某個高手寫的,只更新到v0.02版本,并沒有提交到iptables的標準里。雖然可以用而且性能比Apache的方案要高一
些,但是風險較大,而且配置麻煩(既要編譯內核,又要配置iptables的rules),所以沒有用這種方式。
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/320994622009326115641438
posted @
2009-04-26 11:57 C.B.K 閱讀(4203) |
評論 (0) |
編輯 收藏
隨著訪問量的不斷提高,以及對響應速度的要求,進行負載均衡設置就顯得非常必要了。公司的系統在最初設計的時候就已經考慮到了負載均衡的規劃,www靜態
服務器配置了兩臺,由于初期項目時間緊,并且訪問量并不高,所以當時只用了一臺,另一臺在內網中,只是進行了同步,并為發揮出效用來。此次就是對負載均衡
的一個簡單測試。
先介紹一下apache mod_proxy_balancer的幾個配置規則(從網上找的):
將Apache作為LoadBalance前置機分別有三種不同的部署方式,分別是:
1 )輪詢均衡策略的配置
進入Apache的conf目錄,打開httpd.conf文件,在文件的末尾加入:
ProxyPass / balancer://proxy/ #注意這里以"/"結尾
<Proxy balancer://proxy>
BalancerMember http://192.168.6.37:6888/
BalancerMember http://192.168.6.38:6888/
</Proxy>
我們來觀察上述的參數“ProxyPass / balancer://proxy/”,其中,“ProxyPass”是配置虛擬服務器的命令,“/”代表發送Web請求的URL前綴,如:http://myserver/或者http://myserver/aaa,這些URL都將符合上述過濾條件;“balancer://proxy/”表示要配置負載均衡,proxy代表負載均衡名;BalancerMember 及其后面的URL表示要配置的后臺服務器,其中URL為后臺服務器請求時的URL。以上面的配置為例,實現負載均衡的原理如下:
假設Apache接收到http://localhost/aaa請求,由于該請求滿足ProxyPass條件(其URL前綴為“/”),該請求會被分發到后臺某一個BalancerMember,譬如,該請求可能會轉發到 http://192.168.6.37:6888/aaa進行處理。當第二個滿足條件的URL請求過來時,該請求可能會被分發到另外一臺BalancerMember,譬如,可能會轉發到http://192.168.6.38:6888/。如此循環反復,便實現了負載均衡的機制。
2) 按權重分配均衡策略的配置
ProxyPass / balancer://proxy/ #注意這里以"/"結尾
<Proxy balancer://proxy>
BalancerMember http://192.168.6.37:6888/ loadfactor=3
BalancerMember http://192.168.6.38:6888/ loadfactor=1
</Proxy>
參數”loadfactor”表示后臺服務器負載到由Apache發送請求的權值,該值默認為1,可以將該值設置為1到100之間的任何值。以上面的配置
為例,介紹如何實現按權重分配的負載均衡,現假設Apache收到http://myserver/aaa
4次這樣的請求,該請求分別被負載到后臺服務器,則有3次連續的這樣請求被負載到BalancerMember為http://192.168.6.37:6888的服務器,有1次這樣的請求被負載BalancerMember為http://192.168.6.38:6888后臺服務器。實現了按照權重連續分配的均衡策略。
3) 權重請求響應負載均衡策略的配置
ProxyPass / balancer://proxy/ lbmethod=bytraffic #注意這里以"/"結尾
<Proxy balancer://proxy>
BalancerMember http://192.168.6.37:6888/ loadfactor=3
BalancerMember http://192.168.6.38:6888/ loadfactor=1
</Proxy>
參數“lbmethod=bytraffic”表示后臺服務器負載請求和響應的字節數,處理字節數的多少是以權值的方式來表示的。
“loadfactor”表示后臺服務器處理負載請求和響應字節數的權值,該值默認為1,可以將該值設置在1到100的任何值。根據以上配置是這么進行均
衡負載的,假設Apache接收到http://myserver/aaa請求,將請求轉發給后臺服務器,如果BalancerMember為http://192.168.6.37:6888后臺服務器負載到這個請求,那么它處理請求和響應的字節數是BalancerMember為http://192.168.6.38:6888 服務器的3倍(回想(2)均衡配置,(2)是以請求數作為權重負載均衡的,(3)是以流量為權重負載均衡的,這是最大的區別)。
看明白了沒有,根據不同的需要,可以按這三種方式進行配置。我按照第三種配置的,感覺上這種對于負載的均衡更全面合理。我的配置很簡單,如下:
先配置均衡器:
<Proxy balancer://proxy>
BalancerMember ajp://127.0.0.1:8009/ loadfactor=1
BalancerMember http://192.168.10.6:8083/ loadfactor=1
</Proxy>
其中http://192.168.10.6:8083實際上是另外一個端口啟動的apache,為了測試,它就簡單的直接轉發所有請求到tomcat。
對于上次的VirtualHost進行以下的修改即可:
<VirtualHost *:80>
ServerName www.test.com
DocumentRoot /www
DirectoryIndex index.html index.jsp
<Directory "/www">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<Directory "/control">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
ProxyPass /nxt/images/ !
ProxyPass /nxt/js/ !
ProxyPass /nxt/css/ !
#ProxyPass / ajp://127.0.0.1:8009/
#ProxyPassReverse / ajp://127.0.0.1:8009/
ProxyPass / balancer://proxy/
ProxyPassReverse / balancer://proxy/
</VirtualHost>
注釋掉之前的ajp轉發,而配置成通過balancer去處理。
通過觀察access log,的確有部分請求發送到了8083端口的apache上,而有部分是直接ajp轉發到tomcat上了。對于更多的負載均衡的參數檢測,待空了再做。
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/32099462200932611555639
posted @
2009-04-26 11:56 C.B.K 閱讀(150) |
評論 (0) |
編輯 收藏
一、集群和負載均衡的概念
(一)集群的概念
集群(Cluster)是由兩臺或多臺節點機(服務器)構成的一種松散耦合的計算節點集合,為用
戶提供網絡服務或應用程序(包括數據庫、Web服務和文件服務等)的單一客戶視圖,同時提供接近容錯機的故障恢復能力。集群系統一般通過兩臺或多臺節點服
務器系統通過相應的硬件及軟件互連,每個群集節點都是運行其自己進程的獨立服務器。這些進程可以彼此通信,對網絡客戶機來說就像是形成了一個單一系統,協
同起來向用戶提供應用程序、系統資源和數據。除了作為單一系統提供服務,集群系統還具有恢復服務器級故障的能力。集群系統還可通過在集群中繼續增加服務器
的方式,從內部增加服務器的處理能力,并通過系統級的冗余提供固有的可靠性和可用性。
(二)集群的分類
1、高性能計算科學集群:
以解決復雜的科學計算問題為目的的IA集群系統。是并行計算的基礎,它可以不使用專門的由十至上萬個獨立處理器組成的并行超級計算機,而是采用通過高速
連接來鏈接的一組1/2/4
CPU的IA服務器,并且在公共消息傳遞層上進行通信以運行并行應用程序。這樣的計算集群,其處理能力與真正超級并行機相等,并且具有優良的性價比。
2、負載均衡集群:
負載均衡集群為企業需求提供更實用的系統。該系統使各節點的負載流量可以在服務器集群中盡可能平均合理地分攤處理。該負載需要均衡計算的應用程序處理端
口負載或網絡流量負載。這樣的系統非常適合于運行同一組應用程序的大量用戶。每個節點都可以處理一部分負載,并且可以在節點之間動態分配負載,以實現平
衡。對于網絡流量也如此。通常,網絡服務器應用程序接受了大量入網流量,無法迅速處理,這就需要將流量發送給在其它節點。負載均衡算法還可以根據每個節點
不同的可用資源或網絡的特殊環境來進行優化。
3、高可用性集群:
為保證集群整體服務的高可用,考慮計算硬件和軟件的容錯性。如果高可用性群集中的某個節點發生了故障,那么將由另外的節點代替它。整個系統環境對于用戶是一致的。
實際應用的集群系統中,這三種基本類型經常會發生混合與交雜。
(三)典型集群
科學計算集群:
1、Beowulf
當談到 Linux
集群時,許多人的第一反映是 Beowulf。那是最著名的 Linux科學軟件集群系統。實際上,它是一組適用于在 Linux
內核上運行的公共軟件包的通稱。其中包括流行的軟件消息傳遞 API,如“消息傳送接口”(MPI) 或“并行虛擬機”(PVM),對 Linux
內核的修改,以允許結合幾個以太網接口、高性能網絡驅動器,對虛擬內存管理器的更改,以及分布式進程間通信 (DIPC)
服務。公共全局進程標識空間允許使用 DIPC 機制從任何節點訪問任何進程。
2、MOSIX
Beowulf類似于給系統安裝的一個支持
集群的外掛軟件,提供了應用級的集群能力。而MOSIX是徹底修改Linux的內核,從系統級提供了集群能力,它對應用而言是完全透明的,原有的應用程
序,可以不經改動,就能正常運行在MOSIX系統之上。集群中的任何節點都可以自由地加入和移除,來接替其它節點的工作,或是擴充系統。MOSIX
使用自適應進程負載均衡和內存引導算法使整體性能最大化。應用程序進程可以在節點之間實現遷移,以利用最好的資源,這類似于對稱多處理器系統可以在各個處
理器之間切換應用程序。由于MOSIX通過修改內核來實現集群功能,所以存在兼容性問題,部分系統級應用程序將無法正常運行。
負載均衡/高可用性集群
3、LVS(Linux Virtual Server)
這是一個由國人主持的項目。
它是一個負載均衡/高可用性集群,主要針對大業務量的網絡應用(如新聞服務、網上銀行、電子商務等)。
LVS
是建立在一個主控服務器(通常為雙機)(director)及若干真實服務器(real-server)所組成的集群之上。real-server負責實
際提供服務,主控服務器根據指定的調度算法對real-server進行控制。而集群的結構對于用戶來說是透明的,客戶端只與單個的IP(集群系統的虛擬
IP)進行通信,也就是說從客戶端的視角來看,這里只存在單個服務器。
N54537Real-server可以提供眾多服務,如ftp,
http, dns, telnet, nntp, smtp
等。主控服務器負責對Real-Server進行控制。客戶端在向LVS發出服務請求時,Director會通過特定的調度算法來指定由某個Real-
Server來應答請求,而客戶端只與Load Balancer的IP(即虛擬IP,VIP)進行通信。
其他集群:
現在集群系統可謂五花八門,絕大部分的OS開發商,服務器開發商都提供了系統級的
集群產品,最典型的是各類雙機系統,還有各類科研院校提供的集群系統。以及各類軟件開發商提供的應用級別的集群系統,如數據庫集
群,Application Server 集群,Web Server集群,郵件集群等等。
(四)負載均衡
1、概念
由于目前現有網絡的各個核心部分隨著業務量的提高,訪問量和數據流量的快速增長,其處理能力和計算強度也相應地增大,使得單一的服務器設備根本無法承擔。
在此情況下,如果扔掉現有設備去做大量的硬件升級,這樣將造成現有資源的浪費,而且如果再面臨下一次業務量的提升時,這又將導致再一次硬件升級的高額成本
投入,甚至性能再卓越的設備也不能滿足當前業務量增長的需求。
針對此情況而衍生出來的一種廉價有效透明的方法以擴展現有網絡設備和服務器的帶寬、增加吞吐量、加強網絡數據處理能力、提高網絡的靈活性和可用性的技術就是負載均衡(Load Balance)。
2、特點和分類
負載均衡(Server Load Balance)一般用于提高服務器的整體處理能力,并提高可靠性,可用性,可維護性,最終目的是加快服務器的響應速度,從而提高用戶的體驗度。
負載均衡從結構上分為本地負載均衡(Local Server Load Balance)和地域負載均衡(Global Server Load
Balance)(全局負載均衡),一是指對本地的服務器群做負載均衡,另一是指對分別放置在不同的地理位置、有不同的網絡及服務器群之間作負載均衡。
地域負載均衡有以下的特點:
(1)解決網絡擁塞問題,服務就近提供,實現地理位置無關性
(2)對用戶提供更好的訪問質量
(3)提高服務器響應速度
(4)提高服務器及其他資源的利用效率
(5)避免了數據中心單點失效
3、負載均衡技術主要應用
(1)DNS負載均衡
最早的負載均衡技術是通過DNS來實現的,在DNS中為多個地址配置同一個名字,因而查詢這個名字的客戶機將得到其中一個地址,從而使得不同的客戶訪問不
同的服務器,達到負載均衡的目的。DNS負載均衡是一種簡單而有效的方法,但是它不能區分服務器的差異,也不能反映服務器的當前運行狀態。
(2)代理服務器負載均衡 使用代理服務器,可以將請求轉發給內部的服務器,使用這種加速模式顯然可以提升靜態網頁的訪問速度。然而,也可以考慮這樣一種技術,使用代理服務器將請求均勻轉發給多臺服務器,從而達到負載均衡的目的。
(3)地址轉換網關負載均衡 支持負載均衡的地址轉換網關,可以將一個外部IP地址映射為多個內部IP地址,對每次TCP連接請求動態使用其中一個內部地址,達到負載均衡的目的。
(4)協議內部支持負載均衡 除了這三種負載均衡方式之外,有的協議內部支持與負載均衡相關的功能,例如HTTP協議中的重定向能力等,HTTP運行于TCP連接的最高層。
(5)NAT
負載均衡 NAT(Network Address Translation
網絡地址轉換)簡單地說就是將一個IP地址轉換為另一個IP地址,一般用于未經注冊的內部地址與合法的、已獲注冊的Internet
IP地址間進行轉換。適用于解決Internet IP地址緊張、不想讓網絡外部知道內部網絡結構等的場合下。
(6)反向代理負載均
衡
普通代理方式是代理內部網絡用戶訪問internet上服務器的連接請求,客戶端必須指定代理服務器,并將本來要直接發送到internet上服務器的連
接請求發送給代理服務器處理。反向代理(Reverse
Proxy)方式是指以代理服務器來接受internet上的連接請求,然后將請求轉發給內部網絡上的服務器,并將從服務器上得到的結果返回給
internet上請求連接的客戶端,此時代理服務器對外就表現為一個服務器。反向代理負載均衡技術是把將來自internet上的連接請求以反向代理的
方式動態地轉發給內部網絡上的多臺服務器進行處理,從而達到負載均衡的目的。
(7)混合型負載均衡
在有些大型網絡,由于多個服務器群內硬件設備、各自的規模、提供的服務等的差異,我們可以考慮給每個服務器群采用最合適的負載均衡方式,然后又在這多個服
務器群間再一次負載均衡或群集起來以一個整體向外界提供服務(即把這多個服務器群當做一個新的服務器群),從而達到最佳的性能。我們將這種方式稱之為混合
型負載均衡。此種方式有時也用于單臺均衡設備的性能不能滿足大量連接請求的情況下。
二、搭建集群和實現負載平衡
(一)前期準備
我的系統用的是windowsXP專業版,我要做的是,用一個apache和多個(這里以兩個作為示例)tomcat,通過jk方式,構造一個集群。以下是要首先準備的東西:
1、jdk,我用的版本是jdk1.5.0_06,下載地址是http://192.18.108.216/ECom/EComTicketServlet/BEGIND597A309654D73D910E051D73D539D5F/-2147483648/2438196255/1/852050/851882/2438196255/2ts+/westCoastFSEND/jdk-1.5.0_13-oth-JPR/jdk-1.5.0_13-oth-JPR:3/jdk-1_5_0_13-windows-i586-p.exe
2、apache,我用的版本是2.2.4,下載地址是http://apache.justdn.org/httpd/binaries/win32/apache_2.2.4-win32-x86-openssl-0.9.8d.msi
3、tomcat,我用的版本是5.5的解壓版本,這里要注意:不能用安裝的版本,因為一臺機器上裝兩個一樣的tomcat,是會出錯誤的。下載地址是http://apache.mirror.phpchina.com/tomcat/tomcat-5/v5.5.25/bin/apache-tomcat-5.5.25.zip
4、jk,這個jk的版本,本來有兩個的,但是版本2已經被廢棄掉了,目前可用的jk版本是1.2.25。每個apache的版本,都會有一個特定的jk與之對應,所以這里要用的jk也必須是為apache-2.2.4開發的那個才行。它的下載地址是http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/win32/jk-1.2.25/mod_jk-apache-2.2.4.so
有了這四樣東西,我們就可以開始做集群了。
(二)安裝
1、相信需要看這篇文章的人,JDK的安裝一定不會陌生,這里不在贅述。只是需要提醒一下:環境變量別忘記配置了。
2、安裝apache也沒有什么難度,就是在安裝過程中要配置域名、網址和管理員郵箱之類的信息,這
個信息完全可以按照提示,然后修改下填入即可,之后想修改的話直接到配置文件中改就行了。除了這個地方,還要保證機器上的80端口沒有被其他程序占用。至
于安裝路徑,完全取決于個人愛好。其他的默認就行了。安裝成功后,系統右下角的托盤區會有個圖標,我們可以通過這個啟動apache,如果那個小紅點變成
綠色,說明服務已經正常啟動了(如果服務沒有啟動起來,說明安裝過程中的配置有錯誤,建議卸載后重裝)。如果按照默認,端口是80的話,那打開瀏覽器,輸
入:http://localhost/ ,應該可以看到 " It works “的字樣。這樣就可以進入下一步了。
3、解壓縮tomcat,記得要做兩份。這里不妨將兩個tomcat命名為:tomcat-
5.5.25_1和tomcat-5.5.25_2,其實這兩個文件夾中的東西是完全一樣的。但是我為了在同一臺機器上做集群,那就要保證兩個
tomcat運行起來不會在端口上起沖突。進入tomcat-5.5.25_1/conf目錄,用文本編輯器打開并修改server.xml,將該
tomcat的默認8080端口改為8088(其實沒必要改,我改這個是因為我機器上還有其他tomcat占用著8080端口)。然后進入tomcat-
5.5.25_2/conf目錄,同樣將8080修改掉,至于改成多少沒多大關系,只要不占用其他程序的端口,應該不會出什么問題。這樣,tomcat就
算安裝好了。
4、jk這東西是一個連接模塊,不用安裝,直接將mod_jk-apache-2.2.4.so這個文件拷貝到apache安裝目錄下的modules文件夾下面就行了。
這樣,安裝完成,下面開始配置。
(三)配置
這個地方才是搭建集群的關鍵所在,我也會盡我的可能寫的詳細點。
1、配置tomcat
為防止沖突,進入第二個tomcat主目錄,然后進入conf目錄,打開server.xml修改配
置。主要是修改端口,我這里把所有的端口信息,都在原有基礎上加1000,即原端口是8009,我改為9009。當然,你不必和我一樣,只要保證不沖突就
OK!這些配置在apache的配置中可能會用到。
2、配置apache
(1)進入apache的主目錄,然后進入conf文件夾,用文本編輯器打開httpd.conf,在該文件末尾加上如下幾行:
### 加載 mod_jk 模塊
LoadModule jk_module modules/mod_jk-apache-2.2.4.so
### 配置 mod_jk
JkWorkersFile conf/workers.properties #加載集群中的workers
JkMountFile conf/uriworkermap.properties #加載workers的請求處理分配文件
JkLogFile logs/mod_jk.log #指定jk的日志輸出文件
JkLogLevel warn #指定日志級別
(2)不要改變目錄,新建一個文件:workers.properties,該文件用來配置web容器的信息。該文件的內容如下:
# worker列表
worker.list=controller, status
#第一個server的配置,server名為s1
#ajp13 端口號,在tomcat下server.xml配置,默認8009
worker.s1.port=8009
#tomcat的主機地址,如不為本機,請填寫ip地址
worker.s1.host=localhost
worker.s1.type=ajp13
#server的加權比重,值越高,分得的請求越多
worker.s1.lbfactor=1
#第二個server的配置,server名為s2
worker.s2.port=9009
worker.s2.host=localhost
worker.s2.type=ajp13
worker.s2.lbfactor=1
#server名為controller,用于負載均衡
worker.controller.type=lb
worker.retries=3 #重試次數
#指定分擔請求的server列表,用逗號分隔
worker.controller.balanced_workers=s1,s2
#設置用于負載均衡的server的session可否共享 有不少文章說設置為1是可以的,但是我是設置為0才可以的
worker.controller.sticky_session=0
#worker.controller.sticky_session_force=1
worker.status.type=status
(3)不要改變目錄,新建一個文件:uriworkermap.properties,文件內容如下:
/*=controller #所有請求都由controller這個server處理
/jkstatus=status #所有包含jkstatus請求的都由status這個server處理
!/*.gif=controller #所有以.gif結尾的請求都不由controller這個server處理,以下幾個都是一樣的意思
!/*.jpg=controller
!/*.png=controller
!/*.css=controller
!/*.js=controller
!/*.htm=controller
!/*.html=controller
這里的"!”類似于java中的"!”,是“非”的意思。
這樣,apache一塊就配置好了。
3、再修改tomcat配置:這里兩個tomcat都要配置。
仍然是打開第一步中的那個server.xml文件,找到<Engine
name="Catalina"
defaultHost="localhost">這一行,在里面加上一句:jvmRoute="s1",即把該句改為:<Engine
name="Catalina" defaultHost="localhost"
jvmRoute="s1">。這里的s1就是第二步中配置的用于負載均衡的server的名稱。如果該tomcat的端口是第二步中s1用的端
口,那這里就寫s1,第二個tomcat就應該是s2了。
這樣,配置就完成了。
(四)運行
進入兩個tomcat的bin目錄,執行兩個tomcat的startup.bat啟動這兩個
tomcat,然后將apache重新啟動后,運行起來看看效果吧。如果不出意外,兩個tomcat的窗口應該是你一次我一次的打印日志信息了,而且此時
session也是共享了的。
到這里,集群搭建好了,負載均衡也實現了。
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/32099462200932611544216
posted @
2009-04-26 11:54 C.B.K 閱讀(195) |
評論 (0) |
編輯 收藏
附錄B SQL*PLUS
Sql*plus 中使用綁定變量:
sql> variable x number;
sql> exec :x := 7788;
sql> SELECT empno,ename from scott.emp where empno=:x;
SQL*PLUS 是Oracle提供的一個工具程序,它不僅可以用于測試,運行SQL語句和PL/SQL塊,而且還可以用于管理Oracle數據庫,
1.啟動sql*plus
為了使用sql*plus,必須首先要啟動sql*plus。Oracle不僅提供了命令行和圖形界面的sql*plus,而且還可以在web瀏覽器中
運行.
(1)在命令運行sql*plus
在命令行運行sql*plus是使用sqlplus命令來完成的,該命令適用于任何操作系統平臺,
語法如下:
sqlplus [username]/[password][@server]
如上所示:username用于指定數據庫用戶名,password用于指定用戶口令,server則用于指定主機字符串(網絡服務名).
當連接到本地數據時,不需要提供網絡服務名,如果要連接到遠程數據庫,則必須要使用網絡服務名.
(2)在windows環境中運行sql*plus
如果在windows環境中安裝了oralce數據庫產品,那么可以在窗口環境中運行sql*plus
具體方法: "開始->程序->oracle-oradb10g_home1->application development->sql*plus"
2.連接命令
(1)conn[ect]
該命令用于連接到數據庫。注意,使用該命令建立新會話時,會自動斷開先前會話,示例如下:
sql>conn scott/yhai1981@demo
(2)disc[onnect]
該命令用于斷開已經存在的數據庫連接。注:該命令只是斷開連接會話,而不會退出sql*plus,示例如下:
sql>disc
(3)passw[ord]
該命令用于修改用戶的口令。注,任何用戶都可以使用該命令修改其自身口令,但如果要修改其他用戶的口令時,
則必須以DBA身份(sys和system)登錄,在sql*plus中,當修改用戶口令時,可以使用該命令取代sql命令alter user,
示例如下:
sql>passw
更改scott的口令
舊口令:******
新口令:******
重新鍵入新口令:******
口令已更改
sql>
(4)exit
該命令用于退出 sql*plus,另外你也可以使用quit命令退出sql*plus.使用該命令不僅會斷開連接,而且也會退出sql*plus
注:默認情況下,當執行該命令時會自動提交事務。
3,編輯命令
(1)l[ist]
該命令用于列出sql緩沖區的內容,使用該命令可以列出sql緩沖某行,某幾行或所有行的內容。在顯示結果中,數據字為具體
的行號,而"*"則表示當前行。
示例一:列出sql緩沖區所有內容
sql>l
示例二:列出sql緩沖區首行內容:
sql>l1
(2)a[ppend]
該命令用于在sql緩沖區的當前行尾部添加內容。注:該命令將內容追加到標記為"*"的行的尾部,示例如下:
sql>l
1 select empno,ename,sal,hiredate,comm,deptno
2 from emp
3* where deptno=10
sql>a and job='CLERK'
sql>l
SQL> list
1 select empno,ename,sal,hiredate,comm,deptno
2 from emp
3* where deptno=10 and job='CLERK'
(3)c[hange]
該命令用于修改sql緩沖區的內容。如果在編寫sql語句時寫錯了某個詞,那么使用該命令可以進行修改,
sql>select ename from temp where deptno=10;
SQL> c /temp/emp
1* select ename from emp where deptno=10
(4)del
該命令用于刪除sql緩沖區中內容,使用它可以刪除某行,某幾行或所有行,在默認情況下,當直接執行
del時,只刪除當前行的內容,示例如下:
SQL> l
1 select ename
2 from emp
3* where deptno=20
sql>del
SQL> l
1 select ename
2* from emp
如果一次要刪除多行,則指定起始行號和終止行號,例如"del 3 5"
(5)i[nput]
該命令用于在sql緩沖區的當前行后新增加一行。示例如下:
SQL> l
1 select ename
2* from emp
sql>i where deptno=30
如果要在首行前增加內容,則使用"0文本"
sql>0 create table temp as
SQL> l
1 create table temp as
2 select ename
3 from emp
4* where deptno=30
(6) n
該數值用于定位sql緩沖區的當前行,示例如下:
(7)edi[t]
該命令用于編輯sql緩沖區的內容。當運行該命令時,在windows平臺中會自動啟動"記事本",以編輯sql緩沖區
(8)run和/
run的/命令都可以用于運行sql緩沖區中的sql語句。注:當使用run命令時,還會列出sql緩沖區內容,eg:
SQL> run
1* select ename from emp where deptno=20
4.文件操縱命令
(1)save
該命令用于將當前sql緩沖區的內容保存到sql腳本中。當執行該命令時,默認選項為create,即建立新文件。
eg:
SQL> save c:\a.sql create
已創建 file c:\a.sql
當執行命令之后,就會建立新腳本文件a.sql,并將sql緩沖區內容存放到該文件中。如果sql已經存在,使用
replace選項可以替撚已存在的sql腳本,如果要給已存在的sql腳本追加內容,可以使用append選項。
(2)get
該命令與save命令作用恰好相反,用于將sql腳本中的所有內容裝載到sql緩沖區中。
eg:
SQL> get c:\a.sql
1* select ename from emp where deptno=20
(3)start和@
start和@命令用于運行sql腳本文件。注:當運行sql腳本文件時,應該指定文件路徑.eg:
SQL> @c:\a.sql
ENAME
----------
SMITH
JONES
SCOTT
ADAMS
FORD
(4)@@
該命令與@命令類似,也可以運行腳本文件,但主要作用是在腳本文件中嵌套調用其它的腳本文件。當使用該命令
嵌套腳本文件時,可在調用文件所在目錄下查找相應文件名。
(5)ed[it]
該命令不僅可用于編輯sql緩沖區內容,也可以用于編輯sql腳本文件。當運行該命令時,會啟動默認的系統編輯
器來編輯sql腳本。運行方法為:
sql>edit c:/a.sql
(6)spool
該命令用于將sql*plus屏幕內容存放到文本文件中。執行該命令時,應首先建立假脫機文件,并將隨后sql*plus
屏幕的所有內容全部存放到該文件中,最后使用spool off命令關閉假脫機文件。eg:
sql>spool c:\a.sql
5.格式命令
sql*plus不僅可以用于執行sql語句、pl/sql塊,而且還可以根據select結果生成報表。使用sql*plus的格式命令
可以控制報表的顯示格式,例如使用column命令可以控制列的顯示格式,使用ttitle命令可以指定頁標題;使用
btitle命令可以指定頁腳注。
(1)col[umn]
該命令用于控制列的顯示格式。column命令包含有四個選項,其中clear選項用于清除已定義列的顯示格式:
heading選項用于指定列的顯示標題;justify選項用于指定列標題的對齊格式(left,center,right);format選項用于
指定列的顯示格式,其中格式模型包含以下一些元素。
An:設置char,varchar2類型列的顯示寬度;
9: 在number類型列上禁止顯示前導0;
0: 在number類型列上強制顯示前導0;
$: 在number類型列前顯示美元符號;
L: 在number類型列前顯示本地貨幣符號;
.: 指定number類型列的小數點位置;
,: 指定number類型列的千分隔符;
eg1:使用column設置列顯示格式
sql>col ename heading 'name' format a10
sql>col sal heading 'sal' format L99999.99
sql>select ename,sal,hiredate from emp
sql>where empno=7788;
name sal HIREDATE
---------- ------------------- -------------------
SCOTT ¥3000.00 04/19/1987 00:00:00
sql>col ename clear
sql>col sal clear
sql>select ename,sal,hiredate from emp
sql>where empno=7788;
(2)title
該命令用于指定頁標題,頁標題會自動顯示在頁的中央。如果頁標題由多個詞組成,則用單引號引住。如果要將頁
標題分布在多行顯示,則用"|"分開不同單詞。如果不希望顯示頁標題,則使用"ttitle off"命令,禁止顯示,eg:
SQL> set linesize 40
SQL> ttitle 'employee report'
SQL> select ename,sal,hiredate from emp where empno=7788;
星期二 5月 20 第 1
employee report
ENAME SAL
---------- ----------
HIREDATE
-------------------
SCOTT 3000
04/19/1987 00:00:00
(3)btitle
該命令用于指定頁腳注,頁腳注會自動顯示在頁的中央。如果頁腳注由多個詞組成,則用單引號引注。如果要將頁腳注
分布在多行顯示,則用"|"分開不同單詞。如果不希望顯示頁腳注,則使用"btitle off"命令,禁止顯示。eg:
SQL> btitle 'page end'
SQL> select ename,sal,hiredate from emp where empno=7788
ENAME SAL
---------- ----------
HIREDATE
-------------------
SCOTT 3000
04/19/1987 00:00:00
page end
(4)break
該命令用于禁止顯示重復行,并將顯示結果分隔為幾個部分,以表現更友好的顯示結果,通常應該在order by 的排序列上
使用該命令。eg:
SQL> set pagesize 40
SQL> break on deptno skip 1
SQL> select deptno,ename,sal from emp order by deptno
2 ;
DEPTNO ENAME SAL
---------- ---------- ----------
10 CLARK 2450
KING 5000
MILLER 1300
20 JONES 2975
FORD 3000
ADAMS 1100
SMITH 800
SCOTT 3000
30 WARD 1250
TURNER 1500
ALLEN 1600
JAMES 950
BLAKE 2850
MARTIN 1250
6.交互式命令
如果經常要執行某些sql語句和sql*plus命令,可以將這些語句和命令存放到sql腳本中。通過使用sql腳本,
一方面可以降低命令輸入量,另一方面可以避免用戶的輸入錯誤。為了使得sql腳本可以根據不同輸入獲得
不同結果,需要在sql腳本中包含交互式命令。通過使用交互式命令,可以在sql*plus中定義變量,并且在運行
sql腳本時可以為這些變量動態輸入數據。下面介紹sql*plus的交互命令,以及引用變量所使用的標號。
(1)&
引用替代變量(substitution variable)時,必須要帶有該標號。如果替代變量已經定義,則會直接使用其數據,
如果替代變量沒有定義,則會臨時定義替代變量(該替代變量只在當前語句中起作用),并需要為其輸入數據。
注:如果替代變量為數字列則提供數據,則可以直接引用;如果替代變量為字符類型列或日期類型列提供數據,
則必須要用單引號引注。eg:
SQL> select ename,sal from emp where deptno=&no and job='&job';
輸入 no 的值: 20
輸入 job 的值: CLERK
原值 1: select ename,sal from emp where deptno=&no and job='&job'
新值 1: select ename,sal from emp where deptno=20 and job='CLERK'
(2)&&
該標號類似于單個&標號。但需要注意,&標號所定義的替代變量只在當前語句中起作用;而&&標號所定義的變量
會在當前sql*plus環境中一直生效。eg:
SQL> select ename,sal from emp where deptno=&&no and job='&&job' --定義了no變量
輸入 no 的值: 20
輸入 job 的值: CLERK
原值 1: select ename,sal from emp where deptno=&&no and job='&&job'
新值 1: select ename,sal from emp where deptno=20 and job='CLERK'
SQL> select ename,sal from emp where deptno=&no;
原值 1: select ename,sal from emp where deptno=&no --直接引用no變量
新值 1: select ename,sal from emp where deptno=20
ENAME SAL
---------- ----------
SMITH 800
JONES 2975
SCOTT 3000
ADAMS 1100
FORD 3000
如例所示,當第一次引用no變量時,使用&&標號需要為其輸入數據;當第二次引用no變量時,
使用&標號直接引用其原有值,而不需要輸入數據。
(3)define
該命令用于定義類型為char的替代變量,而且該命令的定義的替代變量只在當前sql*plus環境中起作用。
當使用該命令定義變量時,如果變量值包含空格或區分大小寫,則用引號引注。另外,使用"define變量名"可以檢查變量
是否已經定義。eg:
sql>set verify off
sql>define title=CLERK
sql>select ename,sal from where job='&title';
(4)accept
該命令可以用于定義char,number和date類型的替代變量。與define命令相比,accept命令更加靈活。當使用該命令定義替代
變量時,還可以指定變量輸入提示、變量輸入格式、隱藏輸入內容。
eg1:指定變量輸入提示
SQL> accept title prompt '請輸入崗位:'
請輸入崗位:CLERK
SQL> select ename,sal from emp where job='&title';
原值 1: select ename,sal from emp where job='&title'
新值 1: select ename,sal from emp where job='CLERK'
ENAME SAL
---------- ----------
SMITH 800
ADAMS 1100
JAMES 950
MILLER 1300
eg2:隱藏用戶輸入
sql>accept pwd hide
(5)undefine
該命令用于清除替代變量的定義。eg:
sql>undefine pwd
SQL> disc
從 Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options 斷開
SQL> conn scott/&pwd
輸入 pwd 的值: yhai1981
已連接
(6)prompt的pause
prompt命令用于輸出提示信息,而pause命令則用于暫停腳本執行。在sql腳本中結合使用這兩條命令,可以控制sql腳本
的暫停的執行。假定在a.sql腳本中包含以下命令:
prompt '按<Return>鍵繼續'
pause
當運行該sql腳本時,會暫停執行,eg:
sql>@c:\a.sql
'按<Return>鍵繼續'
(7)variable
該命令用于在sql*plus中定義綁定變量。當在sql語句或pl/sql塊中引用綁定變量時,必須要在綁定變量前加冒號(:);
當直接給綁定變量賦值時,需要使用execute命令(類似于調用存儲過程).示例如下:
sql>var no number
sql>exec :no:=7788
sql>select ename from emp where empno=:no;
ename
------------------
scott
(8)print
該命令用于輸出綁定變量結果,eg:
SQL> print no
NO
----------
7788
7.顯示和設置環境變量
使用sql*plus的環境變量可以控制其運行環境,例如設置行顯示寬度,設置每頁顯示的行數、
設置自動提交標記、設置自動跟蹤等等。使用show命令可以顯示當前sql*plus的環境變量設置
:使用set命令可以修改當前sql*plus的環境變量設置。下面介紹常用的sql*plus環境變量。
(1)顯示所有環境變量
為了顯示sql*plus的所有環境變量,必須要使用show all命令。示例如下:
SQL> show all
appinfo 為 OFF 并且已設置為 "SQL*Plus"
arraysize 15
autocommit OFF
autoprint OFF
autorecovery OFF
autotrace OFF
blockterminator "." (hex 2e)
btitle OFF 為下一條 SELECT 語句的前幾個字符
cmdsep OFF
colsep " "
compatibility version NATIVE
concat "." (hex 2e)
copycommit 0
COPYTYPECHECK 為 ON
define "&" (hex 26)
describe DEPTH 1 LINENUM OFF INDENT ON
echo OFF
editfile "afiedt.buf"
embedded OFF
escape OFF
用于 6 或更多行的 FEEDBACK ON
flagger OFF
flush ON
heading ON
headsep "|" (hex 7c)
instance "local"
linesize 80
lno 4
loboffset 1
logsource ""
long 80
longchunksize 80
markup HTML OFF HEAD "<style type='text/css'> body {font:10pt
Arial,Helvetica,sans-serif; color:black; background:White;} p
{font:10pt Arial,Helvetica,sans-serif; color:black; background:White;}
table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black;
background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;}
th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699;
background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt
Arial,Helvetica,Geneva,sans-serif; color:#336699;
background-color:White; border-bottom:1px solid #cccc99;
margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2
{font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699;
background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt
Arial,Helvetica,sans-serif; color:#663300; background:#ffffff;
margin-top:0pt; margin-bottom:0pt;
vertical-align:top;}</style><title>SQL*Plus
Report</title>" BODY "" TABLE "border='1' width='90%'
align='center' summary='Script output'" SPOOL OFF ENTMAP ON PREFORMAT
OFF
newpage 1
null ""
numformat ""
numwidth 10
pagesize 14
PAUSE 為 OFF
pno 1
recsep WRAP
recsepchar " " (hex 20)
release 1002000100
repfooter OFF 為 NULL
repheader OFF 為 NULL
serveroutput OFF
shiftinout INVISIBLE
showmode OFF
spool ON
sqlblanklines OFF
sqlcase MIXED
sqlcode 0
sqlcontinue "> "
sqlnumber ON
sqlpluscompatibility 10.2.0
sqlprefix "#" (hex 23)
sqlprompt "SQL> "
sqlterminator ";" (hex 3b)
suffix "sql"
tab ON
termout ON
timing OFF
trimout ON
trimspool OFF
ttitle OFF 為下一條 SELECT 語句的前幾個字符
underline "-" (hex 2d)
USER 為 "SCOTT"
verify ON
wrap : 將換至下一行
SQL> spool off
(2)arraysize
該環境變量用于指定數組提取尺寸,其默認值為15.該值越大,網絡開銷將會越低,但占用內存會增加。假定使用默認值,
如果查詢返回行數為50行,則需要通過網絡傳送4將數據;如果設置為25,則網絡傳送次數只有兩次。eg:
SQL> show arraysize
arraysize 15
SQL> set arraysize 25
(3)autocommit
該環境變量用于設置是否自動提交dml語句,其默認值為off(表示禁止自動提交)。當設置為ON時,每次執行DML
語句都會自動提交。eg:
SQL> show autocommit
autocommit OFF
SQL> set autocommit on
SQL> show autocommit
autocommit IMMEDIATE
(4)colsep
該環境變量用于設置列之間的分隔符,默認分隔符為空格。如果要使用其它分隔符,則使用set命令進行設置。eg:
sql>set colsep |
SQL> select ename,sal from emp where empno=7788
ENAME | SAL
----------|----------
SCOTT | 3000
(5)feedback
該環境變量用于指定顯示反饋行數信息的最低行數,其默認值為6。如果要禁止顯示行數反饋信息,則將feedback
設置為off。假設只要有查詢結果就返回行數,那么可以將該環境變量設置為1.eg:
sql>set feedback 1
sql>select ename,sal from emp where empno=7788;
ENAME | SAL
----------|----------
SCOTT | 3000
已選擇 1 行。
(6)heading
該環境變量用于設置是否顯示標題,其默認值為on。如果不顯示列標題,則設置為off。eg:
sql>set heading off
sql>select ename,sal from emp where empno=7788
SCOTT | 3000
(7)linesize
該環境變量用于設置行寬度,默認值為80。在默認情況下,如果數據長度超過80個字符,那么在sql*plus中會折
行顯示數據結果。要在一行中顯示全部數據,應該設置更大的值。eg:
(8)pagesize
該環境變量用于設置每頁所顯示的行數,默認值為14
set pagesize 0; //輸出每頁行數,缺省為24,為了避免分頁,可設定為0。
(9)long
該環境變量用于設置long和lob類型列的顯示長度。默認值為80,也就是說當查詢long或lob列時,只會顯示該列的前80個字符,
應該設置更大的值。eg:
sql>show long
long 80
sql>set long 300
(10)serveroutput
該環境變量用于控制服務器輸出,其默認值為off,表示禁止服務器輸出。在默認情況下,當調用dbms_output包時,
不會在sql*plus屏幕上顯示輸出結果。在調用dbms_output包時,為了在屏幕上輸出結果,必須要將serveroutput設置
為on。eg:
sql>set serveroutput on
sql>exec dbms_output.put_line('hello')
(11)termout
該環境變量用于控制sql腳本的輸出,其默認值為ON。當使用默認值時,如果sql腳本有輸出結果,則會在屏幕上輸出
顯示結果,如果設置為OFF,則不會在屏幕上輸出sql腳本。eg:
SQL> set termout off
SQL> @c:\a
(12)time
該環境變量用于設置在sql提示符前是否顯示系統時間,默認值為off,表示禁止顯示系統時間。如果設置為on,
則在sql提示符前會顯示系統時間.eg:
SQL> set time on
12:09:59 SQL>
(13)timing
該環境變量用于設置是否要顯示sql語句執行時間,默認值為off,表示不會顯示sql語句執行時間。如果設置為
ON,則會顯示sql語句執行時間。eg:
sql>set timing on
SQL> select count(*) from emp;
COUNT(*)
----------
14
已選擇 1 行。
已用時間: 00: 00: 00.03
(14)trimspool
set trimout on; //去除標準輸出每行的拖尾空格,缺省為off
set trimspool on; //去除重定向(spool)輸出每行的拖尾空格,缺省為off
如果trimspool設置為on,將移除spool文件中的尾部空格 ,trimout同trimspool功能相似,只不過對象是控制臺。
If trimspool is set to on, it will remove trailing blanks in spooled files.
See also trimout which does the same thing to the output to the console (terminal).
eg:
set trimspool off
spool c:\temp\trimspool.txt
declare
v_name varchar2(30);
begin
SELECT table_name into v_name
FROM all_tables
WHERE rownum =1;
dbms_output.put_line(v_name);
end;
/
set trimspool on
declare
v_name varchar2(30);
begin
SELECT table_name into v_name
FROM all_tables
WHERE rownum =1;
dbms_output.put_line(v_name);
end;
/
spool off
-- from ITPUB
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/32099462200932325331787
posted @
2009-04-23 14:54 C.B.K 閱讀(1403) |
評論 (0) |
編輯 收藏
如果機房馬上要關門了,或者你急著要和MM約會,請直接跳到第六個自然段。
我們這里說的KMP不是拿來放電影的(雖然我很喜歡這個軟件),而是一種算法。KMP算法是拿來處理字符串匹配的。換句話說,給你兩個字符串,你需要回
答,B串是否是A串的子串(A串是否包含B串)。比如,字符串A="I'm
matrix67",字符串B="matrix",我們就說B是A的子串。你可以委婉地問你的MM:“假如你要向你喜歡的人表白的話,我的名字是你的告白
語中的子串嗎?”
解決這類問題,通常我們的方法是枚舉從A串的什么位置起開始與B匹配,然后驗證是否匹配。假如A串長度為n,B串長度為m,那么這種方法的復雜度是O
(mn)的。雖然很多時候復雜度達不到mn(驗證時只看頭一兩個字母就發現不匹配了),但我們有許多“最壞情況”,比如,A=
"aaaaaaaaaaaaaaaaaaaaaaaaaab",B="aaaaaaaab"。我們將介紹的是一種最壞情況下O(n)的算法(這里假設
m<=n),即傳說中的KMP算法。
之所以叫做KMP,是因為這個算法是由Knuth、Morris、Pratt三個提出來的,取了這三個人的名字的頭一個字母。這時,或許你突然明白了
AVL
樹為什么叫AVL,或者Bellman-Ford為什么中間是一杠不是一個點。有時一個東西有七八個人研究過,那怎么命名呢?通常這個東西干脆就不用人名
字命名了,免得發生爭議,比如“3x+1問題”。扯遠了。
個人認為KMP是最沒有必要講的東西,因為這個東西網上能找到很多資料。但網上的講法基本上都涉及到“移動(shift)”、“Next函數”等概念,這
非常容易產生誤解(至少一年半前我看這些資料學習KMP時就沒搞清楚)。在這里,我換一種方法來解釋KMP算法。
假如,A="abababaababacb",B="ababacb",我們來看看KMP是怎么工作的。我們用兩個指針i和j分別表示,A[i-j+
1..i]與B[1..j]完全相等。也就是說,i是不斷增加的,隨著i的增加j相應地變化,且j滿足以A[i]結尾的長度為j的字符串正好匹配B串的前
j個字符(j當然越大越好),現在需要檢驗A[i+1]和B[j+1]的關系。當A[i+1]=B[j+1]時,i和j各加一;什么時候j=m了,我們就
說B是A的子串(B串已經整完了),并且可以根據這時的i值算出匹配的位置。當A[i+1]<>B[j+1],KMP的策略是調整j的位置
(減小j值)使得A[i-j+1..i]與B[1..j]保持匹配且新的B[j+1]恰好與A[i+1]匹配(從而使得i和j能繼續增加)。我們看一看當
i=j=5時的情況。
i = 1 2 3 4 5 6 7 8 9 ……
A = a b a b a b a a b a b …
B = a b a b a c b
j = 1 2 3 4 5 6 7
此時,A[6]<>B[6]。這表明,此時j不能等于5了,我們要把j改成比它小的值j'。j'可能是多少呢?仔細想一下,我們發現,j'必
須要使得B[1..j]中的頭j'個字母和末j'個字母完全相等(這樣j變成了j'后才能繼續保持i和j的性質)。這個j'當然要越大越好。在這里,B
[1..5]="ababa",頭3個字母和末3個字母都是"aba"。而當新的j為3時,A[6]恰好和B[4]相等。于是,i變成了6,而j則變成了
4:
i = 1 2 3 4 5 6 7 8 9 ……
A = a b a b a b a a b a b …
B = a b a b a c b
j = 1 2 3 4 5 6 7
從上面的這個例子,我們可以看到,新的j可以取多少與i無關,只與B串有關。我們完全可以預處理出這樣一個數組P[j],表示當匹配到B數組的第j個字母
而第j+1個字母不能匹配了時,新的j最大是多少。P[j]應該是所有滿足B[1..P[j]]=B[j-P[j]+1..j]的最大值。
再后來,A[7]=B[5],i和j又各增加1。這時,又出現了A[i+1]<>B[j+1]的情況:
i = 1 2 3 4 5 6 7 8 9 ……
A = a b a b a b a a b a b …
B = a b a b a c b
j = 1 2 3 4 5 6 7
由于P[5]=3,因此新的j=3:
i = 1 2 3 4 5 6 7 8 9 ……
A = a b a b a b a a b a b …
B = a b a b a c b
j = 1 2 3 4 5 6 7
這時,新的j=3仍然不能滿足A[i+1]=B[j+1],此時我們再次減小j值,將j再次更新為P[3]:
i = 1 2 3 4 5 6 7 8 9 ……
A = a b a b a b a a b a b …
B = a b a b a c b
j = 1 2 3 4 5 6 7
現在,i還是7,j已經變成1了。而此時A[8]居然仍然不等于B[j+1]。這樣,j必須減小到P[1],即0:
i = 1 2 3 4 5 6 7 8 9 ……
A = a b a b a b a a b a b …
B = a b a b a c b
j = 0 1 2 3 4 5 6 7
終于,A[8]=B[1],i變為8,j為1。事實上,有可能j到了0仍然不能滿足A[i+1]=B[j+1](比如A[8]="d"時)。因此,準確的說法是,當j=0了時,我們增加i值但忽略j直到出現A[i]=B[1]為止。
這個過程的代碼很短(真的很短),我們在這里給出:
程序代碼
j:=0;
for i:=1 to n do
begin
while (j>0) and (B[j+1]<>A[i]) do j:=P[j];
if B[j+1]=A[i] then j:=j+1;
if j=m then
begin
writeln('Pattern occurs with shift ',i-m);
j:=P[j];
end;
end;
最后的j:=P[j]是為了讓程序繼續做下去,因為我們有可能找到多處匹配。
這個程序或許比想像中的要簡單,因為對于i值的不斷增加,代碼用的是for循環。因此,這個代碼可以這樣形象地理解:掃描字符串A,并更新可以匹配到B的什么位置。
現在,我們還遺留了兩個重要的問題:一,為什么這個程序是線性的;二,如何快速預處理P數組。
為什么這個程序是O(n)的?其實,主要的爭議在于,while循環使得執行次數出現了不確定因素。我們將用到時間復雜度的攤還分析中的主要策略,簡單地
說就是通過觀察某一個變量或函數值的變化來對零散的、雜亂的、不規則的執行次數進行累計。KMP的時間復雜度分析可謂攤還分析的典型。我們從上述程序的j
值入手。每一次執行while循環都會使j減小(但不能減成負的),而另外的改變j值的地方只有第五行。每次執行了這一行,j都只能加1;因此,整個過程
中j最多加了n個1。于是,j最多只有n次減小的機會(j值減小的次數當然不能超過n,因為j永遠是非負整數)。這告訴我們,while循環總共最多執行
了n次。按照攤還分析的說法,平攤到每次for循環中后,一次for循環的復雜度為O(1)。整個過程顯然是O(n)的。這樣的分析對于后面P數組預處理
的過程同樣有效,同樣可以得到預處理過程的復雜度為O(m)。
預處理不需要按照P的定義寫成O(m^2)甚至O(m^3)的。我們可以通過P[1],P[2],...,P[j-1]的值來獲得P[j]的值。對于剛才
的B="ababacb",假如我們已經求出了P[1],P[2],P[3]和P[4],看看我們應該怎么求出P[5]和P[6]。P[4]=2,那么P
[5]顯然等于P[4]+1,因為由P[4]可以知道,B[1,2]已經和B[3,4]相等了,現在又有B[3]=B[5],所以P[5]可以由P[4]
后面加一個字符得到。P[6]也等于P[5]+1嗎?顯然不是,因為B[ P[5]+1
]<>B[6]。那么,我們要考慮“退一步”了。我們考慮P[6]是否有可能由P[5]的情況所包含的子串得到,即是否P[6]=P[
P[5] ]+1。這里想不通的話可以仔細看一下:
1 2 3 4 5 6 7
B = a b a b a c b
P = 0 0 1 2 3 ?
P[5]=3是因為B[1..3]和B[3..5]都是"aba";而P[3]=1則告訴我們,B[1]和B[5]都是"a"。既然P[6]不能由P
[5]得到,或許可以由P[3]得到(如果B[2]恰好和B[6]相等的話,P[6]就等于P[3]+1了)。顯然,P[6]也不能通過P[3]得到,因
為B[2]<>B[6]。事實上,這樣一直推到P[1]也不行,最后,我們得到,P[6]=0。
怎么這個預處理過程跟前面的KMP主程序這么像呢?其實,KMP的預處理本身就是一個B串“自我匹配”的過程。它的代碼和上面的代碼神似:
程序代碼
P[1]:=0;
j:=0;
for i:=2 to m do
begin
while (j>0) and (B[j+1]<>B[i]) do j:=P[j];
if B[j+1]=B[i] then j:=j+1;
P[i]:=j;
end;
最后補充一點:由于KMP算法只預處理B串,因此這種算法很適合這樣的問題:給定一個B串和一群不同的A串,問B是哪些A串的子串。
串匹配是一個很有研究價值的問題。事實上,我們還有后綴樹,自動機等很多方法,這些算法都巧妙地運用了預處理,從而可以在線性的時間里解決字符串的匹配。我們以后來說。
Matrix67原創
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/32099462200931645748543
posted @
2009-04-16 16:58 C.B.K 閱讀(78) |
評論 (0) |
編輯 收藏
(1)給金額添加逗號
import java.text.*;
NumberFormat formater = new DecimalFormat("###,###.##");
formater.format(12342351432534.24565);
(2)日期格式換
Date now = new Date();
SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
formater.format(now());
SimpleDateFormat
模式字母(所有其他字符 'A'
到 'Z'
和 'a'
到
'z'
都被保留):
模式字母通常是重復的,其數量確定其精確表示:
- Text: 對于格式化來說,如果模式字母的數量大于或等于
4,則使用完全形式;否則,在可用的情況下使用短形式或縮寫形式。對于分析來說,兩種形式都是可接受的,與模式字母的數量無關。
- Number: 對于格式化來說,模式字母的數量是最小的數位,如果數位不夠,則用
0 填充以達到此數量。對于分析來說,模式字母的數量被忽略,除非必須分開兩個相鄰字段。
- Year: 對于格式化來說,如果模式字母的數量為 2,則年份截取為 2
位數,否則將年份解釋為 number。 SimpleDateFormat
示例
以下示例顯示了如何在美國語言環境中解釋日期和時間模式。給定的日期和時間為美國太平洋時區的本地時間 2001-07-04 12:08:56。
日期和時間模式
| 結果
|
"yyyy.MM.dd G 'at' HH:mm:ss z"
| 2001.07.04 AD at 12:08:56 PDT
|
"EEE, MMM d, ''yy"
| Wed, Jul 4, '01
|
"h:mm a"
| 12:08 PM
|
"hh 'o''clock' a, zzzz"
| 12 o'clock PM, Pacific Daylight Time
|
"K:mm a, z"
| 0:08 PM, PDT
|
"yyyyy.MMMMM.dd GGG hh:mm aaa"
| 02001.July.04 AD 12:08 PM
|
"EEE, d MMM yyyy HH:mm:ss Z"
| Wed, 4 Jul 2001 12:08:56 -0700
|
"yyMMddHHmmssZ"
| 010704120856-0700
|
"yyyy-MM-dd'T'HH:mm:ss.SSSZ"
| 2001-07-04T12:08:56.235-0700 |
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/32099462200931621628957
posted @
2009-04-16 14:16 C.B.K 閱讀(82) |
評論 (0) |
編輯 收藏
(一)
開門見山.今天我要說的是不用HQL執行SAVE和DELETE方法,用hibernate的executeQuery來執行SQL
其原理如下(從SessionFactory里獲得個Session,在調用session的connection方法,通過Statement來執行靜態SQL,最后執行executeQuery就可以了)具體如下:
protected Session session = null; protected Transaction tr = null;
String sql = "insert into
as_dept2role(roleid,dept_id)value('"+roleId+"','"+deptId+"')";
session=HibernateSessionFactory.getSession();
session.beginTransaction();
//獲取connection,執行靜態SQL
Statement state = session.connection().createStatement();
state.executeQuery(sql);
tr.commit(); session.close();
當然關于 關閉SESSION 這些方法我寫的簡單些,主要是為了寫 執行SQL這些方法
對于刪除只要寫個刪除語句就可以了
:Transaction tr = session.beginTransaction();
* session.connection() 方法過時 用下面來代替 *
DataSource ds= SessionFactoryUtils.getDataSource(getSessionFactory());
conn=ds.getConnection();
============================================
(二)
public Object get(Class cls, String szId) {
Object obj = this.getHibernateTemplate().get(cls, szId);
return obj;
}
obj.getsessionFaction.opensession返回session
Session session = dao.openSession();
Connection conn = session.connection();
List recordList = new ArrayList();
StringBuffer sql = new StringBuffer();
sql.append("select b.user_name, c.org_name ");
sql.append("from orgmeetinglinkman a, am_user b, organization c ");
sql.append("where a.login_name = b.login_name ");
sql.append("and a.org_id = c.org_id ");
PreparedStatement ps = conn.prepareStatement(sql.toString());
ResultSet rs = ps.execu
============================================
(三)
public List findWithSQL(final String sql) {
List list = (List) this.getHibernateTemplate().execute(
new HibernateCallback() {
public Object doInHibernate(Session session)
throws SQLException, HibernateException {
SQLQuery query = session.createSQLQuery(sql);
query.addScalar("NX",new org.hibernate.type.StringType());
List children = query.list();
return children;
}
});
return list;
}
/**
* 查詢并返回結果集,結果集中的內容已經都轉為了字符串
*/
public List<List<String>> findSql(final String sql) {
// TODO Auto-generated method stub
System.out.println("findSql---sql1----->"+sql);
List<List<String>> mainObjList=
(List<List<String>>) getHibernateTemplate().execute(new
HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
int n=-1;
Connection con=null;
PreparedStatement stmt=null;
ResultSet rs=null;
try
{
DataSource ds= SessionFactoryUtils.getDataSource(getSessionFactory());
if(ds==null)
{
throw new SQLException("get dataSource is null");
}
con=ds.getConnection();
System.out.println("findSql---sql2----->"+sql);
stmt=con.prepareStatement(sql);
rs=stmt.executeQuery();
} catch (HibernateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
List<List<String>> list=new ArrayList<List<String>>();//每行為一個list
try
{
ResultSetMetaData rsmd=rs.getMetaData();
int colsNum=rsmd.getColumnCount();//取得列數
int rsNum=0;
while(rs.next())
{
rsNum++;
System.out.println("rsNum==="+rsNum+" ");
List<String> subList=new ArrayList<String> ();//每列的類型為string
for(int i=1;i<=colsNum;i++)
{
System.out.println("\ti==="+i);
//int type= rsmd.getColumnType(i);
String columnType=getDataType(rsmd.getColumnType(i),rsmd.getScale(i));
String val="";
if(columnType.equalsIgnoreCase("Date"))
{
Timestamp timest= rs.getTimestamp(i);
if(timest!=null)
{
long times=timest.getTime();
Date date=new Date(times);
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.CHINA);
val=df.format(date);
}
}
else if(columnType.equalsIgnoreCase("Number"))
{
Object obj=rs.getObject(i);
if(obj!=null)
{
int m=rs.getInt(i);
val=Integer.toString(m);
}
}
else if(columnType.equalsIgnoreCase("blob"))
{
val="不支持blob數據的讀取";
}
else if(columnType.equalsIgnoreCase("clob"))
{
val=getOracleClobField(rs, i);
}
else
{
val=rs.getString(i);
}
if(val==null)
{
val="";
}
subList.add(val);
}
if(subList.size()>0)
{
list.add(subList);
}
}
}
catch(Exception ex5)
{
ex5.printStackTrace();
System.out.println("ex5.getMessage="+ex5.getMessage());
list=null;
}
finally
{
try {
if (rs != null) {
rs.close();
rs = null;
}
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
System.out.println("e2.getMessage="+e2.getMessage());
}
try {
if (stmt != null) {
stmt.close();
stmt = null;
}
} catch (Exception e3) {
// TODO: handle exception
e3.printStackTrace();
System.out.println("e3.getMessage="+e3.getMessage());
}
try {
if (con != null) {
con.close();
con = null;
}
} catch (Exception e4) {
// TODO: handle exception
e4.printStackTrace();
System.out.println("e4.getMessage="+e4.getMessage());
}
}
return list;
}
});
return mainObjList;
}
// String columnType=getDataType(rmd.getColumnType(i),rmd.getScale(i));
private String getOracleClobField(ResultSet rset, int index)
throws Exception
{
StringBuffer buffS = new StringBuffer();
Clob clob = rset.getClob(index + 1);
if(clob == null)
return " ";
Reader reader = clob.getCharacterStream();
char buff[] = new char[1024];
for(int len = 0; (len = reader.read(buff)) != -1;)
buffS.append(buff, 0, len);
return buffS.toString();
}
private static String getDataType(int type,int scale)
{
String dataType="";
switch(type){
case Types.LONGVARCHAR: //-1
dataType="Long";
break;
case Types.CHAR: //1
dataType="Character";
break;
case Types.NUMERIC: //2
switch(scale)
{
case 0:
dataType="Number";
break;
case -127:
dataType="Float";
break;
default:
dataType="Number";
}
break;
case Types.VARCHAR: //12
dataType="String";
break;
case Types.DATE: //91
dataType="Date";
break;
case Types.TIMESTAMP: //93
dataType="Date";
break;
case Types.BLOB :
dataType="Blob";
break;
default:
dataType="String";
}
return dataType;
}
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/32099462200931511221288
posted @
2009-04-15 23:22 C.B.K 閱讀(18790) |
評論 (1) |
編輯 收藏
匈牙利命名法
匈牙利命名法是一種編程時的命名規范。基本原則是:變量名=屬性+類型+對象描述,其中每一對象的名稱都要求有明確含義,可以取對象名字全稱或名字的一部分。命名要基于容易記憶容易理解的原則。保證名字的連貫性是非常重要的。
舉例來說,表單的名稱為form,那么在匈牙利命名法中可以簡寫為frm,則當表單變量名稱為
Switchboard時,變量全稱應該為
frmSwitchboard。這樣可以很容易從變量名看出Switchboard是一個表單,同樣,如果此變量類型為標簽,那么就應命名成
lblSwitchboard。可以看出,匈牙利命名法非常便于記憶,而且使變量名非常清晰易懂,這樣,增強了代碼的可讀性,方便各程序員之間相互交流代
碼。
據說這種命名法是一位叫 Charles Simonyi
的匈牙利程序員發明的,后來他在微軟呆了幾年,于是這種命名法就通過微軟的各種產品和文檔資料向世界傳播開了。現在,大部分程序員不管自己使用什么軟件進
行開發,或多或少都使用了這種命名法。這種命名法的出發點是把變量名按:屬性+類型+對象描述的順序組合起來,以使程序員作變量時對變量的類型和其它屬性
有直觀的了解,下面是HN變量命名規范,其中也有一些是我個人的偏向:
屬性部分
全局變量
g_
常量
c_
c++類成員變量
m_
靜態變量
s_
類型部分
指針
p
函數
fn
無效
v
句柄
h
長整型
l
布爾
b
浮點型(有時也指文件)
f
雙字
dw
字符串
sz
短整型
n
雙精度浮點
d
計數
c(通常用cnt)
字符
ch(通常用c)
整型
i(通常用n)
字節
by
字
w
實型
r
無符號
u
描述部分
最大
Max
最小
Min
初始化
Init
臨時變量
T(或Temp)
源對象
Src
目的對象
Dest
這里順便寫幾個例子:
hwnd : h 是類型描述,表示句柄, wnd 是變量對象描述,表示窗口,所以 hwnd 表示窗口句柄;
pfnEatApple : pfn 是類型描述,表示指向函數的指針, EatApple 是變量對象描述,所以它表示
指向 EatApple 函數的函數指針變量。
g_cch : g_ 是屬性描述,表示全局變量,c 和 ch 分別是計數類型和字符類型,一起表示變量類
型,這里忽略了對象描述,所以它表示一個對字符進行計數的全局變量。
上面就是HN命名法的一般規則。
小結:匈牙利命名法
匈牙利命名法
MFC、句柄、控件及結構的命名規范 Windows類型 樣本變量 MFC類 樣本變量
HWND hWnd; CWnd* pWnd;
HDLG hDlg; CDialog* pDlg;
HDC hDC; CDC* pDC;
HGDIOBJ hGdiObj; CGdiObject* pGdiObj;
HPEN hPen; CPen* pPen;
HBRUSH hBrush; CBrush* pBrush;
HFONT hFont; CFont* pFont;
HBITMAP hBitmap; CBitmap* pBitmap;
HPALETTE hPaltte; CPalette* pPalette;
HRGN hRgn; CRgn* pRgn;
HMENU hMenu; CMenu* pMenu;
HWND hCtl; CState* pState;
HWND hCtl; CButton* pButton;
HWND hCtl; CEdit* pEdit;
HWND hCtl; CListBox* pListBox;
HWND hCtl; CComboBox* pComboBox;
HWND hCtl; CScrollBar* pScrollBar;
HSZ hszStr; CString pStr;
POINT pt; CPoint pt;
SIZE size; CSize size;
RECT rect; CRect rect;
一般前綴命名規范 前綴 類型 實例
C 類或結構 CDocument,CPrintInfo
m_ 成員變量 m_pDoc,m_nCustomers
變量命名規范 前綴 類型 描述 實例
ch char 8位字符 chGrade
ch TCHAR 如果_UNICODE定義,則為16位字符 chName
b BOOL 布爾值 bEnable
n int 整型(其大小依賴于操作系統) nLength
n UINT 無符號值(其大小依賴于操作系統) nHeight
w WORD 16位無符號值 wPos
l LONG 32位有符號整型 lOffset
dw DWORD 32位無符號整型 dwRange
p * 指針 pDoc
lp FAR* 遠指針 lpszName
lpsz LPSTR 32位字符串指針 lpszName
lpsz LPCSTR 32位常量字符串指針 lpszName
lpsz LPCTSTR 如果_UNICODE定義,則為32位常量字符串指針 lpszName
h handle Windows對象句柄 hWnd
lpfn callback 指向CALLBACK函數的遠指針
前綴 符號類型 實例 范圍
IDR_ 不同類型的多個資源共享標識 IDR_MAIINFRAME 1~0x6FFF
IDD_ 對話框資源 IDD_SPELL_CHECK 1~0x6FFF
HIDD_ 對話框資源的Help上下文 HIDD_SPELL_CHECK 0x20001~0x26FF
IDB_ 位圖資源 IDB_COMPANY_LOGO 1~0x6FFF
IDC_ 光標資源 IDC_PENCIL 1~0x6FFF
IDI_ 圖標資源 IDI_NOTEPAD 1~0x6FFF
ID_ 來自菜單項或工具欄的命令 ID_TOOLS_SPELLING 0x8000~0xDFFF
HID_ 命令Help上下文 HID_TOOLS_SPELLING 0x18000~0x1DFFF
IDP_ 消息框提示 IDP_INVALID_PARTNO 8~0xDEEF
HIDP_ 消息框Help上下文 HIDP_INVALID_PARTNO 0x30008~0x3DEFF
IDS_ 串資源 IDS_COPYRIGHT 1~0x7EEF
IDC_ 對話框內的控件 IDC_RECALC 8~0xDEEF
Microsoft MFC宏命名規范 名稱 類型
_AFXDLL 唯一的動態連接庫(Dynamic Link Library,DLL)版本
_ALPHA 僅編譯DEC Alpha處理器
_DEBUG 包括診斷的調試版本
_MBCS 編譯多字節字符集
_UNICODE 在一個應用程序中打開Unicode
AFXAPI MFC提供的函數
CALLBACK 通過指針回調的函數
庫標識符命名法 標識符 值和含義
u ANSI(N)或Unicode(U)
d 調試或發行:D = 調試;忽略標識符為發行。
靜態庫版本命名規范 庫 描述
NAFXCWD.LIB 調試版本:MFC靜態連接庫
NAFXCW.LIB 發行版本:MFC靜態連接庫
UAFXCWD.LIB 調試版本:具有Unicode支持的MFC靜態連接庫
UAFXCW.LIB 發行版本:具有Unicode支持的MFC靜態連接庫
動態連接庫命名規范 名稱 類型
_AFXDLL 唯一的動態連接庫(DLL)版本
WINAPI Windows所提供的函數
Windows.h中新的命名規范 類型 定義描述
WINAPI 使用在API聲明中的FAR PASCAL位置,如果正在編寫一個具有導出API人口點的DLL,則可以在自己的API中使用該類型
CALLBACK 使用在應用程序回叫例程,如窗口和對話框過程中的FAR PASCAL的位置
LPCSTR 與LPSTR相同,只是LPCSTR用于只讀串指針,其定義類似(const char FAR*)
UINT 可移植的無符號整型類型,其大小由主機環境決定(對于Windows NT和Windows 9x為32位);它是unsigned int的同義詞
LRESULT 窗口程序返回值的類型
LPARAM 聲明lParam所使用的類型,lParam是窗口程序的第四個參數
WPARAM 聲明wParam所使用的類型,wParam是窗口程序的第三個參數
LPVOID 一般指針類型,與(void *)相同,可以用來代替LPSTR
--------------------------------------------------------------------------------
抨擊匈牙利命名法
匈牙利命名法是一種編程時的命名規范。命名規范是程序書寫規范中最重要也是最富爭議的地方,自
古乃兵家必爭之地。命名規范有何用?四個字:名正言順。用二分法,命名規范分為好的命名規范和壞的命名規范,也就是說名正言順的命名規范和名不正言不順的
命名規范。好的舞鞋是讓舞者感覺不到其存在的舞鞋,壞的舞鞋是讓舞者帶著鐐銬起舞。一個壞的命名規范具有的破壞力比一個好的命名規范具有的創造力要大得
多。
本文要證明的是:匈牙利命名法是一個壞的命名規范。本文的作用范圍為靜態強類型編程語言。本文的分析范本為C語言和C++語言。下文中的匈法為匈牙利命名法的簡稱。
一 匈牙利命名法的成本
匈法的表現形式為給變量名附加上類型名前綴,例
如:nFoo,szFoo,pFoo,cpFoo分別表示整型變量,字符串型變量,指針型變量和常指針型變量。可以看出,匈法將變量的類型信息從單一地點
(聲明變量處)復制到了多個地點(使用變量處),這是冗余法。冗余法的成本之一是要維護副本的一致性。這個成本在編寫和維護代碼的過程中需要改變變量的類
型時付出。冗余法的成本之二是占用了額外的空間。一個優秀的書寫者會自覺地遵從一個法則:代碼最小組織單位的長度以30個自然行以下為宜,如果超過50行
就應該重新組織。一個變量的書寫空間會給這一法則添加不必要的難度。
二 匈牙利命名法的收益
這里要證明匈牙利命名法的收益是含糊的,無法預期的。
范本1:strcpy(pstrFoo,pcstrFoo2) Vs strcpy(foo,foo2)
匈法在這里有什么收益呢?我看不到。沒有一個程序員會承認自己不知道strcpy函數的參數類型吧。
范本2:unknown_function(nFoo) Vs unknown_function(foo)
匈法在這里有什么收益呢?我看不到。對于一個不知道確定類型的函數,程序員應該去查看該函數的
文檔,這是一種成本。使用匈法的唯一好處是看代碼的人知道這個函數要求一個整型參數,這又有什么用處呢?函數是一種接口,參數的類型僅僅是接口中的一小部
分。諸如函數的功能、出口信息、線程安全性、異常安全性、參數合法性等重要信息還是必須查閱文檔。
范本3:nFoo=nBar Vs foo=bar
匈法在這里有什么收益呢?我看不到。使用匈法的唯一好處是看代碼的人知道這里發生了一個整型變
量的復制動作,聽起來沒什么問題,可以安心睡大覺了。如果他看到的是nFoo=szBar,可能會從美夢中驚醒。且慢,事情真的會是這樣嗎?我想首先被驚
醒的應該是編譯器。另一方面,nFoo=nBar只是在語法上合法而已,看代碼的人真正關心的是語義的合法性,匈法對此毫無幫助。另一方面,一個優秀的書
寫者會自覺地遵從一個法則:代碼最小組織單位中的臨時變量以一兩個為宜,如果超過三個就應該重新組織。結合前述第一個法則,可以得出這樣的結論:易于理解
的代碼本身就應該是易于理解的,這是代碼的內建高質量。好的命名規范對內建高質量的助益相當有限,而壞的命名規范對內建高質量的損害比人們想象的要大。
三 匈牙利命名法的實施
這里要證明匈牙利命名法在C語言是難以實施的,在C++語言中是無法實施的。從邏輯上講,對匈法的收益做出否定的結論以后,再來論證匈法的可行性,是畫蛇添足。不過有鑒于小馬哥曾讓已射殺之敵死灰復燃,我還是再踏上一支腳為妙。
前面講過,匈法是類型系統的冗余,所以實施匈法的關鍵是我們是否能夠精確地對類型系統進行復制。這取決于類型系統的復雜性。
先來看看C語言:
1.內置類型:int,char,float,double 復制為 n,ch,f,d?好像沒有什么問題。不過誰來告訴我void應該怎么表示?
2.組合類型:array,union,enum,struct 復制為 a,u,e,s?好像比較別扭。
這里的難點不是為主類型取名,而是為副類型取名。an表示整型數組?sfoo,sbar表示結構foo,結構bar?ausfoo表示聯合結構foo數組?累不累啊。
3.特殊類型:pointer。pointer在理論上應該是組合類型,但是在C語言中可以認為是內置類型,因為C語言并沒有非常嚴格地區分不同的指針類型。下面開始表演:pausfoo表示聯合結構foo數組指針?ppp表示指針的指針的指針?
噩夢還沒有結束,再來看看類型系統更阿為豐富的C++語言:
1.class:如果說C語言中的struct還可以用stru搪塞過去的話,不要夢想用
cls來搪塞C++中的class。嚴格地講,class根本就并不是一個類型,而是創造類型的工具,在C++中,語言內置類型的數量和class創造的
用戶自定義類型的數量相比完全可以忽略不計。stdvectorFoo表示標準庫向量類型變量Foo?瘋狂的念頭。
2.命名空間:boostfilesystemiteratorFoo,表示boost空間filesystem子空間遍歷目錄類型變量Foo?程序員要崩潰了。
3.模板:你記得std::map<std::string,std::string>類型的確切名字嗎?我是記不得了,好像超過255個字符,還是饒了我吧。
4.模板參數:template <class T, class
BinaryPredicate>const T& max(const T& a, const T& b,
BinaryPredicate comp) 聰明的你,請用匈法為T命名。上帝在發笑。
5.類型修飾:static,extern,mutable,register,volatile,const,short,long,unsigned 噩夢加上修飾是什么?還是噩夢。
文章來源:
http://blog.163.com/ccbobo_cat/blog/static/32099462200931411226261
posted @
2009-04-14 23:02 C.B.K 閱讀(93) |
評論 (0) |
編輯 收藏