posts - 40,  comments - 4,  trackbacks - 0
            2006年11月24日

            在Java語言中, abstract class 和interface 是支持抽象類定義的兩種機制。正是由于這兩種機制的存在,才賦予了Java強大的 面向對象能力。abstract class和interface之間在對于抽象類定義的支持方面具有很大的相似性,甚至可以相互替換,因此很多開發者在進 行抽象類定義時對于abstract class和interface的選擇顯得比較隨意。其實,兩者之間還是有很大的區別的,對于它們的選擇甚至反映出對 于問題領域本質的理解、對于設計意圖的理解是否正確、合理。本文將對它們之間的區別進行一番剖析,試圖給開發者提供一個在二者之間進行選擇的依據。

            理解抽象類

            abstract class和interface在Java語言中都是用來進行抽象類(本文 中的抽象類并非從abstract class翻譯而來,它表示的是一個抽象體,而abstract class為Java語言中用于定義抽象類的一種方法, 請讀者注意區分)定義的,那么什么是抽象類,使用抽象類能為我們帶來什么好處呢?

            在 面向對象的概念中,我們知道所有的對象都是通過類來描繪的,但是反過來卻不是這樣。并不是 所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。抽象類往往用來表征我們在對問題領域進行分析、 設計中得出的抽象概念,是對一系列看上去不同,但是本質上相同的具體概念的抽象。比如:如果我們進行一個圖形編輯軟件的開發,就會發現問題領域存在著圓、 三角形這樣一些具體概念,它們是不同的,但是它們又都屬于形狀這樣一個概念,形狀這個概念在問題領域是不存在的,它就是一個抽象概念。正是因為抽象的概念 在問題領域沒有對應的具體概念,所以用以表征抽象概念的抽象類是不能夠實例化的。

            在面向對象領域,抽象類主要用來進行類型隱藏。 我們可以構造出一個固定的一組行為的抽象描 述,但是這組行為卻能夠有任意個可能的具體實現方式。這個抽象描述就是抽象類,而這一組任意個可能的具體實現則表現為所有可能的派生類。模塊可以操作一個 抽象體。由于模塊依賴于一個固定的抽象體,因此它可以是不允許修改的;同時,通過從這個抽象體派生,也可擴展此模塊的行為功能。熟悉OCP的讀者一定知 道,為了能夠實現面向對象設計的一個最核心的原則OCP(Open-Closed Principle),抽象類是其中的關鍵所在。

            從語法定義層面看abstract class 和 interface

            在語法層面,Java語言對于abstract class和interface給出了不同的定義方式,下面以定義一個名為Demo的抽象類為例來說明這種不同。

            使用abstract class的方式定義Demo抽象類的方式如下:

          abstract class Demo{
          abstract void method1();
          abstract void method2();


            使用interface的方式定義Demo抽象類的方式如下:

          interface Demo{
          void method1();
          void method2();

          }
            在abstract class方式中,Demo可以有自己的數據成員,也可以有非 abstract的成員方法,而在interface方式的實現中,Demo只能夠有靜態的不能被修改的數據成員(也就是必須是static final 的,不過在interface中一般不定義數據成員),所有的成員方法都是abstract的。從某種意義上說,interface是一種特殊形式的 abstract class。

            從編程的角度來看,abstract class和interface都可以用來實現 "design by contract" 的思想。但是在具體的使用上面還是有一些區別的。

            首先,abstract class 在 Java 語言中表示的是一種繼承關系,一個類只能使用一次繼承關系(因為Java不支持多繼承 -- 轉注)。但是,一個類卻可以實現多個interface。也許,這是Java語言的設計者在考慮Java對于多重繼承的支持方面的一種折中考慮吧。

            其次,在abstract class的定義中,我們可以賦予方法的默認行為。但是在interface的定義中,方法卻不能擁有默認行為,為了繞過這個限制,必須使用委托,但是這會增加一些復雜性,有時會造成很大的麻煩。

            在 抽象類中不能定義默認行為還存在另一個比較嚴重的問題,那就是可能會造成維護上的麻煩。因 為如果后來想修改類的界面(一般通過 abstract class 或者interface來表示)以適應新的情況(比如,添加新的方法或者給已用的方法中添 加新的參數)時,就會非常的麻煩,可能要花費很多的時間(對于派生類很多的情況,尤為如此)。但是如果界面是通過abstract class來實現的,那 么可能就只需要修改定義在abstract class中的默認行為就可以了。

            同樣,如果不能在抽象類中定義默認行為,就會導致同樣的方法實現出現在該抽象類的每一個派生類中,違反了 "one rule,one place" 原則,造成代碼重復,同樣不利于以后的維護。因此,在abstract class和interface間進行選擇時要非常的小心。

            從設計理念層面看 abstract class 和 interface

            上面主要從語法定義和編程的角度論述了abstract class和interface的區 別,這些層面的區別是比較低層次的、非本質的。本小節將從另一個層面:abstract class和interface所反映出的設計理念,來分析一下二者的區別。作者認為,從這個層面進行分析才能理解二者概念的本質所在。

            前面已經提到過,abstract class在Java語言中體現了一種繼承關系,要想使得 繼承關系合理,父類和派生類之間必須存在"is-a"關系,即父類和派生類在概念本質上應該是相同的。對于interface來說則不然,并不要求interface的實現者和interface定義在概念本質上是一致的, 僅僅是實現了interface定義的契約而已。為了使論述便于理解,下面將通過一個簡單的實例進行說明。

            考慮這樣一個例子,假設在我們的問題領域中有一個關于Door的抽象概念,該Door具有執行兩個動作open和close,此時我們可以通過abstract class或者interface來定義一個表示該抽象概念的類型,定義方式分別如下所示:

            使用abstract class方式定義Door:

          abstract class Door{
          abstract void open();
          abstract void close();
          }
            使用interface方式定義Door:

          interface Door{
          void open();
          void close();
          }
            其他具體的Door類型可以extends使用abstract class方式定義的Door或者implements使用interface方式定義的Door。看起來好像使用abstract class和interface沒有大的區別。

            如果現在要求Door還要具有報警的功能。我們該如何設計針對該例子的類結構呢(在本例中, 主要是為了展示 abstract class 和interface 反映在設計理念上的區別,其他方面無關的問題都做了簡化或者忽略)?下面將羅列出可能的解 決方案,并從設計理念層面對這些不同的方案進行分析。

            解決方案一:

            簡單的在Door的定義中增加一個alarm方法,如下:

          abstract class Door{
          abstract void open();
          abstract void close();
          abstract void alarm();
          }
            或者

          interface Door{
          void open();
          void close();
          void alarm();
          }
            那么具有報警功能的AlarmDoor的定義方式如下:

          class AlarmDoor extends Door{
          void open(){…}
          void close(){…}
          void alarm(){…}
          }
            或者

          class AlarmDoor implements Door{
          void open(){…}
          void close(){…}
          void alarm(){…}

            這種方法違反了面向對象設計中的一個核心原則 ISP (Interface Segregation Principle),在Door的定義中把Door概念本身固有的行為方法和另外一個概念"報警器"的行為方 法混在了一起。這樣引起的一個問題是那些僅僅依賴于Door這個概念的模塊會因為"報警器"這個概念的改變(比如:修改alarm方法的參數)而改變,反 之依然。

            解決方案二:

            既然open、close和alarm屬于兩個不同的概念,根據ISP原則應該把它們分別定 義在代表這兩個概念的抽象類中。定義方式有:這兩個概念都使用 abstract class 方式定義;兩個概念都使用interface方式定義;一個概念 使用 abstract class 方式定義,另一個概念使用interface方式定義。

            顯然,由于Java語言不支持多重繼承,所以兩個概念都使用abstract class方式定義是不可行的。后面兩種方式都是可行的,但是對于它們的選擇卻反映出對于問題領域中的概念本質的理解、對于設計意圖的反映是否正確、合理。我們一一來分析、說明。

            如果兩個概念都使用interface方式來定義,那么就反映出兩個問題:1、我們可能沒有 理解清楚問題領域,AlarmDoor在概念本質上到底是Door還是報警器?2、如果我們對于問題領域的理解沒有問題,比如:我們通過對于問題領域的分 析發現AlarmDoor在概念本質上和Door是一致的,那么我們在實現時就沒有能夠正確的揭示我們的設計意圖,因為在這兩個概念的定義上(均使用 interface方式定義)反映不出上述含義。

            如果我們對于問題領域的理解是:AlarmDoor在概念本質上是Door,同時它有具有報 警的功能。我們該如何來設計、實現來明確的反映出我們的意思呢?前面已經說過,abstract class在Java語言中表示一種繼承關系,而繼承關系 在本質上是"is-a"關系。所以對于Door這個概念,我們應該使用abstarct class方式來定義。另外,AlarmDoor又具有報警功能,說 明它又能夠完成報警概念中定義的行為,所以報警概念可以通過interface方式定義。如下所示:

          abstract class Door{
          abstract void open();
          abstract void close();
          }
          interface Alarm{
          void alarm();
          }
          class Alarm Door extends Door implements Alarm{
          void open(){…}
          void close(){…}
          void alarm(){…}
          }
            這種實現方式基本上能夠明確的反映出我們對于問題領域的理解,正確的揭示我們的設計意圖。其 實abstract class表示的是"is-a"關系,interface表示的是"like-a"關系,大家在選擇時可以作為一個依據,當然這是建立在對問題領域的理解上的,比如:如果我們認為AlarmDoor在概念本質上是報警器,同時又具有Door的功能,那么上述的定義方式就要反過來了。

            小結

            1.abstract class 在 Java 語言中表示的是一種繼承關系,一個類只能使用一次繼承關系。但是,一個類卻可以實現多個interface。

            2.在abstract class 中可以有自己的數據成員,也可以有非abstarct的成員方法,而在interface中,只能夠有靜態的不能被修改的數據成員(也就是必須是static final的,不過在 interface中一般不定義數據成員),所有的成員方法都是abstract的。

            3.abstract class和interface所反映出的設計理念不同。其實abstract class表示的是"is-a"關系,interface表示的是"like-a"關系。

            4.實現抽象類和接口的類必須實現其中的所有方法。抽象類中可以有非抽象方法。接口中則不能有實現方法。

            5.接口中定義的變量默認是public static final 型,且必須給其初值,所以實現類中不能重新定義,也不能改變其值。

            6.抽象類中的變量默認是 friendly 型,其值可以在子類中重新定義,也可以重新賦值。

            7.接口中的方法默認都是 public,abstract 類型的。

            結論

            abstract class 和 interface 是 Java語言中的兩種定義抽象類的方式,它們之間有很大的相似性。但是對于它們的選擇卻又往往反映出對于問題領域中的概 念本質的理解、對于設計意圖的反映是否正確、合理,因為它們表現了概念間的不同的關系(雖然都能夠實現需求的功能)。這其實也是語言的一種的慣用法,希望讀者朋友能夠細細體會。

          posted @ 2008-11-26 11:24 larryjava 閱讀(173) | 評論 (0)編輯 收藏
          1.為什么要用抽象類實現接口
             答:

          抽象類和接口比起來,有一個好處,就是某些函數可以實現具體的方法,而并不一定是聲明抽象的方法,而接口只能聲明抽象方法,所以用一個抽象類來實現某個接口可以實現一些通用的方法,而這些具體實現的方法里還可以調用抽象方法,所以減少了子類中的重復代碼。

          java庫里也有不少這這樣的設計,

          比如java.util.AbstractList實現了java.util.List,而其實某些方法就是調用了抽象方法。

          還有一個好處就是可以給子類一個默認的實現,而不必給所有的子類實現所有的方法。

          另外還有一個好處就是可以提供一些公用的方法給子類使用。

          2.
          posted @ 2008-11-26 11:23 larryjava 閱讀(147) | 評論 (0)編輯 收藏
          第一種通過spring中的CronTrigger復雜觸發器實現

          第二通過spring中的SimpleTrigger簡單觸發器實現


          參考:
                  http://www.javaeye.com/topic/115666
                 http://www.javaeye.com/topic/117244


          posted @ 2008-11-06 17:06 larryjava 閱讀(395) | 評論 (0)編輯 收藏
          在這里希望和大家分享 iRedMail 開源郵件方案的詳細安裝、配置文檔,希望對大家有所幫助。

          基于 Postfix + MySQL 的文檔:http://www.iredmail.org/wiki/index.php/IRedMail-doc-MySQL-0.2
          基于 Postfix + OpenLDAP 的文檔:http://www.iredmail.org/wiki/index.php/IRedMail-doc-OpenLDAP-0.2

          Extmail webmail系統  http://www.extmail.org/
          Postfix  http://www.postfix.org.cn
          posted @ 2008-09-19 20:41 larryjava 閱讀(224) | 評論 (0)編輯 收藏

          使用Hibernate的sum函數進行數據的統計時,出現一個錯誤:

           

          String sql = "select SUM(nf.fee) from CFee as nf where   nf.adminAccount='testaccount' ";   
          public long getListSqlCountsLong(String sql) {   
                  beginTransaction();   
                  List li 
          = getSession().createQuery(sql).list();   
                  
          if (li == null || li.isEmpty()) {   
                      
          return 0;   
                  }
           else {                        return ((Integer) li.get(0)).longValue();   
                  }
             
              }
           
          這樣使用報null錯誤.
          List的size明明等于1,但li.get(0)還是為空.(數據庫中查詢的賬號sum本來就為null??可能是.)
          解決方法:
          String sql = "select SUM(nf.fee) from CFee as nf where   nf.adminAccount='testaccount' ";   
          public long getListSqlCountsLong(String sql) {   
                  beginTransaction();   
                  List li 
          = getSession().createQuery(sql).list();   
                  
          if (li == null || li.isEmpty()) {   
                      
          return 0;   
                  }
           else {       
                          
          if (li.get(0== null{   
                          
          return 0;   
                      }
             
                      
          return ((Integer) li.get(0)).longValue();   
                  }
             
              }
            
          解決方法很簡單,就是增加一個判斷就可以了,如果li.get(0)為空,則返回0,不為空,返回值.
          posted @ 2008-05-09 13:17 larryjava 閱讀(4021) | 評論 (0)編輯 收藏
                  
          傳統的JS壓縮(刪除注釋,刪除多余空格等)提供的壓縮率有時還是不盡不意,幸虧現在的瀏覽器都支持壓縮傳輸(通過設置http header的Content-Encoding=gzip),可以通過服務器的配置(如apache)為你的js提供壓縮傳輸,或是appfuse中使用的GZipFilter使tomcat也提供這種能力

          現在的問題是這種動態的壓縮會導致服務器CPU占用率過高,現在我想到的解決辨法是通過提供靜態壓縮(就是將js預先通過gzip.exe壓縮好)

          一.下面描述在tomcat中的應用

          1.將prototype.js通過gzip.exe壓縮保存成prototype.gzjs
          2.設置header,我編寫了一個簡單的AddHeadersFilter來將所有以gzjs結尾的文件增加設置header Content-Encoding=gzip
          web.xml中的配置
          	<filter>
          <filter-name>AddHeaderFilter</filter-name>
          <filter-class>
          badqiu.web.filter.AddHeaderFilter
          </filter-class>
          <init-param>
          <param-name>headers</param-name>
          <param-value>Content-Encoding=gzip</param-value>
          </init-param>
          </filter>
          <filter-mapping>
          <filter-name>AddHeaderFilter</filter-name>
          <url-pattern>*.gzjs</url-pattern>
          </filter-mapping>
          


          測試prototype.js是否正常的代碼
          <html>
          <head>
          <!-- type="text/javascript"不可少,有些瀏覽器缺少這個不能運行,具體已經忘記了 -->
          <script src="prototype.gzjs" type="text/javascript"></script>
          </head>
          <body>
          <input id="username" name="username" value="badqiu"/><br />
          <input id="email" value="badqiu@gmail.com"/>
          <script>
          <!-- 測試prototype的方法是否正常-->
          alert($F('username'))
          </script>
          </body>
          </html>
          


          在Apache httpd中可以直接通過在httpd.conf增加AddEncoding x-gzip .gzjs來映射.gzjs文件的header

          二.相關壓縮率數據
          1. prototype.js 1.5.0_rc0原始大小56KB,未經任何處理直接使用gzip壓縮為12KB,總壓縮率79%
          2. 通過js壓縮工具壓縮過的protytype.js為20KB,使用gzip壓縮為10KB,總壓縮率為83%
          3. 實際項目中的多個js合并成的文件 439KB,直接通過gzip壓縮為85KB,總壓縮率81%
          4. 439KB經過js壓縮為165KB,再經過gzip壓縮為65KB,總壓縮率86%

          基本上你都可以忽略js壓縮工具的壓縮率,直接使用gzip壓縮

          gzip下載地址 http://www.gzip.org
          tomcat的壓縮配置示例下載地址: http://www.aygfsteel.com/Files/badqiu/gziptest.rar
          posted @ 2008-02-22 11:32 larryjava 閱讀(373) | 評論 (0)編輯 收藏

          經過我的多次測試實踐,在linux和window下測試通過,win的比較簡單,因為在默認的情況下,組播就已經打開。
          1 在linux 下同一臺服務器上測試通過(注意端口不要沖突。特別要注意那個tcpListenPort=”4001″ )
          2 在window下的同一臺服務器上測試通過,注意要點同上
          3 window下多臺不同主機上測試通過,沒有什么好注意點,可以完全備份一個tomcat
          4.linux多臺不同tomcat服務器上測試通過。這個也是最后實現,最實際的方案。(一般不用在win下部署tomcatweb應用。呵呵。我覺得)

          這里講下第四中情況

          先講一下環境:都是在Red Hat Linux AS4上測試通過
          Apache:ip:192.168.1.11 (一臺) 版本:2.0/2.2 (做均換負載服務器)
          Tomcat:ip1:192.168.1.12 ip2:192.168.1.13 (兩臺) 版本:5.0、5.5 (web應用的Real Server)
          Jdk:版本1.5 安裝在 192.168.1.12 和192.168.1.13上的tomcat服務器上

          安裝tomcat和apache ,在這里就不講了。
          軟件都可以在www.apache.org 的網站上找到(apache,tomcat,mod_jk)

          1.下載mod_jk.so 文件放到apache 下的modules下
          地址:http://apache.mirror.phpchina.com/tomcat/tomcat-connectors/jk/binaries/ 請選擇正確的操作系統和Apache的版本。
          2.在apache的conf下建立文件workers.properties

          添加內容:

          #
          # workers.properties
          #

          # list the workers by name
          worker.list=tomcatlb, status

          # localhost server 1
          # ------------------------
          worker.tomcat12.port=8009
          worker.tomcat12.host=192.168.1.12
          worker.tomcat12.type=ajp13
          worker.tomcat12.lbfactor=1
          worker.tomcat12.connection_pool_timeout=750
          worker.tomcat12.socket_keepalive=0
          worker.tomcat12.socket_timeout=300000
          worker.tomcat12.connect_timeout=10000
          worker.tomcat12.reply_timeout=330000

          # localhost server 3
          # ------------------------
          worker.tomcat13.port=8009
          worker.tomcat13.host=192.168.1.13
          worker.tomcat13.type=ajp13
          worker.tomcat13.lbfactor=1
          worker.tomcat13.connection_pool_timeout=750
          worker.tomcat13.socket_keepalive=0
          worker.tomcat13.socket_timeout=300000
          worker.tomcat13.connect_timeout=10000
          worker.tomcat13.reply_timeout=330000

          worker.tomcatlb.type=lb
          worker.retries=3
          worker.tomcatlb.balanced_workers=tomcat12,tomcat13
          worker.tomcatlb.sticky_session=1

          worker.status.type=status

          3.在conf下添加一個mod_jk.conf文件

          LoadModule    jk_module  modules/mod_jk.so

          #configure mod_jk
          JkWorkersFile conf/workers.properties
          JkLogFile logs/mod_jk.log
          JkLogLevel debug

          4.增加一個虛擬機配置文件vhosts.conf (這個不是必須的,可以將JkMount 的寫其他的配置文件中)

          <VirtualHost *:80>
              ServerAdmin webmaster@dummy-host.example.com
              DocumentRoot /data/google
              ServerName my.linuxcoffee.org
              ErrorLog logs/my.linuxcoffee.org-error_log
              CustomLog logs/my.linuxcoffee.org-access_log common
              DirectoryIndex index.htm  index.html

          JkMount /*.jsp tomcatlb
          JkMount /*.action tomcatlb
          JKMount /jkstatus status
          </VirtualHost>

          4.修改conf下的httpd.conf文件加上

          Include conf/vhosts.conf
          Include conf/mod_jk.conf

          5.配置tomcat
          講Cluster 前的注釋去掉,啟用tomcat集群功能。
          一般不需要修改什么東西,但在我這邊,兩臺linux的tomcat就是死活找不到node,而同樣的配置文件在window下的跑得很是正常。
          有個東西要說明下,因為tomcat的session同步功能需要用到組播,windows默認情況下是開通組播服務的,但是linux默認情況下并沒有開通,可以通過指令打開route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0,如果需要服務器啟動時即開通組播需在/etc/sysconfig/static-routes文件內加入eht0 net 224.0.0.0 netmask 240.0.0.0。具體組播概念請查閱CCNP相關內容。
          可以通過netstate -g 來查看組播狀態,也可以在route -e 命令中看到

          原來一直提示這個問題
          信息: Manager [/clusterapp]: skipping state transfer. No members active in cluster group.
          最后測試只要修改在Cluster之間的一段代碼

          <Receiver         
          className="
          org.apache.catalina.cluster.tcp.ReplicationListener
          "
                          
          tcpListenAddress="auto"
                          
          tcpListenPort="4001"
                          
          tcpSelectorTimeout="100"
                          
          tcpThreadCount="6"/>

          改為

          <Receiver         
          className="
          org.apache.catalina.cluster.tcp.ReplicationListener
          "
                          
          tcpListenAddress="192.168.1.12"
                          
          tcpListenPort="4001"
                          
          tcpSelectorTimeout="100"
                          
          tcpThreadCount="6"/>

          在13的服務器上也將這一段修改為自己的ip

          然后打開jvmRoute ,跟workers.properties 的兩個tomcat名字相匹配
          ip1

          <Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat12"/>

          ip2

          <Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat13"/>

          好了,apache和tomcat的配置好了,可以訪問了。
          這里,再提供一個鏈接,可以監控和配置負載均衡的各種信息
          http://192.168.1.11/jkstatus或http://my.linuxcoffee.org、jkstatus來訪問網站。

          注:需要在web.xml的display-name后面 下加上一段。 這個跟順序有關的,不然,xml文件會變紅哦。

          <?xml version="1.0" encoding="UTF-8"?>
          <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
          <display-name>TomcatDemo</display-name>
          <distributable/>
          </web-app>

          參考文章:
          Tomcat 5 Home Page
          Clustering Home Page on Tomcat site
          Load Balancer Home Page on Tomcat site

          posted @ 2008-01-13 20:48 larryjava 閱讀(1298) | 評論 (0)編輯 收藏


            

          <script language="javascript">
            g_blnCheckUnload 
          = true;
            
          function RunOnBeforeUnload() {
               
          if (g_blnCheckUnload) {window.event.returnValue = 'You will lose any unsaved content';   
               }
            
            }

          </script>
          <body  onbeforeunload="RunOnBeforeUnload()">
          </body>
          二、
          <script>
          function window.onbeforeunload()
          {
              
          if(event.clientX>document.body.clientWidth&&event.clientY<0||event.altKey)
              
          {
                  window.event.returnValue
          ="確定上傳完成嗎?";
              }
          else
              
          {
                  alert(
          "你在刷新");
              }

          }

          </script>
          posted @ 2007-12-11 13:35 larryjava 閱讀(314) | 評論 (0)編輯 收藏
          父窗口代碼:
          <a href="javascript:void(0)" onclick="window.open('child.html','child','width=400,height=300,left=200,top=200');">打開子窗口</a>


          子窗口代碼:
          <script language="JavaScript" type="text/javascript"> <!-- function refreshParent() {     window.opener.location.href = window.opener.location.href;     if (window.opener.progressWindow)     {         window.opener.progressWindow.close();     }     window.close(); } //--> </script>  <a href="javascript:void(0)" onclick="refreshParent()">刷新父窗口并關閉當前窗口</a> 


          點此查看示例
          posted @ 2007-12-05 15:04 larryjava 閱讀(797) | 評論 (0)編輯 收藏

           

          <script language=javascript> 

          function gbcount(message,total,used,remain)
          {
          var max;
          max 
          = total.value;
          if (message.value.length > max) {
          message.value 
          = message.value.substring(0,max);
          used.value 
          = max;
          remain.value 
          = 0;
          alert(
          "內容不允許超過 1000 個字!");
          }

          else {
            
          var iLength = 0;
           
          for(var i = 0;i<message.value.length;i++)
           
          {
           
          if(message.value.charCodeAt(i) >255)//字母數字的ascii編碼都小于255而漢字的編碼肯定大于255
           {
           iLength 
          += 2;
           }
          else if(message.value.charCodeAt(i)==32)//空格
           {
             iLength 
          += 0;
           }
          else//字母或數字
            {
              iLength 
          += 1;
            }

           }

          used.value
          =iLength;
          //used.value = message.value.length;
          remain.value = max - used.value;
          }

          }

          </script>
          <form>
          <textarea    onkeydown=gbcount(this.form.contents,this.form.total,this.form.used,this.form.remain); onkeyup=gbcount(this.form.contents,this.form.total,this.form.used,this.form.remain); cols="80" rows="8" wrap="VIRTUAL" id="contents">
          </textarea>
          最多字數:
          <INPUT  disabled maxLength=4 name=total size=3 value=1000> 
          已用字數:
          <INPUT  disabled maxLength=4 name=used size=3 value=0> 
          可用字數:
          <INPUT  disabled maxLength=4 name=remain size=3 value=1000>
          </form>

          <htmel><title>字數</title>
          <script language="javascript">
          function gbcount(message,total,used,remain)
          {
          var max;
          max=total.value;
          if(message.value.length > max){
          message.value = message.value.substring(0,max);
          used.value = max;
          remain.value = 0;
          alert('不能超過300個字!');
          }
          else{
          used.value = message.value.length;
          remain.value = max - used.value;
          }
          }
          </script>

          <body><form>
          <textarea  cols="60" rows="8" id="memo1" onkeydown="gbcount(this.form.memo1,this.form.total1,this.form.used1,this.form.remain1);"  onkeyup="gbcount(this.form.memo1,this.form.total1,this.form.used1,this.form.remain1);"></textarea>
          <br>
          最多字數:<INPUT disabled maxLength=4 name=total1 size=3 value=500>
          已用字數:<INPUT disabled maxLength=4 name=used1 size=3 value=0>
          剩余字數:<INPUT disabled maxLength=4 name=remain1 size=3 value=500> </form>
          </body></html>

          posted @ 2007-09-17 13:09 larryjava 閱讀(843) | 評論 (0)編輯 收藏

          http://www.dhtmlgoodies.com/
          http://webfx.eae.net/
          http://www.miniajax.com/
          http://www.dynamicdrive.com

          posted @ 2007-09-13 09:24 larryjava 閱讀(112) | 評論 (0)編輯 收藏
          <directory /some/where/dir> 
          <FilesMatch "\.(mov|avi|bov|rm)"> 
          Order Deny,Allow 
          Deny from all 
          </FilesMatch> 
          </directory>

          限制指定的文件后綴…
          posted @ 2007-08-23 10:23 larryjava 閱讀(310) | 評論 (0)編輯 收藏
           

          項目中Struts/Spring/Hibernate的基本流程

           

          Struts+Spring+Hibernate  develepment process:

          1.Write your business class : DTO,FormBean,Action,Service Interface,Service Implementation.

           2.Write JSP pages.
          3.struts-config.xml Configuration : FormBean,Action,Forward pages.
          4.applicationContext-service.xml Configuration: add your Service Interface and Service Implementation.
          5.Add your service factory Get method to ServiceFactory.java
          6.Build project and Generate the Description file(*.hbm.xml) of DTO.
          7.applicationContext.xml Configuration: add *.hbm.xml file to applicationContext for O/R mapping. 

          Spring+hibernate的單元測試Junit

           spring提供的單元測試是強大的,spring的單元測試很簡單,封裝的很好。我們要用spring的單元測試測試我們寫的adddelete等方法時候需要spring提供的一個額外包spring-mock.jar,我已經傳上來了。你只要熟悉單元測試,編寫一個測試案例,然后把繼承改為org.springframework.test.AbstractTransactionalDataSourceSpringContextTests就可以了,此時編譯器會提示你要實現
            /**
            *  必須實現的方法
            */
            public  String[]  getConfigLocations(){
            String[]  config  =  new  String[]{"applicationContext.xml","applicationContext-dao.xml","applicationContext-hibernate.xml","applicationContext-service.xml"};
            return  config;
            }
            看了大家應該明白,就是把你配置好的xml賦值給它,
            然后大家就可以通過下面方法:
            下面的applicationContext這個變量是你只要繼承了剛才那個抽象類就可以得到的一個恒量。
            FriendService  friendService  =  (FriendService)applicationContext.getBean("friendService");
            得到你的實例來進行業務邏輯測試了,是不是很簡單,大家試試吧,它在此時完成以后會把數據庫回滾一次,不會影響你的數據庫記錄,非常好。

           

          spring中提供 ContextLoaderListenter類,用來加載contextxml文件。

          springstruts提供ContextLoaderPlugIn類,此類也可以加載contextxml文件。

          區別在于,兩種方式加載的WebApplicationContext,以不同的Key存放在ServletContext中。而如果你定義了HibernateFilter的話,spring會利用WebApplicationContextUtils來獲取WebApplicationContext而此類并不識別ContextLoaderPlugIn類所加載的上下文,此時便會拋出異常: No WebApplicationContext found: no ContextLoaderListener registered?

          利用ContextLoaderListenter來加載daoservice級別的context,而對于strutsaction,用ContextLoaderPlugIn加載。

          2005年漂泊的一年,先后求職于南京,上海和北京三地,因此慘遭京滬寧三地java高手蹂躪。
          這些都是面試java架構師的比較變態的題目:
          1
          。變態指數 4
          int x=4;
          System.out.println("value is " +((x>4)?99.9:9));
          答案 9.0 問號表達式的后面兩個條件有要求,因為前面的是float,所以后面轉為float.
          估計出題者才通過SCJP的考試。
          2.
          變態指數 5
          public class Test {

          public static void main(String[] args) {
          int x = 4;
          java.util.Date date = (x > 4) ? new A() : new B();
          }
          }

          class A extends java.util.Date {}
          class B extends java.util.Date {}
          答案 jdk1.4編譯不通過,1.5可以
          不知道出題人的意圖
          3.
          變態指數 6
          String s=new String("abc");
          創建了幾個String對象?
          答案 2
          這樣的公司最好不要去

          4.變態指數 7
          const
          是不是java的關鍵字?
          答案 constjava的關鍵字,但是java沒有實現它
          一般人絕對用不到它

          5.
          變態指數 8
          short s1 = 1; s1 = s1 + 1;有什么錯? short s1 = 1; s1 += 1;有什么錯?
          答案 12對,1因為向上轉型了,最后導致類型不匹配錯誤 ,
          因為s1+=是一個操作符,能夠自動轉型,
          short s1 = 1;
          s1 = s1+1;
          這句話在c++里面可以的
          不知道出題人的意圖
          6.
          變態指數 9
          上海貝爾的面試題:你認為效率最高的方法,實現從1加到100.
          答案 1-100的累加相當于加50101,這樣循環次數從100次降為50次:
          int sun = 0
          for(int i = 1,j = 100 ; i <= 50 ; i++,j--){
              sun = sun + i + j;

          出題人腦子有問題,直接(1+100)*50不是最快...其實類似這樣的優化應該不是程序員考慮的范疇吧
          7.
          變態指數 10
           System.out.println(5.0942*1000);
               System.out.println(5.0943*1000);
            System.out.println(5.0944*1000);
          的結果
          答案 :5094.2 5094.299999999999 5094.400000000001
          原理和浮點數的計算機表示方式有關 ,你不用上機,就答對了,你最好去微軟,接替安德爾森.

          posted @ 2007-07-05 17:33 larryjava 閱讀(897) | 評論 (0)編輯 收藏

          <script  language="javascript">
          function test(){
          if(escape(document.all.type.value).indexOf("%u")!=-1) alert("含有漢字");
          else alert("全是字符");

          }
          </script>
          <input type="text" name="type"><input type="button" name="test" onclick="test();">

          posted @ 2007-07-05 17:31 larryjava 閱讀(218) | 評論 (0)編輯 收藏
                                                                             應用系統架構設計   

          我們在做著表面上看似是對于各種不同應用的開發,其實背后所對應的架構設計都是相對穩定的。在一個好的架構下編程,不僅對于開發人員是一件賞心悅目的事情,更重要的是軟件能夠表現出一個健康的姿態;而架構設計的不合理,不僅讓開發人員受苦受難,軟件本身的生命周期更是受到嚴重威脅。這里我將針對在微軟dotNet平臺上做應用開發系統的一般架構流程設計做一個粗淺的討論。

           

          總體設計圖 

           表示層

          表示層由UI(User Interface)和UI控制邏輯組成。

          l         UI(User Interface)

          UI是客戶端的用戶界面,負責從用戶方接收命令,請求,數據,傳遞給業務層處理,然后將結果呈現出來。根據客戶端的不同我們大體將應用程序分為BS(Browser-Server) 瀏覽器結構,CS(Client-Server)桌面客戶端結構。

          BS的優點是無需操心客戶端,只需要部署維護好服務器即可。CS的優點在于強大的界面交互表達能力。RIA(Rich Internet Application)是為了融合這兩種結構優點的一種技術,它依賴在客戶端一次性安裝一個通用解釋器之后即獲得強大的界面交互表達能力和無需部署具體客戶端的方便性。具體的實現技術很多,例如微軟的SmartClient, Avalon; Macromedia的Flex;以JS為基礎的Bindows;Ajax等等很多。

           

          l         UI控制邏輯

          UI控制邏輯負責處理UI和業務層之間的數據交互,UI之間狀態流程的控制,同時負責簡單的數據驗證和格式化等功能。具體的說在dotNet事件驅動的編程模型下,UI控制邏輯被自然的實現在了事件函數中,例如PageLoad事件函數,ButtonClick事件函數。在這些事件函數中,主要任務就是做UI控件與業務實體的數據交換與業務調用,但面對大量的數據交換工作量與維護量就成了最大的問題。而在復雜應用的系統中,狀態與流程的管理是必須要考慮的因素,它們同樣是業務邏輯的一部分,如果不加以封裝的直接寫在事件函數中將導致業務依賴表示層。下面分別討論這兩個問題。

           

          1.         1.UI與業務實體之間的數據交互

          此階段負責數據交換的業務實體稱為DTO(Data Transfer Object),處理輸入時我們從UI控件的獲得數據填入DTO再向下傳播,處理輸出時用戶發出請求業務層會將數據以DTO的形式返出再賦給UI控件展現。因此需要一種方式來自動解決這樣的來回賦值問題。遺憾的是dotNet下的不少控件雖然支持數據綁定但仍然沒有一個現成完整的解決辦法。我們可以自己設計一個Adapter按照某種映射關系來自動處理這樣的綁定,這樣的映射關系最好是UI控件與DTO屬性的事先命名約定,以此種方式的約定作為映射關系無需增加任何配置文件和配置工作即可實現。

           

          2.         2.狀態與流程的管理

          既然是業務邏輯的一部分就不應該耦合再表示層當中。MVC(Model-View-Controller)模式提供了實現這一目標的方法。Controller是整個方案的核心,它是一個流程管理器,來自UI所有的命令與數據經過Controller分發給業務層或其他UI,這樣我們可以把流程,權限等邏輯單獨封裝,例如配置文件中,達到最大化的業務重用。dotNet下MVC的方案并不像Java下有那么多選擇,目前有以下幾種選擇:

          微軟的UIPAB,它可以處理bs,cs下的流程跳轉,可以使得相同的業務系統有webform和winform不同的展現方式。

          開源的Mavrick.Net,它只適用于Asp.Net應用程序,它對流程,國際化,頁面包裝,xslt頁面轉換提供了很好的支持。

          開源的Lattis,同樣只適用于Asp.Net應用程序。

           

          業務層

          業務層封裝了實際業務邏輯,包含數據驗證,事物處理,權限處理等業務相關操作,是整個應用系統的核心。因此設計一個能夠真實反映實際需要的業務層是非常必要的,我們將實際業務具體分為業務數據與業務操作兩部分。

           

          l         業務數據

          業務數據又是業務邏輯的核心,最終業務數據將以一種固定的格式表現于內存中,在系統的各個層次間傳輸,充當DTO角色。表達業務數據的方式一般分為兩種Table Model和Domain Model。

          Table Model是將數據庫中的表直接映射成為業務數據對象,這樣的優點是適合于機器操作,ADO.NET直接提供了這種操作的便利,但對于復雜業務關系的表達就很不直觀。只適合于業務需求與數據表對應關系很直接的需要快速開發的情況。通常我們選用Dataset或者強類型Dataset(Strong Typed Dataset),強類型Dataset支持編譯時的類型檢查,效率上要略高于普通Dataset。Dataset有很多方便的特性:無需自己編寫維護類,支持序列化,數據副本保存,支持數據集合,對控件綁定支持效果好,微軟提供了相應的生成工具以及持久方案。但缺點也是明顯,復雜數據表現不直觀,做為DTO在各個層次間傳輸,尤其是分布式環境,龐大的體積,相對緩慢的實例化對于性能造成很大壓力。

          Domain Model則是根據實際業務按照現實方式用OO思想建模,這樣很適合業務復雜的系統。通常采用自定義數據實體(Custom Data Entity)方式表達。自定義數據實體,有著良好的性能,編譯時的類型檢查,數據表現方式非常直觀符合實際業務的操作方式等優點,但需要自己定義維護類,在分布式環境下需要自己編寫序列化方法。

          綜合各種因素考慮,雖然業務簡單對應直接的系統我們以Table Model建模開發效率很高但難免保證系統日后不會變的復雜,因此出于復用性,擴展性,性能等方面選用Domain Model建模為佳。

           

          l         業務操作

          業務操作負責對業務數據進行各種業務相關的處理,例如驗證,流向,整合,事物,權限等,但它不負責有關對數據源的操作。它與業務數據的關系設計有2種方式。

          分離業務數據與業務操作,將業務數據單獨封裝到只有數據get,set的數據類中,這個數據類只充當DTO。將業務操作封裝到獨立的service類中與業務數據一起充當業務層。這樣當系統不復雜的時候顯的簡單直觀,而隨著系統日益復雜,service類會變的雜亂,而將本身耦合緊密的數據與操作分離對于復用也是不利的因素。具體可參考Martin Fowler 的貧血的Domain Model一文,但我并不傾向于業務層直接訪問數據源。

          整合業務數據與業務操作,將業務數據與相關的業務操作封裝在一起稱為業務實體,業務實體作為統一的業務層為表示層提供服務,同時也負責作為DTO在各個層次間傳輸,我傾向于這樣完整的Domain Model設計方式,每個業務實體都可以做為一個單獨組件形式存在,對于組件化復用有著莫大的好處。

           

          l         業務模塊間的依賴

          各個業務模塊之間的依賴,有時候會是難以解決的問題,尤其是一些可以重復利用的業務組件,例如權限管理,郵件發送等等。管理好這些各種不同的業務組件是我們的目標,IoC容器為我們提供了最完美的方案,通過它將不同的模塊注入到系統中我們可以在不知道這個組件存在的情況下調用它。但目前只有不成熟的Spring.Net一個選擇,我們只有一聲嘆息,因此也就不多討論了。

           

          業務數據訪問層

          業務數據訪問層是一個針對具體應用系統的專屬層,它為業務層提供與數據源交互的最小操作方式,僅僅是業務層需要的數據訪問接口,業務層完全依賴業務數據訪問層所提供的服務。這些服務負責從業務層接收數據或返回業務實體,它屏蔽了實際業務數據與機器存儲方式的差別。當然,數據層選用抽象的解決方案同樣可以達到這個效果,但業務數據訪問層最大的特點就是針對具體業務做抽象,而抽象的數據層訪問方案是針對通用做抽象。往往業務中針對具體的設計生命力會變的更強,這樣我們可以最大限度的保持了上層代碼的復用性,當需要更換存儲策略如果數據層訪問差別太大,通過更換數據層無法解決問題的時候我們最多只需要更換業務數據訪問層,而無需改變業務層。

           

          業務數據訪問層由DAO(Data Access Object)層和系統服務層兩部分組成。DAO層為每個業務實體提供最基本的數據訪問服務,系統服務層為系統全局提供與業務關系不大的通用數據訪問服務,這兩層處于系統中的同一個層次位置。

           

          業務層與業務數據訪問層關系圖

           

           

          數據層

          數據層的宗旨就是為數據源提供一個可供外界訪問的接口,我們應該選用一種能夠提供數據源無關的抽象數據訪問接口并通過在其下掛接各種不同的DataProviador來訪問數據源的數據層組件,這樣做便于移植到不同的數據源上。目前有以下3種數據層方案:

           

          1.        1. 封裝ADO.Net

          這些數據訪問組件都是基于ADO.Net的淺封裝,它的優點在于封裝層次低所以速度最快,我們可以手動組織sql語句用來適應復雜的操作以及個性的優化等。缺點是無法直接處理自定義數據實體方式的業務實體對象,需要將業務實體中的數據屬性以參數形式傳入傳出。這樣的方式雖然最為保險,但隨著系統規模增大,開發效率,質量,,后期的維護,二次開發都變成尤為突出的問題,對開發人員的要求會變的越來越高。另外對于事物操作封裝不是很好,無法提供聲明性事物,經常會在業務層出現訪問數據層的需要。這樣的組件目前應用的很廣泛,例如微軟在EnterpriseLibrary中提供的DAAB(Data Access Application Block),還有以前的DAAB3.1。EnterpriseLibrary是個成熟的產品,包括了數據訪問,異常,日志,緩存,加密,配置,安全等組件做為通用服務非常適合。

           

          2.        2. OR-Mapping組件

          ORM是最好的數據持久解決方案,它的優點在于能夠以面向對象的方式操縱數據,因此可以直接處理自定義數據實體的業務對象,我們根本不用操心sql語句以及底層存儲方式,這樣極大的簡化的代碼提高了開發效率,對于日后維護擴展都帶來極大的便利。缺點在于屏蔽了底層使得我們無法針對具體數據源做優化,而且對于復雜關聯的sql操作有些力不從心,同時性能也差一些但輔助以緩存情況會好很多,而在dotNet下最大的問題就是沒有一個成熟便宜的ORM產品供我們使用,全部都是beta版本和商業版本。這些版本或多或少都存在一些問題,以至于真正應用中需要經過仔細考察。例如NHibernate,Gentle.Net,XPO,Grove.Net等等非常多。

           

          3.        3. DataMapper(SqlMapper)

          SqlMapper為以上兩種方式提供了一個折中的選擇,它可以以面向對象的方式直接處理自定義數據實體的業務對象,同時可以根據與數據源與業務實體的映射關系執行手寫的sql語句,這樣完全使得我們可以針對具體數據源做優化,對于復雜操作同樣可以勝任。目前只有iBatis.Net一個產品,它是一個java移至的開源項目,已經比較成熟,可以在無需編譯的情況下隨意替換DAO。

           

           

          至此,整個架構方案的討論已經完成,我們可以看出dotNet下可供選擇的解決方案是那么的有限,反看Java世界,有那么多成熟可供利用的組件框架,流口水中...不過dotNet也正在走向成熟,我們需要時間等待。這個架構設計的思路只代表了我個人的理解,而且也并不是說所有的開發都是這么一套方案,在具體環境中需要做具體的調整。希望能起到一個拋磚引玉的作用。我的郵箱是i-simon AT msn.com,由于我經驗尚淺,有不正確或不足的地方歡迎指正討論,另外本文將根據技術的最新進展持續更新。

          posted @ 2007-05-29 13:11 larryjava 閱讀(190) | 評論 (0)編輯 收藏
          1. DAO的職責就是增刪改查,不該有多余的邏輯。這個問題其實我碰到過很多人寫的代碼和接口的設計都非常不合理。我個人有一個標準,你可以參考一下,如果用Hibernate的話,DAO的實現代碼絕不會超過15行,至少我現在的DAO就是這樣的。DAO互相調用?這是絕對不可能的,除非你設計有問題。

          2. Service層的職責就是實現具體的業務操作。我不認為Service之間有必要相互調用,至少目前我還沒有碰到過有必要互相調用的情況,我認為良好的設計也是可以避免這一點的。

          3. 配置文件多使用autowire就可以變得異常簡單,除非你認為autowire會影響性能。

          4. 看實際情況,我Facade有時候是個好主意,不過我還沒有使用過,Service接口直接暴露給Action層。
          posted @ 2007-05-23 08:55 larryjava 閱讀(153) | 評論 (0)編輯 收藏

          ■ 影像地圖

            <MAP> <AREA>

            欲明白本篇【HTML徹底剖析】之標記分類,請看 【標記一覽】。
            也請先明白圍堵標記與空標記的分別,請看 【HTML概念】。

          ■ <MAP> <AREA>:

          <MAP>...</MAP>
          用法:      當在AREA元素中使用時,創建一個客戶端的圖形鏡像
          開始/結束標識: 必須/必須
          屬性:      %coreattrs
                   name="..."將要創建的圖形鏡像的名字
          空:       不允許

          <AREA>
          用法:      用來定義鏈接和錨
          開始/結束標識: 必須/非法
          屬性:      shape="..."允許我們使用已定義的形狀定義客戶端的圖形鏡像(default, rect, circle, poly)
                   coords="..."使用像素或者長度百分比來定義形狀的尺寸
                   href="..."所鏈接的源文件的URL
                   target="..."決定把源文件顯示在什么地方(用戶自定義, _blank, _parent, _self, _top)
                   nohref="..."說明該域沒有反應
                   alt="..."顯示可替換的文本
                   tabindex="..."通過使用定義過的"tabindex"屬性設置不同元素之間獲得焦點的順序
          空:       允許

            相信不會太多人手動設定 Image Map,通常使用網頁編輯部工具的向導,那是很方便的方法,至于 <MAP> <AREA> 的詳細的介紹,我們以后有空會補上。

          ★target的屬性:
          ★_blank 在新窗口打開
          ★_parent 在父級窗口打開
          ★_self 在本窗口打開
          ★_top 在整個瀏覽器窗口打開

          在HTML中有一個具有把圖片劃分成多個作用區域,并鏈接到不同網頁的標記,那就是 <area>地圖作用區域標記。
            <area>標記主要用于圖像地圖,通過該標記可以在圖像地圖中設定作用區域(又稱為熱點),這樣當用戶的鼠標移到指定的作用區域點擊時,會自動鏈接到預先設定好的頁面。其基本語法結構如下:
          <area class=type  id=Value href=url alt=text  shape=area-shape  coods=value>
          其中。class和id:是分別指定熱點的類型和id號。
          alt:用于設定熱點的替代性文字。
          href:用于設定該熱點所鏈接的url地址。
          shape和coords:是兩個主要的參數,用于設定熱點的形狀和大小。其基本用法如下:
          <area shape="rect" coords="x1, y1,x2,y2" href=url>表示設定熱點的形狀為矩形,左上角頂點坐標為(X1,y1),右下角頂點坐標為(X2,y2)。
          <area shape="circle" coords="x1, y1,r" href=url>表示設定熱點的形狀為圓形,圓心坐標為(X1,y1),半徑為r。
          <area shape="poligon" coords="x1, y1,x2,y2 ......" href=url>表示設定熱點的形狀為多邊形,各頂點坐標依次為(X1,y1)、(X2,y2)、(x3,y3) ......。
            <area>標記是在圖像地圖中劃分作用區域的,因此其劃分的作用區域必須在圖像地圖的區域內,所以在用 <area> 標記劃分區域前必須用HTML的另一個標記<map>來設定圖像地圖的作用區域,并為指定的圖像地圖設定名稱,該標記的用法很簡單,即<map name="圖像地圖名稱"> ...... </map>。
            下面通過一個例子來說明這兩個標記的用法:
            這里是一幅新書架的圖片,要做的效果是:當鼠標點“網址大全”這本書時,新開一窗口,顯示關于這本書的簡介及訂單的網頁(urlall.htm);當 鼠標點“網站設計攻略”這本書時,新開一窗口,顯示關于這本書的簡介及訂單的網頁(siteall.htm);當鼠標點“網頁技巧大全”這本書時,新開一 窗口,顯示關于這本書的簡介及訂單的網頁(pagejqlall.htm)。制作方法:
            1、插入圖片,并設置好圖像的有關參數,且在<img>標記中設置參數usemap="newbook" ismap,以表示對圖像地圖(newbook)的引用;
            2、用<map>標記設定圖像地圖的作用區域,并取名為:newbook;
            3、分別用<area>標記針對三本書的位置劃分出三個矩形作用區域,并設定好其鏈接參數href。
            制作完成,本例的源代碼如下:
          <img src="image/htmlp3.gif" width="207" height="148" alt="新書架" hspace="10" align="left" usemap="#newbook" border="0">
          <map name="newbook">
          <area shape="rect" coords="56,69,78,139" href="urlall.htm" target="_blank" alt="這里收集十萬多個網址。" title="這里收集十萬多個網址。">
          <area shape="rect" coords="82,70,103,136" href="siteall.htm" target="_blank" alt="網站設計師的啟蒙讀本。" title="網站設計師的啟蒙讀本。">
          <area shape="rect" coords="106,68,128,136" href="pageall.htm" target="_blank" alt="網頁制作者不可不讀的書。" title="網頁制作者不可不讀的書。">
          </map>

            在制作本文介紹的效果時應注意的幾點:
            1、在<img>標記不要忘記設置usemap、ismap參數,且usemap的參數值必須與<map>標記中的name參數值相同,也就是說,“圖像地圖名稱”要一致;
            2、同一“圖像地圖”中的所有熱點區域都要在圖像地圖的范圍內,即所有<area>標記均要在<map>與</map>之間;
            3、在<area>標記中的 cords 參數設定的坐標格式要與shape參數設定的作用區域形狀配套,避免出現在shape參數設置的矩形作用區域,而在cords 中設置的卻是多邊形區域頂點坐標的現象出現。

          posted @ 2007-05-10 12:59 larryjava 閱讀(913) | 評論 (0)編輯 收藏
          手機與電話的正則表達式 
          驗證手機號碼的正確性:
          ^0{0,1}13[0-9]{9}$

          驗證電話號碼的正確性:(
          ^[0-9]{3,4}\-[0-9]{3,8}$)|(^[0-9]{3,8}$)

          驗證有效 日期時間 的正則表達式(已解決閏二月)

          ^((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s(((0?[0-9])|([1-2][0-3]))\:([0-5]?[0-9])((\s)|(\:([0-5]?[0-9])))))?$

          C# Code Test:

          public class Class1
          {
          static void Main(string[] args)
          {
          // string regex = @"^((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s(((0?[0-9])|([1-2][0-3]))\:([0-5]?[0-9])((\s)|(\:([0-5]?[0-9])))))?$";
          string regex = @"^((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578]
          )|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[4
          69])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\
          s]
          ?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([1
          3579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((
          0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((
          0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9]
          )
          |(2[0-8]))))))"; //日期部分
          regex += @"(\s(((0?[0-9])|([1-2][0-3]))\:([0-5]?[0-9])((\s)|(\:([0-5]?[0-9])))))?$"//時間部分
          System.Text.RegularExpressions.RegexOptions options = ((System.Text.RegularExpressions.RegexOptions.IgnorePatternWhitespace | System.Text.RegularExpressions.RegexOptions.Multiline) | System.Text.RegularExpressions.RegexOptions.IgnoreCase);
          System.Text.RegularExpressions.Regex reg 
          = new System.Text.RegularExpressions.Regex(regex, options);

          string s 
          = "2003-02-29 23:59:59";
          System.Console.Out.WriteLine(s 
          + " {0}",reg.IsMatch(s));

          = "2004-02-29 23:59:59";
          System.Console.Out.WriteLine(s 
          + " {0}",reg.IsMatch(s));

          = "2004-04-30 0:59:59";
          System.Console.Out.WriteLine(s 
          + " {0}",reg.IsMatch(s));

          = "2004-04-30 01:11:0";
          System.Console.Out.WriteLine(s 
          + " {0}",reg.IsMatch(s));

          = "2004-04-30 0:0:0";
          System.Console.Out.WriteLine(s 
          + " {0}",reg.IsMatch(s));

          = "2004-04-30 00:00:00";
          System.Console.Out.WriteLine(s 
          + " {0}",reg.IsMatch(s));
          }

          }



          posted @ 2007-05-10 11:26 larryjava 閱讀(1021) | 評論 (0)編輯 收藏
                404錯誤頁出現這個問題,我在web.xml定義了如下的定義,
            <error-page>
              <error-code>404</error-code>
              <location>/error_404.htm</location>
            </error-page>
          路徑的是對的,奇怪的是我測試時輸入一個不存在的頁,出現404錯誤提示出現的卻不是我所定義的頁面,這就怪了.
          主要有以下幾個因素:
          1.使用 tomcat 服務器
          2.tomcat服務器版本
          3.瀏覽器問題
          4.IE的設置
          5.錯誤頁本身的大小

          下面是提供的解決方法:

          1.升級tomcat (換成其它服務器,代價沉重)
          2.ie 設定   工具-->Internet選項-->高級--->顯示http友好錯誤信息(取消選擇) ,
          3. 把錯誤頁做大一點,具體幾個字節,沒測試,估計三四百足夠了, (加一個div塊,display設為none就可以了)
          4.設置指定錯誤頁頁狀態為正確,騙過IE的自定義錯誤頁 方法
          <%
              response.setStatus(200); // 200 = HttpServletResponse.SC_OK
          %>

          posted @ 2007-05-10 11:21 larryjava 閱讀(966) | 評論 (1)編輯 收藏

          操作系統的時間格式不同可能會有不同的結果,你先ECHO一下就看到了
          例如:
          C:\>echo %DATE%
          星期二 2002-10-22

          C:\>echo %date:~4,10%
          2002-10-22

          C:\>echo %date:~0,3%
          星期二

          C:\>echo %date:~-10%
          2002-10-22
          你可以在控制面板里設置日期格式

          posted @ 2007-04-20 16:23 larryjava 閱讀(1904) | 評論 (0)編輯 收藏
          1  目的

             規范數據庫設計

          2  概述

             從數據庫設計原則  設計文檔幾方面論述數據庫設計的規范思想及命名規則。

          3  數據庫應用結構
             
             根據對一般業務系統的分析,將數據庫和程序系統統一進行整體描述,展示數據庫

          表之間以及與程序模塊間的關系。

             3.1 數據表和程序模塊的分類

             根據“處理特點”,將數據表和程序模塊進行分類如下:

             數據表分類:業務數據表、基本編碼表、輔助編碼表、系統信息表、累計數據表、結

          算數據表、決策數據表。
             程序模塊分類:初始化、業務處理、完整性檢測與修正、結算處理、統計處理。
              
                 3.1.1 數據表分類說明
             
             業務數據表:記錄業務發生的過程和結果。如,合同、出倉單、申請單、憑證。
             基本編碼表:描述業務實體的基本信息和編碼。如,產品、客戶、供應商、雇員。
             輔助編碼表:描述屬性的列表值。如,合同類型、職稱、民族、付款方式。
             系統信息表:存放與系統操作、業務控制有關的參數。如,用戶信息、權限、用戶配

          置信息、成本核算方式。
             累計數據表:存放業務的當前值和累計值。如,當前庫存、當前存款、累計銷售、累

          計支出、應收賬款。
             結算數據表:存放各個時期末的結存數。如,月末庫存、月末銀行存款、應收賬款月

          結。
             決策數據表:存放各個時期內發生的統計值。如,月銷售統計、月回款統計、出入庫

          統計。

                 3.1.2 程序模塊分類說明

             初始化:系統運行前對系統進行數據的初始化。如,庫存初始化。
             業務處理:業務過程的控制和結果記錄。如,合同錄入、費用審批、出入庫。
             完整性檢測與修正:對累計數據表進行檢查并自動修正。如對當前庫存、當前存款、

          累計銷售的檢查和重新計算
             結算處理:計算并記錄各個時期末的結存數。庫存月結、應收賬款月結。
             統計處理:計算并記錄各個時期內發生的統計數。如,統計月銷售、統計月回款、統

          計出入庫。

             3.2 數據表間的關系

             業務數據表<-->基本編碼表 主-外鍵關系。如,合同表<-->客戶編碼表;
             業務數據表<-->輔助編碼表 主-外鍵關系。如,合同表<-->付款方式;
             業務數據表、累計數據表、結算數據表:累計數據表=結算數據表(上期末) + 業務數

          據表(本期內發生)。如當前庫存=上月末庫存數+(本月入庫數-本月出庫數);
             決策數據表<-->業務數據表 決策數據表的數據是由業務數據表中數據導出(統計)的;

             3.3 數據表與程序模塊間的關系
                
             由一個例子(倉庫管理)來說明數據表與程序模塊之間的關系:
             . 系統使用前,由初始化模塊對庫存數(累計數據表)和上月末庫存數(結存數據表)進

          行初始化;
             . 當有入庫業務發生時,由入庫模塊(業務處理)將入庫單錄入并保存到入庫單明細帳(

          業務數據表)中,同時將入庫數累加到庫存數(累計數據表)中;
             . 定期或不定期,庫存數核算模塊(檢查完整性檢測與修正)根據上月末的庫存數(結存

          數據表)、本月已發生數(業務數據表)檢查當前的庫存數(累計數據表)是否符合,不符合

          則給出提示,可手工或自動進行更正(當前庫存數=上月末庫存數+本月入庫數-本月出庫數

          );
             . 每月初,進行上月的月結處理。月結模塊(結算處理)根據上月初的庫存數(結存數據

          表)、上月發生數(業務數據表)計算出上月末的庫存數(累計數據表)。公式為:上月末庫

          存數=上月初庫存數+上月入庫數-上月出庫數;
             . 每個月月結后,庫存業務月統計模塊(統計處理)統計上月的各種庫存商品的入庫和

          出庫數,便于查詢和生成報表,也作為決策支持的數據基礎

             3.4 數據表命名時對數據表分類的考慮

             . 業務數據表:t_d_<系統標識>_<表標識>。如銷售系統的合同表 t_d_SH_Contract 

          或 t_d_SH_合同;
             . 基本編碼表:t_b_[<系統標識>]_<表標識>。如客戶編碼表t_b_Customer 或 t_b_客

          戶;
             . 輔助編碼表:t_a_[<系統標識>]_<表標識>。如合同類別t_a_ContType 或 t_a_合同

          類別;
             . 系統信息表:t_s_[<系統標識>]_<表標識>。如用戶表t_s_User 或 t_s_用戶;
             . 累計數據表:t_t_<系統標識>_<表標識>。如當前庫存表t_t_SO_Stock 或 t_t_SO_

          庫存;
             . 結算數據表:t_c_<系統標識>_<表標識>。如庫存月結表t_c_SO_StockMonth 或 

          t_c_SO_庫存月結;
             . 決策數據表:t_w_<系統標識>_<表標識>。如月銷售統計表t_w_SH_SellMonth 或 

          t_w_SH_月銷售統計;
              
             注:[]內的內容表示可選。如“t_s_[<系統標識>]_<表標識>”表示t_s_SH_User 和 

          t_s_User 都是符合規則的。

          4  數據庫結構原則
             
             規定除數據庫設計所遵循的范式外的一些適用原則,在遵循數據庫設計范式的基礎上

          ,合理地劃分表,添加狀態和控制字段等。

             4.1 輔助編碼表

             為了使輔助編碼表能起到預期的效能,又不因過多的輔助編碼表難以管理,故對輔助

          編碼表的使用作如下規定:

             1. 當某輔助編碼表的編碼允許用戶添加時,應設計成“獨立”的數據表;否則,將不

          允許用戶添加編碼的各輔助編碼表合并成一個“通用”的輔助編碼表。
             2. “獨立”的輔助編碼表與主表的列采用主-外約束保證列數據完整性。
             3. “通用”的輔助編碼表與各主表間沒有約束關系,主表列的數據完整性由列說明的

          “域”來保證。
             4. “通用”的輔助編碼表除編碼和名稱列外,還有一個標識列,用來標識合并前的各

          碼表,該標識列+編碼列作為該表的主鍵。
             5. 對于“獨立”的輔助編碼表,用戶只可添加新的編碼和改變名稱,并且不能改變一

          個編碼所代表的意義;對于“通用”的輔助編碼表,原則上不允許用戶修改,或只有限地

          允許修改名稱。
             
             4.2 基本編碼表

             1. 基本編碼表可以有如下的標識列:內編碼、外編碼、助記碼、簡稱、全稱。內編碼

          (唯一編碼)作為主鍵有程序自動生成,用戶不可見;外編碼(唯一編碼)由用戶按某種

          規則自行定義,用戶可見;助記碼為拼音縮,方便錄入,不唯一,重碼時由列表選擇;簡

          稱用于列表顯示和報表,以便縮短行寬。以上的列在實現時可視情況和習慣加以刪減。
             2. 當碼表的列較多且也行較多時,可將上述的標識列和常用的信息存于一個表,將其

          它的信息另表存儲。

             4.3 業務數據表

             1. 設有‘錄入人’和‘錄入日期’列,由系統自動記錄。
             2. 記錄單據的表中設置“自動單據號”,由兩個字符開始以區分單據類型,后跟一數

          字序列表示序號。‘自動單據號’由系統自動生成,作為主表的主鍵,不允許用戶修改。

          當有對應的紙質單據時,設置“單據號”用于記錄紙質單據的單據號。
             3. 明細表中設有行序號,自動記錄行的錄入順序。
             4. 設置“存檔標記”列,用于抽取數據到決策數據庫時的更新標記。插入新行或修改

          已有行時設置該標記;數據抽取后清除該標記。
             5. 對于用于查詢過濾條件的列,不可為空,以免行“丟失”。
             6. 對于數值列,不可為空,“0”作為默認值。
             7. 對于必要的“冗余”列,如客戶名稱,應有相應的程序保持各“冗余”列的同一性

          ,以免出現異議。
             8. 設置“過程狀態”列和“記錄狀態”列。過程狀態列用于記錄如創建、審核、記賬

          、沖紅等狀態;記錄狀態用于記錄如有效、刪除等狀態。
             
          5  數據庫命名原則

             5.1 表名

             . 業務數據表:t_d_<系統標識>_<表標識>。
             . 基本編碼表:t_b_[<系統標識>]_<表標識>。
             . 輔助編碼表:t_a_[<系統標識>]_<表標識>。
             . 系統信息表:t_s_[<系統標識>]_<表標識>。
             . 累計數據表:t_t_<系統標識>_<表標識>。
             . 結算數據表:t_c_<系統標識>_<表標識>。
             . 決策數據表:t_w_<系統標識>_<表標識>。

             5.2 視圖

             v_<視圖類型>_[<系統標識>]_<視圖標識>。視圖類型參見《表的分類》。

             5.3 存儲過程

             p_[<系統標識>]_<存儲過程標識>

             5.4 函數

             f_[<系統標識>]_<函數標識>

             5.5 觸發器

             tr_<表名>_<i,u,d的任意組合>  (after)
             ti_<表名>_<i,u,d的任意組合>  (instead)

             5.6 自定義數據類型

             ud_<自定義數據類型標識>_<數據類型>

             5.7 Default

             df_<Default標識>

             5.8 Rule

             ru_<Rule標識>

             5.9 主鍵

             pk_<表名>_<主鍵標識>

             5.10 外鍵

             fk_<表名>_<主表名>_<外鍵標識>
          posted @ 2007-04-09 16:46 larryjava 閱讀(168) | 評論 (0)編輯 收藏

          jikes 是一個速度遠快于 javac 的 java 編譯器.

          整合 ant 的方法
          1. 設置環境變量 JIKESHOME 為 jikes 的路徑
          2. 設置 ANT_OPTS=-Dbuild.compiler=jikes
          3. 將 jikes 路徑添加到系統 PATH 中

          注意區分大小寫.
          然后在所有的ant任務就默認使用 jikes 了, 如果你想在單個工程中使用 ant, 就不要添加 ANT_OPTS 環境變量, 只需要修改 build.xml 中 javac 標簽中的 compiler 為 jikes, 例如:

          <javacdestdir="${build.dir}"debug="true"deprecation="false"optimize="false"failonerror="true"compiler="jikes">

          jikes 中可以設置如下值:

          • classic ( JDK 1.1 或者 1.2 標準 ) – 也可以使用 javac1.1 和 javac1.2 作為別名.
          • modern ( JDK 1.3/1.4/1.5 標準 ) – javac1.3, javac1.4, javac1.5 可以作為別名.
          • jikes
          • jvc - 微軟的那個編譯器
          • kjc - kopi 編譯器
          • gcj - GCC 中的 gcj 編譯器
          • sj - Symantec 的 java 編譯器
          • extJavac 根據現有 jvm 決定使用 classic 或者 modern 模式

          另外 jikes 中還有幾個附加的屬性設置:

          build.compiler.emacs=false
          build.compiler.fulldepend=false
          build.compiler.pedantic=false
          build.compiler.warnings=true

          build.compiler.warnings 這個屬性設置最好在 javac 標簽中使用 nowarn 屬性.
          保存為 build.properties 文件, 在 build.xml 中這樣調用:

          <propertyfile="build.properties"/>

          就可以使用 jikes 的附加屬性了。

          整合 tomcat 的方法:

          先如上設置 JIKESHOME 和系統 PATH ,在 web 應用的 web.xml 中添加:

          ?

          <servlet>?
          ????
          <servlet-name>?
          ????jsp?
          ????
          </servlet-name>?
          ????
          <servlet-class>?
          ????org.apache.jasper.servlet.JspServlet?
          ????
          </servlet-class>?
          ????
          <init-param>?
          ????????
          <param-name>jspCompilerPlugin</param-name>?
          ????????
          <param-value>org.apache.jasper.compiler.JikesJavaCompiler</param-value>?
          ????
          </init-param>?
          ????
          <load-on-startup>?
          ????
          -1?
          ????
          </load-on-startup>?
          ????
          </servlet>?
          ????
          <servlet-mapping>?
          ????????
          <servlet-name>?
          ????????jsp?
          ????????
          </servlet-name>?
          ????????
          <url-pattern>?
          ????????
          *.jsp?
          ????????
          </url-pattern>?
          ????
          </servlet-mapping>

          如果想要在所有 WEB 應用中使用 jikes, 則設置環境變量 CATALINA_OPTS=-Dbuild.compiler.emacs=true, 然后打開 ${TOMCAT_HOME}/conf/web.xml, 找到:

          <servlet>?
          ????
          <servlet-name>jsp</servlet-name>?
          ????
          <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>?
          ????
          <init-param>?
          ????????
          <param-name>fork</param-name>?
          ????????
          <param-value>false</param-value>?
          ????????
          </init-param>?
          ????
          <init-param>?
          ????
          <param-name>xpoweredBy</param-name>?
          ????????
          <param-value>false</param-value>?
          ????????
          </init-param>?
          ????
          <load-on-startup>3</load-on-startup>?
          </servlet>

          改為:

          <servlet>?
          ????
          <servlet-name>jsp</servlet-name>?
          ????
          <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>?
          ????
          <init-param>?
          ????????
          <param-name>fork</param-name>?
          ????????
          <param-value>false</param-value>?
          ????
          </init-param>?
          ????
          <init-param>?
          ????????
          <param-name>compiler</param-name>?
          ????????
          <param-value>jikes</param-value>?
          ????
          </init-param>?
          ????
          <init-param>?
          ????????
          <param-name>xpoweredBy</param-name>?
          ????????
          <param-value>false</param-value>?
          ????
          </init-param>?
          ????
          <load-on-startup>3</load-on-startup>?
          </servlet>
          posted @ 2007-02-05 10:03 larryjava 閱讀(271) | 評論 (0)編輯 收藏
          # !/ bin / sh
          #
          #?chkconfig:?
          345 ? 86 ? 14
          #?description:?manager?tomcat
          #
          #?filename:
          / etc / rc.d / init.d / tomcat5
          #

          javaDir
          = `ls? / usr / java`
          for ?java?in?$javaDir
          do
          export?JAVA_HOME
          = " /usr/java/${java} "
          done

          export?TOMCAT_HOME
          = " /usr/tomcat5 "

          case ?$ 1 ?in
          start)?$TOMCAT_HOME
          / bin / startup.sh
          ;;
          stop)?$TOMCAT_HOME
          / bin / shutdown.sh
          ;;
          restart)?$TOMCAT_HOME
          / bin / shutdown.sh
          $TOMCAT_HOME
          / bin / startup.sh
          ;;
          * )?echo? " Usage:?$0?{start|stop|restart} "
          ;;
          esac
          exit?
          0
          posted @ 2007-02-02 09:40 larryjava 閱讀(251) | 評論 (0)編輯 收藏
          Tomcat啟動可以用自帶的確jsvc來實現:jsvc本來要從 http://jakarta.apache.org/ 下載 commons-daemon-1.0-Alpha ,不過tomcat 已經自己帶了一個了,在tomcat/bin目錄下有一個jsvc.tar.gz 解壓,編譯: #tar -xzvf jsvc.tar.gz #cd jsvc-src 運行#sh support/buildconf.sh #./configure --with-java=/usr/java#make(注意:tomcat-5.0.18版本帶的jsvc源代碼有一個低級錯誤--少一個分號,會導致編譯不成功,可以自己加上這個分號) tomcat自己帶的jsvc-src/native目錄下還有兩個腳本 Tomcat.sh 和 Tomcat5.sh ,可以用作啟動和停止tomcat的腳本,我把Tomcat5.sh略作修改,文件如下: 代碼:
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          #!/bin/sh
          #
          # Startup Script for Tomcat5
          #
          # chkconfig: 345 87 13
          # description: Tomcat Daemon
          # processname: jsvc
          # pidfile: /var/run/jsvc.pid
          # config:
          #
          # Source function library.
          . /etc/rc.d/init.d/functions
          #
          prog=tomcat
          #
          # Small shell script to show how to start/stop Tomcat using jsvc
          # If you want to have Tomcat running on port 80 please modify the server.xml
          # file:
          #
          #???
          #??? #?????????????? port="80" minProcessors="5" maxProcessors="75"
          #?????????????? enableLookups="true" redirectPort="8443"
          #?????????????? acceptCount="10" debug="0" connectionTimeout="60000"/>
          #
          # You need a developement version of Tomcat (Apache Tomcat/4.1-dev)
          #
          # Adapt the following lines to your configuration #設定自己的參數
          JAVA_HOME=/usr/local/j2sdk1.4.2-04
          CATALINA_HOME=/usr/local/jakarta-tomcat-5.0.19
          DAEMON_HOME=$CATALINA_HOME/bin
          #需要在系統中設定一個沒有權限的
          #用戶來運行,這樣比較安全
          TOMCAT_USER=tomcat5
          TMP_DIR=/var/tmp
          CATALINA_OPTS=
          CLASSPATH=\
          $JAVA_HOME/lib/tools.jar:\
          $CATALINA_HOME/bin/commons-daemon.jar:\
          $CATALINA_HOME/bin/bootstrap.jar start(){
          ??? echo -n $"Starting $prog: "
          ??? #
          ??? # Start Tomcat
          ??? #
          ??? $DAEMON_HOME/jsvc-src/jsvc \
          ??? -user $TOMCAT_USER \
          ??? -home $JAVA_HOME \
          ??? -Dcatalina.home=$CATALINA_HOME \
          ??? -Djava.io.tmpdir=$TMP_DIR \
          ??? -outfile $CATALINA_HOME/logs/catalina.out \
          ??? -errfile '&1' \
          ??? $CATALINA_OPTS \
          ??? -cp $CLASSPATH \
          ??? org.apache.catalina.startup.Bootstrap
          ??? #
          ??? # To get a verbose JVM
          ??? #-verbose \
          ??? # To get a debug of jsvc.
          ??? #-debug \
          ??? RETVAL=$?
          ??? [ $RETVAL = 0 ] && touch /var/lock/subsys/jsvc
          ??? [ $RETVAL = 0 ] && echo_success || echo_failure
          ??? echo
          ??? return $RETVAL
          }
          stop(){
          ??? echo -n $"Stopping $prog: "
          ??? #
          ??? # Stop Tomcat
          ??? #
          ??? PID=`cat /var/run/jsvc.pid`
          ??? kill $PID
          ??? RETVAL=$?
          ??? [ $RETVAL = 0 ] && rm /var/lock/subsys/jsvc
          ??? [ $RETVAL = 0 ] && echo_success || echo_failure
          ??? echo
          ??? return $RETVAL
          } case "$1" in
          ? start)
          ??????? start
          ??? ;; ? stop)
          ??????? stop
          ??? ;; ? restart|reload)
          ??????? stop
          ??????? start
          ??? ;; ? *)
          ??? echo "Usage $0 start/stop"
          ??? exit 1;;
          esac^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^把這段代碼保存為 /etc/rc.d/init.d/tomcat ,然后運行 #chkconfig --add tomcat用--list看一下是否系統已有tomcat啟動文件
          #ckhconfig --list即可把tomcat 添加為系統服務自動隨系統啟動了。這個腳本會在runlevel 3/4/5三種模式自動啟動。注意這段腳本是為tomcat5創建的,如果你用tomcat4,則需要在另一個tomcat.sh的基礎上修改。??
          posted @ 2007-02-02 09:26 larryjava 閱讀(164) | 評論 (0)編輯 收藏
          webwork默認的類型轉換是不支持lob的,開發的時候formBean直接用域模型代替,往往根據域模型生成的model有lob字段,webwork不支持,我們需要手工加個。
          java 代碼
          ?

          ??

          public?class?ClobConverter?extends?DefaultTypeConverter?{???
          ???
          ????@Override???
          ????
          public?Object?convertValue(Map?map,?Object?object,?Class?clazz)?{???
          ????????
          if?(null?!=?object?&&?clazz?==?Clob.class)?{???
          ????????????
          return?ClobUtils.createClob(String.valueOf(object));???
          ????????}
          ???
          ????????
          return?super.convertValue(map,?object,?clazz);???
          ????}
          ???
          }
          ???


          在classpath中加上如下的全局的類型轉換:xwork-conversion.properties
          properties代碼

          java.sql.Clob=com.shunpe.framework.typeconverter.ClobConverter?

          ?

          posted @ 2007-01-13 18:17 larryjava 閱讀(193) | 評論 (0)編輯 收藏

          返回值進行區分:
          1.如果是String型

          代碼
          1. < ww: if ?test = " sftd.equals(\ " 4 \ " ) " ></ ww: if >
            2.如果是char型
          代碼
          1. < ww: if ?test = " sftd.equals('4') " ></ ww: if >

          3.如果是int型

          代碼
          1. < ww: if ?test = " sftd==4 " ></ ww: if > ?
            ?

          在循環中:

          代碼
          1. < select?name = " belong " > ??
            < ww:iterator?value = " sortBigList " ?status = " index " > ??
            < option?value = " <ww:property?value= " id " /> " ? < ww: if ?test = " %{id==model.belong} " > selected </ ww: if >>< ww:property?value = " lb " /></ option > ??
            </ ww:iterator > ??
            </ select > ??

          注意:id==model.belong,而不是belong==model.belong

          定義變量

          代碼
          <ww:set?name="tt1"?value="'aaaaaaaaaaaaaa'"/>????
          <ww:property?value="#tt1"/>???

          注意:字符串要加''

          日期顯示:

          <ww:property?value="createTime.toString()"?/>

          <ww:if?test="selectedByOthers!='true'">

          <input?onclick="ST(this);?"?type="checkbox"?name="$$SelectDoc"?value="<ww:property?value='id'/>"?style="border:?0pt;"/>

          </ww:if>

          <ww:else>

          <input?type="radio"?name="$$SelectDoc"?value="<ww:property?value='id'/>|<ww:property?value='topic'/>"

          <ww:if?test="id.toString().equals(aboutDocid)">checked</ww:if>?

          <ww:if?test="#status.count?%?2">style="border:?0pt;"</ww:if>

          <ww:else>style="border:?0pt;background-color:#F7F7F7"</ww:else>?>

          </ww:else>

          在ww:if比較時id.toString().equals(aboutDocid)中的id是長整型,必須通過toString()成為字符串后再與字符型的aboutDocid比較,否則不報錯,卻也得不到想要的結果。因為這些代碼是寫在jsp頁面的,這個小細節經常忘記,導致顯示的結果不正確卻又一時想不起原因來。:)

          posted @ 2007-01-13 17:45 larryjava 閱讀(293) | 評論 (0)編輯 收藏
          轉載于CSDN

          在.net開發中,充分利用免費控件是好事情,但是如果不能修改控件達到自己的需求,就要動用JS大法了,前提是研究好瀏覽器模型 的各種對象的方法屬性。尤其是熟悉CSS+HTML就會做的很酷。就JS語言本身來說要求不高。

          1,動態刪除Table 里面內容技巧,不需要寫太多代碼,一行:
          tb.removeNode(true)

          2,動態增加行,除了CreateElement方法,還可以這樣比較短小:

          <table id=tb1></table>
          <SCRIPT>
          function addTable(){
          ? var row1 = tb1.insertRow();
          ? var cell1=row1.insertCell();
          ? var cell2=row1.insertCell();
          ? cell1.innerText="灰豆寶寶";
          ? cell2.innerText="超級大笨狼"
          }
          </SCRIPT>
          <INPUT TYPE = "button" VALUE = "AddTable" onclick = "addTable()">

          3,在DIV中動態增加Table

          <SCRIPT>
          function addTable(){
          ? var tb1 = document.createElement("table");
          ? tb1.border="1px";
          ? var row1 = tb1.insertRow();
          ? var cell1=row1.insertCell();
          ? var cell2=row1.insertCell();
          ? mydiv.appendChild(tb1);
          ? cell1.innerText="wanghr100";
          ? cell2.innerText="panyuguang962"
          }
          </SCRIPT>
          <BODY>
          <div id=mydiv style="width:400;height:300;"></div>
          <INPUT TYPE = "button" VALUE = "AddTable" onclick = "addTable()">

          4,在DIV中刪除Table,簡單只要Div.innerHTML=""就可以。

          以上是部分實用相對短小的代碼,當然有其他各種辦法實現,不過一般都比上面的長,比如組合使用DIV對象的insertAdjacentHTML 方法等,在不同需要下使用不同方法,前提是研究好瀏覽器模型 的各種對象的方法屬性。尤其是熟悉CSS+HTML就會做的很酷。就JS語言本身來說要求不高。

          以下是以Document對象為例,相關方法有:

          Method Description
          attachEvent
          createAttribute ?
          createComment ?
          createDocumentFragment
          createElement
          createEventObject
          createStyleSheet
          createTextNode
          detachEvent
          getElementById ?
          getElementsByName
          getElementsByTagName
          mergeAttributes
          recalc
          write ?
          writeln
          以DIV對象為例相關方法有:
          addBehavior
          appendChild
          applyElement
          attachEvent
          clearAttributes
          cloneNode
          contains
          detachEvent
          getAdjacentText ?
          getAttribute ?
          getAttributeNode
          getElementsByTagName
          hasChildNodes
          insertAdjacentElement
          insertAdjacentHTML
          insertAdjacentText
          insertBefore
          mergeAttributes
          normalize
          removeAttribute
          removeAttributeNode ?
          removeBehavior
          removeChild
          removeExpression
          removeNode
          replaceAdjacentText
          replaceChild
          replaceNode
          setActive
          setAttribute
          setAttributeNode
          setExpression ?

          其他,比如下拉列表對象,和拖拽操作等我有時間也整理比較一下,實現相同功能,相對比較短的精彩代碼是值得收藏的。


          1. removeNode(true) 非IE瀏覽器不支持的,應該用 obj.parentNode.removeChild(obj);
          2. insertRow(x) insertCell(y) 這個參數是IE里是可以缺省,但是在非IE瀏覽器里不可缺省


          <SCRIPT>
          function addTable(){
          ? var tb1 = document.createElement("TABLE");
          ? tb1.border="1px";
          ? var row1 = tb1.insertRow(0);
          ? var cell1=row1.insertCell(0);
          ? var cell2=row1.insertCell(1);
          ? document.getElementById("mydiv").appendChild(tb1);
          ? cell1.innerHTML="wanghr100";
          ? cell2.innerHTML="panyuguang962";
          ? row1.insertCell(2).innerHTML="要注意:給的例子要考慮全面";
          }
          </SCRIPT>
          <BODY>
          <div id="mydiv" style="width:400;height:300;"></div>
          <INPUT TYPE = "button" VALUE = "AddTable" onclick = "addTable()">

          posted @ 2006-11-24 19:10 larryjava 閱讀(393) | 評論 (0)編輯 收藏
          主站蜘蛛池模板: 东方市| 社会| 襄樊市| 沅江市| 潞西市| 阿拉善右旗| 阿拉善左旗| 八宿县| 乳源| 二手房| 台南县| 西林县| 恩平市| 汉源县| 耒阳市| 明溪县| 宜君县| 衡南县| 台北市| 内江市| 德清县| 温宿县| 阳谷县| 延长县| 兴城市| 大余县| 北海市| 黎平县| 门头沟区| 岢岚县| 保定市| 大连市| 司法| 香河县| 石嘴山市| 汽车| 平凉市| 陆河县| 胶南市| 灵石县| 龙里县|