PariScamper的java天空

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            14 Posts :: 0 Stories :: 7 Comments :: 0 Trackbacks

          2007年10月23日 #

          以下文章在我配置vsftpd時(shí)有幫助,特轉(zhuǎn)載:

          關(guān)于“vsftpd 部分本地用戶不能登錄,部分可以”的問題,我重新做了一些實(shí)驗(yàn),我把這個(gè)問題結(jié)合實(shí)驗(yàn)的結(jié)果再重新描述一下,請(qǐng)各位高人,幫忙看看可能的原因。 謝謝了!

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

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

          他們的home目錄都是/home/xxxx。/home和/home/xxxx的權(quán)限都是755。
          以上這些帳號(hào)都不能ftp登錄,這些都是平常經(jīng)常使用的,可以用shell登錄的。

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

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

          為了驗(yàn)證以上設(shè)想,我試著再創(chuàng)建了一個(gè)帳號(hào),
          useradd -G test -d /home/usr3 usr3
          /home, /home/usr3 的權(quán)限都是755。

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

          至此,我覺得可以確定是由于/home分區(qū)的原因,而造成“主目錄在/home分區(qū)的帳號(hào)”都不能登錄。
          參考文章:
          -----------------------------------------------------------------------------------------
          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 閱讀(453) | 評(píng)論 (0)編輯 收藏

          1          什么是 Clone ,容易實(shí)現(xiàn)嗎?

          簡單地說, Clone 就是對(duì)于給定的一個(gè)對(duì)象實(shí)例 o ,得到另一個(gè)對(duì)象實(shí)例 o’ o o’

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

                 直觀上看,似乎很容易為一個(gè)類加上 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;

              }

          }

           

          然而,稍加推敲,就會(huì)發(fā)現(xiàn)這樣的實(shí)現(xiàn)方法有兩個(gè)問題:

          1.         要想某個(gè)類有 clone 功能,必須單獨(dú)為其實(shí)現(xiàn) clone() 函數(shù),函數(shù)實(shí)現(xiàn)代碼與該類定義密切相關(guān)。

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

          2          Java 對(duì) clone 的支持

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

          protected native Object clone() throws CloneNotSupportedException;

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

          與具體平臺(tái)相關(guān)的底層工作。

          事實(shí)上,類 Object clone() 方法首先會(huì)檢查 this.getClass() 是否實(shí)現(xiàn)了 Cloneable 接口。

          Cloneable 只是一個(gè)標(biāo)志接口而已,用來標(biāo)志該類是否有克隆功能。

          public interface Cloneable {

          }

                 如果 this.getClass() 沒有實(shí)現(xiàn) Cloneable 接口, clone() 就會(huì)拋 CloneNotSupportedException 返回。否則就會(huì)創(chuàng)建一個(gè)類型為 this.getClass() 的對(duì)象 other ,并將 this field 的值賦值給 other 的對(duì)應(yīng) field ,然后返回 other

                 如此一來,我們要定義一個(gè)具有 Clone 功能的類就相當(dāng)方便:

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

          2.         Override Object clone() 方法,在該方法中調(diào)用 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 從何而來

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

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

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

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

                 Java Collection 類庫中具體數(shù)據(jù)結(jié)構(gòu)類( ArrayList/LinkedList HashSet/TreeSet HashMap/TreeMap 等)都具有克隆功能,且都是 Shallow Clone ,這樣設(shè)計(jì)是合理的,因?yàn)樗鼈儾恢来娣牌渲械拿總€(gè)數(shù)據(jù)對(duì)象是否也有克隆功能。 System.arrayCopy() 的實(shí)現(xiàn)采用的也是 Shallow Clone

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

          class ImmutableClass {

                 MutableClass m;

          ImmutableClass(MutableClass m) {

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

          }

          public MutableClass getM() {

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

          }

          }

           

                

          3.2     如何實(shí)現(xiàn) Deep Clone

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

          如果有,確保包含的可變類本身都實(shí)現(xiàn)了 Deep Clone

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

          對(duì)于每一個(gè)可變類類型的字段 field

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

          返回 o

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

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

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

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

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

                 強(qiáng)調(diào)一點(diǎn),“同時(shí)使用commons-loggingLog4j”,與“單獨(dú)使用Log4j”相比,并不會(huì)帶來更大的學(xué)習(xí)、配置和維護(hù)成本,反而更加簡化了我們的工作。我想這也是為什么“所有用到Log4j的項(xiàng)目一般也同時(shí)會(huì)用到commons-loggin”的原因之一吧。

          Commons-logging能幫我們做什么?
          l         提供一個(gè)統(tǒng)一的日志接口,簡單了操作,同時(shí)避免項(xiàng)目與某個(gè)日志實(shí)現(xiàn)系統(tǒng)緊密a耦合
          l         很貼心的幫我們自動(dòng)選擇適當(dāng)?shù)娜罩緦?shí)現(xiàn)系統(tǒng)(這一點(diǎn)非常好!)
          l         它甚至不需要配置

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

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

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

          就這么簡單!

          代碼應(yīng)該怎么寫?

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

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

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

          注意這里定義的是static成員,以避免產(chǎn)生多個(gè)實(shí)例。

          LogFactory.getLog()方法的參數(shù)使用的是當(dāng)前類的class,這是目前被普通認(rèn)為的最好的方式。為什么不寫作LogFactory.getLog(this.getClass())?因?yàn)?/span>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,通過該類的成員方法,我們就可以將不同性質(zhì)的日志信息輸出到目的地(目的地是哪里?視配置可定,可能是stdout,也可能是文件,還可能是發(fā)送到郵件,甚至發(fā)送短信到手機(jī)……詳見下文對(duì)log4j.properties的介紹):
          l         debug()   輸出“調(diào)試”級(jí)別的日志信息;
          l         info()      輸出“信息”級(jí)別的日志信息;
          l         warn()    輸出“警告”級(jí)別的日志信息;
          l         error()     輸出“錯(cuò)誤”級(jí)別的日志信息;
          l         fatal()      輸出“致命錯(cuò)誤”級(jí)別的日志信息;

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

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

          上面所介紹的方法是目前被普通應(yīng)用的,可以說是被標(biāo)準(zhǔn)化了的方法,幾乎所有的人都是這么用。如果不信,或想確認(rèn)一下,就去下載幾個(gè)知名的Java開源項(xiàng)目源代碼看一下吧。  

          下面給出一個(gè)完整的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中,上述代碼肯定可以很順利的編譯通過。那它的執(zhí)行結(jié)果是怎么樣的呢?恐怕會(huì)有很大的不同,請(qǐng)繼續(xù)往下看。  

          Log4j在哪里呢?它發(fā)揮作用了嗎?

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

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

          注意:配置文件log4j.properties對(duì)Log4j來說是必須的。如果classpath中沒有該配置文件,或者配置不對(duì),將會(huì)引發(fā)運(yùn)行時(shí)異常。

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

          關(guān)于Log4j比較全面的配置

          LOG4J的配置之簡單使它遍及于越來越多的應(yīng)用中了:Log4J配置文件實(shí)現(xiàn)了輸出到控制臺(tái)、文件、

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

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

          # 應(yīng)用于控制臺(tái)
          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

          #應(yīng)用于文件
          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


          # 應(yīng)用于文件回滾
          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

          #應(yīng)用于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

          # 發(fā)送日志給郵件
          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


          # 用于數(shù)據(jù)庫
          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 閱讀(2061) | 評(píng)論 (2)編輯 收藏

          就servlet規(guī)范本身,數(shù)據(jù)可以放在3個(gè)地方:request、session、servletContext.

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

          session:
          好處:不用每次都去數(shù)據(jù)庫抓,少做操作。
          弊處:每個(gè)客戶都有一個(gè)session,只能自己使用,不同session可能保存大量重復(fù)數(shù)據(jù);
          可能耗費(fèi)大量服務(wù)器內(nèi)存;
          另外session構(gòu)建在cookie和url重寫的基礎(chǔ)上,所以用session實(shí)現(xiàn)會(huì)話跟蹤,會(huì)用掉一點(diǎn)點(diǎn)服務(wù)器帶寬和客戶端保持聯(lián)絡(luò),
          當(dāng)然session越多,耗費(fèi)的帶寬越多,理論上也會(huì)對(duì)性能造成影響。
          集群的session同步會(huì)是個(gè)問題。

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


          其實(shí)以上3中方法都有利有弊,各自的好處在某種條件下,也都會(huì)轉(zhuǎn)變?yōu)楸滋帯K圆环辆C合使用,相當(dāng)于一個(gè)“第三方用法”(只講一下思路,否則太過繁瑣,涉及到的相關(guān)技術(shù)點(diǎn)請(qǐng)參考有關(guān)技術(shù)資料):

          request不說了,重點(diǎn)說說session和servletContext:

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

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

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

          有時(shí)候?qū)で蠡驅(qū)崿F(xiàn)“平衡”(或者說盡取其利而摒其害),要付出很大代價(jià),根據(jù)不同的情況,這些代價(jià)或是值得,或是不值得。也可以“兩害相權(quán)取其輕”,或許是最便捷的方法。

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

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

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

          主站蜘蛛池模板: 禹州市| 册亨县| 井冈山市| 津南区| 芜湖县| 通化市| 库伦旗| 获嘉县| 内江市| 光山县| 镇安县| 昌黎县| 铁岭市| 夏邑县| 化州市| 大宁县| 永嘉县| 瓦房店市| 右玉县| 通辽市| 松江区| 久治县| 石河子市| 玛沁县| 临沭县| 交口县| 松滋市| 淳化县| 丹棱县| 固阳县| 德格县| 廊坊市| 鹤山市| 白沙| 秭归县| 荆门市| 巫溪县| 黎城县| 馆陶县| 肃宁县| 达拉特旗|