
2006年9月26日
北京英語角(BeiJing)www.52en.com
=================================
北大英語角:每周六晚7:00 俄文樓前空地
清華英語角:每周三晚7:00-10:00 西階(west of Great Hall)
人大英語角:每周五晚 人大東門花園,老外多,質量不錯
北外英語角:每周五晚6:30-8:30外研社后花園
朝陽文化館:每周六下午3:00-5:00 門票6元地點在小莊,收費,但質量好
posted @
2007-04-25 09:29 阿成 閱讀(2140) |
評論 (6) |
編輯 收藏
1.未到火候,千萬別說。有些男孩才跟人家約過幾次,就提出要建立“更進一步”的關系,這十有八九要壞湯。愛情上的事妙就妙在一切盡在不言中。說清楚了,話挑明了,反而不美。本來人家肯單獨出來跟你說話,這說明女孩對你不無好感。但是這種好感有時連她們自己都說不清,你卻急于挑明,破壞了這種朦朧美,那就別怪人家敬而遠之以致退避三舍了。看看周圍那些還沒開始就夭折的愛情,許多都是由男孩沒有掌握好火候造成的。
2.收起拳頭是為了更好的出擊。被女孩拒絕了怎么辦呢?有人說應該窮追猛打、堅持不懈。其實不然。除非你是一個啥也不在乎的人,否則你很難承受女孩的白眼和同伴們嘲弄的目光。倒不如偃旗息鼓、暫時撤退。這不僅保護了你的尊嚴而且還留了條后路,從而為日后反攻創造機會。就讓她在人群里闖蕩。等她碰得頭破血流時,你再去找她,她才能認識到原來你才是最愛她的人。即使實在割舍不下,要去找她,也應注意方式方法。千萬別讓她覺得你討厭。而這一點往往是很難做到的。
3.不要太露骨。要學會不聲不響地關心她,用你的誠實和善意對待她。只有這樣你才能在一大幫圍著她呱呱亂叫的男孩當中引起她的注意。記住,只有特別的你才會引起她特別的關注。
4.非請勿入。一個老是往女孩寢室跑的男孩是不會引起女孩太多的好感的。有些學生會干部借口工作常往女生寢室跑,去了后就老賴在那不走,結果給人家帶來了諸多不便,效果只會適得其反。產生這種結果的根本原因還是因為太露骨。
5.戰略上藐視...,戰術上重視...。有時你喜愛的女孩會和你有些接觸,比如談談話、聊聊天、一起工作等等。你最好能以平常的心態看待這些事情,不要背上包袱、患得患失。例如不要太在意她無意中說的話,有些男孩容易自作多情,源出于此。但對每一次這樣的機會則應引起足夠的重視,例如初次談話要注意掌握好分寸,最好不要涉及情愛范疇,不妨說說小時候的事。你如果只奔主體那就要糟!女孩非得象警惕狼一樣地警惕你。
6.馬屁最好少拍。你夸她長得漂亮,如果她真的漂亮,那么你不過是第七百個夸她漂亮的人,而她映象最深的恐怕是第一個這樣夸她的人;如果她相貌普通,你這樣夸她能產生什么樣的結果誰也說不準。要是讓她發現你言不由衷,那你就死定了。記住,哄女孩只有在女孩成為你的女朋友之后才能哄,還沒追到手就開始哄是沒有掌握好火候的表現。
7.少來點大男子主義。有個男孩好不容易請得他傾慕已久的女孩去吃飯,花了他半個月生活費。后來他去付賬時發現女孩已經替他付了,他就要還她錢。女孩不愿意。他覺得女孩剝了他的面子,大為光火。女孩氣得哭了。本來女孩替他付賬這說明她對他有好感,他不思討好反而發脾氣,如此就難怪他要打光棍了。幾乎沒有一個女孩會對那些不尊重女性的男孩有好感,切記!切記!。
8.團結大多數。幾乎每個女孩都有一兩個最知心的女友,當其他道路都不通時,她們是你通往勝利的成功之路。你可以通過她們了解女孩到底對你有沒有意思,還可以通過她們傳達你的意思。這比你直接說要好得多。可千萬別忽視這一支生力軍,我不止一次地看到男孩通過這個方法大功告成的。
最后要提醒大家的是,愛情從來都沒有固定的公式。別人成功的方法也許正是你的敗著;別人失敗的方法也許恰是你的妙著。我這里只提一點原則性的東西,切不可生搬硬套。如果因此而壞了你的好事切莫來找我。女孩要是不喜歡你,就是玉皇大帝也沒有法子。還是古人說的好:不戰而屈人之兵,上之上策也。
posted @
2007-04-23 19:12 阿成 閱讀(513) |
評論 (0) |
編輯 收藏
ThreadLocal
類是悄悄地出現在 Java 平臺版本 1.2 中的。雖然支持線程局部變量早就是許多線程工具(例如 Posix pthreads
工具)的一部分,但 Java Threads API 的最初設計卻沒有這項有用的功能。而且,最初的實現也相當低效。由于這些原因, ThreadLocal
極少受到關注,但對簡化線程安全并發程序的開發來說,它卻是很方便的。在 輕松使用線程的第 3 部分,Java 軟件顧問 Brian Goetz 研究了 ThreadLocal
并提供了一些使用技巧。
參加 Brian 的 多線程 Java 編程討論論壇以獲得您工程中的線程和并發問題的幫助。
編寫線程安全類是困難的。它不但要求仔細分析在什么條件可以對變量進行讀寫,而且要求仔細分析其它類能如何使用某個類。 有時,要在不影響類的功能、易用性或性能的情況下使類成為線程安全的是很困難的。有些類保留從一個方法調用到下一個方法調用的狀態信息,要在實踐中使這樣的類成為線程安全的是困難的。
管理非線程安全類的使用比試圖使類成為線程安全的要更容易些。非線程安全類通常可以安全地在多線程程序中使用,只要您能確保一個線程所用的類的實例不被其它線程使用。例如,JDBC Connection
類是非線程安全的 — 兩個線程不能在小粒度級上安全地共享一個 Connection
— 但如果每個線程都有它自己的 Connection
,那么多個線程就可以同時安全地進行數據庫操作。
不使用 ThreadLocal
為每個線程維護一個單獨的 JDBC 連接(或任何其它對象)當然是可能的;Thread API 給了我們把對象和線程聯系起來所需的所有工具。而 ThreadLocal 則使我們能更容易地把線程和它的每線程(per-thread)數據成功地聯系起來。
什么是線程局部變量(thread-local variable)?
線程局部變量高效地為每個使用它的線程提供單獨的線程局部變量值的副本。每個線程只能看到與自己相聯系的值,而不知道別的線程可能正在使用或修改它們自己的副本。一些編譯器(例如 Microsoft Visual C++ 編譯器或 IBM XL FORTRAN 編譯器)用存儲類別修飾符(像 static
或 volatile
)把對線程局部變量的支持集成到了其語言中。Java 編譯器對線程局部變量不提供特別的語言支持;相反地,它用 ThreadLocal
類實現這些支持, 核心 Thread
類中有這個類的特別支持。
因為線程局部變量是通過一個類來實現的,而不是作為 Java 語言本身的一部分,所以 Java 語言線程局部變量的使用語法比內建線程局部變量語言的使用語法要笨拙一些。要創建一個線程局部變量,請實例化類 ThreadLocal
的一個對象。 ThreadLocal
類的行為與 java.lang.ref
中的各種 Reference
類的行為很相似; ThreadLocal
類充當存儲或檢索一個值時的間接句柄。清單 1 顯示了 ThreadLocal
接口。
清單 1. ThreadLocal 接口
public class ThreadLocal {
public Object get();
public void set(Object newValue);
public Object initialValue();
}
|
get()
訪問器檢索變量的當前線程的值; set()
訪問器修改當前線程的值。 initialValue()
方法是可選的,如果線程未使用過某個變量,那么您可以用這個方法來設置這個變量的初始值;它允許延遲初始化。用一個示例實現來說明 ThreadLocal 的工作方式是最好的方法。清單 2 顯示了 ThreadLocal
的一個實現方式。它不是一個特別好的實現(雖然它與最初實現非常相似),所以很可能性能不佳,但它清楚地說明了 ThreadLocal 的工作方式。
清單 2. ThreadLocal 的糟糕實現
public class ThreadLocal {
private Map values = Collections.synchronizedMap(new HashMap());
public Object get() {
Thread curThread = Thread.currentThread();
Object o = values.get(curThread);
if (o == null && !values.containsKey(curThread)) {
o = initialValue();
values.put(curThread, o);
}
return o;
}
public void set(Object newValue) {
values.put(Thread.currentThread(), newValue);
}
public Object initialValue() {
return null;
}
}
|
這個實現的性能不會很好,因為每個 get()
和 set()
操作都需要 values
映射表上的同步,而且如果多個線程同時訪問同一個 ThreadLocal
,那么將發生爭用。此外,這個實現也是不切實際的,因為用 Thread
對象做 values
映射表中的關鍵字將導致無法在線程退出后對 Thread
進行垃圾回收,而且也無法對死線程的 ThreadLocal
的特定于線程的值進行垃圾回收。
用 ThreadLocal 實現每線程 Singleton
線程局部變量常被用來描繪有狀態“單子”(Singleton) 或線程安全的共享對象,或者是通過把不安全的整個變量封裝進 ThreadLocal
,或者是通過把對象的特定于線程的狀態封裝進 ThreadLocal
。例如,在與數據庫有緊密聯系的應用程序中,程序的很多方法可能都需要訪問數據庫。在系統的每個方法中都包含一個 Connection
作為參數是不方便的 — 用“單子”來訪問連接可能是一個雖然更粗糙,但卻方便得多的技術。然而,多個線程不能安全地共享一個 JDBC Connection
。如清單 3 所示,通過使用“單子”中的 ThreadLocal
,我們就能讓我們的程序中的任何類容易地獲取每線程 Connection
的一個引用。這樣,我們可以認為 ThreadLocal
允許我們創建 每線程單子。
清單 3. 把一個 JDBC 連接存儲到一個每線程 Singleton 中
public class ConnectionDispenser {
private static class ThreadLocalConnection extends ThreadLocal {
public Object initialValue() {
return DriverManager.getConnection(ConfigurationSingleton.getDbUrl());
}
}
private ThreadLocalConnection conn = new ThreadLocalConnection();
public static Connection getConnection() {
return (Connection) conn.get();
}
}
|
任何創建的花費比使用的花費相對昂貴些的有狀態或非線程安全的對象,例如 JDBC Connection
或正則表達式匹配器,都是可以使用每線程單子(singleton)技術的好地方。當然,在類似這樣的地方,您可以使用其它技術,例如用池,來安全地管理共享訪問。然而,從可伸縮性角度看,即使是用池也存在一些潛在缺陷。因為池實現必須使用同步,以維護池數據結構的完整性,如果所有線程使用同一個池,那么在有很多線程頻繁地對池進行訪問的系統中,程序性能將因爭用而降低。
用 ThreadLocal 簡化調試日志紀錄
其它適合使用 ThreadLocal
但用池卻不能成為很好的替代技術的應用程序包括存儲或累積每線程上下文信息以備稍后檢索之用這樣的應用程序。例如,假設您想創建一個用于管理多線程應用程序調試信息的工具。您可以用如清單 4 所示的 DebugLogger
類作為線程局部容器來累積調試信息。在一個工作單元的開頭,您清空容器,而當一個錯誤出現時,您查詢該容器以檢索這個工作單元迄今為止生成的所有調試信息。
清單 4. 用 ThreadLocal 管理每線程調試日志
public class DebugLogger {
private static class ThreadLocalList extends ThreadLocal {
public Object initialValue() {
return new ArrayList();
}
public List getList() {
return (List) super.get();
}
}
private ThreadLocalList list = new ThreadLocalList();
private static String[] stringArray = new String[0];
public void clear() {
list.getList().clear();
}
public void put(String text) {
list.getList().add(text);
}
public String[] get() {
return list.getList().toArray(stringArray);
}
}
|
在您的代碼中,您可以調用 DebugLogger.put()
來保存您的程序正在做什么的信息,而且,稍后如果有必要(例如發生了一個錯誤),您能夠容易地檢索與某個特定線程相關的調試信息。 與簡單地把所有信息轉儲到一個日志文件,然后努力找出哪個日志記錄來自哪個線程(還要擔心線程爭用日志紀錄對象)相比,這種技術簡便得多,也有效得多。
ThreadLocal
在基于 servlet 的應用程序或工作單元是一個整體請求的任何多線程應用程序服務器中也是很有用的,因為在處理請求的整個過程中將要用到單個線程。您可以通過前面講述的每線程單子技術用 ThreadLocal
變量來存儲各種每請求(per-request)上下文信息。
ThreadLocal 的線程安全性稍差的堂兄弟,InheritableThreadLocal
ThreadLocal 類有一個親戚,InheritableThreadLocal,它以相似的方式工作,但適用于種類完全不同的應用程序。創建一個線程時如果保存了所有 InheritableThreadLocal
對象的值,那么這些值也將自動傳遞給子線程。如果一個子線程調用 InheritableThreadLocal
的 get()
,那么它將與它的父線程看到同一個對象。為保護線程安全性,您應該只對不可變對象(一旦創建,其狀態就永遠不會被改變的對象)使用 InheritableThreadLocal
,因為對象被多個線程共享。 InheritableThreadLocal
很合適用于把數據從父線程傳到子線程,例如用戶標識(user id)或事務標識(transaction id),但不能是有狀態對象,例如 JDBC Connection
。
ThreadLocal 的性能
雖然線程局部變量早已赫赫有名并被包括 Posix pthreads
規范在內的很多線程框架支持,但最初的 Java 線程設計中卻省略了它,只是在 Java 平臺的版本 1.2 中才添加上去。在很多方面, ThreadLocal
仍在發展之中;在版本 1.3 中它被重寫,版本 1.4 中又重寫了一次,兩次都專門是為了性能問題。
在 JDK 1.2 中, ThreadLocal
的實現方式與清單 2 中的方式非常相似,除了用同步 WeakHashMap
代替 HashMap
來存儲 values 之外。(以一些額外的性能開銷為代價,使用 WeakHashMap 解決了無法對 Thread 對象進行垃圾回收的問題。)不用說, ThreadLocal
的性能是相當差的。
Java 平臺版本 1.3 提供的 ThreadLocal
版本已經盡量更好了;它不使用任何同步,從而不存在可伸縮性問題,而且它也不使用弱引用。相反地,人們通過給 Thread
添加一個實例變量(該變量用于保存當前線程的從線程局部變量到它的值的映射的 HashMap
)來修改 Thread
類以支持 ThreadLocal
。因為檢索或設置一個線程局部變量的過程不涉及對可能被另一個線程讀寫的數據的讀寫操作,所以您可以不用任何同步就實現 ThreadLocal.get()
和 set()
。而且,因為每線程值的引用被存儲在自已的 Thread
對象中,所以當對 Thread
進行垃圾回收時,也能對該 Thread
的每線程值進行垃圾回收。
不幸的是,即使有了這些改進,Java 1.3 中的 ThreadLocal
的性能仍然出奇地慢。據我的粗略測量,在雙處理器 Linux 系統上的 Sun 1.3 JDK 中進行 ThreadLocal.get()
操作,所耗費的時間大約是無爭用同步的兩倍。性能這么差的原因是 Thread.currentThread()
方法的花費非常大,占了 ThreadLocal.get()
運行時間的三分之二還多。雖然有這些缺點,JDK 1.3 ThreadLocal.get()
仍然比爭用同步快得多,所以如果在任何存在嚴重爭用的地方(可能是有非常多的線程,或者同步塊被頻繁地執行,或者同步塊很大), ThreadLocal
可能仍然要高效得多。
在 Java 平臺的最新版本,即版本 1.4b2 中, ThreadLocal
和 Thread.currentThread()
的性能都有了很大提高。有了這些提高, ThreadLocal
應該比其它技術,如用池,更快。由于它比其它技術更簡單,也更不易出錯,人們最終將發現它是避免線程間出現不希望的交互的有效途徑。
ThreadLocal 的好處
ThreadLocal
能帶來很多好處。它常常是把有狀態類描繪成線程安全的,或者封裝非線程安全類以使它們能夠在多線程環境中安全地使用的最容易的方式。使用 ThreadLocal
使我們可以繞過為實現線程安全而對何時需要同步進行判斷的復雜過程,而且因為它不需要任何同步,所以也改善了可伸縮性。除簡單之外,用 ThreadLocal
存儲每線程單子或每線程上下文信息在歸檔方面還有一個頗有價值好處 — 通過使用 ThreadLocal
,存儲在 ThreadLocal
中的對象都是 不被線程共享的是清晰的,從而簡化了判斷一個類是否線程安全的工作。
我希望您從這個系列中得到了樂趣,也學到了知識,我也鼓勵您到我的 討論論壇中來深入研究多線程問題。
posted @
2007-04-09 20:52 阿成 閱讀(2437) |
評論 (1) |
編輯 收藏
Servlet是在多線程環境下的。即可能有多個請求發給一個servelt實例,每個請求是一個線程。
struts下的action也類似,同樣在多線程環境下。可以參考struts user guide: http://struts.apache.org/struts-action/userGuide/building_controller.html 中的Action Class Design Guidelines一節: Write code for a multi-threaded environment - Our controller servlet creates only one instance of your Action class, and uses this one instance to service all requests. Thus, you need to write thread-safe Action classes. Follow the same guidelines you would use to write thread-safe Servlets.
譯:為多線程環境編寫代碼。我們的controller servlet指揮創建你的Action 類的一個實例,用此實例來服務所有的請求。因此,你必須編寫線程安全的Action類。遵循與寫線程安全的servlet同樣的方針。
1.什么是線程安全的代碼
在多線程環境下能正確執行的代碼就是線程安全的。
安全的意思是能正確執行,否則后果是程序執行錯誤,可能出現各種異常情況。
2.如何編寫線程安全的代碼
很多書籍里都詳細講解了如何這方面的問題,他們主要講解的是如何同步線程對共享資源的使用的問題。主要是對synchronized關鍵字的各種用法,以及鎖的概念。
Java1.5中也提供了如讀寫鎖這類的工具類。這些都需要較高的技巧,而且相對難于調試。
但是,線程同步是不得以的方法,是比較復雜的,而且會帶來性能的損失。等效的代碼中,不需要同步在編寫容易度和性能上會更好些。
我這里強調的是什么代碼是始終為線程安全的、是不需要同步的。如下:
1)常量始終是線程安全的,因為只存在讀操作。
2)對構造器的訪問(new 操作)是線程安全的,因為每次都新建一個實例,不會訪問共享的資源。
3)最重要的是:局部變量是線程安全的。因為每執行一個方法,都會在獨立的空間創建局部變量,它不是共享的資源。局部變量包括方法的參數變量。
struts user guide里有:
Only Use Local Variables - The most important principle that aids in thread-safe coding is to use only local variables, not instance variables , in your Action class.
譯:只使用用局部變量。--編寫線程安全的代碼最重要的原則就是,在Action類中只使用局部變量,不使用實例變量。
總結:
在Java的Web服務器環境下開發,要注意線程安全的問題。最簡單的實現方式就是在Servlet和Struts Action里不要使用類變量、實例變量,但可以使用類常量和實例常量。
如果有這些變量,可以將它們轉換為方法的參數傳入,以消除它們。
注意一個容易混淆的地方:被Servlet或Action調用的類中(如值對象、領域模型類)中是否可以安全的使用實例變量?如果你在每次方法調用時
新建一個對象,再調用它們的方法,則不存在同步問題---因為它們不是多個線程共享的資源,只有共享的資源才需要同步---而Servlet和Action的實例對于多個線程是共享的。
換句話說,Servlet和Action的實例會被多個線程同時調用,而過了這一層,如果在你自己的代碼中沒有另外啟動線程,且每次調用后續業務對象時都是先新建一個實例再調用,則都是線程安全的。
posted @
2007-04-09 20:31 阿成 閱讀(496) |
評論 (0) |
編輯 收藏
java.lang.Object
|
+--javax.servlet.GenericServlet
|
+--javax.servlet.http.HttpServlet
|
+--org.apache.struts.action.ActionServlet
Struts提供了一個缺省版本的ActionServlet類,你可以繼承這個類,覆蓋其中的一些方法來達到你的特殊處理的需要。ActionServlet繼承與javax.servlet.http.HttpServlet,所以在本質上它和一個普通的servlet沒有區別,你完全可以把它當做一個servlet來看待,只是在其中完成的功能不同罷了。ActionServlet主要完成如下功能:
將一個來自客戶端的URI映射到一個相應的Action類
- 如果是這個Action類是第一次被調用,那么實例化一個并放入緩存
- 如果在配置文件(struts-config.xml)中指定了相應的ActionForm,那么從Request中抓取數據填充FormBean
- 調用這個Action類的perform()方法,傳入ActionMapping的一個引用,對應的ActionForm、以及由容器傳給ActionServlet的HttpServletRequest、HttpServletResponse對象。
確省版本的ActionServlet會從配置文件web.xml中讀取如下初始化參數:
- application
應用使用的資源包(resources bundle)的基類
- factory
用于創建應用的MessageResources對象的MessageResourcesFactory的類名。確省是org.apache.struts.util.PropertyMessageResourcesFactory。
- config
Struts的配置文件,確省是/WEB-INF/struts-config.xml。注意這兒是與應用Context關聯的相對路徑。
- content
定義了確省的內容類型和編碼格式,它會被自動地被設置到每個response中,如果JSP/Servlet中沒有明確的設置。確省是text/html。
- debug
調試信息的級別。默認為0,比當前級別高的調試信息會被log到日志文件中。
- detail
與debug的作用類似,只是這個detail是initMapping()時專用的。調試信息會被打印到System.out,而不是日志文件。
- formBean
ActionFormBean的實現類,確省為org.apache.struts.action.ActionFormBean
- forward
應用中使用的ActionForward類,確省是org.apache.struts.action.ActionForward。
- locale
指定了確省使用的Locale對象。設為true,當得到一個session時,會自動在session中存儲一個以Action.LOCALE_KEY標示的Locale對象,如果session中還沒有與Action.LOCALE_KEY綁定的Locale對象。
- mapping
應用中使用的ActionMapping類,確省是org.apache.struts.action.ActionMapping。
- multipartClass
文件上傳使用的MutipartRequestHandler的實現類。確省為org.apache.struts.upload.DiskMultipartRequestHandler
- nocache
如果設為true,那么ActionServlet會自動在每個到客戶端的響應中添加nocache的HTML頭,這樣客戶端就不會對應用中的頁面進行緩存。確省為false
- null
如果設置為true,那么應用在得到一個未定義的message資源時,會返回null,而不是返回一個錯誤信息。確省是true。
- maxFileSize
文件上傳的大小上限,確省為250M
- bufferSize
文件上傳時的緩沖區的大小,確省為4M
- tempDir
設置用于上傳時的臨時目錄。工作目錄會作為一個Servlet環境(Context)的屬性提供。
- validate
Are we using the new configuration file format?確省為true。
- validating
在解析配置XML文件是是否進行有效性的驗證。確省為true
ActionServlet中應用了命令設計模式。
一個Servlet在由容器生成時,首先會調用init()方法進行初始化,在接到一個HTTP請求時,調用相應的方法進行處理;比如GET請求調用doGet()方法,POST請求調用doPost()方法。所以首先看看ActionServlet的init()方法,你就會很清楚為什么ActionServlet可以完成這些功能了。
init()
在它的init()方法中,ActionServlet依次調用如下protected的方法完成初始化:
- initActions() - 大家可能還曾有這個疑問:Struts為什么可以找到一個請求URI對應的action類呢?答案就在這兒,ActionServlet有一個actions屬性,類型為org.apache.struts.util.FastHashMap,用于存儲以類的全名為key的已實例化的Action類。在init()時首先調用的就是initActions()方法,在這個方法中只是簡單的清除map中的所有的名值對,
-
- synchronized (actions) {
- actions.setFast(false);
- actions.clear();
- actions.setFast(true);
- }
首先把actions設為slow模式,這時對FastHashMap的訪問是線程同步的,然后清除actions中的所有的已存在的名/值對,最后再把actions的模式設為fast。由于FastHashMap是struts在java.util.HashMap的基礎上的一個擴展類,是為了適應多線程、并且對HashMap的訪問大部分是只讀的特殊環境的需要。大家知道java.util.HashMap是非線程安全的,所以HashMap一般適用于單線程環境下。org.apache.struts.FastHashMap就是繼承于java.util.HashMap,在其中添加多線程的支持產生的。在fast模式下的工作方式是這樣的:讀取是非線程同步的;寫入時首先克隆當前map,然后在這個克隆上做寫入操做,完成后用這個修改后的克隆版本替換原來的map。那么在什么時候會把Actions類添加到這個map中呢?我們已經提到了struts是動態的生成Action類的實例的,在每次ActionServlet接收到一個GET或POST的HTTP請求時,會在這個map中查找對應的Action類的實例,如果不存在,那么就實例化一個,并放入map中。可見這個actions屬性起到了對Action類實例的緩存的作用。
- initInternal() - 初始化ActionServlet內部使用的資源包MessageResources,使用MessageResources.getMessageResources(internalName)得到 internalName為"org.apache.struts.action.ActionResources"對應的ActionResources.properties文件。這個資源包主要用于ActionServlet處理過程中的用到的提示信息,這兒不展開討論。
- initDebug() - 從web.xml中讀取本應用的debug級別參數getServletConfig().getInitParameter("debug"),然后賦給debug屬性。
- initApplication()- 初始化應用資源包,并放置入ServletContext中。
-
- String factory =getServletConfig().getInitParameter(“factory”);
- String oldFacory = MessageResourcesFactory.getFactoryClass();
- if (factory !=null)
- MessageResourcesFactory.setFactoryClass(factory);
- String value = getServletConfig().getInitParameter("application");
- MessageResourcesFactory factoryObject =
- MessageResourcesFactory.createFactory();
- application = factoryObject.createResources(value);
- MessageResourcesFactory.setFactory(oldFactory);
- getServletContext().setAttribute(Action.MESSAGES_KEY, application);
說明:文中引用的代碼片斷可能會省略了一些例外檢查等非主線的內容,敬請注意。
首先從配置文件中讀取factory參數,如果這個參數不為空,那么就在MessageResourcesFactory中使用這個指定的Factory類;否則,使用默認的工廠類org.apche.struts.util.PropertyMessageResourceFactory。然后調用MessageResourcesFactory的靜態createFactory()方法,生成一個具體的MessageResourceFactory對象(注意:MessageResourcesFactory是抽象類)。這樣就可以調用這個具體的MessageResourceFactory的createResource()方法得到配置文件(web.xml)中定義的資源文件了。
上面的application對象類型為MessageResources。在web.xml中在配置ActionServlet時可以指定一個特定的工廠類。不能直接MessageResourcesFactory的createResources()方法,因為這個方法是abstract的。創建factoryObject的過程如下:
-
- MessageResourceFactory factoryObject=
- MessageResourcesFactory.createFactory();
- application = factoryObject.createResources(value);
<li>initMapping() - 為應用初始化mapping信息ActionServlet有一個protected的屬性:mapping,封裝了一個ActionMapping的對象集合,以便于管理、查找ActionMapping。mappings是org.apache.struts.action.ActionMappings類的實例。主要有兩個方法:addMapping(ActionMapping mapping)和findMapping(String path)。ActionMapping也是使用上面提到的org.apache.struts.util.FastHashMap類來存儲所有的ActionMapping對象。
-
- mappings.setServlet(this);
- ……
- // Initialize the name of our ActionFormBean implementation class
- value = getServletConfig().getInitParameter("formBean");
- if (value != null)
- formBeanClass = value;
-
- // Initialize the name of our ActionForward implementation class
- value = getServletConfig().getInitParameter("forward");
- if (value != null)
- forwardClass = value;
-
- // Initialize the name of our ActionMapping implementation class
- value = getServletConfig().getInitParameter("mapping");
- if (value != null)
- mappingClass = value;
在initMapping()中,首先鏈接mappings對象到本servlet實例。其實這句話的作用很簡單,在ActionMappings中會有一個ActionServlet類型的屬性,這個屬性就界定了這個ActionMappings對象所屬的ActionServlet。Struts的實現比較靈活,其中的ActionFormBean、ActionForward、ActionMapping類你完全可以使用自己實現的子類,來定制Struts的工作方式。上面的代碼就從配置文件(web.xml)中讀取formBean、forward、mapping參數,這些參數就是你定制的ActionFormBean、ActionForward、ActionMapping類名。
-
- // Initialize the context-relative path to our configuration resources
- value = getServletConfig().getInitParameter("config");
- if (value != null)
- config = value;
- // Acquire an input stream to our configuration resource
- InputStream input = getServletContext().getResourceAsStream(config);
- Digester digester = null;
- digester = initDigester(detail);
- try {
- formBeans.setFast(false);
- forwards.setFast(false);
- mappings.setFast(false);
- digester.parse(input);
- mappings.setFast(true);
- forwards.setFast(true);
- formBeans.setFast(true);
- } catch (SAXException e) {
- throw new ServletException
- (internal.getMessage("configParse", config), e);
- } finally {
- input.close();
- }
從web.xml讀取Struts的配置文件的位置。使用org.apache.struts.digester.Digester解析config參數標示的配置文件,通常為“/WEB-INF/struts-config.xml”,解析出所有的data-source、form-bean、action-mapping、forward。從上面的程序片斷看到,Digester僅僅調用了一個parse()方法,那么,Digester是怎樣把解析struts-config.xml文件并把解析的結果form-bean等信息存儲到屬性變量formBeans等中的呢?你可以注意到在調用digester.parse(InputStream)之前,首先調用了initDigester()方法:
-
- Digester digester = new Digester();
- digester.push(this);
- digester.addObjectCreate("struts-config/action-mappings/action",
- mappingClass, "className");
- digester.addSetProperties("struts-config/action-mappings/action");
- digester.addSetNext("struts-config/action-mappings/action",
- "addMapping",
- "org.apache.struts.action.ActionMapping");
-
- digester.addSetProperty
- ("struts-config/action-mappings/action/set-property",
- "property", "value");
在這個方法中首先生成一個Digester對象,然后設置解析的規則和回調,如果你對XML、SAX不是很熟,這兒不必糾纏太深。要注意的是addSetNext()方法,設置了每一個要解析元素的Set Next回調方法,而這個方法就是由digester解析器的父提供的。上面的片斷中的“addMapping”就是ActionServlet本身定義的一個方法,將由Digester回調。Digester就是籍此把解析出的每一個FormBean、ActionForward、ActionMapping等存儲到屬性變量formBeans、forwards、mappings等中的。
- initUpload() - 初始化有關Upload的一些參數,比如:bufferSize、tempDir。
- initDataSource() -取出在initMapping()中從配置文件中讀取的每一個DataSource,設置LogWriter,如果為GenericDataSource的實例,則打開數據源。然后,把每個dataSource放入Context中。
dataSource.setLogWriter(scw);
((GenericDataSource)dataSource).open();
getServletContext().setAttribute(key,dataSource);
- initOther() - 設置其它尚未初始化的的參數(content、locale、nocache),并發布formBeans、forwards、mappings到Context:
getServletContext().setAttribute(Action.FORM_BEANS_KEY, formBeans);
getServletContext().setAttribute(Action.FORWARDS_KEY, forwards);
getServletContext().setAttribute(Action.MAPPINGS_KEY, mappings);
- initServlet() - 初始化Controller Servlet的Servlet Mapping。這兒也使用了Digester工具,掃描web.xml所有的<web-app/servlet-mapping>,尋找servlet-name與當前Servlet相同的mapping,置入Context。代碼如下;
-
- Digester digester = new Digester();
- digester.push(this);
- digester.setDebug(debug);
- digester.setValidating(validating);
- digester.addCallMethod(“web-appservlet-mapping”,“addServletMapping”, 2);
- digester.addCallParm(“web-appservlet-mappingservlet-name”, 0);
- digester.addCallParm(“web-appservlet-mappingurl-pattern”, 1);
- InputStream is = getServletContext().getResourceAsStream(“/WEB-INFweb.xml”);
- digester.parse(is);
- getServletContext().setAttribute(Action.SERVLET_KEY,servletMapping);
posted @
2007-04-06 09:48 阿成 閱讀(464) |
評論 (0) |
編輯 收藏
關鍵字: ? 轉貼????
CSS全稱Cascading Style Sheet。層疊式樣式表。從三年前就開始使用CSS了,但一直以來都小看了它。CSS的出現其實是一次革命,它試圖將網站的內容與表現分開。 一、CSS的四種實現方式: 1.內嵌式:
2.外鏈式:
3.導入式
3.屬性式: 二.CSS的定義: 選擇對象{屬性1:值1;屬性2:值2;屬性3:值3;屬性n:值n……} 如: td{font-size:12px;color:#FFFF00} .myname{font-size:12px;color:#FFFF00} a:hover{font-size:12px;color:#FFFF00;text-decoration: underline;} 三.四種選擇對象 1.HTML selector (TagName) 2.class selector (.NAME) 3.ID selector (#IDname) 4.特殊對象 (a:hover a:link a:visited a:active) 1.HTML selector HTML selector就是HTML的置標符,如:DIV、TD、H1。HTML selector的作用范圍是應用了該樣式的所有頁面中的所有該置標符。 例: td { color: #FF0000; } --> 注意:在中沒有應用什么,其中文字自動變紅色。 2.class selector 定義class selector需要往其名稱其加一個點“.”。如“.classname”。class selector的作用范圍是所有包含“class="classname"”的置標符。 例: .fontRed { color: #FF0000; } --> 注意:在第二個中沒有“class="fontRed"”,所以文字沒有變紅色。 3.ID selector 定義ID selector需要往其名稱其加一個點“#”。如“#IDname”。ID selector的作用范圍是所有包含“ID="classname"”的置標符。 例:
#fontRed { color: #FF0000; } --> 注意:在第二個中沒有“ID="fontRed"”,所以文字沒有變紅色。 4.特殊對象 特殊對象包括四種,是針對鏈接對象設置的: a:hover 鼠標移上時的超鏈接 a:link 常規,非訪問超鏈接 a:visited 訪問過的超鏈接 a:active 鼠標點擊時的超鏈接 特殊對象的作用范圍是所有置標符(這句話有待商榷,因為下面很快就有一種方法可以把“所有”兩個字推翻)。 例: a:hover { color: #0000FF; text-decoration: underline; } --> 注意下面,很有用!!! a.classname:hover a#IDname:hover 這兩種寫法,是分別配合.classname與#IDname使用的。它的作用范圍變成了所有包含“class="classname"”或“ID="IDname"”的置標符。這種寫法,可以幫助你在同一頁面中實現多種a:hover效果,可以看一下藝網的主頁上導航欄文字與普通文章標題在鼠標時的區別。 四.應用: 1.置標符 自動應用 2.特制類 class="NAME" 3.ID ID="IDname" 4.特殊對象 自動應用 五.CSS屬性 CSS的屬性有很多,像上文中用到最多的color,表示文字的顏色。background-color表示背景色。這個是最主要的,但是因為沒有什么難度,參考一下相關手冊就可以了。
注明兩點 第一點:css的方式現在一般都采用外部連接,這個用起來方便,編譯起來也方便 第二點:我用的是frontpage2003,很多css的參數都會自動提示,似乎好像以前我沒有用到過~~dw有的
CSS 標簽屬性/屬性參考 這里列出了目前支持的樣式表(CSS)標簽屬性。標有星號(*)的標簽屬性可于 Microsoft? Internet Explorer 5 中使用。標有兩個星號(**)的標簽屬性可于 Internet Explorer 5.5 中使用。帶有兩個加號(++)的標簽屬性可于 Internet Explorer 6 中使用。如果某個標簽屬性或屬性已經提交給萬維網協會(W3C)但尚未作為標準發布,則標有“已提交”。若某個標簽屬性或屬性既未提交給 W3C 也不是標準,將標有“擴展”。
CSS 標簽屬性/屬性
行為屬性 behavior
字體和文本屬性 direction*
direction font font-family font-size font-style font-variant font-weight ime-mode layout-grid layout-grid-char layout-grid-line layout-grid-mode layout-grid-type letter-spacing line-break line-height min-height ++ ruby-align ruby-overhang ruby-position text-align text-autospace text-decoration text-indent text-justify text-kashida-space text-overflow ++ text-transform text-underline-position unicode-bidi vertical-align white-space** word-break word-spacing ++(于 Macintosh 版本 4.0 中可用) word-wrap writing-mode
顏色和背景屬性 background-attachment background-color background-image background-position background-position-x background-position-y background-repeat color
版面屬性 border border-bottom border-bottom-color border-bottom-style border-bottom-width border-collapse* border-color border-left border-left-color border-left-style border-left-width border-right border-right-color border-right-style border-right-width border-style border-top border-top-color border-top-style border-top-width border-width clear float layout-flow margin margin-bottom margin-left margin-right margin-top padding padding-bottom padding-left padding-right padding-top scrollbar-3dlight-color scrollbar-arrow-color scrollbar-base-color scrollbar-darkshadow-color scrollbar-face-color scrollbar-highlight-color scrollbar-shadow-color table-layout* zoom
分類屬性 display
list-style list-style-image list-style-position list-style-type
定位屬性 bottom*
clip height left overflow overflow-x overflow-y position right* top visibility width z-index
打印屬性 page**
pageBreakAfter pageBreakBefore
濾鏡屬性 filter
偽類和其它屬性 :active
@charset cursor :first-letter** :first-line** @font-face :hover @import !important :link @media* @page** :visited 有關表格邊框的css語法整理
我們知道Dreamweaver在表格制作方面做得非常出色,但是在某些時候還是必須結合css才能達到一些特定效果,下面我們先把有關表格邊框的css語法整理出來,然后另外介紹怎樣用css美化表格的邊框。
有關表格邊框的css語法
具體內容包括:上邊框寬度、右邊框寬度、下邊框寬度、左邊框寬度、邊框寬度、邊框顏色、邊框樣式、上邊框、下邊框、左邊框、右邊框、邊框、寬度、高度、有關標簽等。
1.上邊框寬度
語法: border-top-width: <值>
允許值: thin | medium | thick | <長度>
初始值: medium
適用于: 所有對象
向下兼容: 否
上邊框寬度屬性用于指定一個元素上邊框的寬度。值可以是三個關鍵字其中的一個,都不受字體大小或長度的影響,可以用于實現成比例的寬度。不允許使用負值。也可以用在上邊框、邊框的寬度或邊框的屬性略寫。
2.右邊框寬度
語法: border-right-width: <值>
允許值: thin | medium | thick | <長度>
初始值: medium
適用于: 所有對象
向下兼容: 否
右邊框寬度屬性用于指定元素的右邊框的寬度。值可以是三個關鍵字其中的一個,都不受字體大小或長度的影響,可以用于實現成比例的寬度。不允許使用負值。也可以用在右邊框、邊框的寬度或邊框的屬性略寫。
3.下邊框寬度
語法: border-bottom-width: <值>
允許值: thin | medium | thick | <長度>
初始值: medium
適用于: 所有對象
向下兼容: 否
下邊框寬度屬性用于指定元素的下邊框的寬度。值可以是三個關鍵字其中的一個,都不受字體大小或長度的影響,可以用于實現成比例的寬度。不允許使用負值。也可以用在下邊框、邊框的寬度或邊框的屬性略寫。
4.左邊框寬度
語法: border-left-width: <值>
允許值: thin | medium | thick | <長度>
初始值: medium
適用于: 所有對象
向下兼容: 否
左邊框寬度屬性用于指定元素的左邊框的寬度。值可以是三個關鍵字其中的一個,都不受字體大小或長度的影響,可以用于實現成比例的寬度。不允許使用負值。也可以用在左邊框、邊框的寬度或邊框的屬性略寫。
5.邊框寬度
語法: border-width: <值>
允許值: [ thin | medium | thick | <長度> ]{1,4}
初始值: 未定義
適用于: 所有對象
向下兼容: 否
邊框寬度屬性用一到四個值來設置元素的邊界,值是一個關鍵字或長度。不允許使用負值長度。如果四個值都給出了,它們分別應用于上、右、下和左邊框的式樣。如果給出一個值,它將被運用到各邊上。如果兩個或三個值給出了,省略了的值與對邊相等。 這個屬性是上邊框寬度、右邊框寬度、下邊框寬度和左邊框寬度屬性的略寫。也可以使用略寫的邊框屬性。
6.邊框顏色
語法: border-color: <值>
允許值: <顏色>{1,4}
初始值: 顏色屬性的值
適用于: 所有對象
向下兼容: 否
邊框顏色屬性設置一個元素的邊框顏色。可以使用一到四個關鍵字。如果四個值都給出了,它們分別應用于上、右、下和左邊框的式樣。如果給出一個值,它將被運用到各邊上。如果兩個或三個值給出了,省略了的值與對邊相等。也可以使用略寫的邊框屬性。
7.邊框樣式
語法: border-style: <值>
允許值: [ none | dotted | dashed | solid | double | groove | ridge | inset | outset ]{1,4}
初始值: none
適用于: 所有對象
向下兼容: 否
邊框樣式屬性用于設置一個元素邊框的樣式。這個屬性必須用于指定可見的邊框。可以使用一到四個關鍵字。如果四個值都給出了,它們分別應用于上、右、下和左邊框的式樣。如果給出一個值,它將被運用到各邊上。如果兩個或三個值給出了,省略了的值與對邊相等。也可以使用略寫的邊框屬性。
none:無樣式; dotted:點線; dashed:虛線; solid:實線; double:雙線; groove:槽線; ridge:脊線; inset:內凹; outset:外凸。 8.上邊框
語法: border-top: <值>
允許值: <上邊框寬度> || <邊框式樣> || <顏色>
初始值: 未定義
適用于: 所有對象
向下兼容: 否
上邊框屬性是一個用于設置一個元素上邊框的寬度、式樣和顏色的略寫。注意只能給出一個邊框式樣。也可以使用略寫的邊框屬性。
9.右邊框
語法: border-right: <值>
允許值: <右邊框寬度> || <邊框式樣> || <顏色>
初始值: 未定義
適用于: 所有對象
向下兼容: 否
右邊框屬性是一個用于設置一個元素右邊框的寬度、式樣、和顏色的略寫。注意只能給出一個邊框式樣。也可以使用略寫的邊框屬性。
10.下邊框
語法: border-bottom: <值>
允許值: <下邊框寬度> || <邊框式樣> || <顏色>
初始值: 未定義
適用于: 所有對象
向下兼容: 否
下邊框屬性是一個用于設置一個元素的下邊框的寬度、式樣和顏色的略寫。注意只能給出一個邊框式樣。也可以使用略寫的邊框屬性。
11.左邊框
語法: border-left: <值>
允許值: <左邊框寬度> || <邊框式樣> || <顏色>
初始值: 未定義
適用于: 所有對象
向下兼容: 否
左邊框屬性是一個用于設置一個元素左邊框的寬度、式樣和顏色的略寫。注意只能給出一個邊框式樣。也可以使用略寫的邊框屬性。
12.邊框
語法: border: <值>
允許值: <邊框寬度> || <邊框式樣> || <顏色>
初始值: 未定義
適用于: 所有對象
向下兼容: 否
邊框屬性是一個用于設置一個元素邊框的寬度、式樣和顏色的略寫。
邊框聲明的例子包括:
H2 { border: groove 3em } A:link { border: solid blue } A:visited { border: thin dotted #800080 } A:active { border: thick double red }
邊框屬性只能設置四種邊框;只能給出一組邊框的寬度和式樣。為了給出一個元素的四種邊框的不同的值,網頁制作者必須用一個或更多的屬性,如:上邊框、右邊框、下邊框、左邊框、邊框顏色、邊框寬度、邊框式樣、上邊框寬度、右邊框寬度、下邊框寬度或左邊框寬度。
13.寬度
語法: width: <值>
允許值: <長度> | <百分比> | auto
初始值: auto
適用于: 塊級和替換元素
向下兼容: 否
寬度屬性的初始值為“auto”,即為該元素的原有寬度(有就是元素自己的寬度)。百分比參考上級元素的寬度。不允許使用負的長度值。
14.高度
語法: height: <值>
允許值: <長度> | auto
初始值: auto
適用于: 塊級和替換元素
向下兼容: 否
高度屬性的初始值為“auto”,即為該元素的原有高度(有就是元素自己的高度,)。百分比參考上級元素的寬度。不允許使用負的長度值。
15.有關標簽
table:表格標簽,對整個表格樣式的定義要放在table中; td:單元格標簽,對單元格樣式的定義要放在td中。
css濾鏡
隨著網頁設計技術的發展,人們已經不滿足于原有的一些HTML標記,而是希望能夠為頁面添加一些多媒體屬性,例如濾鏡的和漸變的效果。CSS技術的飛快發展使這些需求成為了現實。從現在開始我要為大家介紹一個新的CSS擴展部分:CSS濾鏡屬性(Filter Properties)。使用這種技術可以把可視化的濾鏡和轉換效果添加到一個標準的HTML元素上,例如圖片、文本容器、以及其他一些對象。對于濾鏡和漸變效果,前者是基礎,因為后者就是濾鏡效果的不斷變化和演示更替。當濾鏡和漸變效果結合到一個基本的SCRIPT小程序中后,網頁設計者就可以擁有一個建立動態交互文檔的強大工具。也就是CSS FILTER+ SCRIPT, 這就說明想要建立動態的文檔還要一些SCRIPT (腳本語言)的基礎。 可視化濾鏡屬性只能用在HTML控件元素上。所謂的HTML空間元素就是它們在頁面上定義了一個矩形空間,瀏覽器的窗口可以顯示這些空間。下面列出了HTML合法的控件和它們的說明。
備注:可惜只有IE4.0以上支持,如果是別的瀏覽器,那就.......
元素 說明 BODY 網頁文檔的主體元素,所有的可見范圍都在<BODY>元素內 BUTTON 表單域的按鈕,可以有“發送(submit)”、“重置(reset)”等形式 DIV 定義了網頁上的一個區域,這個區域的高度、寬度或者絕對位置都是以知的 IMG 圖片元素,通過指定“src"屬性來指定圖片的來源 INPUT 輸入表單域 MARQUEE 移動字幕效果 SPAN 定義了網頁上的一個區域,這個區域的高度、寬度或者絕對位置都是以知的 TABLE 表格 TD 表格數據單元格 TEXTAREA 文本區域 TFOOT 多行輸入文本框 TH 表格標題單元格 THEAD 表格標題 TR 表格行
IE4.0以上支持的濾鏡屬性表
濾鏡效果 描述 Alpha 設置透明度 Blru 建立模糊效果 Chroma 把指定的顏色設置為透明 DropShadow 建立一種偏移的影象輪廓,即投射陰影 FlipH 水平反轉 FlipV 垂直反轉 Glow 為對象的外邊界增加光效 Grayscale 降低圖片的彩色度 Invert 將色彩、飽和度以及亮度值完全反轉建立底片效果 Light 在一個對象上進行燈光投影 Mask 為一個對象建立透明膜 Shadow 建立一個對象的固體輪廓,即陰影效果 Wave 在X軸和Y軸方向利用正弦波紋打亂圖片 Xray 只顯示對象的輪廓
1、Alpha 濾鏡
語法:{FILTER:ALPHA(opacity=opacity,finishopacity=finishopacity,style=style,startx=startx, starty=starty,finishx=finishx,finishy=finishy)}
"Alpha"屬性是把一個目標元素與背景混合。設計者可以指定數值來控制混合的程度。這種“與背景混合”通俗地說就是一個元素的透明度。通過指定坐標,可以指定點、線、面的透明度。他們的參數含義分別如下: “opacity"代表透明度水準。默認的范圍是從0 到 100,他們其實是百分比的形式。也就是說,0代表完全透明,100代表完全不透明。”finishopacity"是一個可選參數,如果想要設置漸變的透明效果,就可以使用他們來指定結束時的透明度。范圍也是0 到 100。“style" 參數指定了透明區域的形狀特征。其中0代表統一形狀、1代表線形、2代表放射狀、3代表長方形。”STARTX“和”STARTY“代表漸變透明效果的開始X和Y坐標。”FINISHX“和”FINISHY“代表漸變透明效果結束X和Y 的坐標。
效果如下:
2、Blur 濾鏡
語法:對于HTML:{ilter:blur(add=add,direction=direction,strength=strength)} 對于Script語言: [oblurfilter=] object.filters.blur 用手指在一幅尚未干透的油畫上迅速劃過時,畫面就會變得模糊。”Blur"就是產生同樣的模糊效果。 “ADD”參數是一個布爾判斷“TRUE(默認)”或者“FALSE”。它指定圖片是否被改變成印象派的模糊效果。模糊效果是按順時針的方向進行的,“DIRECTION”參數用來設置模糊的方向。其中0度代表垂直向上,然后每45度為一個單位。它的默認值是向左的270度。“STRENGTH“值只能使用整數來指定,她代表有多少像素的寬度將受到模糊影響。默認是5個。對于網頁上的字體,如果設置他的模糊”ADD=1“,那么這些字體的效果會非常好看的。如下: filter:blur(add=ture,direction=135,strength=10)
3、FlipH, FlipV 濾鏡
語法:{filter:filph} ,{filter:filpv} 分別是水平反轉和垂直反轉,具體如下:
4、Chroma 濾鏡
語法:{filter:chroma(color=color)} 使用”Chroma"屬性可以設置一個對象中指定的顏色為透明色,參數COLOR即要透明的顏色。下面是蘭色文字,然后用Chroma 濾鏡過濾掉蘭色,就成了下面的樣子。 filter:chroma(color=blue)
滴水檐坊
5、DropShadow 濾鏡
語法:{filter:dropshadow(color=color,offx=ofx,offy=offy,positive=positive)}
“DropShaow"顧名思義就是添加對象的陰影效果。其工作原理是建立一個偏移量,加上較深。"Color"代表投射陰影的顏色,"offx"和"offy"分別是X方向和Y方向陰影的餓偏移量。"Positive"參數是一個布爾值,如果為“TRUE(非0)”,那么就為任何的非透明像素建立可見的投影。如果為“FASLE(0)”,那么就為透明的像素部分建立透明效果
6、Glow 濾鏡
語法:{filter:glow(color=color,strength)} 當對一個對象使用"glow"屬性后,這個對象的邊緣就會產生類似發光的效果。“COLOR”是指定發光的顏色,“STRENGTH”則是強度的表現,可以從1到255之間的任何整數來指定這個力度。 filter:glow(color=red,strength=10) 后的效果
7、Gray ,Invert,Xray 濾鏡
語法:{filter:gray} ,{filter:invert},{filter:xray}
Gray濾鏡是把一張圖片變成灰度圖;Invert濾鏡是把對象的可視化屬性全部翻轉,包括色彩、飽和度、和亮度值;Xray濾鏡是讓對象反映出它的輪廓并把這些輪廓加亮,也就是所謂的“X”光片。
效果如下:
、Light 濾鏡
語法:Filter{light}
這個屬性模擬光源的投射效果。一旦為對象定義了“LIGHT"濾鏡屬性,那么就可以調用它的“方法(Method)"來設置或者改變屬性。“LIGHT"可用的方法有:
AddAmbient 加入包圍的光源 AddCone 加入錐形光源 AddPoint 加入點光源 Changcolor 改變光的顏色 Changstrength 改變光源的強度 Clear 清除所有的光源 MoveLight 移動光源 可以定義光源的虛擬位置,以及通過調整X軸和Y軸的數值來控制光源焦點的位置,還可以調整光源的形式(點光源或者錐形光源)指定光源是否模糊邊界、光源的顏色、亮度等屬性。如果動態的設置光源,可能回產生一些意想不到的效果。后面幾頁會有具體范例。
9、Mask 濾鏡
語法:{filter:mask(color=color)}
使用"MASK"屬性可以為對象建立一個覆蓋于表面的膜,其效果就象戴者有色眼鏡看物體一樣。
10、Shadow 濾鏡
語法:{filter:shadow(color=color,direction=direction)}
利用“Shadow”屬性可以在指定的方向建立物體的投影,COLOR是投影色,DIRECTION是設置投影的方向。其中0度代表垂直向上,然后每45度為一個單位。它的默認值是向左的270度。
filter:shadow(color=red,direction=225) filter:shadow(color=blue,direction=225) filter:shadow(color=gray,direction=225) 效果分別如下:
11、Wave 濾鏡 語法:{filter:wave(add=add,freq=freq,lightstrength=strength,phase=phase,strength=strength)} "wave" 屬性把對象按垂直的波形樣式打亂。默認是“TRUE(非0)”, “ADD”表示是否要把對象按照波形樣式打亂,
“FREQ”是波紋的頻率,也就是指定在對象上一共需要產生多少個完整的波紋,
“LIGHTSTRENGTH”參數可以對于波紋增強光影的效果,范圍0----100,
“PHASE”參數用來設置正弦波的偏移量。
“STRENGTH”代表振幅大小。
|
posted @
2006-10-25 19:11 阿成 閱讀(315) |
評論 (0) |
編輯 收藏
Java虛擬機的深入研究
作者:劉學超
1??Java技術與Java虛擬機
說起Java,人們首先想到的是Java編程語言,然而事實上,Java是一種技術,它由四方面組成: Java編程語言、Java類文件格式、Java虛擬機和Java應用程序接口(Java API)。它們的關系如下圖所示:
圖1??Java四個方面的關系
運行期環境代表著Java平臺,開發人員編寫Java代碼(.java文件),然后將之編譯成字節碼(.class文件)。最后字節碼被裝入內存,一旦字節碼進入虛擬機,它就會被解釋器解釋執行,或者是被即時代碼發生器有選擇的轉換成機器碼執行。從上圖也可以看出Java平臺由Java虛擬機和Java應用程序接口搭建,Java語言則是進入這個平臺的通道,用Java語言編寫并編譯的程序可以運行在這個平臺上。這個平臺的結構如下圖所示:
在Java平臺的結構中, 可以看出,Java虛擬機(JVM) 處在核心的位置,是程序與底層操作系統和硬件無關的關鍵。它的下方是移植接口,移植接口由兩部分組成:適配器和Java操作系統, 其中依賴于平臺的部分稱為適配器;JVM 通過移植接口在具體的平臺和操作系統上實現;在JVM 的上方是Java的基本類庫和擴展類庫以及它們的API, 利用Java API編寫的應用程序(application) 和小程序(Java applet) 可以在任何Java平臺上運行而無需考慮底層平臺, 就是因為有Java虛擬機(JVM)實現了程序與操作系統的分離,從而實現了Java 的平臺無關性。
那么到底什么是Java虛擬機(JVM)呢?通常我們談論JVM時,我們的意思可能是:
- 對JVM規范的的比較抽象的說明;
- 對JVM的具體實現;
- 在程序運行期間所生成的一個JVM實例。
對JVM規范的的抽象說明是一些概念的集合,它們已經在書《The Java Virtual Machine Specification》(《Java虛擬機規范》)中被詳細地描述了;對JVM的具體實現要么是軟件,要么是軟件和硬件的組合,它已經被許多生產廠商所實現,并存在于多種平臺之上;運行Java程序的任務由JVM的運行期實例單個承擔。在本文中我們所討論的Java虛擬機(JVM)主要針對第三種情況而言。它可以被看成一個想象中的機器,在實際的計算機上通過軟件模擬來實現,有自己想象中的硬件,如處理器、堆棧、寄存器等,還有自己相應的指令系統。
JVM在它的生存周期中有一個明確的任務,那就是運行Java程序,因此當Java程序啟動的時候,就產生JVM的一個實例;當程序運行結束的時候,該實例也跟著消失了。下面我們從JVM的體系結構和它的運行過程這兩個方面來對它進行比較深入的研究。
2??Java虛擬機的體系結構
剛才已經提到,JVM可以由不同的廠商來實現。由于廠商的不同必然導致JVM在實現上的一些不同,然而JVM還是可以實現跨平臺的特性,這就要歸功于設計JVM時的體系結構了。
我們知道,一個JVM實例的行為不光是它自己的事,還涉及到它的子系統、存儲區域、數據類型和指令這些部分,它們描述了JVM的一個抽象的內部體系結構,其目的不光規定實現JVM時它內部的體系結構,更重要的是提供了一種方式,用于嚴格定義實現時的外部行為。每個JVM都有兩種機制,一個是裝載具有合適名稱的類(類或是接口),叫做類裝載子系統;另外的一個負責執行包含在已裝載的類或接口中的指令,叫做運行引擎。每個JVM又包括方法區、堆、Java棧、程序計數器和本地方法棧這五個部分,這幾個部分和類裝載機制與運行引擎機制一起組成的體系結構圖為:
圖3??JVM的體系結構
JVM的每個實例都有一個它自己的方法域和一個堆,運行于JVM內的所有的線程都共享這些區域;當虛擬機裝載類文件的時候,它解析其中的二進制數據所包含的類信息,并把它們放到方法域中;當程序運行的時候,JVM把程序初始化的所有對象置于堆上;而每個線程創建的時候,都會擁有自己的程序計數器和Java棧,其中程序計數器中的值指向下一條即將被執行的指令,線程的Java棧則存儲為該線程調用Java方法的狀態;本地方法調用的狀態被存儲在本地方法棧,該方法棧依賴于具體的實現。
下面分別對這幾個部分進行說明。
執行引擎處于JVM的核心位置,在Java虛擬機規范中,它的行為是由指令集所決定的。盡管對于每條指令,規范很詳細地說明了當JVM執行字節碼遇到指令時,它的實現應該做什么,但對于怎么做卻言之甚少。Java虛擬機支持大約248個字節碼。每個字節碼執行一種基本的CPU運算,例如,把一個整數加到寄存器,子程序轉移等。Java指令集相當于Java程序的匯編語言。
Java指令集中的指令包含一個單字節的操作符,用于指定要執行的操作,還有0個或多個操作數,提供操作所需的參數或數據。許多指令沒有操作數,僅由一個單字節的操作符構成。
虛擬機的內層循環的執行過程如下:
do{
取一個操作符字節;
根據操作符的值執行一個動作;
}while(程序未結束)
由于指令系統的簡單性,使得虛擬機執行的過程十分簡單,從而有利于提高執行的效率。指令中操作數的數量和大小是由操作符決定的。如果操作數比一個字節大,那么它存儲的順序是高位字節優先。例如,一個16位的參數存放時占用兩個字節,其值為:
第一個字節*256+第二個字節字節碼。
指令流一般只是字節對齊的。指令tableswitch和lookup是例外,在這兩條指令內部要求強制的4字節邊界對齊。
對于本地方法接口,實現JVM并不要求一定要有它的支持,甚至可以完全沒有。Sun公司實現Java本地接口(JNI)是出于可移植性的考慮,當然我們也可以設計出其它的本地接口來代替Sun公司的JNI。但是這些設計與實現是比較復雜的事情,需要確保垃圾回收器不會將那些正在被本地方法調用的對象釋放掉。
Java的堆是一個運行時數據區,類的實例(對象)從中分配空間,它的管理是由垃圾回收來負責的:不給程序員顯式釋放對象的能力。Java不規定具體使用的垃圾回收算法,可以根據系統的需求使用各種各樣的算法。
Java方法區與傳統語言中的編譯后代碼或是Unix進程中的正文段類似。它保存方法代碼(編譯后的java代碼)和符號表。在當前的Java實現中,方法代碼不包括在垃圾回收堆中,但計劃在將來的版本中實現。每個類文件包含了一個Java類或一個Java界面的編譯后的代碼。可以說類文件是Java語言的執行代碼文件。為了保證類文件的平臺無關性,Java虛擬機規范中對類文件的格式也作了詳細的說明。其具體細節請參考Sun公司的Java虛擬機規范。
Java虛擬機的寄存器用于保存機器的運行狀態,與微處理器中的某些專用寄存器類似。Java虛擬機的寄存器有四種:
- pc: Java程序計數器;
- optop: 指向操作數棧頂端的指針;
- frame: 指向當前執行方法的執行環境的指針;。
- vars: 指向當前執行方法的局部變量區第一個變量的指針。
在上述體系結構圖中,我們所說的是第一種,即程序計數器,每個線程一旦被創建就擁有了自己的程序計數器。當線程執行Java方法的時候,它包含該線程正在被執行的指令的地址。但是若線程執行的是一個本地的方法,那么程序計數器的值就不會被定義。
Java虛擬機的棧有三個區域:局部變量區、運行環境區、操作數區。
局部變量區
每個Java方法使用一個固定大小的局部變量集。它們按照與vars寄存器的字偏移量來尋址。局部變量都是32位的。長整數和雙精度浮點數占據了兩個局部變量的空間,卻按照第一個局部變量的索引來尋址。(例如,一個具有索引n的局部變量,如果是一個雙精度浮點數,那么它實際占據了索引n和n+1所代表的存儲空間)虛擬機規范并不要求在局部變量中的64位的值是64位對齊的。虛擬機提供了把局部變量中的值裝載到操作數棧的指令,也提供了把操作數棧中的值寫入局部變量的指令。
運行環境區
在運行環境中包含的信息用于動態鏈接,正常的方法返回以及異常捕捉。
動態鏈接
運行環境包括對指向當前類和當前方法的解釋器符號表的指針,用于支持方法代碼的動態鏈接。方法的class文件代碼在引用要調用的方法和要訪問的變量時使用符號。動態鏈接把符號形式的方法調用翻譯成實際方法調用,裝載必要的類以解釋還沒有定義的符號,并把變量訪問翻譯成與這些變量運行時的存儲結構相應的偏移地址。動態鏈接方法和變量使得方法中使用的其它類的變化不會影響到本程序的代碼。
正常的方法返回
如果當前方法正常地結束了,在執行了一條具有正確類型的返回指令時,調用的方法會得到一個返回值。執行環境在正常返回的情況下用于恢復調用者的寄存器,并把調用者的程序計數器增加一個恰當的數值,以跳過已執行過的方法調用指令,然后在調用者的執行環境中繼續執行下去。
異常捕捉
異常情況在Java中被稱作Error(錯誤)或Exception(異常),是Throwable類的子類,在程序中的原因是:①動態鏈接錯,如無法找到所需的class文件。②運行時錯,如對一個空指針的引用。程序使用了throw語句。
當異常發生時,Java虛擬機采取如下措施:
- 檢查與當前方法相聯系的catch子句表。每個catch子句包含其有效指令范圍,能夠處理的異常類型,以及處理異常的代碼塊地址。
- 與異常相匹配的catch子句應該符合下面的條件:造成異常的指令在其指令范圍之內,發生的異常類型是其能處理的異常類型的子類型。如果找到了匹配的catch子句,那么系統轉移到指定的異常處理塊處執行;如果沒有找到異常處理塊,重復尋找匹配的catch子句的過程,直到當前方法的所有嵌套的catch子句都被檢查過。
- 由于虛擬機從第一個匹配的catch子句處繼續執行,所以catch子句表中的順序是很重要的。因為Java代碼是結構化的,因此總可以把某個方法的所有的異常處理器都按序排列到一個表中,對任意可能的程序計數器的值,都可以用線性的順序找到合適的異常處理塊,以處理在該程序計數器值下發生的異常情況。
- 如果找不到匹配的catch子句,那么當前方法得到一個"未截獲異常"的結果并返回到當前方法的調用者,好像異常剛剛在其調用者中發生一樣。如果在調用者中仍然沒有找到相應的異常處理塊,那么這種錯誤將被傳播下去。如果錯誤被傳播到最頂層,那么系統將調用一個缺省的異常處理塊。
操作數棧區
機器指令只從操作數棧中取操作數,對它們進行操作,并把結果返回到棧中。選擇棧結構的原因是:在只有少量寄存器或非通用寄存器的機器(如Intel486)上,也能夠高效地模擬虛擬機的行為。操作數棧是32位的。它用于給方法傳遞參數,并從方法接收結果,也用于支持操作的參數,并保存操作的結果。例如,iadd指令將兩個整數相加。相加的兩個整數應該是操作數棧頂的兩個字。這兩個字是由先前的指令壓進堆棧的。這兩個整數將從堆棧彈出、相加,并把結果壓回到操作數棧中。
每個原始數據類型都有專門的指令對它們進行必須的操作。每個操作數在棧中需要一個存儲位置,除了long和double型,它們需要兩個位置。操作數只能被適用于其類型的操作符所操作。例如,壓入兩個int類型的數,如果把它們當作是一個long類型的數則是非法的。在Sun的虛擬機實現中,這個限制由字節碼驗證器強制實行。但是,有少數操作(操作符dupe和swap),用于對運行時數據區進行操作時是不考慮類型的。
本地方法棧,當一個線程調用本地方法時,它就不再受到虛擬機關于結構和安全限制方面的約束,它既可以訪問虛擬機的運行期數據區,也可以使用本地處理器以及任何類型的棧。例如,本地棧是一個C語言的棧,那么當C程序調用C函數時,函數的參數以某種順序被壓入棧,結果則返回給調用函數。在實現Java虛擬機時,本地方法接口使用的是C語言的模型棧,那么它的本地方法棧的調度與使用則完全與C語言的棧相同。
3??Java虛擬機的運行過程
上面對虛擬機的各個部分進行了比較詳細的說明,下面通過一個具體的例子來分析它的運行過程。
虛擬機通過調用某個指定類的方法main啟動,傳遞給main一個字符串數組參數,使指定的類被裝載,同時鏈接該類所使用的其它的類型,并且初始化它們。例如對于程序:
class HelloApp
{
public static void main(String[] args)
{
System.out.println("Hello World!");
for (int i = 0; i < args.length; i++ )
{
System.out.println(args[i]);
}
}
}
編譯后在命令行模式下鍵入: java HelloApp run virtual machine
將通過調用HelloApp的方法main來啟動java虛擬機,傳遞給main一個包含三個字符串"run"、"virtual"、"machine"的數組。現在我們略述虛擬機在執行HelloApp時可能采取的步驟。
開始試圖執行類HelloApp的main方法,發現該類并沒有被裝載,也就是說虛擬機當前不包含該類的二進制代表,于是虛擬機使用ClassLoader試圖尋找這樣的二進制代表。如果這個進程失敗,則拋出一個異常。類被裝載后同時在main方法被調用之前,必須對類HelloApp與其它類型進行鏈接然后初始化。鏈接包含三個階段:檢驗,準備和解析。檢驗檢查被裝載的主類的符號和語義,準備則創建類或接口的靜態域以及把這些域初始化為標準的默認值,解析負責檢查主類對其它類或接口的符號引用,在這一步它是可選的。類的初始化是對類中聲明的靜態初始化函數和靜態域的初始化構造方法的執行。一個類在初始化之前它的父類必須被初始化。整個過程如下:
圖4:虛擬機的運行過程
4??結束語
本文通過對JVM的體系結構的深入研究以及一個Java程序執行時虛擬機的運行過程的詳細分析,意在剖析清楚Java虛擬機的機理。
posted @
2006-10-15 15:39 阿成 閱讀(360) |
評論 (0) |
編輯 收藏
struts的validator資料見:struts validator
附一個正則表達式的資料:
正則表達式
正則表達式(regular expression)描述了一種字符串匹配的模式,可以用來檢查一個串是否含有某種子串、將匹配的子串做替換或者從某個串中取出符合某個條件的子串等。
列目錄時, dir *.txt或ls *.txt中的*.txt就
不是一個正則表達式,因為這里*與正則式的*的含義是不同的。
為便于理解和記憶,先從一些概念入手,所有特殊字符或字符組合有一個總表在后面,最后一些例子供理解相應的概念。
正則表達式
是由普通字符(例如字符 a 到 z)以及特殊字符(稱為元字符)組成的文字模式。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。
可以通過在一對分隔符之間放入表達式模式的各種組件來構造一個正則表達式,即/expression/
普通字符
由所有那些未顯式指定為元字符的打印和非打印字符組成。這包括所有的大寫和小寫字母字符,所有數字,所有標點符號以及一些符號。
非打印字符
字符 | 含義 |
\cx | 匹配由x指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 'c' 字符。 |
\f | 匹配一個換頁符。等價于 \x0c 和 \cL。 |
\n | 匹配一個換行符。等價于 \x0a 和 \cJ。 |
\r | 匹配一個回車符。等價于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等價于 [^ \f\n\r\t\v]。 |
\t | 匹配一個制表符。等價于 \x09 和 \cI。 |
\v | 匹配一個垂直制表符。等價于 \x0b 和 \cK。 |
特殊字符
所謂特殊字符,就是一些有特殊含義的字符,如上面說的"*.txt"中的*,簡單的說就是表示任何字符串的意思。如果要查找文件名中有*的文件,則需要對*進行轉義,即在其前加一個\。ls \*.txt。正則表達式有以下特殊字符。
特別字符 | 說明 |
$ | 匹配輸入字符串的結尾位置。如果設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,請使用 \$。 |
( ) | 標記一個子表達式的開始和結束位置。子表達式可以獲取供以后使用。要匹配這些字符,請使用 \( 和 \)。 |
* | 匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 \*。 |
+ | 匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 \+。 |
. | 匹配除換行符 \n之外的任何單字符。要匹配 .,請使用 \。 |
[ | 標記一個中括號表達式的開始。要匹配 [,請使用 \[。 |
? | 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 \?。 |
\ | 將下一個字符標記為或特殊字符、或原義字符、或向后引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("。 |
^ | 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符本身,請使用 \^。 |
{ | 標記限定符表達式的開始。要匹配 {,請使用 \{。 |
| | 指明兩項之間的一個選擇。要匹配 |,請使用 \|。 |
構造正則表達式的方法和創建數學表達式的方法一樣。也就是用多種元字符與操作符將小的表達式結合在一起來創建更大的表達式。正則表達式的組件可以是單個的字符、字符集合、字符范圍、字符間的選擇或者所有這些組件的任意組合。
限定符
限定符用來指定正則表達式的一個給定組件必須要出現多少次才能滿足匹配。有*或+或?或{n}或{n,}或{n,m}共6種。
*、+和?限定符都是貪婪的,因為它們會盡可能多的匹配文字,只有在它們的后面加上一個?就可以實現非貪婪或最小匹配。
正則表達式的限定符有:
字符 | 描述 |
* | 匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價于{0,}。 |
+ | 匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價于 {1,}。 |
? | 匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價于 {0,1}。 |
{n} | n 是一個非負整數。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。 |
{n,} | n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價于 'o+'。'o{0,}' 則等價于 'o*'。 |
{n,m} | m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價于 'o?'。請注意在逗號和兩個數之間不能有空格。 |
定位符
用來描述字符串或單詞的邊界,^和$分別指字符串的開始與結束,\b描述單詞的前或后邊界,\B表示非單詞邊界。
不能對定位符使用限定符。選擇
用圓括號將所有選擇項括起來,相鄰的選擇項之間用|分隔。但用圓括號會有一個副作用,是相關的匹配會被緩存,此時可用?:放在第一個選項前來消除這種副作用。
其中?:是非捕獲元之一,還有兩個非捕獲元是?=和?!,這兩個還有更多的含義,前者為正向預查,在任何開始匹配圓括號內的正則表達式模式的位置來匹配搜索字符串,后者為負向預查,在任何開始不匹配該正則表達式模式的位置來匹配搜索字符串。
后向引用
對一個正則表達式模式或部分模式兩邊添加圓括號將導致相關匹配存儲到一個臨時緩沖區中,所捕獲的每個子匹配都按照在正則表達式模式中從左至右所遇到的內容存儲。存儲子匹配的緩沖區編號從 1 開始,連續編號直至最大 99 個子表達式。每個緩沖區都可以使用 '\n' 訪問,其中 n 為一個標識特定緩沖區的一位或兩位十進制數。
可以使用非捕獲元字符 '?:', '?=', or '?!' 來忽略對相關匹配的保存。
各種操作符的運算優先級
相同優先級的從左到右進行運算,不同優先級的運算先高后低。各種操作符的優先級從高到低如下:
操作符 | 描述 |
\ | 轉義符 |
(), (?:), (?=), [] | 圓括號和方括號 |
*, +, ?, {n}, {n,}, {n,m} | 限定符 |
^, $, \anymetacharacter | 位置和順序 |
| | “或”操作 |
全部符號解釋
字符 | 描述 |
\ | 將下一個字符標記為一個特殊字符、或一個原義字符、或一個 向后引用、或一個八進制轉義符。例如,'n' 匹配字符 "n"。'\n' 匹配一個換行符。序列 '\\' 匹配 "\" 而 "\(" 則匹配 "("。 |
^ | 匹配輸入字符串的開始位置。如果設置了 RegExp 對象的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 之后的位置。 |
$ | 匹配輸入字符串的結束位置。如果設置了RegExp 對象的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 之前的位置。 |
* | 匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價于{0,}。 |
+ | 匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價于 {1,}。 |
? | 匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價于 {0,1}。 |
{n} | n 是一個非負整數。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。 |
{n,} | n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價于 'o+'。'o{0,}' 則等價于 'o*'。 |
{n,m} | m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價于 'o?'。請注意在逗號和兩個數之間不能有空格。 |
? | 當該字符緊跟在任何一個其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對于字符串 "oooo",'o+?' 將匹配單個 "o",而 'o+' 將匹配所有 'o'。 |
. | 匹配除 "\n" 之外的任何單個字符。要匹配包括 '\n' 在內的任何字符,請使用象 '[.\n]' 的模式。 |
(pattern) | 匹配 pattern 并獲取這一匹配。所獲取的匹配可以從產生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括號字符,請使用 '\(' 或 '\)'。 |
(?:pattern) | 匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以后使用。這在使用 "或" 字符 (|) 來組合一個模式的各個部分是很有用。例如, 'industr(?:y|ies) 就是一個比 'industry|industries' 更簡略的表達式。 |
(?=pattern) | 正向預查,在任何匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始。 |
(?!pattern) | 負向預查,在任何不匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始 |
x|y | 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配 "zood" 或 "food"。 |
[xyz] | 字符集合。匹配所包含的任意一個字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。 |
[^xyz] | 負值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。 |
[a-z] | 字符范圍。匹配指定范圍內的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范圍內的任意小寫字母字符。 |
[^a-z] | 負值字符范圍。匹配任何不在指定范圍內的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范圍內的任意字符。 |
\b | 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
\cx | 匹配由 x 指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 'c' 字符。 |
\d | 匹配一個數字字符。等價于 [0-9]。 |
\D | 匹配一個非數字字符。等價于 [^0-9]。 |
\f | 匹配一個換頁符。等價于 \x0c 和 \cL。 |
\n | 匹配一個換行符。等價于 \x0a 和 \cJ。 |
\r | 匹配一個回車符。等價于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等價于 [^ \f\n\r\t\v]。 |
\t | 匹配一個制表符。等價于 \x09 和 \cI。 |
\v | 匹配一個垂直制表符。等價于 \x0b 和 \cK。 |
\w | 匹配包括下劃線的任何單詞字符。等價于'[A-Za-z0-9_]'。 |
\W | 匹配任何非單詞字符。等價于 '[^A-Za-z0-9_]'。 |
\xn | 匹配 n,其中 n 為十六進制轉義值。十六進制轉義值必須為確定的兩個數字長。例如,'\x41' 匹配 "A"。'\x041' 則等價于 '\x04' & "1"。正則表達式中可以使用 ASCII 編碼。. |
\num | 匹配 num,其中 num 是一個正整數。對所獲取的匹配的引用。例如,'(.)\1' 匹配兩個連續的相同字符。 |
\n | 標識一個八進制轉義值或一個向后引用。如果 \n 之前至少 n 個獲取的子表達式,則 n 為向后引用。否則,如果 n 為八進制數字 (0-7),則 n 為一個八進制轉義值。 |
\nm | 標識一個八進制轉義值或一個向后引用。如果 \nm 之前至少有 nm 個獲得子表達式,則 nm 為向后引用。如果 \nm 之前至少有 n 個獲取,則 n 為一個后跟文字 m 的向后引用。如果前面的條件都不滿足,若 n 和 m 均為八進制數字 (0-7),則 \nm 將匹配八進制轉義值 nm。 |
\nml | 如果 n 為八進制數字 (0-3),且 m 和 l 均為八進制數字 (0-7),則匹配八進制轉義值 nml。 |
\un | 匹配 n,其中 n 是一個用四個十六進制數字表示的 Unicode 字符。例如, \u00A9 匹配版權符號 (?)。 |
部分例子
正則表達式 | 說明 |
/\b([a-z]+) \1\b/gi | 一個單詞連續出現的位置 |
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ | 將一個URL解析為協議、域、端口及相對路徑 |
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/ | 定位章節的位置 |
/[-a-z]/ | A至z共26個字母再加一個-號。 |
/ter\b/ | 可匹配chapter,而不能terminal |
/\Bapt/ | 可匹配chapter,而不能aptitude |
/Windows(?=95 |98 |NT )/ | 可匹配Windows95或Windows98或WindowsNT,當找到一個匹配后,從Windows后面開始進行下一次的檢索匹配。 |
posted @
2006-10-13 09:36 阿成 閱讀(302) |
評論 (0) |
編輯 收藏
前兩天晚上在經過一個十字路口的時候,不知中了什么邪,跑著橫穿馬路,正好被一個出租車撞上,
撞的偶pp上,那叫一個險。幸虧是撞的pp上,而且車速不算快。身上是些皮外傷。
所以奉勸大家寧等3小時,別搶1妙。
要是真有急事兒,非要搶那1妙,那就別猶豫,跑快點。
posted @
2006-10-09 08:57 阿成 閱讀(338) |
評論 (0) |
編輯 收藏
真的很快,工作了感覺時間過得太快了。真是time fly啊

明天就101了,感覺剛過完51。
回家修養幾天。
posted @
2006-09-30 17:06 阿成 閱讀(270) |
評論 (0) |
編輯 收藏
現在我最缺什么?最需求在哪些方面改進?
最近一些小事讓我逐漸意識到自己這工作一年多來一直沒有重視或者說不敢的弱點。我開始問自己現在在社會上混,都需要些什么?我一一列舉,作為程序員,我開始想到java、數據庫、服務器、、、、、、,發現,都是一些技術方面的。光有這些行嗎?肯定不行。開始想到了一些其他的東西,圓滑,這兩個字沒那么簡單,里面有著一系列東西。我問自己,我作為一個寫程序的技術人員,他媽的我需要干這個?我做到了嗎?我沒做做到。而且差的很遠很遠。說這些不是腦子一熱,或者什么憑空想象,是所見所聞。而我得性格似乎與這個東西有隔閡,似乎不太容易做到,而且對它產生了煩感和誤解。看著茫茫人海,各奔前程,我也逐漸開始理解了。如果你沒有做到或像我一樣或不理解,就仔細觀察一下周圍的環境,會明白的。經過反復的思考,決定該改正一些了。但我不會超越我自己的一些底線,我會對自己認準的朋友保持一顆真誠的心,不敢說已做到仗義,講義氣,但會一直為之努力。也希望每個人在圓滑的同時盡量保留自己的底線。我也會盡快的適應這個所謂的高科技時代。
posted @
2006-09-26 14:35 阿成 閱讀(194) |
評論 (0) |
編輯 收藏
部門的經理挺好,周末組織部門同事去懷柔玩了一次,因為國慶、中秋快到了。
這次和上次去秦皇島還沒隔多長時間。
早上7點就起床了,吃完早飯,大家到齊之后就出發了。
先去的紅螺寺,這原來是一個皇家寺院。里面的大佛聽多。阿彌托佛、釋迦摩尼、藥師佛等等,
然后又看了500羅漢,據說里面總能找到一個與你想的。中午吃飯,點了好幾條虹尊魚,頓的,烤的都吃了,不過覺得一般。下午去了神堂裕,里面是一些小溪呀,山呀,在里面走走不錯,回歸大自然,凈化一下,在工作呀、學習呀都能提高效率。
晚上回來后已經快7點了,接著腐敗,找地兒吃飯。挺爽的。
十一之后逐漸變冷估計今年即便有活動,也是在市里了。下次出去估計的明年了。
posted @
2006-09-26 14:04 阿成 閱讀(258) |
評論 (0) |
編輯 收藏