PariScamper的java天空

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            14 Posts :: 0 Stories :: 7 Comments :: 0 Trackbacks

          2007年10月23日 #

          以下文章在我配置vsftpd時有幫助,特轉載:

          關于“vsftpd 部分本地用戶不能登錄,部分可以”的問題,我重新做了一些實驗,我把這個問題結合實驗的結果再重新描述一下,請各位高人,幫忙看看可能的原因。 謝謝了!

          系統中原來就有的本地帳號都不能登錄,我的/etc/vsftpd/vsftpd.conf文件的配置如下:
          local_enable=YES
          write_enable=YES
          chroot_local_user=YES
          pam_service_name=vsftpd
          /etc/pam.d/vsftpd存在且正常。

          登錄時錯誤信息都是一樣的:
          500 OOPS: cannot change directory:/home/xxxx
          Login failed.
          421 Service not available, remote server has closed connection

          他們的home目錄都是/home/xxxx。/home和/home/xxxx的權限都是755。
          以上這些帳號都不能ftp登錄,這些都是平常經常使用的,可以用shell登錄的。

          我新創建了一個usr1帳號,
          # useradd -G test -d /tmp/usr1 usr1
          能ftp登錄,他的home為/tmp/usr1,在/分區上。而/home我是mount到/dev/hda9上的。
          #mount
          /dev/hdb1 on / type ext3 (rw)
          /dev/hda9 on /home type ext2 (rw)

          所以,我猜想:是否是由于/home分區的原因,而造成“主目錄在/home分區的帳號”都不能登錄呢?

          為了驗證以上設想,我試著再創建了一個帳號,
          useradd -G test -d /home/usr3 usr3
          /home, /home/usr3 的權限都是755。

          usr3 ftp登錄失敗。
          500 OOPS: cannot change directory:/home/usr3
          Login failed.
          421 Service not available, remote server has closed connection

          至此,我覺得可以確定是由于/home分區的原因,而造成“主目錄在/home分區的帳號”都不能登錄。
          參考文章:
          -----------------------------------------------------------------------------------------
          I finished my second upgrade to Fedora Core 4. Not everything is ironed out yet with the build of course. But one thing is for sure a lot has happened to the RedHat I knew before.

          I must say of all the changes, for me the nicest addition is the new SELinux extensions. For deep background on the reasons for and theory of SELinux read, The Inevitability of Failure: The Flawed Assumption of Security in Modern Computing Environments

          The more I work with SELinux the more I realize I need to know about it, and how exactly it does all its stuff. It certainly changes things relating to users, directories and access. As I am starting to learn it, I'm sure I'm doing things the hard-way. :)

          The major difference, so far for me, in Red Hat's SELinux is the way ftp is handled. vsftpd is still the server which is great. However, it seems to be designed to run as a daemon rather than invoked via xinet.d. If you grab a working copy of the xinet.d file for vsftpd you can invoke it via xinet.d wrapper. I did my first server upgrade in this manner. The current one I am trying as a daemon. I certainly think I will miss some of the features that the xinet.d wrapper brings, and may yet return to it.

          Of all the issues I saw most notable is if you want to enable chroot directory's outside of the normal /home/xxx vsftpd. These will fail with a

              500 OOPS: cannot change directory: /mnt/xxxxx

          I was able to use ftp if I logged in with an account with a directory in /home, but once I set a user account to have a home drive outside of /home (in this case on a mounted secondary disk) vsftpd barfs the above.


          I found information at the NSA that indicates you can disable SELinux protection of the ftp daemon.

              setsebool -P ftpd_disable_trans 1

          This seems a bit drastic. It certainly works for now though.

          I think ultimately the issue resides with policies, but as SELinux policies are new to me, it will take time before it all gets sorted out. As I spend time with the new SELinux extensions in Fedora Core 4 I will keep you updated on my thoughts and configuration lessons.


          ---------------------------------------------------------------------------------------

          解決辦法:
          --------------------------------------------------------------------------------------
           # setsebool ftpd_disable_trans 1
            # service vsftpd restart
          我用的是FC4,按照你上一帖子里的方法試了,馬上就解決了。所以,可以確定原因就在SELinux。
          ------------------------------------------------------------------------------------

          posted @ 2008-02-27 22:45 PariScamper 閱讀(448) | 評論 (0)編輯 收藏

          1          什么是 Clone ,容易實現嗎?

          簡單地說, Clone 就是對于給定的一個對象實例 o ,得到另一個對象實例 o’ o o’

          型相同( o.getClass() == o’.getClass() ),內容相同(對于 o/o’ 中的字段 f ,如果 f 是基本數據類型,則 o.f == o’.f ;如果 f 是對象引用,則 o.f == o’.f o.f 指向的對象與 o’.f 指向的對象的內容相同)。通常稱 o’ o 的克隆或副本。

                 直觀上看,似乎很容易為一個類加上 clone 方法:

          class A {

                 private Type1 field1;

              private Type2 field2;

               …..

              public Object clone() {

                        A a = new A();

                  a.field1 = a.getField1();

                  a.field2 = a.getField2();

                  ……

                  return a;

              }

          }

           

          然而,稍加推敲,就會發現這樣的實現方法有兩個問題:

          1.         要想某個類有 clone 功能,必須單獨為其實現 clone() 函數,函數實現代碼與該類定義密切相關。

          2.         即使基類 A 已有 clone() 函數,其子類 ExtendA 若要具備 clone 功能,則必須 override 其基類 A clone() 函數。否則,對類型為 ExtendA 的對象 ea clone() 方法的調用,會執行于類 A 中定義的 clone() 方法而返回一個類型為 A 的對象,它顯然不是 ea 的克隆。

          2          Java clone 的支持

          萬類之初的 Object 類有 clone() 方法:

          protected native Object clone() throws CloneNotSupportedException;

          該方法是 protected 的,顯然是留待被子類 override 的。該方法又是 native 的,必然做了

          與具體平臺相關的底層工作。

          事實上,類 Object clone() 方法首先會檢查 this.getClass() 是否實現了 Cloneable 接口。

          Cloneable 只是一個標志接口而已,用來標志該類是否有克隆功能。

          public interface Cloneable {

          }

                 如果 this.getClass() 沒有實現 Cloneable 接口, clone() 就會拋 CloneNotSupportedException 返回。否則就會創建一個類型為 this.getClass() 的對象 other ,并將 this field 的值賦值給 other 的對應 field ,然后返回 other

                 如此一來,我們要定義一個具有 Clone 功能的類就相當方便:

          1.         在類的聲明中加入“ implements Cloneable ”,標志該類有克隆功能;

          2.         Override Object clone() 方法,在該方法中調用 super.clone()

          class CloneableClass implements Cloneable {

                 ……

          public Object clone() {

                 try {

                        return super.clone(); // 直接讓 Object.clone() 為我們代勞一切

              } catch (CloneNotSupportedException e) {

                        throw new InternalError();

                 }

          }

          }

           

          3          Shallow Clone Deep Clone

          3.1     Shallow Deep 從何而來

          一個具有克隆功能的類,如果有可變( Mutable )類類型的字段 field ,如何為其克隆(副

          本)對象 o’ 中的 field 賦值?

                 方法一、如 Object clone() 方法所實現:設原始對象為 o ,其克隆對象是 o’ ,執行 o’.field = o.field 。這樣, o’.field o.field 指向同一個可變對象 m o o’ 可能會相互影響(一個對象的狀態可能會隨著另一個對象的狀態的改變而改變)。這樣的 Clone 稱為 Shallow Clone 。這也是 Object clone() 方法的實現方式。

                 方法二、將 o.field 指向的可變對象 m 克隆,得到 m’ ,將 m’ 的引用賦值給 o’.field 。這樣 o’ o 內容相同,且相互之間無影響(一個對象狀態的改變不會影響另一個對象的狀態)。這樣的 Clone 稱為 Deep Clone

                 Java Collection 類庫中具體數據結構類( ArrayList/LinkedList HashSet/TreeSet HashMap/TreeMap 等)都具有克隆功能,且都是 Shallow Clone ,這樣設計是合理的,因為它們不知道存放其中的每個數據對象是否也有克隆功能。 System.arrayCopy() 的實現采用的也是 Shallow Clone

                 Deep Clone 對于實現不可變( Immutable )類很有幫助。設一個類包含可變類 M 類型的 field ,如何將其設計為不可變類呢?先為 M 實現 Deep Clone 功能,然后這樣設計類 ImmutableClass

          class ImmutableClass {

                 MutableClass m;

          ImmutableClass(MutableClass m) {

                 this.m = m.clone(); // 將傳入的 m clone 賦值給內部 m

          }

          public MutableClass getM() {

              return this.m.clone(); // 將內部 m clone 返回給外部

          }

          }

           

                

          3.2     如何實現 Deep Clone

          檢查類有無可變類類型的字段。如果無,返回 super.clone() 即可;

          如果有,確保包含的可變類本身都實現了 Deep Clone

          Object o = super.clone(); // 先執行淺克隆,確保類型正確和基本類型及非可變類類型字段內容正確

          對于每一個可變類類型的字段 field

                 o.field = this.getField().clone();

          返回 o

          posted @ 2007-12-12 14:49 PariScamper 閱讀(757) | 評論 (0)編輯 收藏

          什么要用日志(Log?
          這個……就不必說了吧。

          為什么不用System.out.println()?
          功能太弱;不易于控制。如果暫時不想輸出了怎么辦?如果想輸出到文件怎么辦?如果想部分輸出怎么辦?……

          為什么同時使用commons-loggingLog4j?為什么不僅使用其中之一?
          Commons-loggin的目的是為“所有的Java日志實現”提供一個統一的接口,它自身的日志功能平常弱(只有一個簡單的SimpleLog?),所以一般不會單獨使用它。

          Log4j的功能非常全面強大,是目前的首選。我發現幾乎所有的Java開源項目都會用到Log4j,但我同時發現,所有用到Log4j的項目一般也同時會用到commons-loggin。我想,大家都不希望自己的項目與Log4j綁定的太緊密吧。另外一個我能想到的“同時使用commons-loggingLog4j”的原因是,簡化使用和配置。

                 強調一點,“同時使用commons-loggingLog4j”,與“單獨使用Log4j”相比,并不會帶來更大的學習、配置和維護成本,反而更加簡化了我們的工作。我想這也是為什么“所有用到Log4j的項目一般也同時會用到commons-loggin”的原因之一吧。

          Commons-logging能幫我們做什么?
          l         提供一個統一的日志接口,簡單了操作,同時避免項目與某個日志實現系統緊密a耦合
          l         很貼心的幫我們自動選擇適當的日志實現系統(這一點非常好!)
          l         它甚至不需要配置

          這里看一下它怎么“‘很貼心的’幫我們‘自動選擇’‘適當的’日志實現系統”:
          1)        首先在classpath下尋找自己的配置文件commons-logging.properties,如果找到,則使用其中定義的Log實現類;
          2)        如果找不到commons-logging.properties文件,則在查找是否已定義系統環境變量org.apache.commons.logging.Log,找到則使用其定義的Log實現類;
          3)        否則,查看classpath中是否有Log4j的包,如果發現,則自動使用Log4j作為日志實現類;
          4)        否則,使用JDK自身的日志實現類(JDK1.4以后才有日志實現類);
          5)        否則,使用commons-logging自己提供的一個簡單的日志實現類SimpleLog
          (以上順序不保證完全準確,請參考官方文檔)

          可見,commons-logging總是能找到一個日志實現類,并且盡可能找到一個“最合適”的日志實現類。我說它“很貼心”實際上是因為:1、可以不需要配置文件;2、自動判斷有沒有Log4j包,有則自動使用之;3、最悲觀的情況下也總能保證提供一個日志實現(SimpleLog)。 
                 可以看到,commons-logging對編程者和Log4j都非常友好。

                 為了簡化配置commons-logging,一般不使用commons-logging的配置文件,也不設置與commons-logging相關的系統環境變量,而只需將Log4jJar包放置到classpash中就可以了。這樣就很簡單地完成了commons-loggingLog4j的融合。如果不想用Log4j了怎么辦?只需將classpath中的Log4jJar包刪除即可。

          就這么簡單!

          代碼應該怎么寫?

          我們在需要輸出日志信息的“每一人”類中做如下的三個工作:
          1、導入所有需的commongs-logging類:
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;

          如果愿意簡化的話,還可以兩行合為一行:
          import org.apache.commons.logging.*;  

          2、在自己的類中定義一個org.apache.commons.logging.Log類的私有靜態類成員:
          private static Log log = LogFactory.getLog(YouClassName.class);

          注意這里定義的是static成員,以避免產生多個實例。

          LogFactory.getLog()方法的參數使用的是當前類的class,這是目前被普通認為的最好的方式。為什么不寫作LogFactory.getLog(this.getClass())?因為static類成員訪問不到this指針!

          3、使用org.apache.commons.logging.Log類的成員方法輸出日志信息:
          log.debug("111");
          log.info("222");
          log.warn("333");
          log.error("444");
          log.fatal("555");

          這里的log,就是上面第二步中定義的類成員變量,其類型是org.apache.commons.logging.Log,通過該類的成員方法,我們就可以將不同性質的日志信息輸出到目的地(目的地是哪里?視配置可定,可能是stdout,也可能是文件,還可能是發送到郵件,甚至發送短信到手機……詳見下文對log4j.properties的介紹):
          l         debug()   輸出“調試”級別的日志信息;
          l         info()      輸出“信息”級別的日志信息;
          l         warn()    輸出“警告”級別的日志信息;
          l         error()     輸出“錯誤”級別的日志信息;
          l         fatal()      輸出“致命錯誤”級別的日志信息;

          根據不同的性質,日志信息通常被分成不同的級別,從低到高依次是:“調試(DEBUG)”“信息(INFO)”“警告(WARN)”“錯誤(ERROR)”“致命錯誤(FATAL)”。為什么要把日志信息分成不同的級別呢?這實際上是方便我們更好的控制它。比如,通過Log4j的配置文件,我們可以設置“輸出‘調試’及以上級別的日志信息”(即“調試”“信息”“警告”“錯誤”“致命錯誤”),這對項目開發人員可能是有用的;我們還可以設置“輸出“警告”及以上級別的日志信息”(即“警告”“錯誤”“致命錯誤”),這對項目最終用戶可能是有用的。 
                 僅從字面上理解,也可以大致得出結論:最常用的應該是debug()info();而warn()error()fatal()僅在相應事件發生后才使用。  

          從上面三個步驟可以看出,使用commons-logging的日志接口非常的簡單,不需要記憶太多東西:僅僅用到了兩個類Log, LogFactory,并且兩個類的方法都非常少(后者只用到一個方法,前者經常用到的也只是上面第三步中列出的幾個),同時參數又非常簡單。

          上面所介紹的方法是目前被普通應用的,可以說是被標準化了的方法,幾乎所有的人都是這么用。如果不信,或想確認一下,就去下載幾個知名的Java開源項目源代碼看一下吧。  

          下面給出一個完整的Java類的代碼: 
          package liigo.testlog; 
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory; 

          public class TestLog
              private static Log log = LogFactory.getLog(TestLog.class); 
              public void test()    
                  log.debug("111"); 
                  log.info("222"); 
                  log.warn("333"); 
                  log.error("444"); 
                  log.fatal("555"); 
               

              public static void main(String[] args)    
                  TestLog testLog = new TestLog(); 
                  testLog.test(); 
              }
           

          只要保證commons-loggingjar包在classpath中,上述代碼肯定可以很順利的編譯通過。那它的執行結果是怎么樣的呢?恐怕會有很大的不同,請繼續往下看。  

          Log4j在哪里呢?它發揮作用了嗎?

          應該注意到,我們上面給出的源代碼,完全沒有涉及到Log4j——這正是我們所希望的,這也正是commons-logging所要達到的目標之一。

          可是,怎么才能讓Log4j發揮它的作用呢?答案很簡單,只需滿足“classpath中有Log4jjar包”。前面已經說過了,commons-logging會自動發現并應用Log4j。所以只要它存在,它就發揮作用。(它不存在呢?自然就不發揮作用,commons-logging會另行選擇其它的日志實現類。)

          注意:配置文件log4j.propertiesLog4j來說是必須的。如果classpath中沒有該配置文件,或者配置不對,將會引發運行時異常。

                 這樣,要正確地應用Log4j輸出日志信息,log4j.properties的作用就很重要了。好在該文件有通用的模板,復制一份(稍加修改)就可以使用。幾乎每一個Java項目目錄內都會有一個log4j.properties文件,可下載幾個Java開源項目源代碼查看。本文最后也附一個模板性質的log4j.properties文件,直接復制過去就可以用,或者根據自己的需要稍加修改。后文將會log4j.properties文件適當作一些介紹。

          關于Log4j比較全面的配置

          LOG4J的配置之簡單使它遍及于越來越多的應用中了:Log4J配置文件實現了輸出到控制臺、文件、

          回滾文件、發送日志郵件、輸出到數據庫日志表、自定義標簽等全套功能。擇其一二使用就夠用了

          log4j.rootLogger=DEBUG,CONSOLE,A1,im
          log4j.addivity.org.apache=true 
           

          # 應用于控制臺
          log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
          log4j.appender.Threshold=DEBUG
          log4j.appender.CONSOLE.Target=System.out
          log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
          log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          #log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n

          #應用于文件
          log4j.appender.FILE=org.apache.log4j.FileAppender
          log4j.appender.FILE.File=file.log
          log4j.appender.FILE.Append=false
          log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
          log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          # Use this layout for LogFactor 5 analysis


          # 應用于文件回滾
          log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
          log4j.appender.ROLLING_FILE.Threshold=ERROR
          log4j.appender.ROLLING_FILE.File=rolling.log
          log4j.appender.ROLLING_FILE.Append=true
          log4j.appender.ROLLING_FILE.MaxFileSize=10KB
          log4j.appender.ROLLING_FILE.MaxBackupIndex=1
          log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
          log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

          #應用于socket
          log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
          log4j.appender.SOCKET.RemoteHost=localhost
          log4j.appender.SOCKET.Port=5001
          log4j.appender.SOCKET.LocationInfo=true
          # Set up for Log Facter 5
          log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
          log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n


          # Log Factor 5 Appender
          log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
          log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000

          # 發送日志給郵件
          log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
          log4j.appender.MAIL.Threshold=FATAL
          log4j.appender.MAIL.BufferSize=10
          log4j.appender.MAIL.From=web@www.wuset.com
          log4j.appender.MAIL.SMTPHost=www.wusetu.com
          log4j.appender.MAIL.Subject=Log4J Message
          log4j.appender.MAIL.To=web@www.wusetu.com
          log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
          log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n


          # 用于數據庫
          log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
          log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
          log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
          log4j.appender.DATABASE.user=root
          log4j.appender.DATABASE.password=
          log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
          log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
          log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n


          log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
          log4j.appender.A1.File=SampleMessages.log4j
          log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'
          log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout

          #自定義Appender
          log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender

          log4j.appender.im.host = mail.cybercorlin.net
          log4j.appender.im.username = username
          log4j.appender.im.password = password
          log4j.appender.im.recipient = corlin@cybercorlin.net

          log4j.appender.im.layout=org.apache.log4j.PatternLayout
          log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n



          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1545873

          posted @ 2007-12-12 14:48 PariScamper 閱讀(2053) | 評論 (2)編輯 收藏

          就servlet規范本身,數據可以放在3個地方:request、session、servletContext.

          request:
          好處:用完就仍,不會導致資源占用的無限增長。
          弊處:每次要用都從數據庫中抓,多做操作,自然會對性能有一些影響。

          session:
          好處:不用每次都去數據庫抓,少做操作。
          弊處:每個客戶都有一個session,只能自己使用,不同session可能保存大量重復數據;
          可能耗費大量服務器內存;
          另外session構建在cookie和url重寫的基礎上,所以用session實現會話跟蹤,會用掉一點點服務器帶寬和客戶端保持聯絡,
          當然session越多,耗費的帶寬越多,理論上也會對性能造成影響。
          集群的session同步會是個問題。

          servletContext:
          好處:不用每次都去數據庫抓,少做操作。
          存儲的數據所有客戶都可以用。
          可減少重復在內存中存儲數據造成的開銷。
          弊處:很多時候相同的數據可能不多(相當于cache的命中率很低)。


          其實以上3中方法都有利有弊,各自的好處在某種條件下,也都會轉變為弊處。所以不妨綜合使用,相當于一個“第三方用法”(只講一下思路,否則太過繁瑣,涉及到的相關技術點請參考有關技術資料):

          request不說了,重點說說session和servletContext:

          --session的可控應用
          session的最大問題是資源回收,兩類回收方法:
          主動回收:瀏覽器被關閉,而為提交觸發清理動作的請求時,該方法失效,而且很常見。
          超時回收:設置session的setMaxInactiveInterval屬性或在web.xml中配置超時時間,然后交給jvm的垃圾處理器處理。
          不過不要報太大希望,jvm的垃圾收集器并不靈光。
          可以用另一種替代方法緩解該問題,比如限制session的數量,可以用HttpSessionListener實現,這樣可以緩解session帶來的吃內存問題,當然這種做法每次都需要判斷session數量,當session達到限定數量時還必須用其他方法處理了,這些細節繁瑣,而且要謹慎處理。

          --servletContext
          如果說session是一個“局部緩存”,那servletContext就是一個“全局緩存”了,不妨把它當作cache(這里不講究用詞的嚴謹性,僅為了更好說明問題)。cache的大小是當前應用可使用的最大內存。cache的最大問題是提高命中率,命中率高,內存占用少,效率高,命中率低,則內存占用多而且效率低。這種應用的技術實現比“session的可空應用”要簡單,適用于相同數據多的地方,這個要事先有所判斷,如果用不好則有弊無利。

          如果僅使用servlet規范給出的3種機制,任何一種都達不到好處兼收的效果,所以要發揮3種方法的好處、摒棄弊處,必須綜合運用,做一些技術框架的構建工作,而且有些地方還比較繁瑣(還好框架是可重用的)。
           

          有時候尋求或實現“平衡”(或者說盡取其利而摒其害),要付出很大代價,根據不同的情況,這些代價或是值得,或是不值得。也可以“兩害相權取其輕”,或許是最便捷的方法。

          posted @ 2007-11-19 13:18 PariScamper 閱讀(784) | 評論 (0)編輯 收藏

          注意如果該字段在Oracle中設定非空性為YES,則即使是插入String a=""或者String a=new String()也是相對于空值。

          posted @ 2007-10-23 15:29 PariScamper 閱讀(7677) | 評論 (3)編輯 收藏

          主站蜘蛛池模板: 凉山| 金沙县| 嵊州市| 钦州市| 永年县| 京山县| 镇沅| 菏泽市| 新郑市| 信宜市| 鄢陵县| 新安县| 尼勒克县| 辛集市| 册亨县| 莲花县| 顺义区| 长武县| 扶沟县| 泾阳县| 绥中县| 新龙县| 大田县| 遂宁市| 澜沧| 绍兴县| 即墨市| 柯坪县| 静乐县| 齐齐哈尔市| 九江县| 兰西县| 兰州市| 香港 | 芦溪县| 泰顺县| 萝北县| 蒙山县| 简阳市| 阳山县| 鞍山市|