<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 120,  comments - 19,  trackbacks - 0
      2006年9月21日
    北京英語(yǔ)角(BeiJing)www.52en.com
    =================================
    北大英語(yǔ)角:每周六晚7:00 俄文樓前空地
    清華英語(yǔ)角:每周三晚7:00-10:00 西階(west of Great Hall)
    人大英語(yǔ)角:每周五晚 人大東門(mén)花園,老外多,質(zhì)量不錯(cuò)
    北外英語(yǔ)角:每周五晚6:30-8:30外研社后花園
    朝陽(yáng)文化館:每周六下午3:00-5:00 門(mén)票6元地點(diǎn)在小莊,收費(fèi),但質(zhì)量好
    posted @ 2007-04-25 09:29 阿成 閱讀(2140) | 評(píng)論 (6)編輯 收藏
    1.未到火候,千萬(wàn)別說(shuō)。有些男孩才跟人家約過(guò)幾次,就提出要建立“更進(jìn)一步”的關(guān)系,這十有八九要壞湯。愛(ài)情上的事妙就妙在一切盡在不言中。說(shuō)清楚了,話(huà)挑明了,反而不美。本來(lái)人家肯單獨(dú)出來(lái)跟你說(shuō)話(huà),這說(shuō)明女孩對(duì)你不無(wú)好感。但是這種好感有時(shí)連她們自己都說(shuō)不清,你卻急于挑明,破壞了這種朦朧美,那就別怪人家敬而遠(yuǎn)之以致退避三舍了。看看周?chē)切┻€沒(méi)開(kāi)始就夭折的愛(ài)情,許多都是由男孩沒(méi)有掌握好火候造成的。

      2.收起拳頭是為了更好的出擊。被女孩拒絕了怎么辦呢?有人說(shuō)應(yīng)該窮追猛打、堅(jiān)持不懈。其實(shí)不然。除非你是一個(gè)啥也不在乎的人,否則你很難承受女孩的白眼和同伴們嘲弄的目光。倒不如偃旗息鼓、暫時(shí)撤退。這不僅保護(hù)了你的尊嚴(yán)而且還留了條后路,從而為日后反攻創(chuàng)造機(jī)會(huì)。就讓她在人群里闖蕩。等她碰得頭破血流時(shí),你再去找她,她才能認(rèn)識(shí)到原來(lái)你才是最?lèi)?ài)她的人。即使實(shí)在割舍不下,要去找她,也應(yīng)注意方式方法。千萬(wàn)別讓她覺(jué)得你討厭。而這一點(diǎn)往往是很難做到的。 

      3.不要太露骨。要學(xué)會(huì)不聲不響地關(guān)心她,用你的誠(chéng)實(shí)和善意對(duì)待她。只有這樣你才能在一大幫圍著她呱呱亂叫的男孩當(dāng)中引起她的注意。記住,只有特別的你才會(huì)引起她特別的關(guān)注。 

      4.非請(qǐng)勿入。一個(gè)老是往女孩寢室跑的男孩是不會(huì)引起女孩太多的好感的。有些學(xué)生會(huì)干部借口工作常往女生寢室跑,去了后就老賴(lài)在那不走,結(jié)果給人家?guī)?lái)了諸多不便,效果只會(huì)適得其反。產(chǎn)生這種結(jié)果的根本原因還是因?yàn)樘豆恰?

      5.戰(zhàn)略上藐視...,戰(zhàn)術(shù)上重視...。有時(shí)你喜愛(ài)的女孩會(huì)和你有些接觸,比如談?wù)勗?huà)、聊聊天、一起工作等等。你最好能以平常的心態(tài)看待這些事情,不要背上包袱、患得患失。例如不要太在意她無(wú)意中說(shuō)的話(huà),有些男孩容易自作多情,源出于此。但對(duì)每一次這樣的機(jī)會(huì)則應(yīng)引起足夠的重視,例如初次談話(huà)要注意掌握好分寸,最好不要涉及情愛(ài)范疇,不妨說(shuō)說(shuō)小時(shí)候的事。你如果只奔主體那就要糟!女孩非得象警惕狼一樣地警惕你。 

      6.馬屁最好少拍。你夸她長(zhǎng)得漂亮,如果她真的漂亮,那么你不過(guò)是第七百個(gè)夸她漂亮的人,而她映象最深的恐怕是第一個(gè)這樣夸她的人;如果她相貌普通,你這樣夸她能產(chǎn)生什么樣的結(jié)果誰(shuí)也說(shuō)不準(zhǔn)。要是讓她發(fā)現(xiàn)你言不由衷,那你就死定了。記住,哄女孩只有在女孩成為你的女朋友之后才能哄,還沒(méi)追到手就開(kāi)始哄是沒(méi)有掌握好火候的表現(xiàn)。 

      7.少來(lái)點(diǎn)大男子主義。有個(gè)男孩好不容易請(qǐng)得他傾慕已久的女孩去吃飯,花了他半個(gè)月生活費(fèi)。后來(lái)他去付賬時(shí)發(fā)現(xiàn)女孩已經(jīng)替他付了,他就要還她錢(qián)。女孩不愿意。他覺(jué)得女孩剝了他的面子,大為光火。女孩氣得哭了。本來(lái)女孩替他付賬這說(shuō)明她對(duì)他有好感,他不思討好反而發(fā)脾氣,如此就難怪他要打光棍了。幾乎沒(méi)有一個(gè)女孩會(huì)對(duì)那些不尊重女性的男孩有好感,切記!切記!。 

      8.團(tuán)結(jié)大多數(shù)。幾乎每個(gè)女孩都有一兩個(gè)最知心的女友,當(dāng)其他道路都不通時(shí),她們是你通往勝利的成功之路。你可以通過(guò)她們了解女孩到底對(duì)你有沒(méi)有意思,還可以通過(guò)她們傳達(dá)你的意思。這比你直接說(shuō)要好得多。可千萬(wàn)別忽視這一支生力軍,我不止一次地看到男孩通過(guò)這個(gè)方法大功告成的。 

      最后要提醒大家的是,愛(ài)情從來(lái)都沒(méi)有固定的公式。別人成功的方法也許正是你的敗著;別人失敗的方法也許恰是你的妙著。我這里只提一點(diǎn)原則性的東西,切不可生搬硬套。如果因此而壞了你的好事切莫來(lái)找我。女孩要是不喜歡你,就是玉皇大帝也沒(méi)有法子。還是古人說(shuō)的好:不戰(zhàn)而屈人之兵,上之上策也。
    posted @ 2007-04-23 19:12 阿成 閱讀(513) | 評(píng)論 (0)編輯 收藏
    ThreadLocal 類(lèi)是悄悄地出現(xiàn)在 Java 平臺(tái)版本 1.2 中的。雖然支持線程局部變量早就是許多線程工具(例如 Posix pthreads 工具)的一部分,但 Java Threads API 的最初設(shè)計(jì)卻沒(méi)有這項(xiàng)有用的功能。而且,最初的實(shí)現(xiàn)也相當(dāng)?shù)托?。由于這些原因, ThreadLocal 極少受到關(guān)注,但對(duì)簡(jiǎn)化線程安全并發(fā)程序的開(kāi)發(fā)來(lái)說(shuō),它卻是很方便的。在 輕松使用線程的第 3 部分,Java 軟件顧問(wèn) Brian Goetz 研究了 ThreadLocal 并提供了一些使用技巧。

    參加 Brian 的 多線程 Java 編程討論論壇以獲得您工程中的線程和并發(fā)問(wèn)題的幫助。

    編寫(xiě)線程安全類(lèi)是困難的。它不但要求仔細(xì)分析在什么條件可以對(duì)變量進(jìn)行讀寫(xiě),而且要求仔細(xì)分析其它類(lèi)能如何使用某個(gè)類(lèi)。 有時(shí),要在不影響類(lèi)的功能、易用性或性能的情況下使類(lèi)成為線程安全的是很困難的。有些類(lèi)保留從一個(gè)方法調(diào)用到下一個(gè)方法調(diào)用的狀態(tài)信息,要在實(shí)踐中使這樣的類(lèi)成為線程安全的是困難的。

    管理非線程安全類(lèi)的使用比試圖使類(lèi)成為線程安全的要更容易些。非線程安全類(lèi)通??梢园踩卦诙嗑€程程序中使用,只要您能確保一個(gè)線程所用的類(lèi)的實(shí)例不被其它線程使用。例如,JDBC Connection 類(lèi)是非線程安全的 — 兩個(gè)線程不能在小粒度級(jí)上安全地共享一個(gè) Connection — 但如果每個(gè)線程都有它自己的 Connection ,那么多個(gè)線程就可以同時(shí)安全地進(jìn)行數(shù)據(jù)庫(kù)操作。

    不使用 ThreadLocal 為每個(gè)線程維護(hù)一個(gè)單獨(dú)的 JDBC 連接(或任何其它對(duì)象)當(dāng)然是可能的;Thread API 給了我們把對(duì)象和線程聯(lián)系起來(lái)所需的所有工具。而 ThreadLocal 則使我們能更容易地把線程和它的每線程(per-thread)數(shù)據(jù)成功地聯(lián)系起來(lái)。

    什么是線程局部變量(thread-local variable)?

    線程局部變量高效地為每個(gè)使用它的線程提供單獨(dú)的線程局部變量值的副本。每個(gè)線程只能看到與自己相聯(lián)系的值,而不知道別的線程可能正在使用或修改它們自己的副本。一些編譯器(例如 Microsoft Visual C++ 編譯器或 IBM XL FORTRAN 編譯器)用存儲(chǔ)類(lèi)別修飾符(像 staticvolatile )把對(duì)線程局部變量的支持集成到了其語(yǔ)言中。Java 編譯器對(duì)線程局部變量不提供特別的語(yǔ)言支持;相反地,它用 ThreadLocal 類(lèi)實(shí)現(xiàn)這些支持, 核心 Thread 類(lèi)中有這個(gè)類(lèi)的特別支持。

    因?yàn)榫€程局部變量是通過(guò)一個(gè)類(lèi)來(lái)實(shí)現(xiàn)的,而不是作為 Java 語(yǔ)言本身的一部分,所以 Java 語(yǔ)言線程局部變量的使用語(yǔ)法比內(nèi)建線程局部變量語(yǔ)言的使用語(yǔ)法要笨拙一些。要?jiǎng)?chuàng)建一個(gè)線程局部變量,請(qǐng)實(shí)例化類(lèi) ThreadLocal 的一個(gè)對(duì)象。 ThreadLocal 類(lèi)的行為與 java.lang.ref 中的各種 Reference 類(lèi)的行為很相似; ThreadLocal 類(lèi)充當(dāng)存儲(chǔ)或檢索一個(gè)值時(shí)的間接句柄。清單 1 顯示了 ThreadLocal 接口。


    清單 1. ThreadLocal 接口
    
                public class ThreadLocal {
                public Object get();
                public void set(Object newValue);
                public Object initialValue();
                }
                

    get() 訪問(wèn)器檢索變量的當(dāng)前線程的值; set() 訪問(wèn)器修改當(dāng)前線程的值。 initialValue() 方法是可選的,如果線程未使用過(guò)某個(gè)變量,那么您可以用這個(gè)方法來(lái)設(shè)置這個(gè)變量的初始值;它允許延遲初始化。用一個(gè)示例實(shí)現(xiàn)來(lái)說(shuō)明 ThreadLocal 的工作方式是最好的方法。清單 2 顯示了 ThreadLocal 的一個(gè)實(shí)現(xiàn)方式。它不是一個(gè)特別好的實(shí)現(xiàn)(雖然它與最初實(shí)現(xiàn)非常相似),所以很可能性能不佳,但它清楚地說(shuō)明了 ThreadLocal 的工作方式。


    清單 2. ThreadLocal 的糟糕實(shí)現(xiàn)
    
                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;
                }
                }
                

    這個(gè)實(shí)現(xiàn)的性能不會(huì)很好,因?yàn)槊總€(gè) get()set() 操作都需要 values 映射表上的同步,而且如果多個(gè)線程同時(shí)訪問(wèn)同一個(gè) ThreadLocal ,那么將發(fā)生爭(zhēng)用。此外,這個(gè)實(shí)現(xiàn)也是不切實(shí)際的,因?yàn)橛?Thread 對(duì)象做 values 映射表中的關(guān)鍵字將導(dǎo)致無(wú)法在線程退出后對(duì) Thread 進(jìn)行垃圾回收,而且也無(wú)法對(duì)死線程的 ThreadLocal 的特定于線程的值進(jìn)行垃圾回收。





    回頁(yè)首


    用 ThreadLocal 實(shí)現(xiàn)每線程 Singleton

    線程局部變量常被用來(lái)描繪有狀態(tài)“單子”(Singleton) 或線程安全的共享對(duì)象,或者是通過(guò)把不安全的整個(gè)變量封裝進(jìn) ThreadLocal ,或者是通過(guò)把對(duì)象的特定于線程的狀態(tài)封裝進(jìn) ThreadLocal 。例如,在與數(shù)據(jù)庫(kù)有緊密聯(lián)系的應(yīng)用程序中,程序的很多方法可能都需要訪問(wèn)數(shù)據(jù)庫(kù)。在系統(tǒng)的每個(gè)方法中都包含一個(gè) Connection 作為參數(shù)是不方便的 — 用“單子”來(lái)訪問(wèn)連接可能是一個(gè)雖然更粗糙,但卻方便得多的技術(shù)。然而,多個(gè)線程不能安全地共享一個(gè) JDBC Connection 。如清單 3 所示,通過(guò)使用“單子”中的 ThreadLocal ,我們就能讓我們的程序中的任何類(lèi)容易地獲取每線程 Connection 的一個(gè)引用。這樣,我們可以認(rèn)為 ThreadLocal 允許我們創(chuàng)建 每線程單子。


    清單 3. 把一個(gè) JDBC 連接存儲(chǔ)到一個(gè)每線程 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();
                }
                }
                

    任何創(chuàng)建的花費(fèi)比使用的花費(fèi)相對(duì)昂貴些的有狀態(tài)或非線程安全的對(duì)象,例如 JDBC Connection 或正則表達(dá)式匹配器,都是可以使用每線程單子(singleton)技術(shù)的好地方。當(dāng)然,在類(lèi)似這樣的地方,您可以使用其它技術(shù),例如用池,來(lái)安全地管理共享訪問(wèn)。然而,從可伸縮性角度看,即使是用池也存在一些潛在缺陷。因?yàn)槌貙?shí)現(xiàn)必須使用同步,以維護(hù)池?cái)?shù)據(jù)結(jié)構(gòu)的完整性,如果所有線程使用同一個(gè)池,那么在有很多線程頻繁地對(duì)池進(jìn)行訪問(wèn)的系統(tǒng)中,程序性能將因爭(zhēng)用而降低。





    回頁(yè)首


    用 ThreadLocal 簡(jiǎn)化調(diào)試日志紀(jì)錄

    其它適合使用 ThreadLocal 但用池卻不能成為很好的替代技術(shù)的應(yīng)用程序包括存儲(chǔ)或累積每線程上下文信息以備稍后檢索之用這樣的應(yīng)用程序。例如,假設(shè)您想創(chuàng)建一個(gè)用于管理多線程應(yīng)用程序調(diào)試信息的工具。您可以用如清單 4 所示的 DebugLogger 類(lèi)作為線程局部容器來(lái)累積調(diào)試信息。在一個(gè)工作單元的開(kāi)頭,您清空容器,而當(dāng)一個(gè)錯(cuò)誤出現(xiàn)時(shí),您查詢(xún)?cè)撊萜饕詸z索這個(gè)工作單元迄今為止生成的所有調(diào)試信息。


    清單 4. 用 ThreadLocal 管理每線程調(diào)試日志
    
                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);
                }
                }
                

    在您的代碼中,您可以調(diào)用 DebugLogger.put() 來(lái)保存您的程序正在做什么的信息,而且,稍后如果有必要(例如發(fā)生了一個(gè)錯(cuò)誤),您能夠容易地檢索與某個(gè)特定線程相關(guān)的調(diào)試信息。 與簡(jiǎn)單地把所有信息轉(zhuǎn)儲(chǔ)到一個(gè)日志文件,然后努力找出哪個(gè)日志記錄來(lái)自哪個(gè)線程(還要擔(dān)心線程爭(zhēng)用日志紀(jì)錄對(duì)象)相比,這種技術(shù)簡(jiǎn)便得多,也有效得多。

    ThreadLocal 在基于 servlet 的應(yīng)用程序或工作單元是一個(gè)整體請(qǐng)求的任何多線程應(yīng)用程序服務(wù)器中也是很有用的,因?yàn)樵谔幚碚?qǐng)求的整個(gè)過(guò)程中將要用到單個(gè)線程。您可以通過(guò)前面講述的每線程單子技術(shù)用 ThreadLocal 變量來(lái)存儲(chǔ)各種每請(qǐng)求(per-request)上下文信息。





    回頁(yè)首


    ThreadLocal 的線程安全性稍差的堂兄弟,InheritableThreadLocal

    ThreadLocal 類(lèi)有一個(gè)親戚,InheritableThreadLocal,它以相似的方式工作,但適用于種類(lèi)完全不同的應(yīng)用程序。創(chuàng)建一個(gè)線程時(shí)如果保存了所有 InheritableThreadLocal 對(duì)象的值,那么這些值也將自動(dòng)傳遞給子線程。如果一個(gè)子線程調(diào)用 InheritableThreadLocalget() ,那么它將與它的父線程看到同一個(gè)對(duì)象。為保護(hù)線程安全性,您應(yīng)該只對(duì)不可變對(duì)象(一旦創(chuàng)建,其狀態(tài)就永遠(yuǎn)不會(huì)被改變的對(duì)象)使用 InheritableThreadLocal ,因?yàn)閷?duì)象被多個(gè)線程共享。 InheritableThreadLocal 很合適用于把數(shù)據(jù)從父線程傳到子線程,例如用戶(hù)標(biāo)識(shí)(user id)或事務(wù)標(biāo)識(shí)(transaction id),但不能是有狀態(tài)對(duì)象,例如 JDBC Connection





    回頁(yè)首


    ThreadLocal 的性能

    雖然線程局部變量早已赫赫有名并被包括 Posix pthreads 規(guī)范在內(nèi)的很多線程框架支持,但最初的 Java 線程設(shè)計(jì)中卻省略了它,只是在 Java 平臺(tái)的版本 1.2 中才添加上去。在很多方面, ThreadLocal 仍在發(fā)展之中;在版本 1.3 中它被重寫(xiě),版本 1.4 中又重寫(xiě)了一次,兩次都專(zhuān)門(mén)是為了性能問(wèn)題。

    在 JDK 1.2 中, ThreadLocal 的實(shí)現(xiàn)方式與清單 2 中的方式非常相似,除了用同步 WeakHashMap 代替 HashMap 來(lái)存儲(chǔ) values 之外。(以一些額外的性能開(kāi)銷(xiāo)為代價(jià),使用 WeakHashMap 解決了無(wú)法對(duì) Thread 對(duì)象進(jìn)行垃圾回收的問(wèn)題。)不用說(shuō), ThreadLocal 的性能是相當(dāng)差的。

    Java 平臺(tái)版本 1.3 提供的 ThreadLocal 版本已經(jīng)盡量更好了;它不使用任何同步,從而不存在可伸縮性問(wèn)題,而且它也不使用弱引用。相反地,人們通過(guò)給 Thread 添加一個(gè)實(shí)例變量(該變量用于保存當(dāng)前線程的從線程局部變量到它的值的映射的 HashMap )來(lái)修改 Thread 類(lèi)以支持 ThreadLocal 。因?yàn)闄z索或設(shè)置一個(gè)線程局部變量的過(guò)程不涉及對(duì)可能被另一個(gè)線程讀寫(xiě)的數(shù)據(jù)的讀寫(xiě)操作,所以您可以不用任何同步就實(shí)現(xiàn) ThreadLocal.get()set() 。而且,因?yàn)槊烤€程值的引用被存儲(chǔ)在自已的 Thread 對(duì)象中,所以當(dāng)對(duì) Thread 進(jìn)行垃圾回收時(shí),也能對(duì)該 Thread 的每線程值進(jìn)行垃圾回收。

    不幸的是,即使有了這些改進(jìn),Java 1.3 中的 ThreadLocal 的性能仍然出奇地慢。據(jù)我的粗略測(cè)量,在雙處理器 Linux 系統(tǒng)上的 Sun 1.3 JDK 中進(jìn)行 ThreadLocal.get() 操作,所耗費(fèi)的時(shí)間大約是無(wú)爭(zhēng)用同步的兩倍。性能這么差的原因是 Thread.currentThread() 方法的花費(fèi)非常大,占了 ThreadLocal.get() 運(yùn)行時(shí)間的三分之二還多。雖然有這些缺點(diǎn),JDK 1.3 ThreadLocal.get() 仍然比爭(zhēng)用同步快得多,所以如果在任何存在嚴(yán)重爭(zhēng)用的地方(可能是有非常多的線程,或者同步塊被頻繁地執(zhí)行,或者同步塊很大), ThreadLocal 可能仍然要高效得多。

    在 Java 平臺(tái)的最新版本,即版本 1.4b2 中, ThreadLocalThread.currentThread() 的性能都有了很大提高。有了這些提高, ThreadLocal 應(yīng)該比其它技術(shù),如用池,更快。由于它比其它技術(shù)更簡(jiǎn)單,也更不易出錯(cuò),人們最終將發(fā)現(xiàn)它是避免線程間出現(xiàn)不希望的交互的有效途徑。





    回頁(yè)首


    ThreadLocal 的好處

    ThreadLocal 能帶來(lái)很多好處。它常常是把有狀態(tài)類(lèi)描繪成線程安全的,或者封裝非線程安全類(lèi)以使它們能夠在多線程環(huán)境中安全地使用的最容易的方式。使用 ThreadLocal 使我們可以繞過(guò)為實(shí)現(xiàn)線程安全而對(duì)何時(shí)需要同步進(jìn)行判斷的復(fù)雜過(guò)程,而且因?yàn)樗恍枰魏瓮?,所以也改善了可伸縮性。除簡(jiǎn)單之外,用 ThreadLocal 存儲(chǔ)每線程單子或每線程上下文信息在歸檔方面還有一個(gè)頗有價(jià)值好處 — 通過(guò)使用 ThreadLocal ,存儲(chǔ)在 ThreadLocal 中的對(duì)象都是 被線程共享的是清晰的,從而簡(jiǎn)化了判斷一個(gè)類(lèi)是否線程安全的工作。

    我希望您從這個(gè)系列中得到了樂(lè)趣,也學(xué)到了知識(shí),我也鼓勵(lì)您到我的 討論論壇中來(lái)深入研究多線程問(wèn)題。

    posted @ 2007-04-09 20:52 阿成 閱讀(2437) | 評(píng)論 (1)編輯 收藏

    Servlet是在多線程環(huán)境下的。即可能有多個(gè)請(qǐng)求發(fā)給一個(gè)servelt實(shí)例,每個(gè)請(qǐng)求是一個(gè)線程。
    struts下的action也類(lèi)似,同樣在多線程環(huán)境下??梢詤⒖約truts user guide: http://struts.apache.org/struts-action/userGuide/building_controller.html 中的Action Class Design Guidelines一節(jié): 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.
    譯:為多線程環(huán)境編寫(xiě)代碼。我們的controller servlet指揮創(chuàng)建你的Action 類(lèi)的一個(gè)實(shí)例,用此實(shí)例來(lái)服務(wù)所有的請(qǐng)求。因此,你必須編寫(xiě)線程安全的Action類(lèi)。遵循與寫(xiě)線程安全的servlet同樣的方針。

    1.什么是線程安全的代碼
    在多線程環(huán)境下能正確執(zhí)行的代碼就是線程安全的。
    安全的意思是能正確執(zhí)行,否則后果是程序執(zhí)行錯(cuò)誤,可能出現(xiàn)各種異常情況。

    2.如何編寫(xiě)線程安全的代碼
    很多書(shū)籍里都詳細(xì)講解了如何這方面的問(wèn)題,他們主要講解的是如何同步線程對(duì)共享資源的使用的問(wèn)題。主要是對(duì)synchronized關(guān)鍵字的各種用法,以及鎖的概念。
    Java1.5中也提供了如讀寫(xiě)鎖這類(lèi)的工具類(lèi)。這些都需要較高的技巧,而且相對(duì)難于調(diào)試。

    但是,線程同步是不得以的方法,是比較復(fù)雜的,而且會(huì)帶來(lái)性能的損失。等效的代碼中,不需要同步在編寫(xiě)容易度和性能上會(huì)更好些。
    我這里強(qiáng)調(diào)的是什么代碼是始終為線程安全的、是不需要同步的。如下:
    1)常量始終是線程安全的,因?yàn)橹淮嬖谧x操作。
    2)對(duì)構(gòu)造器的訪問(wèn)(new 操作)是線程安全的,因?yàn)槊看味夹陆ㄒ粋€(gè)實(shí)例,不會(huì)訪問(wèn)共享的資源。
    3)最重要的是:局部變量是線程安全的。因?yàn)槊繄?zhí)行一個(gè)方法,都會(huì)在獨(dú)立的空間創(chuàng)建局部變量,它不是共享的資源。局部變量包括方法的參數(shù)變量。
    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.
    譯:只使用用局部變量。--編寫(xiě)線程安全的代碼最重要的原則就是,在Action類(lèi)中只使用局部變量,不使用實(shí)例變量。


    總結(jié):
    在Java的Web服務(wù)器環(huán)境下開(kāi)發(fā),要注意線程安全的問(wèn)題。最簡(jiǎn)單的實(shí)現(xiàn)方式就是在Servlet和Struts Action里不要使用類(lèi)變量、實(shí)例變量,但可以使用類(lèi)常量和實(shí)例常量。
    如果有這些變量,可以將它們轉(zhuǎn)換為方法的參數(shù)傳入,以消除它們。
    注意一個(gè)容易混淆的地方:被Servlet或Action調(diào)用的類(lèi)中(如值對(duì)象、領(lǐng)域模型類(lèi))中是否可以安全的使用實(shí)例變量?如果你在每次方法調(diào)用時(shí)
    新建一個(gè)對(duì)象,再調(diào)用它們的方法,則不存在同步問(wèn)題---因?yàn)樗鼈儾皇嵌鄠€(gè)線程共享的資源,只有共享的資源才需要同步---而Servlet和Action的實(shí)例對(duì)于多個(gè)線程是共享的。
    換句話(huà)說(shuō),Servlet和Action的實(shí)例會(huì)被多個(gè)線程同時(shí)調(diào)用,而過(guò)了這一層,如果在你自己的代碼中沒(méi)有另外啟動(dòng)線程,且每次調(diào)用后續(xù)業(yè)務(wù)對(duì)象時(shí)都是先新建一個(gè)實(shí)例再調(diào)用,則都是線程安全的。

    posted @ 2007-04-09 20:31 阿成 閱讀(496) | 評(píng)論 (0)編輯 收藏
    java.lang.Object
      |
      +--javax.servlet.GenericServlet
            |
            +--javax.servlet.http.HttpServlet
                  |
                  +--org.apache.struts.action.ActionServlet

    Struts提供了一個(gè)缺省版本的ActionServlet類(lèi),你可以繼承這個(gè)類(lèi),覆蓋其中的一些方法來(lái)達(dá)到你的特殊處理的需要。ActionServlet繼承與javax.servlet.http.HttpServlet,所以在本質(zhì)上它和一個(gè)普通的servlet沒(méi)有區(qū)別,你完全可以把它當(dāng)做一個(gè)servlet來(lái)看待,只是在其中完成的功能不同罷了。ActionServlet主要完成如下功能:

    將一個(gè)來(lái)自客戶(hù)端的URI映射到一個(gè)相應(yīng)的Action類(lèi)
    • 如果是這個(gè)Action類(lèi)是第一次被調(diào)用,那么實(shí)例化一個(gè)并放入緩存
    • 如果在配置文件(struts-config.xml)中指定了相應(yīng)的ActionForm,那么從Request中抓取數(shù)據(jù)填充FormBean
    • 調(diào)用這個(gè)Action類(lèi)的perform()方法,傳入ActionMapping的一個(gè)引用,對(duì)應(yīng)的ActionForm、以及由容器傳給ActionServlet的HttpServletRequest、HttpServletResponse對(duì)象。


    確省版本的ActionServlet會(huì)從配置文件web.xml中讀取如下初始化參數(shù):
    • application
      應(yīng)用使用的資源包(resources bundle)的基類(lèi)
    • factory
      用于創(chuàng)建應(yīng)用的MessageResources對(duì)象的MessageResourcesFactory的類(lèi)名。確省是org.apache.struts.util.PropertyMessageResourcesFactory。
    • config
      Struts的配置文件,確省是/WEB-INF/struts-config.xml。注意這兒是與應(yīng)用Context關(guān)聯(lián)的相對(duì)路徑。
    • content
      定義了確省的內(nèi)容類(lèi)型和編碼格式,它會(huì)被自動(dòng)地被設(shè)置到每個(gè)response中,如果JSP/Servlet中沒(méi)有明確的設(shè)置。確省是text/html。
    • debug
      調(diào)試信息的級(jí)別。默認(rèn)為0,比當(dāng)前級(jí)別高的調(diào)試信息會(huì)被log到日志文件中。
    • detail
      與debug的作用類(lèi)似,只是這個(gè)detail是initMapping()時(shí)專(zhuān)用的。調(diào)試信息會(huì)被打印到System.out,而不是日志文件。
    • formBean
      ActionFormBean的實(shí)現(xiàn)類(lèi),確省為org.apache.struts.action.ActionFormBean
    • forward
      應(yīng)用中使用的ActionForward類(lèi),確省是org.apache.struts.action.ActionForward。
    • locale
      指定了確省使用的Locale對(duì)象。設(shè)為true,當(dāng)?shù)玫揭粋€(gè)session時(shí),會(huì)自動(dòng)在session中存儲(chǔ)一個(gè)以Action.LOCALE_KEY標(biāo)示的Locale對(duì)象,如果session中還沒(méi)有與Action.LOCALE_KEY綁定的Locale對(duì)象。
    • mapping
      應(yīng)用中使用的ActionMapping類(lèi),確省是org.apache.struts.action.ActionMapping。
    • multipartClass
      文件上傳使用的MutipartRequestHandler的實(shí)現(xiàn)類(lèi)。確省為org.apache.struts.upload.DiskMultipartRequestHandler
    • nocache
      如果設(shè)為true,那么ActionServlet會(huì)自動(dòng)在每個(gè)到客戶(hù)端的響應(yīng)中添加nocache的HTML頭,這樣客戶(hù)端就不會(huì)對(duì)應(yīng)用中的頁(yè)面進(jìn)行緩存。確省為false
    • null
      如果設(shè)置為true,那么應(yīng)用在得到一個(gè)未定義的message資源時(shí),會(huì)返回null,而不是返回一個(gè)錯(cuò)誤信息。確省是true。
    • maxFileSize
      文件上傳的大小上限,確省為250M
    • bufferSize
      文件上傳時(shí)的緩沖區(qū)的大小,確省為4M
    • tempDir
      設(shè)置用于上傳時(shí)的臨時(shí)目錄。工作目錄會(huì)作為一個(gè)Servlet環(huán)境(Context)的屬性提供。
    • validate
      Are we using the new configuration file format?確省為true。
    • validating

    在解析配置XML文件是是否進(jìn)行有效性的驗(yàn)證。確省為true

    ActionServlet中應(yīng)用了命令設(shè)計(jì)模式。

    一個(gè)Servlet在由容器生成時(shí),首先會(huì)調(diào)用init()方法進(jìn)行初始化,在接到一個(gè)HTTP請(qǐng)求時(shí),調(diào)用相應(yīng)的方法進(jìn)行處理;比如GET請(qǐng)求調(diào)用doGet()方法,POST請(qǐng)求調(diào)用doPost()方法。所以首先看看ActionServlet的init()方法,你就會(huì)很清楚為什么ActionServlet可以完成這些功能了。

    init()


    在它的init()方法中,ActionServlet依次調(diào)用如下protected的方法完成初始化:
    • initActions() -     大家可能還曾有這個(gè)疑問(wèn):Struts為什么可以找到一個(gè)請(qǐng)求URI對(duì)應(yīng)的action類(lèi)呢?答案就在這兒,ActionServlet有一個(gè)actions屬性,類(lèi)型為org.apache.struts.util.FastHashMap,用于存儲(chǔ)以類(lèi)的全名為key的已實(shí)例化的Action類(lèi)。在init()時(shí)首先調(diào)用的就是initActions()方法,在這個(gè)方法中只是簡(jiǎn)單的清除map中的所有的名值對(duì),
      1.         synchronized (actions) {
      2.             actions.setFast(false);
      3.             actions.clear();
      4.             actions.setFast(true);
      5.         }

      首先把a(bǔ)ctions設(shè)為slow模式,這時(shí)對(duì)FastHashMap的訪問(wèn)是線程同步的,然后清除actions中的所有的已存在的名/值對(duì),最后再把a(bǔ)ctions的模式設(shè)為fast。由于FastHashMap是struts在java.util.HashMap的基礎(chǔ)上的一個(gè)擴(kuò)展類(lèi),是為了適應(yīng)多線程、并且對(duì)HashMap的訪問(wèn)大部分是只讀的特殊環(huán)境的需要。大家知道java.util.HashMap是非線程安全的,所以HashMap一般適用于單線程環(huán)境下。org.apache.struts.FastHashMap就是繼承于java.util.HashMap,在其中添加多線程的支持產(chǎn)生的。在fast模式下的工作方式是這樣的:讀取是非線程同步的;寫(xiě)入時(shí)首先克隆當(dāng)前map,然后在這個(gè)克隆上做寫(xiě)入操做,完成后用這個(gè)修改后的克隆版本替換原來(lái)的map。那么在什么時(shí)候會(huì)把Actions類(lèi)添加到這個(gè)map中呢?我們已經(jīng)提到了struts是動(dòng)態(tài)的生成Action類(lèi)的實(shí)例的,在每次ActionServlet接收到一個(gè)GET或POST的HTTP請(qǐng)求時(shí),會(huì)在這個(gè)map中查找對(duì)應(yīng)的Action類(lèi)的實(shí)例,如果不存在,那么就實(shí)例化一個(gè),并放入map中??梢?jiàn)這個(gè)actions屬性起到了對(duì)Action類(lèi)實(shí)例的緩存的作用。
    • initInternal() -     初始化ActionServlet內(nèi)部使用的資源包MessageResources,使用MessageResources.getMessageResources(internalName)得到    internalName為"org.apache.struts.action.ActionResources"對(duì)應(yīng)的ActionResources.properties文件。這個(gè)資源包主要用于ActionServlet處理過(guò)程中的用到的提示信息,這兒不展開(kāi)討論。
    • initDebug() -     從web.xml中讀取本應(yīng)用的debug級(jí)別參數(shù)getServletConfig().getInitParameter("debug"),然后賦給debug屬性。
    • initApplication()-    初始化應(yīng)用資源包,并放置入ServletContext中。
      1.         String factory =getServletConfig().getInitParameter(“factory”);    
      2.         String oldFacory = MessageResourcesFactory.getFactoryClass();
      3.         if (factory !=null)
      4.                 MessageResourcesFactory.setFactoryClass(factory);
      5.         String value = getServletConfig().getInitParameter("application");
      6.         MessageResourcesFactory factoryObject =
      7.                 MessageResourcesFactory.createFactory();
      8.         application = factoryObject.createResources(value);
      9.         MessageResourcesFactory.setFactory(oldFactory); 
      10.         getServletContext().setAttribute(Action.MESSAGES_KEY, application);

      說(shuō)明:文中引用的代碼片斷可能會(huì)省略了一些例外檢查等非主線的內(nèi)容,敬請(qǐng)注意。

      首先從配置文件中讀取factory參數(shù),如果這個(gè)參數(shù)不為空,那么就在MessageResourcesFactory中使用這個(gè)指定的Factory類(lèi);否則,使用默認(rèn)的工廠類(lèi)org.apche.struts.util.PropertyMessageResourceFactory。然后調(diào)用MessageResourcesFactory的靜態(tài)createFactory()方法,生成一個(gè)具體的MessageResourceFactory對(duì)象(注意:MessageResourcesFactory是抽象類(lèi))。這樣就可以調(diào)用這個(gè)具體的MessageResourceFactory的createResource()方法得到配置文件(web.xml)中定義的資源文件了。
      上面的application對(duì)象類(lèi)型為MessageResources。在web.xml中在配置ActionServlet時(shí)可以指定一個(gè)特定的工廠類(lèi)。不能直接MessageResourcesFactory的createResources()方法,因?yàn)檫@個(gè)方法是abstract的。創(chuàng)建factoryObject的過(guò)程如下:
      1.     
      2.         MessageResourceFactory factoryObject=
      3.                 MessageResourcesFactory.createFactory();
      4.         application = factoryObject.createResources(value);

      <li>initMapping() -    為應(yīng)用初始化mapping信息ActionServlet有一個(gè)protected的屬性:mapping,封裝了一個(gè)ActionMapping的對(duì)象集合,以便于管理、查找ActionMapping。mappings是org.apache.struts.action.ActionMappings類(lèi)的實(shí)例。主要有兩個(gè)方法:addMapping(ActionMapping mapping)和findMapping(String path)。ActionMapping也是使用上面提到的org.apache.struts.util.FastHashMap類(lèi)來(lái)存儲(chǔ)所有的ActionMapping對(duì)象。
      1.         mappings.setServlet(this);
      2.         ……
      3.         // Initialize the name of our ActionFormBean implementation class
      4.         value = getServletConfig().getInitParameter("formBean");
      5.         if (value != null)
      6.             formBeanClass = value;
      7.     
      8.         // Initialize the name of our ActionForward implementation class
      9.         value = getServletConfig().getInitParameter("forward");
      10.         if (value != null)
      11.                 forwardClass = value;
      12.         // Initialize the name of our ActionMapping implementation class
      13.         value = getServletConfig().getInitParameter("mapping");
      14.         if (value != null)
      15.                 mappingClass = value;

      在initMapping()中,首先鏈接mappings對(duì)象到本servlet實(shí)例。其實(shí)這句話(huà)的作用很簡(jiǎn)單,在ActionMappings中會(huì)有一個(gè)ActionServlet類(lèi)型的屬性,這個(gè)屬性就界定了這個(gè)ActionMappings對(duì)象所屬的ActionServlet。Struts的實(shí)現(xiàn)比較靈活,其中的ActionFormBean、ActionForward、ActionMapping類(lèi)你完全可以使用自己實(shí)現(xiàn)的子類(lèi),來(lái)定制Struts的工作方式。上面的代碼就從配置文件(web.xml)中讀取formBean、forward、mapping參數(shù),這些參數(shù)就是你定制的ActionFormBean、ActionForward、ActionMapping類(lèi)名。
      1.         // Initialize the context-relative path to our configuration resources
      2.         value = getServletConfig().getInitParameter("config");
      3.         if (value != null)
      4.                 config = value;
      5.                 // Acquire an input stream to our configuration resource
      6.         InputStream input = getServletContext().getResourceAsStream(config);
      7.         Digester digester = null;
      8.                 digester = initDigester(detail);
      9.         try {
      10.                 formBeans.setFast(false);
      11.                 forwards.setFast(false);
      12.                 mappings.setFast(false);
      13.                 digester.parse(input);
      14.                 mappings.setFast(true);
      15.                 forwards.setFast(true);
      16.                 formBeans.setFast(true);
      17.         } catch (SAXException e) {
      18.                 throw new ServletException
      19.         (internal.getMessage("configParse", config), e);
      20.         } finally {
      21.                 input.close();
      22.         }

      從web.xml讀取Struts的配置文件的位置。使用org.apache.struts.digester.Digester解析config參數(shù)標(biāo)示的配置文件,通常為“/WEB-INF/struts-config.xml”,解析出所有的data-source、form-bean、action-mapping、forward。從上面的程序片斷看到,Digester僅僅調(diào)用了一個(gè)parse()方法,那么,Digester是怎樣把解析struts-config.xml文件并把解析的結(jié)果form-bean等信息存儲(chǔ)到屬性變量formBeans等中的呢?你可以注意到在調(diào)用digester.parse(InputStream)之前,首先調(diào)用了initDigester()方法:
      1.         Digester digester = new Digester();
      2.         digester.push(this);
      3.         digester.addObjectCreate("struts-config/action-mappings/action",
      4.                                  mappingClass, "className");
      5.         digester.addSetProperties("struts-config/action-mappings/action");
      6.         digester.addSetNext("struts-config/action-mappings/action",
      7.                             "addMapping",
      8.                             "org.apache.struts.action.ActionMapping");
      9.         digester.addSetProperty
      10.             ("struts-config/action-mappings/action/set-property",
      11.              "property""value");

      在這個(gè)方法中首先生成一個(gè)Digester對(duì)象,然后設(shè)置解析的規(guī)則和回調(diào),如果你對(duì)XML、SAX不是很熟,這兒不必糾纏太深。要注意的是addSetNext()方法,設(shè)置了每一個(gè)要解析元素的Set Next回調(diào)方法,而這個(gè)方法就是由digester解析器的父提供的。上面的片斷中的“addMapping”就是ActionServlet本身定義的一個(gè)方法,將由Digester回調(diào)。Digester就是籍此把解析出的每一個(gè)FormBean、ActionForward、ActionMapping等存儲(chǔ)到屬性變量formBeans、forwards、mappings等中的。
    • initUpload() -    初始化有關(guān)Upload的一些參數(shù),比如:bufferSize、tempDir。
    • initDataSource() -取出在initMapping()中從配置文件中讀取的每一個(gè)DataSource,設(shè)置LogWriter,如果為GenericDataSource的實(shí)例,則打開(kāi)數(shù)據(jù)源。然后,把每個(gè)dataSource放入Context中。
      dataSource.setLogWriter(scw);
      ((GenericDataSource)dataSource).open();
      getServletContext().setAttribute(key,dataSource);
    • initOther() -        設(shè)置其它尚未初始化的的參數(shù)(content、locale、nocache),并發(fā)布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與當(dāng)前Servlet相同的mapping,置入Context。代碼如下;
      1.         Digester digester = new Digester();
      2.         digester.push(this);
      3.         digester.setDebug(debug);
      4.         digester.setValidating(validating);
      5.         digester.addCallMethod(“web-appservlet-mapping”,“addServletMapping”, 2);
      6.         digester.addCallParm(“web-appservlet-mappingservlet-name”, 0);
      7.         digester.addCallParm(“web-appservlet-mappingurl-pattern”, 1);
      8.         InputStream is = getServletContext().getResourceAsStream(“/WEB-INFweb.xml”);
      9.         digester.parse(is); 
      10.         getServletContext().setAttribute(Action.SERVLET_KEY,servletMapping);
    posted @ 2007-04-06 09:48 阿成 閱讀(464) | 評(píng)論 (0)編輯 收藏
    關(guān)鍵字: ? 轉(zhuǎn)貼????

    CSS全稱(chēng)Cascading Style Sheet。層疊式樣式表。從三年前就開(kāi)始使用CSS了,但一直以來(lái)都小看了它。CSS的出現(xiàn)其實(shí)是一次革命,它試圖將網(wǎng)站的內(nèi)容與表現(xiàn)分開(kāi)。
    一、CSS的四種實(shí)現(xiàn)方式:
    1.內(nèi)嵌式:

    2.外鏈?zhǔn)剑?/p>

    3.導(dǎo)入式

    3.屬性式:
    二.CSS的定義:
    選擇對(duì)象{屬性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;}
    三.四種選擇對(duì)象
    1.HTML selector (TagName)
    2.class selector (.NAME)
    3.ID selector (#IDname)
    4.特殊對(duì)象 (a:hover a:link a:visited a:active)
    1.HTML selector
    HTML selector就是HTML的置標(biāo)符,如:DIV、TD、H1。HTML selector的作用范圍是應(yīng)用了該樣式的所有頁(yè)面中的所有該置標(biāo)符。
    例:
    td
    { color: #FF0000;
    }
    -->
    注意:在中沒(méi)有應(yīng)用什么,其中文字自動(dòng)變紅色。
    2.class selector
    定義class selector需要往其名稱(chēng)其加一個(gè)點(diǎn)“.”。如“.classname”。class selector的作用范圍是所有包含“class="classname"”的置標(biāo)符。
    例:
    .fontRed
    { color: #FF0000;
    } -->
    注意:在第二個(gè)中沒(méi)有“class="fontRed"”,所以文字沒(méi)有變紅色。
    3.ID selector
    定義ID selector需要往其名稱(chēng)其加一個(gè)點(diǎn)“#”。如“#IDname”。ID selector的作用范圍是所有包含“ID="classname"”的置標(biāo)符。
    例:

    #fontRed
    { color: #FF0000;
    } -->
    注意:在第二個(gè)中沒(méi)有“ID="fontRed"”,所以文字沒(méi)有變紅色。
    4.特殊對(duì)象
    特殊對(duì)象包括四種,是針對(duì)鏈接對(duì)象設(shè)置的:
    a:hover 鼠標(biāo)移上時(shí)的超鏈接
    a:link 常規(guī),非訪問(wèn)超鏈接
    a:visited 訪問(wèn)過(guò)的超鏈接
    a:active 鼠標(biāo)點(diǎn)擊時(shí)的超鏈接
    特殊對(duì)象的作用范圍是所有置標(biāo)符(這句話(huà)有待商榷,因?yàn)橄旅婧芸炀陀幸环N方法可以把“所有”兩個(gè)字推翻)。
    例:
    a:hover
    { color: #0000FF;
    text-decoration: underline;
    } -->
    注意下面,很有用!?。?
    a.classname:hover
    a#IDname:hover
    這兩種寫(xiě)法,是分別配合.classname與#IDname使用的。它的作用范圍變成了所有包含“class="classname"”或“ID="IDname"”的置標(biāo)符。這種寫(xiě)法,可以幫助你在同一頁(yè)面中實(shí)現(xiàn)多種a:hover效果,可以看一下藝網(wǎng)的主頁(yè)上導(dǎo)航欄文字與普通文章標(biāo)題在鼠標(biāo)時(shí)的區(qū)別。
    四.應(yīng)用:
    1.置標(biāo)符 自動(dòng)應(yīng)用
    2.特制類(lèi) class="NAME"
    3.ID ID="IDname"
    4.特殊對(duì)象 自動(dòng)應(yīng)用
    五.CSS屬性
    CSS的屬性有很多,像上文中用到最多的color,表示文字的顏色。background-color表示背景色。這個(gè)是最主要的,但是因?yàn)闆](méi)有什么難度,參考一下相關(guān)手冊(cè)就可以了。

    注明兩點(diǎn)
    第一點(diǎn):css的方式現(xiàn)在一般都采用外部連接,這個(gè)用起來(lái)方便,編譯起來(lái)也方便
    第二點(diǎn):我用的是frontpage2003,很多css的參數(shù)都會(huì)自動(dòng)提示,似乎好像以前我沒(méi)有用到過(guò)~~dw有的

    CSS 標(biāo)簽屬性/屬性參考
    這里列出了目前支持的樣式表(CSS)標(biāo)簽屬性。標(biāo)有星號(hào)(*)的標(biāo)簽屬性可于 Microsoft? Internet Explorer 5 中使用。標(biāo)有兩個(gè)星號(hào)(**)的標(biāo)簽屬性可于 Internet Explorer 5.5 中使用。帶有兩個(gè)加號(hào)(++)的標(biāo)簽屬性可于 Internet Explorer 6 中使用。如果某個(gè)標(biāo)簽屬性或?qū)傩砸呀?jīng)提交給萬(wàn)維網(wǎng)協(xié)會(huì)(W3C)但尚未作為標(biāo)準(zhǔn)發(fā)布,則標(biāo)有“已提交”。若某個(gè)標(biāo)簽屬性或?qū)傩约任刺峤唤o W3C 也不是標(biāo)準(zhǔn),將標(biāo)有“擴(kuò)展”。

    CSS 標(biāo)簽屬性/屬性

    行為屬性 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

    分類(lèi)屬性 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

    偽類(lèi)和其它屬性 :active

    @charset
    cursor
    :first-letter**
    :first-line**
    @font-face
    :hover
    @import
    !important
    :link
    @media*
    @page**
    :visited
    有關(guān)表格邊框的css語(yǔ)法整理

    我們知道Dreamweaver在表格制作方面做得非常出色,但是在某些時(shí)候還是必須結(jié)合css才能達(dá)到一些特定效果,下面我們先把有關(guān)表格邊框的css語(yǔ)法整理出來(lái),然后另外介紹怎樣用css美化表格的邊框。

      有關(guān)表格邊框的css語(yǔ)法

      具體內(nèi)容包括:上邊框?qū)挾取⒂疫吙驅(qū)挾?、下邊框?qū)挾?、左邊框?qū)挾?、邊框?qū)挾取⑦吙蝾伾?、邊框樣式、上邊框、下邊框、左邊框、右邊框、邊框、寬度、高度、有關(guān)標(biāo)簽等。

       1.上邊框?qū)挾?/p>

      語(yǔ)法: border-top-width: <值>

      允許值: thin | medium | thick | <長(zhǎng)度>

      初始值: medium

      適用于: 所有對(duì)象

      向下兼容: 否

      上邊框?qū)挾葘傩杂糜谥付ㄒ粋€(gè)元素上邊框的寬度。值可以是三個(gè)關(guān)鍵字其中的一個(gè),都不受字體大小或長(zhǎng)度的影響,可以用于實(shí)現(xiàn)成比例的寬度。不允許使用負(fù)值。也可以用在上邊框、邊框的寬度或邊框的屬性略寫(xiě)。

      2.右邊框?qū)挾?/p>

      語(yǔ)法: border-right-width: <值>

      允許值: thin | medium | thick | <長(zhǎng)度>

      初始值: medium

      適用于: 所有對(duì)象

      向下兼容: 否

      右邊框?qū)挾葘傩杂糜谥付ㄔ氐挠疫吙虻膶挾?。值可以是三個(gè)關(guān)鍵字其中的一個(gè),都不受字體大小或長(zhǎng)度的影響,可以用于實(shí)現(xiàn)成比例的寬度。不允許使用負(fù)值。也可以用在右邊框、邊框的寬度或邊框的屬性略寫(xiě)。

       3.下邊框?qū)挾?/p>

      語(yǔ)法: border-bottom-width: <值>

      允許值: thin | medium | thick | <長(zhǎng)度>

      初始值: medium

      適用于: 所有對(duì)象

      向下兼容: 否

      下邊框?qū)挾葘傩杂糜谥付ㄔ氐南逻吙虻膶挾取V悼梢允侨齻€(gè)關(guān)鍵字其中的一個(gè),都不受字體大小或長(zhǎng)度的影響,可以用于實(shí)現(xiàn)成比例的寬度。不允許使用負(fù)值。也可以用在下邊框、邊框的寬度或邊框的屬性略寫(xiě)。

       4.左邊框?qū)挾?/p>

      語(yǔ)法: border-left-width: <值>

      允許值: thin | medium | thick | <長(zhǎng)度>

      初始值: medium

      適用于: 所有對(duì)象

      向下兼容: 否

      左邊框?qū)挾葘傩杂糜谥付ㄔ氐淖筮吙虻膶挾取V悼梢允侨齻€(gè)關(guān)鍵字其中的一個(gè),都不受字體大小或長(zhǎng)度的影響,可以用于實(shí)現(xiàn)成比例的寬度。不允許使用負(fù)值。也可以用在左邊框、邊框的寬度或邊框的屬性略寫(xiě)。

      5.邊框?qū)挾?/p>

      語(yǔ)法: border-width: <值>

      允許值: [ thin | medium | thick | <長(zhǎng)度> ]{1,4}

      初始值: 未定義

      適用于: 所有對(duì)象

      向下兼容: 否

      邊框?qū)挾葘傩杂靡坏剿膫€(gè)值來(lái)設(shè)置元素的邊界,值是一個(gè)關(guān)鍵字或長(zhǎng)度。不允許使用負(fù)值長(zhǎng)度。如果四個(gè)值都給出了,它們分別應(yīng)用于上、右、下和左邊框的式樣。如果給出一個(gè)值,它將被運(yùn)用到各邊上。如果兩個(gè)或三個(gè)值給出了,省略了的值與對(duì)邊相等。 這個(gè)屬性是上邊框?qū)挾?、右邊框?qū)挾?、下邊框?qū)挾群妥筮吙驅(qū)挾葘傩缘穆詫?xiě)。也可以使用略寫(xiě)的邊框?qū)傩浴?/p>

      6.邊框顏色

      語(yǔ)法: border-color: <值>

      允許值: <顏色>{1,4}

      初始值: 顏色屬性的值

      適用于: 所有對(duì)象

      向下兼容: 否

      邊框顏色屬性設(shè)置一個(gè)元素的邊框顏色??梢允褂靡坏剿膫€(gè)關(guān)鍵字。如果四個(gè)值都給出了,它們分別應(yīng)用于上、右、下和左邊框的式樣。如果給出一個(gè)值,它將被運(yùn)用到各邊上。如果兩個(gè)或三個(gè)值給出了,省略了的值與對(duì)邊相等。也可以使用略寫(xiě)的邊框?qū)傩浴?/p>

      7.邊框樣式

      語(yǔ)法: border-style: <值>

      允許值: [ none | dotted | dashed | solid | double | groove | ridge | inset | outset ]{1,4}

      初始值: none

      適用于: 所有對(duì)象

      向下兼容: 否

      邊框樣式屬性用于設(shè)置一個(gè)元素邊框的樣式。這個(gè)屬性必須用于指定可見(jiàn)的邊框??梢允褂靡坏剿膫€(gè)關(guān)鍵字。如果四個(gè)值都給出了,它們分別應(yīng)用于上、右、下和左邊框的式樣。如果給出一個(gè)值,它將被運(yùn)用到各邊上。如果兩個(gè)或三個(gè)值給出了,省略了的值與對(duì)邊相等。也可以使用略寫(xiě)的邊框?qū)傩浴?/p>

      none:無(wú)樣式;
      dotted:點(diǎn)線;
      dashed:虛線;
      solid:實(shí)線;
      double:雙線;
      groove:槽線;
      ridge:脊線;
      inset:內(nèi)凹;
      outset:外凸。
    8.上邊框

      語(yǔ)法: border-top: <值>

      允許值: <上邊框?qū)挾?gt; || <邊框式樣> || <顏色>

      初始值: 未定義

      適用于: 所有對(duì)象

      向下兼容: 否

      上邊框?qū)傩允且粋€(gè)用于設(shè)置一個(gè)元素上邊框的寬度、式樣和顏色的略寫(xiě)。注意只能給出一個(gè)邊框式樣。也可以使用略寫(xiě)的邊框?qū)傩浴?/p>

      9.右邊框

      語(yǔ)法: border-right: <值>

      允許值: <右邊框?qū)挾?gt; || <邊框式樣> || <顏色>

      初始值: 未定義

      適用于: 所有對(duì)象

      向下兼容: 否

      右邊框?qū)傩允且粋€(gè)用于設(shè)置一個(gè)元素右邊框的寬度、式樣、和顏色的略寫(xiě)。注意只能給出一個(gè)邊框式樣。也可以使用略寫(xiě)的邊框?qū)傩??! ?

      10.下邊框

      語(yǔ)法: border-bottom: <值>

      允許值: <下邊框?qū)挾?gt; || <邊框式樣> || <顏色>

      初始值: 未定義

      適用于: 所有對(duì)象

      向下兼容: 否

      下邊框?qū)傩允且粋€(gè)用于設(shè)置一個(gè)元素的下邊框的寬度、式樣和顏色的略寫(xiě)。注意只能給出一個(gè)邊框式樣。也可以使用略寫(xiě)的邊框?qū)傩浴?/p>

      11.左邊框

      語(yǔ)法: border-left: <值>

      允許值: <左邊框?qū)挾?gt; || <邊框式樣> || <顏色>

      初始值: 未定義

      適用于: 所有對(duì)象

      向下兼容: 否

      左邊框?qū)傩允且粋€(gè)用于設(shè)置一個(gè)元素左邊框的寬度、式樣和顏色的略寫(xiě)。注意只能給出一個(gè)邊框式樣。也可以使用略寫(xiě)的邊框?qū)傩浴?/p>

       12.邊框

      語(yǔ)法: border: <值>

      允許值: <邊框?qū)挾?gt; || <邊框式樣> || <顏色>

      初始值: 未定義

      適用于: 所有對(duì)象

      向下兼容: 否

      邊框?qū)傩允且粋€(gè)用于設(shè)置一個(gè)元素邊框的寬度、式樣和顏色的略寫(xiě)。

      邊框聲明的例子包括:

      H2 { border: groove 3em }
      A:link { border: solid blue }
      A:visited { border: thin dotted #800080 }
      A:active { border: thick double red }

      邊框?qū)傩灾荒茉O(shè)置四種邊框;只能給出一組邊框的寬度和式樣。為了給出一個(gè)元素的四種邊框的不同的值,網(wǎng)頁(yè)制作者必須用一個(gè)或更多的屬性,如:上邊框、右邊框、下邊框、左邊框、邊框顏色、邊框?qū)挾?、邊框式樣、上邊框?qū)挾?、右邊框?qū)挾取⑾逻吙驅(qū)挾然蜃筮吙驅(qū)挾取?

      13.寬度

      語(yǔ)法: width: <值>

      允許值: <長(zhǎng)度> | <百分比> | auto

      初始值: auto

      適用于: 塊級(jí)和替換元素

      向下兼容: 否

      寬度屬性的初始值為“auto”,即為該元素的原有寬度(有就是元素自己的寬度)。百分比參考上級(jí)元素的寬度。不允許使用負(fù)的長(zhǎng)度值。

      14.高度

      語(yǔ)法: height: <值>

      允許值: <長(zhǎng)度> | auto

      初始值: auto

      適用于: 塊級(jí)和替換元素

      向下兼容: 否

      高度屬性的初始值為“auto”,即為該元素的原有高度(有就是元素自己的高度,)。百分比參考上級(jí)元素的寬度。不允許使用負(fù)的長(zhǎng)度值。

      15.有關(guān)標(biāo)簽

      table:表格標(biāo)簽,對(duì)整個(gè)表格樣式的定義要放在table中;
      td:?jiǎn)卧駱?biāo)簽,對(duì)單元格樣式的定義要放在td中。

    css濾鏡

    隨著網(wǎng)頁(yè)設(shè)計(jì)技術(shù)的發(fā)展,人們已經(jīng)不滿(mǎn)足于原有的一些HTML標(biāo)記,而是希望能夠?yàn)轫?yè)面添加一些多媒體屬性,例如濾鏡的和漸變的效果。CSS技術(shù)的飛快發(fā)展使這些需求成為了現(xiàn)實(shí)。從現(xiàn)在開(kāi)始我要為大家介紹一個(gè)新的CSS擴(kuò)展部分:CSS濾鏡屬性(Filter Properties)。使用這種技術(shù)可以把可視化的濾鏡和轉(zhuǎn)換效果添加到一個(gè)標(biāo)準(zhǔn)的HTML元素上,例如圖片、文本容器、以及其他一些對(duì)象。對(duì)于濾鏡和漸變效果,前者是基礎(chǔ),因?yàn)楹笳呔褪菫V鏡效果的不斷變化和演示更替。當(dāng)濾鏡和漸變效果結(jié)合到一個(gè)基本的SCRIPT小程序中后,網(wǎng)頁(yè)設(shè)計(jì)者就可以擁有一個(gè)建立動(dòng)態(tài)交互文檔的強(qiáng)大工具。也就是CSS FILTER+ SCRIPT, 這就說(shuō)明想要建立動(dòng)態(tài)的文檔還要一些SCRIPT (腳本語(yǔ)言)的基礎(chǔ)。
    可視化濾鏡屬性只能用在HTML控件元素上。所謂的HTML空間元素就是它們?cè)陧?yè)面上定義了一個(gè)矩形空間,瀏覽器的窗口可以顯示這些空間。下面列出了HTML合法的控件和它們的說(shuō)明。

    備注:可惜只有IE4.0以上支持,如果是別的瀏覽器,那就.......

    元素 說(shuō)明
    BODY 網(wǎng)頁(yè)文檔的主體元素,所有的可見(jiàn)范圍都在<BODY>元素內(nèi)
    BUTTON 表單域的按鈕,可以有“發(fā)送(submit)”、“重置(reset)”等形式
    DIV 定義了網(wǎng)頁(yè)上的一個(gè)區(qū)域,這個(gè)區(qū)域的高度、寬度或者絕對(duì)位置都是以知的
    IMG 圖片元素,通過(guò)指定“src"屬性來(lái)指定圖片的來(lái)源
    INPUT 輸入表單域
    MARQUEE 移動(dòng)字幕效果
    SPAN 定義了網(wǎng)頁(yè)上的一個(gè)區(qū)域,這個(gè)區(qū)域的高度、寬度或者絕對(duì)位置都是以知的
    TABLE 表格
    TD 表格數(shù)據(jù)單元格
    TEXTAREA 文本區(qū)域
    TFOOT 多行輸入文本框
    TH 表格標(biāo)題單元格
    THEAD 表格標(biāo)題
    TR 表格行

     

    IE4.0以上支持的濾鏡屬性表

    濾鏡效果 描述
    Alpha 設(shè)置透明度
    Blru 建立模糊效果
    Chroma 把指定的顏色設(shè)置為透明
    DropShadow 建立一種偏移的影象輪廓,即投射陰影
    FlipH 水平反轉(zhuǎn)
    FlipV 垂直反轉(zhuǎn)
    Glow 為對(duì)象的外邊界增加光效
    Grayscale 降低圖片的彩色度
    Invert 將色彩、飽和度以及亮度值完全反轉(zhuǎn)建立底片效果
    Light 在一個(gè)對(duì)象上進(jìn)行燈光投影
    Mask 為一個(gè)對(duì)象建立透明膜
    Shadow 建立一個(gè)對(duì)象的固體輪廓,即陰影效果
    Wave 在X軸和Y軸方向利用正弦波紋打亂圖片
    Xray 只顯示對(duì)象的輪廓

    1、Alpha 濾鏡

    語(yǔ)法:{FILTER:ALPHA(opacity=opacity,finishopacity=finishopacity,style=style,startx=startx,
    starty=starty,finishx=finishx,finishy=finishy)}

    "Alpha"屬性是把一個(gè)目標(biāo)元素與背景混合。設(shè)計(jì)者可以指定數(shù)值來(lái)控制混合的程度。這種“與背景混合”通俗地說(shuō)就是一個(gè)元素的透明度。通過(guò)指定坐標(biāo),可以指定點(diǎn)、線、面的透明度。他們的參數(shù)含義分別如下:
    “opacity"代表透明度水準(zhǔn)。默認(rèn)的范圍是從0 到 100,他們其實(shí)是百分比的形式。也就是說(shuō),0代表完全透明,100代表完全不透明。”finishopacity"是一個(gè)可選參數(shù),如果想要設(shè)置漸變的透明效果,就可以使用他們來(lái)指定結(jié)束時(shí)的透明度。范圍也是0 到 100?!皊tyle" 參數(shù)指定了透明區(qū)域的形狀特征。其中0代表統(tǒng)一形狀、1代表線形、2代表放射狀、3代表長(zhǎng)方形?!盨TARTX“和”STARTY“代表漸變透明效果的開(kāi)始X和Y坐標(biāo)。”FINISHX“和”FINISHY“代表漸變透明效果結(jié)束X和Y 的坐標(biāo)。

    效果如下:

    2、Blur 濾鏡

    語(yǔ)法:對(duì)于HTML:{ilter:blur(add=add,direction=direction,strength=strength)}
    對(duì)于Script語(yǔ)言: [oblurfilter=] object.filters.blur
    用手指在一幅尚未干透的油畫(huà)上迅速劃過(guò)時(shí),畫(huà)面就會(huì)變得模糊?!盉lur"就是產(chǎn)生同樣的模糊效果。
    “ADD”參數(shù)是一個(gè)布爾判斷“TRUE(默認(rèn))”或者“FALSE”。它指定圖片是否被改變成印象派的模糊效果。模糊效果是按順時(shí)針的方向進(jìn)行的,“DIRECTION”參數(shù)用來(lái)設(shè)置模糊的方向。其中0度代表垂直向上,然后每45度為一個(gè)單位。它的默認(rèn)值是向左的270度?!癝TRENGTH“值只能使用整數(shù)來(lái)指定,她代表有多少像素的寬度將受到模糊影響。默認(rèn)是5個(gè)。對(duì)于網(wǎng)頁(yè)上的字體,如果設(shè)置他的模糊”ADD=1“,那么這些字體的效果會(huì)非常好看的。如下:
    filter:blur(add=ture,direction=135,strength=10)

    3、FlipH, FlipV 濾鏡

    語(yǔ)法:{filter:filph} ,{filter:filpv} 分別是水平反轉(zhuǎn)和垂直反轉(zhuǎn),具體如下:

    4、Chroma 濾鏡

    語(yǔ)法:{filter:chroma(color=color)}
    使用”Chroma"屬性可以設(shè)置一個(gè)對(duì)象中指定的顏色為透明色,參數(shù)COLOR即要透明的顏色。下面是蘭色文字,然后用Chroma 濾鏡過(guò)濾掉蘭色,就成了下面的樣子。
    filter:chroma(color=blue)

    滴水檐坊

    5、DropShadow 濾鏡

    語(yǔ)法:{filter:dropshadow(color=color,offx=ofx,offy=offy,positive=positive)}

    “DropShaow"顧名思義就是添加對(duì)象的陰影效果。其工作原理是建立一個(gè)偏移量,加上較深。"Color"代表投射陰影的顏色,"offx"和"offy"分別是X方向和Y方向陰影的餓偏移量。"Positive"參數(shù)是一個(gè)布爾值,如果為“TRUE(非0)”,那么就為任何的非透明像素建立可見(jiàn)的投影。如果為“FASLE(0)”,那么就為透明的像素部分建立透明效果

    6、Glow 濾鏡

    語(yǔ)法:{filter:glow(color=color,strength)}
    當(dāng)對(duì)一個(gè)對(duì)象使用"glow"屬性后,這個(gè)對(duì)象的邊緣就會(huì)產(chǎn)生類(lèi)似發(fā)光的效果?!癈OLOR”是指定發(fā)光的顏色,“STRENGTH”則是強(qiáng)度的表現(xiàn),可以從1到255之間的任何整數(shù)來(lái)指定這個(gè)力度。
    filter:glow(color=red,strength=10) 后的效果

    7、Gray ,Invert,Xray 濾鏡

    語(yǔ)法:{filter:gray} ,{filter:invert},{filter:xray}

    Gray濾鏡是把一張圖片變成灰度圖;Invert濾鏡是把對(duì)象的可視化屬性全部翻轉(zhuǎn),包括色彩、飽和度、和亮度值;Xray濾鏡是讓對(duì)象反映出它的輪廓并把這些輪廓加亮,也就是所謂的“X”光片。

    效果如下:

    、Light 濾鏡

    語(yǔ)法:Filter{light}

    這個(gè)屬性模擬光源的投射效果。一旦為對(duì)象定義了“LIGHT"濾鏡屬性,那么就可以調(diào)用它的“方法(Method)"來(lái)設(shè)置或者改變屬性?!癓IGHT"可用的方法有:

    AddAmbient 加入包圍的光源
    AddCone 加入錐形光源
    AddPoint 加入點(diǎn)光源
    Changcolor 改變光的顏色
    Changstrength 改變光源的強(qiáng)度
    Clear 清除所有的光源
    MoveLight 移動(dòng)光源
    可以定義光源的虛擬位置,以及通過(guò)調(diào)整X軸和Y軸的數(shù)值來(lái)控制光源焦點(diǎn)的位置,還可以調(diào)整光源的形式(點(diǎn)光源或者錐形光源)指定光源是否模糊邊界、光源的顏色、亮度等屬性。如果動(dòng)態(tài)的設(shè)置光源,可能回產(chǎn)生一些意想不到的效果。后面幾頁(yè)會(huì)有具體范例。

    9、Mask 濾鏡

    語(yǔ)法:{filter:mask(color=color)}

    使用"MASK"屬性可以為對(duì)象建立一個(gè)覆蓋于表面的膜,其效果就象戴者有色眼鏡看物體一樣。

    10、Shadow 濾鏡

    語(yǔ)法:{filter:shadow(color=color,direction=direction)}

    利用“Shadow”屬性可以在指定的方向建立物體的投影,COLOR是投影色,DIRECTION是設(shè)置投影的方向。其中0度代表垂直向上,然后每45度為一個(gè)單位。它的默認(rèn)值是向左的270度。

    filter:shadow(color=red,direction=225)
    filter:shadow(color=blue,direction=225)
    filter:shadow(color=gray,direction=225)
    效果分別如下:

    11、Wave 濾鏡 語(yǔ)法:{filter:wave(add=add,freq=freq,lightstrength=strength,phase=phase,strength=strength)}
    "wave" 屬性把對(duì)象按垂直的波形樣式打亂。默認(rèn)是“TRUE(非0)”,
    “ADD”表示是否要把對(duì)象按照波形樣式打亂,

    “FREQ”是波紋的頻率,也就是指定在對(duì)象上一共需要產(chǎn)生多少個(gè)完整的波紋,

    “LIGHTSTRENGTH”參數(shù)可以對(duì)于波紋增強(qiáng)光影的效果,范圍0----100,

    “PHASE”參數(shù)用來(lái)設(shè)置正弦波的偏移量。

    “STRENGTH”代表振幅大小。

    posted @ 2006-10-25 19:11 阿成 閱讀(315) | 評(píng)論 (0)編輯 收藏

    Java虛擬機(jī)的深入研究

    作者:劉學(xué)超

    1??Java技術(shù)與Java虛擬機(jī)

    說(shuō)起Java,人們首先想到的是Java編程語(yǔ)言,然而事實(shí)上,Java是一種技術(shù),它由四方面組成: Java編程語(yǔ)言、Java類(lèi)文件格式、Java虛擬機(jī)和Java應(yīng)用程序接口(Java API)。它們的關(guān)系如下圖所示:

    圖1??Java四個(gè)方面的關(guān)系

    運(yùn)行期環(huán)境代表著Java平臺(tái),開(kāi)發(fā)人員編寫(xiě)Java代碼(.java文件),然后將之編譯成字節(jié)碼(.class文件)。最后字節(jié)碼被裝入內(nèi)存,一旦字節(jié)碼進(jìn)入虛擬機(jī),它就會(huì)被解釋器解釋執(zhí)行,或者是被即時(shí)代碼發(fā)生器有選擇的轉(zhuǎn)換成機(jī)器碼執(zhí)行。從上圖也可以看出Java平臺(tái)由Java虛擬機(jī)和Java應(yīng)用程序接口搭建,Java語(yǔ)言則是進(jìn)入這個(gè)平臺(tái)的通道,用Java語(yǔ)言編寫(xiě)并編譯的程序可以運(yùn)行在這個(gè)平臺(tái)上。這個(gè)平臺(tái)的結(jié)構(gòu)如下圖所示:

    在Java平臺(tái)的結(jié)構(gòu)中, 可以看出,Java虛擬機(jī)(JVM) 處在核心的位置,是程序與底層操作系統(tǒng)和硬件無(wú)關(guān)的關(guān)鍵。它的下方是移植接口,移植接口由兩部分組成:適配器和Java操作系統(tǒng), 其中依賴(lài)于平臺(tái)的部分稱(chēng)為適配器;JVM 通過(guò)移植接口在具體的平臺(tái)和操作系統(tǒng)上實(shí)現(xiàn);在JVM 的上方是Java的基本類(lèi)庫(kù)和擴(kuò)展類(lèi)庫(kù)以及它們的API, 利用Java API編寫(xiě)的應(yīng)用程序(application) 和小程序(Java applet) 可以在任何Java平臺(tái)上運(yùn)行而無(wú)需考慮底層平臺(tái), 就是因?yàn)橛蠮ava虛擬機(jī)(JVM)實(shí)現(xiàn)了程序與操作系統(tǒng)的分離,從而實(shí)現(xiàn)了Java 的平臺(tái)無(wú)關(guān)性。

    那么到底什么是Java虛擬機(jī)(JVM)呢?通常我們談?wù)揓VM時(shí),我們的意思可能是:

    1. 對(duì)JVM規(guī)范的的比較抽象的說(shuō)明;
    2. 對(duì)JVM的具體實(shí)現(xiàn);
    3. 在程序運(yùn)行期間所生成的一個(gè)JVM實(shí)例。

    對(duì)JVM規(guī)范的的抽象說(shuō)明是一些概念的集合,它們已經(jīng)在書(shū)《The Java Virtual Machine Specification》(《Java虛擬機(jī)規(guī)范》)中被詳細(xì)地描述了;對(duì)JVM的具體實(shí)現(xiàn)要么是軟件,要么是軟件和硬件的組合,它已經(jīng)被許多生產(chǎn)廠商所實(shí)現(xiàn),并存在于多種平臺(tái)之上;運(yùn)行Java程序的任務(wù)由JVM的運(yùn)行期實(shí)例單個(gè)承擔(dān)。在本文中我們所討論的Java虛擬機(jī)(JVM)主要針對(duì)第三種情況而言。它可以被看成一個(gè)想象中的機(jī)器,在實(shí)際的計(jì)算機(jī)上通過(guò)軟件模擬來(lái)實(shí)現(xiàn),有自己想象中的硬件,如處理器、堆棧、寄存器等,還有自己相應(yīng)的指令系統(tǒng)。

    JVM在它的生存周期中有一個(gè)明確的任務(wù),那就是運(yùn)行Java程序,因此當(dāng)Java程序啟動(dòng)的時(shí)候,就產(chǎn)生JVM的一個(gè)實(shí)例;當(dāng)程序運(yùn)行結(jié)束的時(shí)候,該實(shí)例也跟著消失了。下面我們從JVM的體系結(jié)構(gòu)和它的運(yùn)行過(guò)程這兩個(gè)方面來(lái)對(duì)它進(jìn)行比較深入的研究。

    2??Java虛擬機(jī)的體系結(jié)構(gòu)

    剛才已經(jīng)提到,JVM可以由不同的廠商來(lái)實(shí)現(xiàn)。由于廠商的不同必然導(dǎo)致JVM在實(shí)現(xiàn)上的一些不同,然而JVM還是可以實(shí)現(xiàn)跨平臺(tái)的特性,這就要?dú)w功于設(shè)計(jì)JVM時(shí)的體系結(jié)構(gòu)了。

    我們知道,一個(gè)JVM實(shí)例的行為不光是它自己的事,還涉及到它的子系統(tǒng)、存儲(chǔ)區(qū)域、數(shù)據(jù)類(lèi)型和指令這些部分,它們描述了JVM的一個(gè)抽象的內(nèi)部體系結(jié)構(gòu),其目的不光規(guī)定實(shí)現(xiàn)JVM時(shí)它內(nèi)部的體系結(jié)構(gòu),更重要的是提供了一種方式,用于嚴(yán)格定義實(shí)現(xiàn)時(shí)的外部行為。每個(gè)JVM都有兩種機(jī)制,一個(gè)是裝載具有合適名稱(chēng)的類(lèi)(類(lèi)或是接口),叫做類(lèi)裝載子系統(tǒng);另外的一個(gè)負(fù)責(zé)執(zhí)行包含在已裝載的類(lèi)或接口中的指令,叫做運(yùn)行引擎。每個(gè)JVM又包括方法區(qū)、堆、Java棧、程序計(jì)數(shù)器和本地方法棧這五個(gè)部分,這幾個(gè)部分和類(lèi)裝載機(jī)制與運(yùn)行引擎機(jī)制一起組成的體系結(jié)構(gòu)圖為:

    圖3??JVM的體系結(jié)構(gòu)

    JVM的每個(gè)實(shí)例都有一個(gè)它自己的方法域和一個(gè)堆,運(yùn)行于JVM內(nèi)的所有的線程都共享這些區(qū)域;當(dāng)虛擬機(jī)裝載類(lèi)文件的時(shí)候,它解析其中的二進(jìn)制數(shù)據(jù)所包含的類(lèi)信息,并把它們放到方法域中;當(dāng)程序運(yùn)行的時(shí)候,JVM把程序初始化的所有對(duì)象置于堆上;而每個(gè)線程創(chuàng)建的時(shí)候,都會(huì)擁有自己的程序計(jì)數(shù)器和Java棧,其中程序計(jì)數(shù)器中的值指向下一條即將被執(zhí)行的指令,線程的Java棧則存儲(chǔ)為該線程調(diào)用Java方法的狀態(tài);本地方法調(diào)用的狀態(tài)被存儲(chǔ)在本地方法棧,該方法棧依賴(lài)于具體的實(shí)現(xiàn)。

    下面分別對(duì)這幾個(gè)部分進(jìn)行說(shuō)明。

    執(zhí)行引擎處于JVM的核心位置,在Java虛擬機(jī)規(guī)范中,它的行為是由指令集所決定的。盡管對(duì)于每條指令,規(guī)范很詳細(xì)地說(shuō)明了當(dāng)JVM執(zhí)行字節(jié)碼遇到指令時(shí),它的實(shí)現(xiàn)應(yīng)該做什么,但對(duì)于怎么做卻言之甚少。Java虛擬機(jī)支持大約248個(gè)字節(jié)碼。每個(gè)字節(jié)碼執(zhí)行一種基本的CPU運(yùn)算,例如,把一個(gè)整數(shù)加到寄存器,子程序轉(zhuǎn)移等。Java指令集相當(dāng)于Java程序的匯編語(yǔ)言。

    Java指令集中的指令包含一個(gè)單字節(jié)的操作符,用于指定要執(zhí)行的操作,還有0個(gè)或多個(gè)操作數(shù),提供操作所需的參數(shù)或數(shù)據(jù)。許多指令沒(méi)有操作數(shù),僅由一個(gè)單字節(jié)的操作符構(gòu)成。

    虛擬機(jī)的內(nèi)層循環(huán)的執(zhí)行過(guò)程如下: 
    do{ 
    取一個(gè)操作符字節(jié); 
    根據(jù)操作符的值執(zhí)行一個(gè)動(dòng)作; 
    }while(程序未結(jié)束)
    

    由于指令系統(tǒng)的簡(jiǎn)單性,使得虛擬機(jī)執(zhí)行的過(guò)程十分簡(jiǎn)單,從而有利于提高執(zhí)行的效率。指令中操作數(shù)的數(shù)量和大小是由操作符決定的。如果操作數(shù)比一個(gè)字節(jié)大,那么它存儲(chǔ)的順序是高位字節(jié)優(yōu)先。例如,一個(gè)16位的參數(shù)存放時(shí)占用兩個(gè)字節(jié),其值為:

    第一個(gè)字節(jié)*256+第二個(gè)字節(jié)字節(jié)碼。

    指令流一般只是字節(jié)對(duì)齊的。指令tableswitch和lookup是例外,在這兩條指令內(nèi)部要求強(qiáng)制的4字節(jié)邊界對(duì)齊。

    對(duì)于本地方法接口,實(shí)現(xiàn)JVM并不要求一定要有它的支持,甚至可以完全沒(méi)有。Sun公司實(shí)現(xiàn)Java本地接口(JNI)是出于可移植性的考慮,當(dāng)然我們也可以設(shè)計(jì)出其它的本地接口來(lái)代替Sun公司的JNI。但是這些設(shè)計(jì)與實(shí)現(xiàn)是比較復(fù)雜的事情,需要確保垃圾回收器不會(huì)將那些正在被本地方法調(diào)用的對(duì)象釋放掉。

    Java的堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),類(lèi)的實(shí)例(對(duì)象)從中分配空間,它的管理是由垃圾回收來(lái)負(fù)責(zé)的:不給程序員顯式釋放對(duì)象的能力。Java不規(guī)定具體使用的垃圾回收算法,可以根據(jù)系統(tǒng)的需求使用各種各樣的算法。

    Java方法區(qū)與傳統(tǒng)語(yǔ)言中的編譯后代碼或是Unix進(jìn)程中的正文段類(lèi)似。它保存方法代碼(編譯后的java代碼)和符號(hào)表。在當(dāng)前的Java實(shí)現(xiàn)中,方法代碼不包括在垃圾回收堆中,但計(jì)劃在將來(lái)的版本中實(shí)現(xiàn)。每個(gè)類(lèi)文件包含了一個(gè)Java類(lèi)或一個(gè)Java界面的編譯后的代碼??梢哉f(shuō)類(lèi)文件是Java語(yǔ)言的執(zhí)行代碼文件。為了保證類(lèi)文件的平臺(tái)無(wú)關(guān)性,Java虛擬機(jī)規(guī)范中對(duì)類(lèi)文件的格式也作了詳細(xì)的說(shuō)明。其具體細(xì)節(jié)請(qǐng)參考Sun公司的Java虛擬機(jī)規(guī)范。

    Java虛擬機(jī)的寄存器用于保存機(jī)器的運(yùn)行狀態(tài),與微處理器中的某些專(zhuān)用寄存器類(lèi)似。Java虛擬機(jī)的寄存器有四種:

    1. pc: Java程序計(jì)數(shù)器;
    2. optop: 指向操作數(shù)棧頂端的指針;
    3. frame: 指向當(dāng)前執(zhí)行方法的執(zhí)行環(huán)境的指針;。
    4. vars: 指向當(dāng)前執(zhí)行方法的局部變量區(qū)第一個(gè)變量的指針。

    在上述體系結(jié)構(gòu)圖中,我們所說(shuō)的是第一種,即程序計(jì)數(shù)器,每個(gè)線程一旦被創(chuàng)建就擁有了自己的程序計(jì)數(shù)器。當(dāng)線程執(zhí)行Java方法的時(shí)候,它包含該線程正在被執(zhí)行的指令的地址。但是若線程執(zhí)行的是一個(gè)本地的方法,那么程序計(jì)數(shù)器的值就不會(huì)被定義。

    Java虛擬機(jī)的棧有三個(gè)區(qū)域:局部變量區(qū)、運(yùn)行環(huán)境區(qū)、操作數(shù)區(qū)。

    局部變量區(qū)

    每個(gè)Java方法使用一個(gè)固定大小的局部變量集。它們按照與vars寄存器的字偏移量來(lái)尋址。局部變量都是32位的。長(zhǎng)整數(shù)和雙精度浮點(diǎn)數(shù)占據(jù)了兩個(gè)局部變量的空間,卻按照第一個(gè)局部變量的索引來(lái)尋址。(例如,一個(gè)具有索引n的局部變量,如果是一個(gè)雙精度浮點(diǎn)數(shù),那么它實(shí)際占據(jù)了索引n和n+1所代表的存儲(chǔ)空間)虛擬機(jī)規(guī)范并不要求在局部變量中的64位的值是64位對(duì)齊的。虛擬機(jī)提供了把局部變量中的值裝載到操作數(shù)棧的指令,也提供了把操作數(shù)棧中的值寫(xiě)入局部變量的指令。

    運(yùn)行環(huán)境區(qū)

    在運(yùn)行環(huán)境中包含的信息用于動(dòng)態(tài)鏈接,正常的方法返回以及異常捕捉。

    動(dòng)態(tài)鏈接

    運(yùn)行環(huán)境包括對(duì)指向當(dāng)前類(lèi)和當(dāng)前方法的解釋器符號(hào)表的指針,用于支持方法代碼的動(dòng)態(tài)鏈接。方法的class文件代碼在引用要調(diào)用的方法和要訪問(wèn)的變量時(shí)使用符號(hào)。動(dòng)態(tài)鏈接把符號(hào)形式的方法調(diào)用翻譯成實(shí)際方法調(diào)用,裝載必要的類(lèi)以解釋還沒(méi)有定義的符號(hào),并把變量訪問(wèn)翻譯成與這些變量運(yùn)行時(shí)的存儲(chǔ)結(jié)構(gòu)相應(yīng)的偏移地址。動(dòng)態(tài)鏈接方法和變量使得方法中使用的其它類(lèi)的變化不會(huì)影響到本程序的代碼。

    正常的方法返回

    如果當(dāng)前方法正常地結(jié)束了,在執(zhí)行了一條具有正確類(lèi)型的返回指令時(shí),調(diào)用的方法會(huì)得到一個(gè)返回值。執(zhí)行環(huán)境在正常返回的情況下用于恢復(fù)調(diào)用者的寄存器,并把調(diào)用者的程序計(jì)數(shù)器增加一個(gè)恰當(dāng)?shù)臄?shù)值,以跳過(guò)已執(zhí)行過(guò)的方法調(diào)用指令,然后在調(diào)用者的執(zhí)行環(huán)境中繼續(xù)執(zhí)行下去。

    異常捕捉

    異常情況在Java中被稱(chēng)作Error(錯(cuò)誤)或Exception(異常),是Throwable類(lèi)的子類(lèi),在程序中的原因是:①動(dòng)態(tài)鏈接錯(cuò),如無(wú)法找到所需的class文件。②運(yùn)行時(shí)錯(cuò),如對(duì)一個(gè)空指針的引用。程序使用了throw語(yǔ)句。

    當(dāng)異常發(fā)生時(shí),Java虛擬機(jī)采取如下措施:

    • 檢查與當(dāng)前方法相聯(lián)系的catch子句表。每個(gè)catch子句包含其有效指令范圍,能夠處理的異常類(lèi)型,以及處理異常的代碼塊地址。
    • 與異常相匹配的catch子句應(yīng)該符合下面的條件:造成異常的指令在其指令范圍之內(nèi),發(fā)生的異常類(lèi)型是其能處理的異常類(lèi)型的子類(lèi)型。如果找到了匹配的catch子句,那么系統(tǒng)轉(zhuǎn)移到指定的異常處理塊處執(zhí)行;如果沒(méi)有找到異常處理塊,重復(fù)尋找匹配的catch子句的過(guò)程,直到當(dāng)前方法的所有嵌套的catch子句都被檢查過(guò)。
    • 由于虛擬機(jī)從第一個(gè)匹配的catch子句處繼續(xù)執(zhí)行,所以catch子句表中的順序是很重要的。因?yàn)镴ava代碼是結(jié)構(gòu)化的,因此總可以把某個(gè)方法的所有的異常處理器都按序排列到一個(gè)表中,對(duì)任意可能的程序計(jì)數(shù)器的值,都可以用線性的順序找到合適的異常處理塊,以處理在該程序計(jì)數(shù)器值下發(fā)生的異常情況。
    • 如果找不到匹配的catch子句,那么當(dāng)前方法得到一個(gè)"未截獲異常"的結(jié)果并返回到當(dāng)前方法的調(diào)用者,好像異常剛剛在其調(diào)用者中發(fā)生一樣。如果在調(diào)用者中仍然沒(méi)有找到相應(yīng)的異常處理塊,那么這種錯(cuò)誤將被傳播下去。如果錯(cuò)誤被傳播到最頂層,那么系統(tǒng)將調(diào)用一個(gè)缺省的異常處理塊。

    操作數(shù)棧區(qū)

    機(jī)器指令只從操作數(shù)棧中取操作數(shù),對(duì)它們進(jìn)行操作,并把結(jié)果返回到棧中。選擇棧結(jié)構(gòu)的原因是:在只有少量寄存器或非通用寄存器的機(jī)器(如Intel486)上,也能夠高效地模擬虛擬機(jī)的行為。操作數(shù)棧是32位的。它用于給方法傳遞參數(shù),并從方法接收結(jié)果,也用于支持操作的參數(shù),并保存操作的結(jié)果。例如,iadd指令將兩個(gè)整數(shù)相加。相加的兩個(gè)整數(shù)應(yīng)該是操作數(shù)棧頂?shù)膬蓚€(gè)字。這兩個(gè)字是由先前的指令壓進(jìn)堆棧的。這兩個(gè)整數(shù)將從堆棧彈出、相加,并把結(jié)果壓回到操作數(shù)棧中。

    每個(gè)原始數(shù)據(jù)類(lèi)型都有專(zhuān)門(mén)的指令對(duì)它們進(jìn)行必須的操作。每個(gè)操作數(shù)在棧中需要一個(gè)存儲(chǔ)位置,除了long和double型,它們需要兩個(gè)位置。操作數(shù)只能被適用于其類(lèi)型的操作符所操作。例如,壓入兩個(gè)int類(lèi)型的數(shù),如果把它們當(dāng)作是一個(gè)long類(lèi)型的數(shù)則是非法的。在Sun的虛擬機(jī)實(shí)現(xiàn)中,這個(gè)限制由字節(jié)碼驗(yàn)證器強(qiáng)制實(shí)行。但是,有少數(shù)操作(操作符dupe和swap),用于對(duì)運(yùn)行時(shí)數(shù)據(jù)區(qū)進(jìn)行操作時(shí)是不考慮類(lèi)型的。

    本地方法棧,當(dāng)一個(gè)線程調(diào)用本地方法時(shí),它就不再受到虛擬機(jī)關(guān)于結(jié)構(gòu)和安全限制方面的約束,它既可以訪問(wèn)虛擬機(jī)的運(yùn)行期數(shù)據(jù)區(qū),也可以使用本地處理器以及任何類(lèi)型的棧。例如,本地棧是一個(gè)C語(yǔ)言的棧,那么當(dāng)C程序調(diào)用C函數(shù)時(shí),函數(shù)的參數(shù)以某種順序被壓入棧,結(jié)果則返回給調(diào)用函數(shù)。在實(shí)現(xiàn)Java虛擬機(jī)時(shí),本地方法接口使用的是C語(yǔ)言的模型棧,那么它的本地方法棧的調(diào)度與使用則完全與C語(yǔ)言的棧相同。

    3??Java虛擬機(jī)的運(yùn)行過(guò)程

    上面對(duì)虛擬機(jī)的各個(gè)部分進(jìn)行了比較詳細(xì)的說(shuō)明,下面通過(guò)一個(gè)具體的例子來(lái)分析它的運(yùn)行過(guò)程。

    虛擬機(jī)通過(guò)調(diào)用某個(gè)指定類(lèi)的方法main啟動(dòng),傳遞給main一個(gè)字符串?dāng)?shù)組參數(shù),使指定的類(lèi)被裝載,同時(shí)鏈接該類(lèi)所使用的其它的類(lèi)型,并且初始化它們。例如對(duì)于程序:

    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

    將通過(guò)調(diào)用HelloApp的方法main來(lái)啟動(dòng)java虛擬機(jī),傳遞給main一個(gè)包含三個(gè)字符串"run"、"virtual"、"machine"的數(shù)組?,F(xiàn)在我們略述虛擬機(jī)在執(zhí)行HelloApp時(shí)可能采取的步驟。

    開(kāi)始試圖執(zhí)行類(lèi)HelloApp的main方法,發(fā)現(xiàn)該類(lèi)并沒(méi)有被裝載,也就是說(shuō)虛擬機(jī)當(dāng)前不包含該類(lèi)的二進(jìn)制代表,于是虛擬機(jī)使用ClassLoader試圖尋找這樣的二進(jìn)制代表。如果這個(gè)進(jìn)程失敗,則拋出一個(gè)異常。類(lèi)被裝載后同時(shí)在main方法被調(diào)用之前,必須對(duì)類(lèi)HelloApp與其它類(lèi)型進(jìn)行鏈接然后初始化。鏈接包含三個(gè)階段:檢驗(yàn),準(zhǔn)備和解析。檢驗(yàn)檢查被裝載的主類(lèi)的符號(hào)和語(yǔ)義,準(zhǔn)備則創(chuàng)建類(lèi)或接口的靜態(tài)域以及把這些域初始化為標(biāo)準(zhǔn)的默認(rèn)值,解析負(fù)責(zé)檢查主類(lèi)對(duì)其它類(lèi)或接口的符號(hào)引用,在這一步它是可選的。類(lèi)的初始化是對(duì)類(lèi)中聲明的靜態(tài)初始化函數(shù)和靜態(tài)域的初始化構(gòu)造方法的執(zhí)行。一個(gè)類(lèi)在初始化之前它的父類(lèi)必須被初始化。整個(gè)過(guò)程如下:

    圖4:虛擬機(jī)的運(yùn)行過(guò)程

    4??結(jié)束語(yǔ)

    本文通過(guò)對(duì)JVM的體系結(jié)構(gòu)的深入研究以及一個(gè)Java程序執(zhí)行時(shí)虛擬機(jī)的運(yùn)行過(guò)程的詳細(xì)分析,意在剖析清楚Java虛擬機(jī)的機(jī)理。

    posted @ 2006-10-15 15:39 阿成 閱讀(360) | 評(píng)論 (0)編輯 收藏

    struts的validator資料見(jiàn):struts validator

    附一個(gè)正則表達(dá)式的資料:

    正則表達(dá)式

      正則表達(dá)式(regular expression)描述了一種字符串匹配的模式,可以用來(lái)檢查一個(gè)串是否含有某種子串、將匹配的子串做替換或者從某個(gè)串中取出符合某個(gè)條件的子串等。
      列目錄時(shí), dir *.txt或ls *.txt中的*.txt就

    是一個(gè)正則表達(dá)式,因?yàn)檫@里*與正則式的*的含義是不同的。

      為便于理解和記憶,先從一些概念入手,所有特殊字符或字符組合有一個(gè)總表在后面,最后一些例子供理解相應(yīng)的概念。

    正則表達(dá)式


      是由普通字符(例如字符 a 到 z)以及特殊字符(稱(chēng)為元字符)組成的文字模式。正則表達(dá)式作為一個(gè)模板,將某個(gè)字符模式與所搜索的字符串進(jìn)行匹配。
      可以通過(guò)在一對(duì)分隔符之間放入表達(dá)式模式的各種組件來(lái)構(gòu)造一個(gè)正則表達(dá)式,即/expression/

    普通字符


      由所有那些未顯式指定為元字符的打印和非打印字符組成。這包括所有的大寫(xiě)和小寫(xiě)字母字符,所有數(shù)字,所有標(biāo)點(diǎn)符號(hào)以及一些符號(hào)。

    非打印字符


    字符 含義
    \cx 匹配由x指明的控制字符。例如, \cM 匹配一個(gè) Control-M 或回車(chē)符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個(gè)原義的 'c' 字符。
    \f 匹配一個(gè)換頁(yè)符。等價(jià)于 \x0c 和 \cL。
    \n 匹配一個(gè)換行符。等價(jià)于 \x0a 和 \cJ。
    \r 匹配一個(gè)回車(chē)符。等價(jià)于 \x0d 和 \cM。
    \s 匹配任何空白字符,包括空格、制表符、換頁(yè)符等等。等價(jià)于 [ \f\n\r\t\v]。
    \S 匹配任何非空白字符。等價(jià)于 [^ \f\n\r\t\v]。
    \t 匹配一個(gè)制表符。等價(jià)于 \x09 和 \cI。
    \v 匹配一個(gè)垂直制表符。等價(jià)于 \x0b 和 \cK。

    特殊字符


      所謂特殊字符,就是一些有特殊含義的字符,如上面說(shuō)的"*.txt"中的*,簡(jiǎn)單的說(shuō)就是表示任何字符串的意思。如果要查找文件名中有*的文件,則需要對(duì)*進(jìn)行轉(zhuǎn)義,即在其前加一個(gè)\。ls \*.txt。正則表達(dá)式有以下特殊字符。

    特別字符說(shuō)明
    $匹配輸入字符串的結(jié)尾位置。如果設(shè)置了 RegExp 對(duì)象的 Multiline 屬性,則 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,請(qǐng)使用 \$。
    ( )標(biāo)記一個(gè)子表達(dá)式的開(kāi)始和結(jié)束位置。子表達(dá)式可以獲取供以后使用。要匹配這些字符,請(qǐng)使用 \( 和 \)。
    *匹配前面的子表達(dá)式零次或多次。要匹配 * 字符,請(qǐng)使用 \*。
    +匹配前面的子表達(dá)式一次或多次。要匹配 + 字符,請(qǐng)使用 \+。
    .匹配除換行符 \n之外的任何單字符。要匹配 .,請(qǐng)使用 \。
    [ 標(biāo)記一個(gè)中括號(hào)表達(dá)式的開(kāi)始。要匹配 [,請(qǐng)使用 \[。
    ?匹配前面的子表達(dá)式零次或一次,或指明一個(gè)非貪婪限定符。要匹配 ? 字符,請(qǐng)使用 \?。
    \將下一個(gè)字符標(biāo)記為或特殊字符、或原義字符、或向后引用、或八進(jìn)制轉(zhuǎn)義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("。
    ^匹配輸入字符串的開(kāi)始位置,除非在方括號(hào)表達(dá)式中使用,此時(shí)它表示不接受該字符集合。要匹配 ^ 字符本身,請(qǐng)使用 \^。
    {標(biāo)記限定符表達(dá)式的開(kāi)始。要匹配 {,請(qǐng)使用 \{。
    |指明兩項(xiàng)之間的一個(gè)選擇。要匹配 |,請(qǐng)使用 \|。


      構(gòu)造正則表達(dá)式的方法和創(chuàng)建數(shù)學(xué)表達(dá)式的方法一樣。也就是用多種元字符與操作符將小的表達(dá)式結(jié)合在一起來(lái)創(chuàng)建更大的表達(dá)式。正則表達(dá)式的組件可以是單個(gè)的字符、字符集合、字符范圍、字符間的選擇或者所有這些組件的任意組合。


    限定符


      限定符用來(lái)指定正則表達(dá)式的一個(gè)給定組件必須要出現(xiàn)多少次才能滿(mǎn)足匹配。有*或+或?或{n}或{n,}或{n,m}共6種。
    *、+和?限定符都是貪婪的,因?yàn)樗鼈儠?huì)盡可能多的匹配文字,只有在它們的后面加上一個(gè)?就可以實(shí)現(xiàn)非貪婪或最小匹配。
      正則表達(dá)式的限定符有:

    字符 描述
    * 匹配前面的子表達(dá)式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價(jià)于{0,}。
    + 匹配前面的子表達(dá)式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價(jià)于 {1,}。
    ? 匹配前面的子表達(dá)式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價(jià)于 {0,1}。
    {n} n 是一個(gè)非負(fù)整數(shù)。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個(gè) o。
    {n,} n 是一個(gè)非負(fù)整數(shù)。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價(jià)于 'o+'。'o{0,}' 則等價(jià)于 'o*'。
    {n,m} m 和 n 均為非負(fù)整數(shù),其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個(gè) o。'o{0,1}' 等價(jià)于 'o?'。請(qǐng)注意在逗號(hào)和兩個(gè)數(shù)之間不能有空格。

    定位符


      用來(lái)描述字符串或單詞的邊界,^和$分別指字符串的開(kāi)始與結(jié)束,\b描述單詞的前或后邊界,\B表示非單詞邊界。

    不能對(duì)定位符使用限定符。

    選擇


      用圓括號(hào)將所有選擇項(xiàng)括起來(lái),相鄰的選擇項(xiàng)之間用|分隔。但用圓括號(hào)會(huì)有一個(gè)副作用,是相關(guān)的匹配會(huì)被緩存,此時(shí)可用?:放在第一個(gè)選項(xiàng)前來(lái)消除這種副作用。
      其中?:是非捕獲元之一,還有兩個(gè)非捕獲元是?=和?!,這兩個(gè)還有更多的含義,前者為正向預(yù)查,在任何開(kāi)始匹配圓括號(hào)內(nèi)的正則表達(dá)式模式的位置來(lái)匹配搜索字符串,后者為負(fù)向預(yù)查,在任何開(kāi)始不匹配該正則表達(dá)式模式的位置來(lái)匹配搜索字符串。

    后向引用


      對(duì)一個(gè)正則表達(dá)式模式或部分模式兩邊添加圓括號(hào)將導(dǎo)致相關(guān)匹配存儲(chǔ)到一個(gè)臨時(shí)緩沖區(qū)中,所捕獲的每個(gè)子匹配都按照在正則表達(dá)式模式中從左至右所遇到的內(nèi)容存儲(chǔ)。存儲(chǔ)子匹配的緩沖區(qū)編號(hào)從 1 開(kāi)始,連續(xù)編號(hào)直至最大 99 個(gè)子表達(dá)式。每個(gè)緩沖區(qū)都可以使用 '\n' 訪問(wèn),其中 n 為一個(gè)標(biāo)識(shí)特定緩沖區(qū)的一位或兩位十進(jìn)制數(shù)。
      可以使用非捕獲元字符 '?:', '?=', or '?!' 來(lái)忽略對(duì)相關(guān)匹配的保存。

    各種操作符的運(yùn)算優(yōu)先級(jí)


      相同優(yōu)先級(jí)的從左到右進(jìn)行運(yùn)算,不同優(yōu)先級(jí)的運(yùn)算先高后低。各種操作符的優(yōu)先級(jí)從高到低如下:

    操作符 描述
    \ 轉(zhuǎn)義符
    (), (?:), (?=), [] 圓括號(hào)和方括號(hào)
    *, +, ?, {n}, {n,}, {n,m} 限定符
    ^, $, \anymetacharacter 位置和順序
    | “或”操作

    全部符號(hào)解釋


    字符 描述
    \ 將下一個(gè)字符標(biāo)記為一個(gè)特殊字符、或一個(gè)原義字符、或一個(gè) 向后引用、或一個(gè)八進(jìn)制轉(zhuǎn)義符。例如,'n' 匹配字符 "n"。'\n' 匹配一個(gè)換行符。序列 '\\' 匹配 "\" 而 "\(" 則匹配 "("。
    ^ 匹配輸入字符串的開(kāi)始位置。如果設(shè)置了 RegExp 對(duì)象的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 之后的位置。
    $ 匹配輸入字符串的結(jié)束位置。如果設(shè)置了RegExp 對(duì)象的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 之前的位置。
    * 匹配前面的子表達(dá)式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價(jià)于{0,}。
    + 匹配前面的子表達(dá)式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價(jià)于 {1,}。
    ? 匹配前面的子表達(dá)式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價(jià)于 {0,1}。
    {n} n 是一個(gè)非負(fù)整數(shù)。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個(gè) o。
    {n,} n 是一個(gè)非負(fù)整數(shù)。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價(jià)于 'o+'。'o{0,}' 則等價(jià)于 'o*'。
    {n,m} m 和 n 均為非負(fù)整數(shù),其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個(gè) o。'o{0,1}' 等價(jià)于 'o?'。請(qǐng)注意在逗號(hào)和兩個(gè)數(shù)之間不能有空格。
    ? 當(dāng)該字符緊跟在任何一個(gè)其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面時(shí),匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認(rèn)的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對(duì)于字符串 "oooo",'o+?' 將匹配單個(gè) "o",而 'o+' 將匹配所有 'o'。
    . 匹配除 "\n" 之外的任何單個(gè)字符。要匹配包括 '\n' 在內(nèi)的任何字符,請(qǐng)使用象 '[.\n]' 的模式。
    (pattern) 匹配 pattern 并獲取這一匹配。所獲取的匹配可以從產(chǎn)生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括號(hào)字符,請(qǐng)使用 '\(' 或 '\)'。
    (?:pattern) 匹配 pattern 但不獲取匹配結(jié)果,也就是說(shuō)這是一個(gè)非獲取匹配,不進(jìn)行存儲(chǔ)供以后使用。這在使用 "或" 字符 (|) 來(lái)組合一個(gè)模式的各個(gè)部分是很有用。例如, 'industr(?:y|ies) 就是一個(gè)比 'industry|industries' 更簡(jiǎn)略的表達(dá)式。
    (?=pattern) 正向預(yù)查,在任何匹配 pattern 的字符串開(kāi)始處匹配查找字符串。這是一個(gè)非獲取匹配,也就是說(shuō),該匹配不需要獲取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。預(yù)查不消耗字符,也就是說(shuō),在一個(gè)匹配發(fā)生后,在最后一次匹配之后立即開(kāi)始下一次匹配的搜索,而不是從包含預(yù)查的字符之后開(kāi)始。
    (?!pattern) 負(fù)向預(yù)查,在任何不匹配 pattern 的字符串開(kāi)始處匹配查找字符串。這是一個(gè)非獲取匹配,也就是說(shuō),該匹配不需要獲取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。預(yù)查不消耗字符,也就是說(shuō),在一個(gè)匹配發(fā)生后,在最后一次匹配之后立即開(kāi)始下一次匹配的搜索,而不是從包含預(yù)查的字符之后開(kāi)始
    x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配 "zood" 或 "food"。
    [xyz] 字符集合。匹配所包含的任意一個(gè)字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
    [^xyz] 負(fù)值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
    [a-z] 字符范圍。匹配指定范圍內(nèi)的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范圍內(nèi)的任意小寫(xiě)字母字符。
    [^a-z] 負(fù)值字符范圍。匹配任何不在指定范圍內(nèi)的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范圍內(nèi)的任意字符。
    \b 匹配一個(gè)單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
    \B 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
    \cx 匹配由 x 指明的控制字符。例如, \cM 匹配一個(gè) Control-M 或回車(chē)符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個(gè)原義的 'c' 字符。
    \d 匹配一個(gè)數(shù)字字符。等價(jià)于 [0-9]。
    \D 匹配一個(gè)非數(shù)字字符。等價(jià)于 [^0-9]。
    \f 匹配一個(gè)換頁(yè)符。等價(jià)于 \x0c 和 \cL。
    \n 匹配一個(gè)換行符。等價(jià)于 \x0a 和 \cJ。
    \r 匹配一個(gè)回車(chē)符。等價(jià)于 \x0d 和 \cM。
    \s 匹配任何空白字符,包括空格、制表符、換頁(yè)符等等。等價(jià)于 [ \f\n\r\t\v]。
    \S 匹配任何非空白字符。等價(jià)于 [^ \f\n\r\t\v]。
    \t 匹配一個(gè)制表符。等價(jià)于 \x09 和 \cI。
    \v 匹配一個(gè)垂直制表符。等價(jià)于 \x0b 和 \cK。
    \w 匹配包括下劃線的任何單詞字符。等價(jià)于'[A-Za-z0-9_]'。
    \W 匹配任何非單詞字符。等價(jià)于 '[^A-Za-z0-9_]'。
    \xn 匹配 n,其中 n 為十六進(jìn)制轉(zhuǎn)義值。十六進(jìn)制轉(zhuǎn)義值必須為確定的兩個(gè)數(shù)字長(zhǎng)。例如,'\x41' 匹配 "A"。'\x041' 則等價(jià)于 '\x04' & "1"。正則表達(dá)式中可以使用 ASCII 編碼。.
    \num 匹配 num,其中 num 是一個(gè)正整數(shù)。對(duì)所獲取的匹配的引用。例如,'(.)\1' 匹配兩個(gè)連續(xù)的相同字符。
    \n 標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后引用。如果 \n 之前至少 n 個(gè)獲取的子表達(dá)式,則 n 為向后引用。否則,如果 n 為八進(jìn)制數(shù)字 (0-7),則 n 為一個(gè)八進(jìn)制轉(zhuǎn)義值。
    \nm 標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后引用。如果 \nm 之前至少有 nm 個(gè)獲得子表達(dá)式,則 nm 為向后引用。如果 \nm 之前至少有 n 個(gè)獲取,則 n 為一個(gè)后跟文字 m 的向后引用。如果前面的條件都不滿(mǎn)足,若 n 和 m 均為八進(jìn)制數(shù)字 (0-7),則 \nm 將匹配八進(jìn)制轉(zhuǎn)義值 nm。
    \nml 如果 n 為八進(jìn)制數(shù)字 (0-3),且 m 和 l 均為八進(jìn)制數(shù)字 (0-7),則匹配八進(jìn)制轉(zhuǎn)義值 nml。
    \un 匹配 n,其中 n 是一個(gè)用四個(gè)十六進(jìn)制數(shù)字表示的 Unicode 字符。例如, \u00A9 匹配版權(quán)符號(hào) (?)。

    部分例子


    正則表達(dá)式說(shuō)明
    /\b([a-z]+) \1\b/gi一個(gè)單詞連續(xù)出現(xiàn)的位置
    /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ 將一個(gè)URL解析為協(xié)議、域、端口及相對(duì)路徑
    /^(?:Chapter|Section) [1-9][0-9]{0,1}$/定位章節(jié)的位置
    /[-a-z]/A至z共26個(gè)字母再加一個(gè)-號(hào)。
    /ter\b/可匹配chapter,而不能terminal
    /\Bapt/可匹配chapter,而不能aptitude
    /Windows(?=95 |98 |NT )/可匹配Windows95或Windows98或WindowsNT,當(dāng)找到一個(gè)匹配后,從Windows后面開(kāi)始進(jìn)行下一次的檢索匹配。
    posted @ 2006-10-13 09:36 阿成 閱讀(302) | 評(píng)論 (0)編輯 收藏
    前兩天晚上在經(jīng)過(guò)一個(gè)十字路口的時(shí)候,不知中了什么邪,跑著橫穿馬路,正好被一個(gè)出租車(chē)撞上,

    撞的偶pp上,那叫一個(gè)險(xiǎn)。幸虧是撞的pp上,而且車(chē)速不算快。身上是些皮外傷。

    所以奉勸大家寧等3小時(shí),別搶1妙。

    要是真有急事兒,非要搶那1妙,那就別猶豫,跑快點(diǎn)。
    posted @ 2006-10-09 08:57 阿成 閱讀(338) | 評(píng)論 (0)編輯 收藏
    真的很快,工作了感覺(jué)時(shí)間過(guò)得太快了。真是time fly啊

    明天就101了,感覺(jué)剛過(guò)完51。

    回家修養(yǎng)幾天。
    posted @ 2006-09-30 17:06 阿成 閱讀(270) | 評(píng)論 (0)編輯 收藏
    現(xiàn)在我最缺什么?最需求在哪些方面改進(jìn)?
    最近一些小事讓我逐漸意識(shí)到自己這工作一年多來(lái)一直沒(méi)有重視或者說(shuō)不敢的弱點(diǎn)。我開(kāi)始問(wèn)自己現(xiàn)在在社會(huì)上混,都需要些什么?我一一列舉,作為程序員,我開(kāi)始想到j(luò)ava、數(shù)據(jù)庫(kù)、服務(wù)器、、、、、、,發(fā)現(xiàn),都是一些技術(shù)方面的。光有這些行嗎?肯定不行。開(kāi)始想到了一些其他的東西,圓滑,這兩個(gè)字沒(méi)那么簡(jiǎn)單,里面有著一系列東西。我問(wèn)自己,我作為一個(gè)寫(xiě)程序的技術(shù)人員,他媽的我需要干這個(gè)?我做到了嗎?我沒(méi)做做到。而且差的很遠(yuǎn)很遠(yuǎn)。說(shuō)這些不是腦子一熱,或者什么憑空想象,是所見(jiàn)所聞。而我得性格似乎與這個(gè)東西有隔閡,似乎不太容易做到,而且對(duì)它產(chǎn)生了煩感和誤解??粗CH撕?,各奔前程,我也逐漸開(kāi)始理解了。如果你沒(méi)有做到或像我一樣或不理解,就仔細(xì)觀察一下周?chē)沫h(huán)境,會(huì)明白的。經(jīng)過(guò)反復(fù)的思考,決定該改正一些了。但我不會(huì)超越我自己的一些底線,我會(huì)對(duì)自己認(rèn)準(zhǔn)的朋友保持一顆真誠(chéng)的心,不敢說(shuō)已做到仗義,講義氣,但會(huì)一直為之努力。也希望每個(gè)人在圓滑的同時(shí)盡量保留自己的底線。我也會(huì)盡快的適應(yīng)這個(gè)所謂的高科技時(shí)代。
    posted @ 2006-09-26 14:35 阿成 閱讀(194) | 評(píng)論 (0)編輯 收藏

    部門(mén)的經(jīng)理挺好,周末組織部門(mén)同事去懷柔玩了一次,因?yàn)閲?guó)慶、中秋快到了。
    這次和上次去秦皇島還沒(méi)隔多長(zhǎng)時(shí)間。

    早上7點(diǎn)就起床了,吃完早飯,大家到齊之后就出發(fā)了。

    先去的紅螺寺,這原來(lái)是一個(gè)皇家寺院。里面的大佛聽(tīng)多。阿彌托佛、釋迦摩尼、藥師佛等等,

    然后又看了500羅漢,據(jù)說(shuō)里面總能找到一個(gè)與你想的。中午吃飯,點(diǎn)了好幾條虹尊魚(yú),頓的,烤的都吃了,不過(guò)覺(jué)得一般。下午去了神堂裕,里面是一些小溪呀,山呀,在里面走走不錯(cuò),回歸大自然,凈化一下,在工作呀、學(xué)習(xí)呀都能提高效率。

    晚上回來(lái)后已經(jīng)快7點(diǎn)了,接著腐敗,找地兒吃飯。挺爽的。

    十一之后逐漸變冷估計(jì)今年即便有活動(dòng),也是在市里了。下次出去估計(jì)的明年了。

    posted @ 2006-09-26 14:04 阿成 閱讀(258) | 評(píng)論 (0)編輯 收藏

    <html>

    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title></title>
    <script language=javascript>
    function fTxtKeyDown(obj)
    {
    ? if(event.keyCode == 32)
    ? {
    ??? event.returnValue=false;
    ??? //空格鍵
    ??? var sRet;
    ??? try {
    ????? sRet = eval(obj.value);
    ??? }
    ??? catch(e) {
    ??? }
    ??? if (isNaN(sRet))
    ??? {
    ????? alert("計(jì)算式輸入錯(cuò)誤");
    ??? }
    ??? else
    ??? {
    ??????? obj.value=sRet;
    ??? }
    ? }
    }

    </script>
    </head>

    <body>
    <font size="2">輸入表達(dá)式(如:3*2-4)后,按空格鍵得到結(jié)果 try</font><br>
    <br>
    <input type=text onkeydown="fTxtKeyDown(this);" size="42">
    </body>

    </html>

    posted @ 2006-09-21 21:20 阿成 閱讀(1004) | 評(píng)論 (0)編輯 收藏
    主站蜘蛛池模板: 亚洲AV第一成肉网| 免免费国产AAAAA片| 亚洲国产成人久久一区WWW| 亚洲综合一区无码精品| 成年人网站免费视频| 亚洲短视频男人的影院| 高清永久免费观看| 亚洲国产成人久久一区久久| 中文字幕乱码亚洲精品一区 | 99爱在线观看免费完整版| 国产黄色一级毛片亚洲黄片大全| 亚洲AV综合永久无码精品天堂| 99re热免费精品视频观看| 亚洲无成人网77777| 99久久99久久免费精品小说| 亚洲av无码不卡一区二区三区| 国产无遮挡又黄又爽免费网站 | 亚洲AV无码久久精品狠狠爱浪潮| 一区二区三区免费精品视频 | 亚洲三级高清免费| 亚洲男人的天堂在线| 91成人在线免费视频| 亚洲视频在线观看一区| 久久免费看少妇高潮V片特黄| 亚洲AV永久无码精品成人| a视频在线免费观看| 亚洲大尺度无码无码专区| 拍拍拍无挡视频免费观看1000 | 最近新韩国日本免费观看 | 亚洲精品一卡2卡3卡四卡乱码| 永久免费毛片在线播放| 亚洲AV综合色区无码二区偷拍| 精品久久久久成人码免费动漫| 亚洲制服丝袜一区二区三区| 国产香蕉九九久久精品免费| 久久亚洲国产最新网站| 久久久久国色AV免费观看性色| 亚洲中文字幕无码mv| 日本免费电影一区| 污视频网站免费观看| 亚洲综合色成在线播放|