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

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

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

    honzeland

    記錄點(diǎn)滴。。。

    常用鏈接

    統(tǒng)計(jì)

    Famous Websites

    Java

    Linux

    P2P

    最新評(píng)論

    2008年4月28日 #

    Interesting books read or being read

    Oracle Performance Tuning for 10gR2, Second Edition -- http://www.amazon.com/Oracle-Performance-Tuning-10gR2-Second/dp/1555583458

    posted @ 2011-04-07 15:30 honzeland 閱讀(202) | 評(píng)論 (0)編輯 收藏

    GAE Logging

    Official document: http://code.google.com/appengine/docs/java/runtime.html#Logging  
    Log4j configuration in production env:
    http://blog.xam.de/2010/03/logging-in-google-appengine-for-java.html 
    http://www.mail-archive.com/google-appengine-java@googlegroups.com/msg06396.html

    posted @ 2010-11-11 12:52 honzeland 閱讀(269) | 評(píng)論 (0)編輯 收藏

    Read a Stress Test Report

    Load Average: 

    1. http://www.teamquest.com/resources/gunther/display/5/index.htm
    2. 
    http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages (Great)

    posted @ 2010-11-05 14:16 honzeland 閱讀(275) | 評(píng)論 (0)編輯 收藏

    GAE Mapping

    Executing Simple Joins Across Owned Relationships

    posted @ 2010-10-27 13:27 honzeland 閱讀(250) | 評(píng)論 (0)編輯 收藏

    Servlet Mappings - rules, pattern....

    http://www.rawbw.com/~davidm/tini/TiniHttpServer/docs/ServletMappings.html

    posted @ 2010-10-22 22:41 honzeland 閱讀(287) | 評(píng)論 (0)編輯 收藏

    GWT-RPC in a Nutshell - go through the internal

    GWT-RPC in a Nutshell: http://www.gdssecurity.com/l/b/2009/10/08/gwt-rpc-in-a-nutshell/

    posted @ 2010-10-22 22:40 honzeland 閱讀(223) | 評(píng)論 (0)編輯 收藏

    [zz] Tuning Your Stress Test Harness

    HTTP://WWW.THESERVERSIDE.COM/NEWS/1365219/TUNING-YOUR-STRESS-TEST-HARNESS?ASRC=SS_CLA_315053&PSRC=CLT_81

    posted @ 2010-09-11 12:27 honzeland 閱讀(243) | 評(píng)論 (0)編輯 收藏

    GWT 2 Spring 3 JPA 2 Hibernate 3.5 Tutorial – Eclipse and Maven 2 showcase

    See details at: http://www.javacodegeeks.com/2010/07/gwt-2-spring-3-jpa-2-hibernate-35.html
    Executing Simple Joins Across Owned Relationships for gae: http://gae-java-persistence.blogspot.com/2010/03/executing-simple-joins-across-owned.html

    posted @ 2010-08-20 13:01 honzeland 閱讀(417) | 評(píng)論 (0)編輯 收藏

    Java remote invocation frameworks (RPC)

    1. Remote Method Invocation (RMI)

    2. Hessian

    3. Burlap

    4. HTTP invoker

    5. EJB

    6. JAX-RPC

    7. JMX

    posted @ 2010-06-09 14:25 honzeland 閱讀(249) | 評(píng)論 (0)編輯 收藏

    Tomcat Architecture Diagram

    zz from http://marakana.com/forums/tomcat/general/106.html


    Valve and Filter:
    "Valve" is Tomcat specific notion, and they get applied at a higher level than anything in a specific webapp. Also, they work only in Tomcat.

    "Filter" is a Servlet Specification notion and should work in any compliant servlet container. They get applied at a lower level than all of Tomcat's
    Valves.

    However, consider also the division between your application and the application  server. Think whether the feature you're planning is part of your application, or is it rather a generic feature of the application server, which could have uses in other applications as well. This would be the correct criteria to decide between Valve and Filter.

    Order for filter: The order in which they are defined matters. The container will execute the filters in the order in which they are defined.

    posted @ 2010-05-10 10:39 honzeland 閱讀(1541) | 評(píng)論 (0)編輯 收藏

    Hibernate Annotations

    Use one single table "blank_fields" for both A and B. "blank_fields" has fields: 'ref_id', 'blank_field', 'type'. 'type' is used to identify which entity the record belongs to. Use 'type' + 'ref_id' to specify the collection of elements for one entity.

    @Entity
    @Table(name 
    = "table_a")
    public class A {
        
    private Set<BlankField> blankFields = new HashSet<BlankField>();
       
        @CollectionOfElements
        @Fetch(FetchMode.SUBSELECT)
        @Enumerated(EnumType.ORDINAL)
        @JoinTable(name 
    = "blank_fields", joinColumns = { @JoinColumn(name = "ref_id") })
        @Cascade(value 
    = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
        @Column(name 
    = "blank_field", nullable = false)
        @SQLInsert(sql 
    = "INSERT INTO blank_fields(ref_id, blank_field, type) VALUES(?,?,0)")
        @Where(clause 
    = "type=0")
        
    public Set<BlankField> getBlankFields() { // BlankField is an enum
            
    return blankFields;
        }

        @SuppressWarnings(
    "unused")
        
    private void setBlankFields(Set<BlankField> blankFields) {
            
    this.blankFields = blankFields;
        }
    // End B

    @Entity
    @Table(name 
    = "table_b")
    public class B {
        
    private Set<BlankField> blankFields = new HashSet<BlankField>();
       
        @CollectionOfElements
        @Fetch(FetchMode.SUBSELECT)
        @Enumerated(EnumType.ORDINAL)
        @JoinTable(name 
    = "blank_fields", joinColumns = { @JoinColumn(name = "ref_id") })
        @Cascade(value 
    = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
        @Column(name 
    = "blank_field", nullable = false)
        @SQLInsert(sql 
    = "INSERT INTO blank_fields(ref_id, blank_field, type) VALUES(?,?,1)"// used for insert
        @Where(clause = "type=1"// used for query, if not @CollectionOfElements, such as @OneToMany, use @WhereJoinTable instead
        public Set<BlankField> getBlankFields() {
            
    return blankFields;
        }

        @SuppressWarnings(
    "unused")
        
    private void setBlankFields(Set<BlankField> blankFields) {
            
    this.blankFields = blankFields;
        }
    }

    當(dāng)然還有其他的方式來(lái)實(shí)現(xiàn)上面的需求,上面采用的單表來(lái)記錄不同實(shí)體的associations(這兒是CollectionOfElements,并且返回的是Set<Enum>,不是Set<Embeddable>),然后用'type'來(lái)區(qū)分不同的實(shí)體,這樣做的好處是:數(shù)據(jù)庫(kù)冗余少,易于擴(kuò)展,對(duì)于新的實(shí)體,只需加一個(gè)type值,而不需更改數(shù)據(jù)庫(kù)表結(jié)構(gòu)。另外一種采用單表的方式是為每個(gè)實(shí)體增加新的字段,如
    "blank_fields": 'a_id', 'b_id', 'blank_field', a_id reference table_a (id), b_id reference table_b (id). 這樣在映射的時(shí)候更簡(jiǎn)單,
    對(duì)于A,映射為
    @JoinTable(name = "blank_fields", joinColumns = { @JoinColumn(name = "a_id") })
    對(duì)于B,映射為
    @JoinTable(name = "blank_fields", joinColumns = { @JoinColumn(name = "b_id") })
    這樣作的缺點(diǎn)是:帶來(lái)了數(shù)據(jù)庫(kù)冗余,對(duì)于blank_fields來(lái)講,任一條記錄,a_id和b_id中只有一個(gè)不為null。當(dāng)多個(gè)實(shí)體共用這個(gè)表時(shí),用上面的方法更合理,如果共用實(shí)體不多時(shí),這種方法更方便。

    posted @ 2010-04-20 17:20 honzeland 閱讀(454) | 評(píng)論 (0)編輯 收藏

    One Hibernate Session Multiple Transactions

    The case to use One Hibernate Session Multiple Transactions:
    each transaction would NOT affect others.
    i.e., open multiple transactions on the same session, even though one transaction rolls back, other transactions can be committed. If one action fails, others should fail too, then we should use one transaction for all actions.

    Note:
    A rollback with a single Session will lead to that Session being cleared (through "Session.clear()").
    So do lazy collections still work if the session is cleared? =>Not of any objects that you loaded up until the rollback. Only for new objects loaded afterwards.
    We should load necessary objects to session for each transactional action to avoid LazyInitializationException, even if those objects are loaded before other forward transactional actions, since forward action may be rolled back and clear the session.

    BTW, Hibernate Session.merge() is different with Session.update() by:
    Item item2 = session.merge(item);
    item2 
    == item; // false, item - DETACHED, item2 - PERSIST
    session.update(item); // no return value, make item PERSIST


    posted @ 2010-03-01 11:47 honzeland 閱讀(409) | 評(píng)論 (0)編輯 收藏

    org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

    發(fā)生這種異常的case:
        @Transactional
        
    public void foo() {
            
    try{
                bar();
            } 
    catch (RuntimeException re) {
                
    // caught but not throw further
                
            }
            
        }

        @Transactional
        
    public void bar() {
            
        }
    如果foo在調(diào)用bar的時(shí)候,bar拋出RuntimeException,Spring在bar return時(shí)將Transactional標(biāo)記為Rollback only, 而foo捕獲了bar的RuntimeException,所以Spring將會(huì)commit foo的事務(wù),但是foo和bar使用的是同一事務(wù),因此在commit foo事務(wù)時(shí),將會(huì)拋出UnexpectedRollbackException。注意:如果foo和bar在同一class中,不會(huì)出現(xiàn)這種情況,因?yàn)椋?br />
    Since this mechanism is based on proxies, only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with @Transactional!

    可以通過(guò)配置log4j來(lái)debug Spring事務(wù)獲取情況:
    To delve more into it I would turn up your log4j logging to debug and also look at what ExerciseModuleController is doing at line 91, e.g.: add a logger for org.springframework.transaction

    posted @ 2010-02-24 18:02 honzeland 閱讀(6984) | 評(píng)論 (0)編輯 收藏

    Discussion for Open Session In View Pattern for Hibernate

    From: http://www.mail-archive.com/stripes-users@lists.sourceforge.net/msg02908.html


    posted @ 2010-01-29 17:20 honzeland 閱讀(212) | 評(píng)論 (0)編輯 收藏

    Quartz scheduled executions

    這周被Quartz折騰了一番。
    我們知道,Quartz采用JobDataMap實(shí)現(xiàn)向Job實(shí)例傳送配置屬性,正如Quartz官方文檔說(shuō)的那樣:

    How can I provide properties/configuration for a Job instance? The key is the JobDataMap, which is part of the JobDetail object.
    The JobDataMap can be used to hold any number of (serializable) objects which you wish to have made available to the job instance when it executes.
    JobDataMap map = context.getJobDetail().getJobDataMap();

    我們通過(guò)map向Job實(shí)例傳送多個(gè)objects,其中有一個(gè)是個(gè)bean,一個(gè)是基本類型。對(duì)于scheduled triggers,我們要求bean對(duì)于所有的序列都不變,包括其屬性,而基本類型可以在Job運(yùn)行過(guò)程中改變,并影響下一個(gè)序列。實(shí)際情況是,對(duì)于下個(gè)序列,bean的屬性被上次的修改了,而基本類型卻維持第一次put到Map里面的值。正好和我們要求的相反。

    受bean的影響,以為map里面包含的都是更新的對(duì)象,即每個(gè)序列里面的JobDetail是同一個(gè)對(duì)象,但是基本類型的結(jié)果否認(rèn)了這一點(diǎn)。回頭重新翻閱了下Quartz的文檔:

    Now, some additional notes about a job's state data (aka JobDataMap): A Job instance can be defined as "stateful" or "non-stateful". Non-stateful jobs only have their JobDataMap stored at the time they are added to the scheduler. This means that any changes made to the contents of the job data map during execution of the job will be lost, and will not seen by the job the next time it executes.

    Job有兩個(gè)子接口:StatefulJob and InterruptableJob,我們繼承的是InterruptableJob,或許Quartz應(yīng)該有個(gè)InterruptableStatefulJob。另外StatefulJob不支持并發(fā)執(zhí)行,和我們的需求不匹配,我們有自己的同步控制,Job必須可以并發(fā)運(yùn)行。

    然后查看了Quartz的相關(guān)源碼:

    // RAMJobStore.storeJob
    public void storeJob(SchedulingContext ctxt, JobDetail newJob,
                
    boolean replaceExisting) throws ObjectAlreadyExistsException {
            JobWrapper jw 
    = new JobWrapper((JobDetail)newJob.clone()); // clone a new one
            .
            jobsByFQN.put(jw.key, jw);
            
    }

    也就是說(shuō),store里面放的是初始JobDetail的克隆,在序列運(yùn)行完時(shí),只有StatefulJob才會(huì)更新store里面的JobDetail:

    // RAMJobStore.triggeredJobComplete
    public void triggeredJobComplete(SchedulingContext ctxt, Trigger trigger,
                JobDetail jobDetail, 
    int triggerInstCode) {
        JobWrapper jw 
    = (JobWrapper) jobsByFQN.get(jobKey);
        
        
    if (jw != null) {
            JobDetail jd 
    = jw.jobDetail;
            
    if (jd.isStateful()) {
                JobDataMap newData 
    = jobDetail.getJobDataMap();
                
    if (newData != null) {
                    newData 
    = (JobDataMap)newData.clone();
                    newData.clearDirtyFlag();
                }
                jd.setJobDataMap(newData); 
    // set to new one
                
            
        }

    }



    然后,每次序列運(yùn)行時(shí)所用的JobDetail,是存放在Store里面的克隆。

    // RAMJobStore.retrieveJob
    public JobDetail retrieveJob(SchedulingContext ctxt, String jobName,
            String groupName) {
        JobWrapper jw 
    = (JobWrapper) jobsByFQN.get(JobWrapper.getJobNameKey(
            jobName, groupName));
        
    return (jw != null? (JobDetail)jw.jobDetail.clone() : null// clone a new
    }


    問(wèn)題很清楚了,存放在Store里面的JobDetail是初始對(duì)象的克隆,然后每個(gè)序列所用的JobDetail, 是Store里面的克隆,只有Stateful job,Store里面的JobDetail才更新。
    最有Quartz里面使用的clone():

    // Shallow copy the jobDataMap.  Note that this means that if a user
    // modifies a value object in this map from the cloned Trigger
    // they will also be modifying this Trigger.
    if (jobDataMap != null) {
        copy.jobDataMap 
    = (JobDataMap)jobDataMap.clone();
    }


    所以對(duì)于前面所講的,修改bean的屬性,會(huì)影響所有clone的對(duì)象,因此,我們可以將基本類型封裝到一個(gè)bean里面,map里面存放的是bean,然后通過(guò)修改bean的屬性,來(lái)達(dá)到影響下一個(gè)序列的目的。

    posted @ 2010-01-21 17:38 honzeland 閱讀(409) | 評(píng)論 (0)編輯 收藏

    Web application design: the REST of the story

    From: Web application design: the REST of the story
    Key points:
    • HTTP is a very general, scalable protocol. While most people only think of HTTP as including the GET and POST methods used by typical interactive browsers, HTTP actually defines several other methods that can be used to manipulate resources in a properly designed application (PUT and DELETE, for instance). The HTTP methods provide the verbs in a web interaction.
    • Servers are completely stateless. Everything necessary to service a request is included by the client in the request.
    • All application resources are described by unique URIs. Performing a GET on a given URI returns a representation of that resource's state (typically an HTML page, but possibly something else like XML). The state of a resource is changed by performing a POST or PUT to the resource URI. Thus, URIs name the nouns in a web interaction.


    posted @ 2010-01-08 14:50 honzeland 閱讀(254) | 評(píng)論 (0)編輯 收藏

    實(shí)話實(shí)說(shuō):應(yīng)用型和研究性

    剛剛看CCTV實(shí)話實(shí)說(shuō),很有感觸,義烏技術(shù)職業(yè)學(xué)院給人眼前一亮,尤其是他們副院長(zhǎng)的一番言論。
    技術(shù)職業(yè)學(xué)院非得要升本科,本科非要成清華,義烏職業(yè)技術(shù)學(xué)院副院長(zhǎng)評(píng)價(jià)當(dāng)前高校的現(xiàn)狀,定位嚴(yán)重有問(wèn)題,技術(shù)職業(yè)學(xué)院應(yīng)該培養(yǎng)應(yīng)用型人才,而清華就應(yīng)該培養(yǎng)研究性人才,兩種學(xué)校的定位不能一樣,培養(yǎng)方式,評(píng)判標(biāo)準(zhǔn)都應(yīng)該不同,而現(xiàn)在大多數(shù)高校的定位都一樣,這是不對(duì)的。個(gè)人非常贊同這個(gè)觀點(diǎn),其實(shí),這個(gè)觀點(diǎn)也可以應(yīng)用到我們這些剛開(kāi)始工作的年輕人身上,消除浮躁,找準(zhǔn)定位,然后沿著定位踏實(shí)做事,并且應(yīng)該采取相應(yīng)的評(píng)判標(biāo)準(zhǔn),這個(gè)很重要。

    posted @ 2009-04-12 19:35 honzeland 閱讀(127) | 評(píng)論 (0)編輯 收藏

    SCEP(Simple Certificate Enrollment Protocol)

    1. RFC documents

    2. SCEP operations
    • PKIOperation:      
      • Certificate Enrollment - request: PKCSReq, response: PENDING, FAILURE, SUCCESS
      • Poll for Requester Initial Certificate - request: GetCertInitial, response: same as for PKCSReq
      • Certificate Access - request: GetCert, response: SUCCESS, FAILURE
      • CRL Access - request: GetCRL, response: raw DER encoded CRL
    • Non-PKIOperation: clear HTTP Get
      • Get Certificate Authority Certificate - GetCACert, GetNextCACert, GetCACaps
      • Get Certificate Authority Certificate Chain - GetCACertChain
    3. Request message formats for PKIOperation
    • Common fields in all PKIOperation messages:
      • senderNonce
      • transactionID
      • the SCEP message being transported(SCEP messages) -> encrypted using the public key of the recipient(Enveloped-data)
        -> signed by one of certificates(Signed-data): the requester can generate a self-signed certificate, or the requester can use
        a previously issued certificate, if the RA/CA supports the RENEWAL option.
    • SCEP messages:
      • PKCSReq: PKCS#10
      • GetCertInitial: messages for old versions of scep clients such as Sscep, AutoSscep, and Openscep, are different with draft-18
               issuerAndSubject ::= SEQUENCE {
                    issuer Name,
                    subject Name
               }
      • GetCert: an ASN.1 IssuerAndSerialNumber type, as specified in PKCS#7 Section 6.7
      • GetCRL: an ASN.1 IssuerAndSerialNumber type, as defined in PKCS#7 Section 6.7

    posted @ 2009-02-17 14:18 honzeland 閱讀(1709) | 評(píng)論 (2)編輯 收藏

    RAM percentage utilised in Linux

    --zz: http://forums13.itrc.hp.com/service/forums/questionanswer.do?admit=109447627+1230261484567+28353475&threadId=1213960

    Question:
    We are planning to calculate the percentage of physical memory utilised as below:

    System Page Size: 4Kbytes
    Memory: 5343128K (1562428K) real, 13632356K (3504760K) virtual, 66088K free Page# 1/604

    Now the formula goes as below:

    (free memory / actual active real memory) * 100
    (66088/1562428) * 100 = 4.22 %

    Please let us know if its the correct formula .

    Mainly we are interested in RAM percentage utilised

    Reply 1:
    Red Hat/Centos v 5 take spare ram and use it for a buffer cache.

    100% memory allocation is pretty meaningless because allocation is almost always near 100%. The 2.6.x kernel permits rapid re-allocation of buffer to other purposes eliminating a performance penalty that you see on an OS like HP-UX

    I'm not thrilled with your formula because it includes swap(virtual memory). If you start digging too deep into virtual memory, your system start paging processes from memory to disk and back again and slows down badly.

    The formula is however essentially correct.

    Reply 2:
    Here, a quick example from the machine under my desk:
    Mem:   3849216k total,  3648280k used,   200936k free,   210960k buffers
    Swap:  4194296k total,       64k used,  4194232k free,  2986460k cached

    If the value of 'Swap used' is up (i.e. hundreds of megabytes), then you've got an issue, but as you can see, it's only 64k here.
    Your formula for how much memory is used is something along the lines of this:

    (Used - (Buffers + Cached) / Total) * 100 = Used-by-programs%
    (Free + Buffers + Cached / Total) * 100 = Free%

    .. Roughly ..



    posted @ 2008-12-26 12:08 honzeland 閱讀(271) | 評(píng)論 (0)編輯 收藏

    GWT/Tomcat will re-call servlet.

     昨天遇到個(gè)非常奇怪的bug:更新了一下后臺(tái)的代碼,結(jié)果每次點(diǎn)擊頁(yè)面都會(huì)導(dǎo)致servlet方法調(diào)用兩次,從而頁(yè)面報(bào)錯(cuò)(邏輯上不讓調(diào)兩次 ),我們的前臺(tái)采用gwt,servlet engine采用tomcat,debug的時(shí)候,斷點(diǎn)放在servlet所調(diào)用的method上,結(jié)果invoke兩次,由此斷定,前臺(tái)代碼的問(wèn)題(有點(diǎn)武斷哦),然后負(fù)責(zé)前臺(tái)的同事debugging前臺(tái)的代碼,噼里啪啦半天。。。,說(shuō)是前臺(tái)好像沒(méi)有調(diào)兩次(之所以用好像,是debugging時(shí)部分代碼走兩次,部分走一次),而我當(dāng)時(shí)的想法是,后臺(tái)怎么操作,也不至于讓servlet調(diào)用兩次吧,所以我個(gè)人就認(rèn)定是前臺(tái)邏輯導(dǎo)致重復(fù)rpc調(diào)用(gwt),但是這個(gè)bug在這兩天才出現(xiàn)的,從svn的歷史記錄來(lái)看,前臺(tái)代碼在這兩天基本沒(méi)什么改變,同事只好從svn上一個(gè)version接一個(gè)version的check,最后確定出兩個(gè)相鄰的versions,前一個(gè)能用,后一個(gè)出bug,這時(shí)我隱約感覺(jué)到是后臺(tái)的問(wèn)題,但是還是想不明白,后臺(tái)的邏輯怎么就能讓前臺(tái)重復(fù)調(diào)用,非常不解,沒(méi)辦法,在同事的建議下,在servlet的那個(gè)method上加上一條debug信息,做了兩次試驗(yàn),一次是完整的代碼,一次是把method中調(diào)用后臺(tái)的接口注釋掉,結(jié)果從日志上看出,前一次試驗(yàn)debug信息打印了兩次,后一次試驗(yàn)debug只打印了一次,此時(shí),確定是后臺(tái)邏輯影響了前臺(tái)的調(diào)用(此時(shí),覺(jué)得走彎路了,為什么不早點(diǎn)做這個(gè)試驗(yàn),其實(shí)確定是前臺(tái)還是后臺(tái)的問(wèn)題,只需要做這樣一個(gè)簡(jiǎn)單的試驗(yàn)。。。)。接下來(lái),我思考的就是到底是什么在作怪呢,對(duì)比svn上的兩個(gè)版本,只有兩處可能的改動(dòng),一處是將return改成throw exception, 一處是調(diào)用了Thread.currentThread.interrupt(),我一個(gè)感覺(jué)是后者,注掉這句后,一切OK,呵呵,慶幸沒(méi)有先嘗試前者,要不改動(dòng)很大,。。。

    剛剛看了gwt的源碼,還沒(méi)找到問(wèn)題的根源,我的觀點(diǎn)是,thread接收到interrupt信號(hào)時(shí),會(huì)重復(fù)發(fā)送rpc調(diào)用,(呵呵,還沒(méi)確定)。。。

    posted @ 2008-12-04 10:26 honzeland 閱讀(1213) | 評(píng)論 (0)編輯 收藏

    感覺(jué)到了責(zé)任。。。

        最近心情不是很好,上周三,父親的一次意外,給家里本來(lái)平靜的生活帶來(lái)了很大的波瀾,我也第一次感受到來(lái)自于家庭的壓力,由此帶來(lái)的一系列問(wèn)題,一直縈繞著我,責(zé)任,responsibility,是這幾天我告誡自己最多的一個(gè)詞,是啊,該到了承受家庭責(zé)任的時(shí)候了。
        父親的這次意外,揪住了全家人的心,我也更多的為兩位老人思考了,這兩天,老想起一句話:人只有經(jīng)歷的多了,才能成熟。我很喜歡類比,其實(shí)就跟我們做數(shù)學(xué)題一樣,看的多了,做的多了,考試的時(shí)候才能迎刃而解,什么東西,或許只有自己親身經(jīng)歷,才能體會(huì)其中的更多細(xì)節(jié),才能激發(fā)更多的收獲。
        祝福父親的身體早日康復(fù),bless。。。

    posted @ 2008-06-25 21:49 honzeland 閱讀(283) | 評(píng)論 (3)編輯 收藏

    命運(yùn)。。。

       最近,時(shí)不時(shí)地回想自己這一路的教育經(jīng)歷,使得我越來(lái)越相信——命運(yùn)!
       總體來(lái)說(shuō),我自認(rèn)為我這一路上走的太順利,缺少更多的經(jīng)歷,缺少一些該有的挫折!
       但是,順利歸順利,在兩次作抉擇的時(shí)候,隨機(jī)的選擇決定現(xiàn)在的方向!一次當(dāng)然是過(guò)獨(dú)木橋——高考,另一次是碩士入學(xué)時(shí)選擇導(dǎo)師!兩次選擇都很隨意,甚至于無(wú)意,尤其是第二次。第一次的隨意更多的是無(wú)知,而第二次的無(wú)意,卻源于自己的不適應(yīng)。隨意帶來(lái)了大學(xué)時(shí)代的混亂,無(wú)意卻給自己帶來(lái)了意外的收獲,人生無(wú)常,命運(yùn)有數(shù)。
       高考時(shí),分?jǐn)?shù)超出了自己的預(yù)料,志愿填的有些草率,一方面,是因?yàn)樽约旱哪贻p和無(wú)知,另一方面是由于周圍缺少必要的指點(diǎn),填的很倉(cāng)促,很隨意,非常的“高效”。正值00年高校擴(kuò)招猖獗之時(shí),我所填報(bào)的學(xué)校就是由三個(gè)學(xué)校合并而成,并且是在高考的前兩個(gè)月宣布合并的,其中有兩個(gè)合并之前不是一本,但是合并之后,肯定都是一本了。我當(dāng)時(shí)選報(bào)了自動(dòng)化這個(gè)專業(yè),當(dāng)時(shí)填的時(shí)候就因?yàn)楦咧邪嘀魅握f(shuō)了一聲:“現(xiàn)在自動(dòng)化是一個(gè)很好的方向。”然而,此時(shí)命運(yùn)開(kāi)始現(xiàn)數(shù),其中有兩個(gè)學(xué)校都有自動(dòng)化這個(gè)專業(yè),一個(gè)之前就是一本(合并后,稱之為‘校本部’,不知道這個(gè)是什么意思,或許我要去查查字典,好好揣測(cè)一下本部的含義。),另一個(gè)是三個(gè)學(xué)校中最差的一個(gè),報(bào)道那天才知道有兩個(gè)自動(dòng)化,但是由于剛合校,還沒(méi)來(lái)得及合并專業(yè),當(dāng)時(shí)就想,我該在哪個(gè)校區(qū)的自動(dòng)化呢?最后隨著師長(zhǎng)的指引,我被校車?yán)搅朔中^(qū),也就是那個(gè)最差的了,一路上,還在思索兩個(gè)自動(dòng)化的分配算法,還是直到開(kāi)學(xué)一個(gè)月以后,一次偶然的機(jī)會(huì),才得知:兩個(gè)自動(dòng)化是根據(jù)當(dāng)時(shí)各省分?jǐn)?shù)的交替順序分配,安徽省生源的第一名在本部,第二名在分校區(qū),第三名本部,第四名分校區(qū)。。。。只能怪自己被動(dòng)的排在了一個(gè)偶數(shù)的序位上,如果用一個(gè)函數(shù)來(lái)表示這個(gè)序位的話,其自變量的個(gè)數(shù)還是蠻多的,當(dāng)年安徽省報(bào)考該校該專業(yè)的人生,你在這些人中的名次,另外還有,我還不太確定的因素,但是我能確定因素的存在。。。
       后來(lái),進(jìn)一步得知,分校區(qū)的自動(dòng)化之前沒(méi)有,我們是第一屆,當(dāng)時(shí)在合校之前就已經(jīng)確定要新增這個(gè)專業(yè),合的時(shí)候,各個(gè)學(xué)校的招生計(jì)劃都沒(méi)變,只是將三個(gè)計(jì)劃簡(jiǎn)單的數(shù)學(xué)累加,現(xiàn)在看來(lái),合校是多么的可笑,一個(gè)學(xué)校從任意層次可以一下成為中國(guó)最好的學(xué)校,只要清華愿意合并它,而合并后再很長(zhǎng)一段時(shí)間,那個(gè)學(xué)校除了學(xué)生的層次提高之外,沒(méi)有任何的改變,教師還是那些教師,設(shè)施還是那些設(shè)施,思想還是那些思想,我不知道這可不可以稱之為赤裸裸的搶劫,它無(wú)視了那些默默地而踏踏實(shí)實(shí)前進(jìn)的高校,助長(zhǎng)了一些不公正的風(fēng)氣,或許正應(yīng)了中國(guó)當(dāng)時(shí)浮躁的社會(huì)氛圍。
       就這樣在這度過(guò)了自己的三年大學(xué)時(shí)光,就在最后一個(gè)大學(xué)暑假之前,學(xué)校經(jīng)過(guò)三年的發(fā)展和磨合,決定將我們這個(gè)專業(yè)撤銷,統(tǒng)一合并到本部去,我們被迫搬回了第一天報(bào)道的地方,其實(shí)兩個(gè)自動(dòng)化的方向是不一樣的,或許我們要慶幸,我們學(xué)習(xí)了兩個(gè)專業(yè),在大學(xué)的四年中,但是或許,更多的人可能會(huì)埋怨兩個(gè)方向影響了自己的學(xué)習(xí),其實(shí),我想,大多數(shù)的人根本不在于什么方向,什么專業(yè)了,一個(gè)大框架的混亂,注定了最終的結(jié)果,就像當(dāng)前的中國(guó)足球。。。
       我要說(shuō)的是,其實(shí)我在大學(xué)中過(guò)得很愉快,我認(rèn)識(shí)了一批很好的同學(xué),我經(jīng)歷了到目前為止最好的一段時(shí)光,雖然期間有很多遺憾,比如沒(méi)談一次戀愛(ài)。。。我想這段時(shí)光勢(shì)必會(huì)在我的記憶集合中占據(jù)非常重要的一塊。這里,我只不過(guò)是要論述命運(yùn)有數(shù),這樣的一個(gè)過(guò)程多少還是影響了我的人生軌跡。
       下面要談?wù)撐业牡诙尉駬瘢T士時(shí)選擇導(dǎo)師。大學(xué)畢業(yè)時(shí),我選擇了繼續(xù)就讀,一切都很順利,到了04年9月,我來(lái)到了新的學(xué)校,在合肥,這兒離家很近,因?yàn)槲沂前不杖耍?jīng)歷了大學(xué)時(shí)回家的艱辛,再加上我又是個(gè)比較戀家的人。剛?cè)胄#陀龅搅艘粋€(gè)。。。。


    明天繼續(xù)。。。。

    posted @ 2008-06-15 23:08 honzeland 閱讀(174) | 評(píng)論 (1)編輯 收藏

    Useful Links: ing...

    About Java:
    http://www.theserverside.com
    http://www.javablogs.com
    http://www.java2s.com
    Java(TM) Platform Performance: Strategies and Tactics
    A Simple Data Access Layer using Hibernate
    Discover the secrets of the Java Serialization API
    Setting up two-way (mutual) SSL with Tomcat on Java5
    Basic Tomcat Tour and Tomcat Security
    When Runtime.exec() won't
    Asynchronous processing support in Servlet 3.0
    About security:
    The Types Of Digital Certificates
    Cryptography Lecture PPT
    MD5 considered harmful today
    Cryptography Tutorials - Herong's Tutorial Notes
    Defective Sign & Encrypt in S/MIME, PKCS#7, MOSS, PEM, PGP, and XML
    Cryptography resources by Bouncycastle
    Others:
    Colors for the webColors for the web
    Test Frameworks
    Lightstreamer: a scalable and reliable Server for pushing live data to Rich Internet Applications
    工資計(jì)算器2009版

    posted @ 2008-06-03 15:09 honzeland 閱讀(286) | 評(píng)論 (0)編輯 收藏

    Vim使用技巧,長(zhǎng)期更新中。。。

    1. 多行注釋:
     ctrl+v 進(jìn)入列模式,向下或向上移動(dòng)光標(biāo),把需要注釋的行的開(kāi)頭標(biāo)記起來(lái),然后按大寫的I,再插入注釋符,比如#,再按esc,就會(huì)全部注釋了.

    posted @ 2008-05-31 17:22 honzeland 閱讀(287) | 評(píng)論 (0)編輯 收藏

    Managing HttpSession Objects

    zz: java.sys-con.com

    Java servlet technology provides developers with functionality, scalability, and portability that can't be found in other server-side languages. One feature of the Java servlet specification that's commonly used, and sometimes misused, is the HttpSession interface. This simple interface allows you to maintain a session or state for Web site visitors.

    In my previous article ("Introduction to Session Management," [JDJ, Vol. 7, issue 9]), I introduced you to session management and the HttpSession interface. In that article, we walked through using the HttpSession API to create, use, and destroy session objects for Web site visitors. The next step is to better understand how to manage the sessions and those objects in a session. This article will help you achieve this by helping you understand the following concepts:

    • Code-based session management through listeners
    • Proper design of the session and the objects it contains
    • Controlling what is in the session and why it's there
    • Session persistence
    • Memory management
    The Java APIs discussed in this article are from Sun's Java Servlet 2.3 specification.

    Listeners
    A listener is an object that's called when a specified event occurs. There are four listener interfaces that allow you to monitor changes to sessions and the objects that are in those sessions:

    • HttpSessionListener
    • HttpSessionBindingListener
    • HttpSessionAttributeListener
    • HttpSessionActivationListener
    Figure 1 provides a method summary for each of the listener interfaces. The implementing class that you write will override these methods to provide the functionality you need.

    HttpSessionListener
    The HttpSessionListener interface is used to monitor when sessions are created and destroyed on the application server. Its best practical use would be to track session use statistics for a server.

    The use of HttpSessionListener requires a configuration entry in the deployment descriptor, or web.xml file, of the application server. This entry points the server to a class that will be called when a session is created or destroyed. The entry required is simple. All you need is a listener and listener-class element in the following format. The listener-class element must be a fully qualified class name.

    <listener>
    <listener-class>package.Class</listener-class>
    </listener>

    As you can see in Figure 1, the class that implements this listener can override two methods: sessionCreated() and sessionDestroyed(). These methods will be notified when the server creates or destroys a session.

    These methods take an HttpSessionEvent object as a parameter. HttpSessionEvent is simply a class that represents notifications of changes to the Web application's sessions. HttpSessionEvent has one method, getSession(), that returns the HttpSession object that's been modified.

    HttpSessionBindingListener
    The HttpSessionBindingListener interface is implemented when an object needs to be notified if it's being bound to a session or unbound from a session.

    This interface has two methods, valueBound() and valueUnbound(), that are notified when the status of the object has changed (see Figure 1).

    These methods have an HttpSessionBindingEvent parameter that can be used to retrieve the session that the object was bound to and the name it was given in the session. In Figure 2, you can see the methods of this object that are used to get the name that's assigned to the object, the session it's bound to, and the actual object.

    HttpSessionAttributeListener
    The HttpSessionAttributeListener interface is used to monitor changes to attributes in any session on the server. This can be useful when you know the name assigned to a specific object that gets put into the session and you want to track how often it's being used.

    As with HttpSessionListener, HttpSessionAttributeListener also requires an entry in the deployment descriptor for the server. This entry tells the server which class to call when an attribute in a session has changed.

    The HttpSessionAttributeListener interface has three methods - attributeAdded(), attributeRemoved(), and attributeReplaced(). These methods, shown in Figure 1, are called by the server when attributes of a session are changed.

    HttpSessionActivationListener
    The final listener, HttpSessionActivationListener, is implemented when an object needs to know if the session that it's bound to is being activated or passivated (moved). You would come across this scenario if your session is being shared across JVMs or your server is persisting the session in a database or file system.

    This interface, displayed in Figure 1, has two methods that are overridden by the implementing class: sessionDidActivate() and sessionWillPassivate(). These methods are called when the status of the session in a JVM is changed.

    Session Persistence
    Today's J2EE-compliant servers allow for fault-tolerance and failover to provide support in the event that a server suddenly becomes unavailable because of hardware, software, or network failure. This support is usually provided by allowing two or more application servers, often called a cluster, to run together and provide backup support for each other. If one server fails, the others pick up the requests and continue on as if nothing happened. This allows your Web site visitors to keep going without interruption.

    A proxy server is usually used in front of the application servers. This server is responsible for directing each HTTP request to the appropriate server. The proxy server can be set up to ensure that the server receiving the first request from a user will continue to receive all subsequent requests from that user. This means that a session created for the user on the application server will continue to be available for that user. If the server suddenly fails, there has to be a system in place to allow the session to continue on without it.

    Session persistence allows the session contents to be saved outside the application server so that other servers can access it. Figure 3 shows the relationship between the persisted session data and the application servers that access it. In this figure, you see a client accessing a Web site's HTTP server. The HTTP server is forwarding requests for application resources to one of the application servers through the use of a proxy server. The application servers are persisting the session data in an external form.

    There are four types of session persistence:

    1. Memory persistence (one server or a cluster of two or more)
    2. File system persistence
    3. Database persistence
    4. Cookie persistence
    Every application server will handle session persistence differently and all servers may not support all types of persistence. Objects that are placed in the session must be serializable for persistence to work.

    Memory Persistence
    In most cases, a single standalone server will store sessions in memory. This allows for fast retrieval and update of the information. It also means that the session information will be lost when the server is shut down. This is usually the default configuration on most application servers. Memory persistence can be used when two or more servers need to share the session information. The application servers can be configured to share any changes made to the session so that the information is available on multiple servers. This redundancy of the session information helps the cluster preserve the session during a failure.

    File System Persistence
    File system persistence can be used to serialize any objects that are in the session. The object contents are placed in a file on the server. The location of the files created is configurable; however, the files must be accessible by all the servers in the cluster. The speed at which the file system is accessed can be a factor in the performance of your Web site. A slow disk drive, for example, would result in a delay as data is read from or written to the file.

    Database Persistence
    Database persistence can be used to provide a central data store for the session contents. Each application server in the cluster must be able to access the database. When sessions are modified, the changes are immediately persisted in the database. A data source is usually set up for JDBC persistence and the connections are pooled. This provides a quicker response. There's also the issue of database failover, which would be addressed at the database level of the system.

    Cookie Persistence
    The fourth type of session persistence, cookie persistence, is so ineffective and insecure that it doesn't deserve consideration when designing a fail-safe system. Cookie persistence, as the name implies, persists session data by storing the session information in browser cookie(s). There's a limitation on data handling because cookies store only text, not objects, and the amount of data that can be transmitted in a cookie is limited. There's also the fact that cookies transmit data back and forth between the client and the server. This prevents you (at least it should) from saving sensitive information, like a social security number. This type of persistence should be used in only the smallest of Web sites, and only if there's a good reason not to store the session in memory.

    The most common type of persistence is database persistence. It provides an efficient way of saving session data and it's usually fairly easy to set up on the application server. Memory persistence in a cluster is also easy to use, if your application server supports it. The only drawback is that sessions can sometimes hold large amounts of data. Storing the session in memory reduces the amount of memory available to the other processes on the server. File system persistence can be slow at times and the file system may not always be accessible to multiple servers.

    Watching the Session Size
    As you and your fellow employees work on a Web application, you may notice that more and more objects are being thrown into the session, often "for convenience" or "just temporarily." The session becomes a quick catch-all for any information you need to get from your servlets to your JSPs. The HttpSession interface makes sessions easy to use, which can lead to the session being overused. This is a concern because the session takes up space. In most cases that would be memory space. In other cases, it could be database or file system space. In all cases, it means more work for the server and more work for the programmers to manage what is there.

    Although the session is convenient because it's accessible from every servlet or JSP, it's not always the best place to put information. Most of the data that's retrieved for display in a Web application will only be used on one page. Instead of putting the information into the session scope, use the request scope and then forward the request from the servlet to the JSP. This causes the objects to be destroyed after the request has ended, which is after the data is displayed by the JSP. If you put the objects into the session, you would either have to remove them in your code or leave them there. Leaving objects in the session is not a good idea because you're using up valuable resources for no reason. This becomes even more of an issue when your Web site has hundreds or thousands of visitors, all of whom have a session that's loaded with objects.

    Some objects should be stored in the session. Objects that may be needed over and over again as a user moves through a Web site are those that should be put into the session. Anything that needs to exist longer than one request can be stored in the session, as long as these objects are removed as soon as they're no longer needed.

    Considerations for Managing Sessions
    When working with sessions, there are a few things to consider before designing or redesigning a Web application:

    • Are sessions needed in the application?
    • How long should the session be inactive before timing out?
    • Are all the objects in the session serializable?
    • Are the objects being bound to the session too large?
    • Do the objects that are in the session really need to be there?
    A Need for Sessions
    If you have unique users on a Web site and need to know who they are or need to get specific information to them, such as search results, then you should be using sessions. If you follow the guidelines set here, there's no reason not to use the HttpSession interface that Java provides. It's easy to use, flexible, secure, and it helps you to build a better Web site.

    There's another architecture that deals with maintaining state for a client. Instead of relying on the HttpSession interface, state for clients can be maintained within Enterprise JavaBeans (EJBs). The EJB architecture takes the business logic for an application and places it in components or beans. A session bean is a type of EJB that exists for a given client/server session and provides database access or other business logic, such as calculations. Session beans can be stateless or they can maintain the state for a client, very much like an HttpSession object.

    There is still some debate over where the state for a Web site visitor should be maintained. The best design for the application at this time is to continue using the HttpSession object for maintaining the state of the presentation layer of the Web application and to use stateful EJBs to maintain the state of the business logic and data layer. There are many other factors that should be considered with EJBs, one being the better performance of stateless beans over those that maintain state. These issues, which are outside the scope of this article, should be considered carefully when architecting an application.

    Session Timeout
    By default, on most servers the session is set to expire after 30 minutes of inactivity. The amount of time can be configured in the deployment descriptor of the Web application. The HttpSession API also provides a setMaxInactiveInterval() method that you can use to specify the timeout period for a session. The getMaxInactiveInterval() method will return this timeout value. The value given is in seconds.

    The length of time will vary depending on what your visitors are doing on your site. If they're logging in to check their account balance, a shorter session timeout period can be used because it doesn't take long for a person to read a couple of numbers. If, on the other hand, the user is logging in to read large amounts of data, you need to be sure that you provide enough time for the user to do what he or she wants without being logged out. If the user is constantly navigating through your site, the session will last indefinitely.

    Implement Serializable
    It's important to make sure that all objects placed in the session can be serialized. This may not be an issue if you know that your Web application will not run in a cluster, but it should still be done anyway. What happens if your Web site grows too big for one server and you suddenly have to move to two? If you implement Serializable in your code now, you won't have to go back and do it later.

    Keep It Simple
    You should design objects that are going to be placed into a session so that they're not too big and don't contain unnecessary information. A JavaBean that contains a customer's name, address, phone number, e-mail address, credit card numbers, and order history should not be placed into the session if you're only going to use the object to get the customer's name.

    Session Contents
    When you're working on a Web site, it's important to know which objects are in the session and why they're needed. The size of the session should be kept as small as possible. If you're building a new Web site, work out ahead of time what goes in the session, why it's there, and where it gets removed. If you're redesigning an existing site, this may be a little tougher, especially when you have hundreds of servlets and JSPs to deal with. In this case, try implementing an HttpSessionAttributeListener to get an idea of what is going into the session. With this information, you may be able to better manage your sessions.

    Conclusion
    Hopefully this article helped you to better understand the design issues involved in using the HttpSession interface. Java provides a more robust session implementation than other languages. It's because of this power and flexibility that you must take the time to properly lay out the use of the session. A well-designed session will help make a Web application better for the programmers and the users.

    References

  • Hall, M. (2002). More Servlets and JavaServer Pages. Prentice Hall PTR.
  • Java Servlet Technology: http://java.sun.com/products/servlet
  • Enterprise JavaBeans Technology: http://java.sun.com/products/ejb
  • Java BluePrints (J2EE): http://java.sun.com/blueprints/guidelines/ designing_enterprise_applications


  • 另外,還有一些收集的材料
    關(guān)于HttpSession的誤解實(shí)在是太多了,本來(lái)是一個(gè)很簡(jiǎn)單的問(wèn)題,怎會(huì)搞的如此的復(fù)雜呢?下面說(shuō)說(shuō)我的理解吧:
    1、HTTP協(xié)議本身是“連接-請(qǐng)求-應(yīng)答-關(guān)閉連接”模式的,是一種無(wú)狀態(tài)協(xié)議(HTTP只是一個(gè)傳輸協(xié)議);
    2、Cookie規(guī)范是為了給HTTP增加狀態(tài)跟蹤用的(如果要精確把握,建議仔細(xì)閱讀一下相關(guān)的RFC),但不是唯一的手段;
    3、所謂Session,指的是客戶端和服務(wù)端之間的一段交互過(guò)程的狀態(tài)信息(數(shù)據(jù));這個(gè)狀態(tài)如何界定,生命期有多長(zhǎng),這是應(yīng)用本身的事情;
    4、由于B/S計(jì)算模型中計(jì)算是在服務(wù)器端完成的,客戶端只有簡(jiǎn)單的顯示邏輯,所以,Session數(shù)據(jù)對(duì)客戶端應(yīng)該是透明的不可理解的并且應(yīng)該受控于服務(wù)端;Session數(shù)據(jù)要么保存到服務(wù)端(HttpSession),要么在客戶端和服務(wù)端之間傳遞(Cookie或url rewritting或Hidden input);
    5、由于HTTP本身的無(wú)狀態(tài)性,服務(wù)端無(wú)法知道客戶端相繼發(fā)來(lái)的請(qǐng)求是來(lái)自一個(gè)客戶的,所以,當(dāng)使用服務(wù)端HttpSession存儲(chǔ)會(huì)話數(shù)據(jù)的時(shí)候客戶端的每個(gè)請(qǐng)求都應(yīng)該包含一個(gè)session的標(biāo)識(shí)(sid, jsessionid 等等)來(lái)告訴服務(wù)端;
    6、會(huì)話數(shù)據(jù)保存在服務(wù)端(如HttpSession)的好處是減少了HTTP請(qǐng)求的長(zhǎng)度,提高了網(wǎng)絡(luò)傳輸效率;客戶端session信息存儲(chǔ)則相反;
    7、客戶端Session存儲(chǔ)只有一個(gè)辦法:cookie(url rewritting和hidden input因?yàn)闊o(wú)法做到持久化,不算,只能作為交換session id的方式,即a method of session tracking),而服務(wù)端做法大致也是一個(gè)道理:容器有個(gè)session管理器(如tomcat的 org.apache.catalina.session包里面的類),提供session的生命周期和持久化管理并提供訪問(wèn)session數(shù)據(jù)的 api;
    8、使用服務(wù)端還是客戶端session存儲(chǔ)要看應(yīng)用的實(shí)際情況的。一般來(lái)說(shuō)不要求用戶注冊(cè)登錄的公共服務(wù)系統(tǒng)(如google)采用 cookie做客戶端session存儲(chǔ)(如google的用戶偏好設(shè)置),而有用戶管理的系統(tǒng)則使用服務(wù)端存儲(chǔ)。原因很顯然:無(wú)需用戶登錄的系統(tǒng)唯一能夠標(biāo)識(shí)用戶的就是用戶的電腦,換一臺(tái)機(jī)器就不知道誰(shuí)是誰(shuí)了,服務(wù)端session存儲(chǔ)根本不管用;而有用戶管理的系統(tǒng)則可以通過(guò)用戶id來(lái)管理用戶個(gè)人數(shù)據(jù),從而提供任意復(fù)雜的個(gè)性化服務(wù);
    9、客戶端和服務(wù)端的session存儲(chǔ)在性能、安全性、跨站能力、編程方便性等方面都有一定的區(qū)別,而且優(yōu)劣并非絕對(duì)(譬如TheServerSide號(hào)稱不使用HttpSession,所以性能好,這很顯然:一個(gè)具有上億的訪問(wèn)用戶的系統(tǒng),要在服務(wù)端數(shù)據(jù)庫(kù)中檢索出用戶的偏好信息顯然是低效的,Session管理器不管用什么數(shù)據(jù)結(jié)構(gòu)和算法都要耗費(fèi)大量?jī)?nèi)存和CPU時(shí)間;而用cookie,則根本不用檢索和維護(hù)session數(shù)據(jù),服務(wù)器可以做成無(wú)狀態(tài)的,當(dāng)然高效);
    reply1:
    不過(guò)我們也不能在session里面放入過(guò)多的東西
    一般來(lái)說(shuō)不能超過(guò)4K
    太多了
    對(duì)系統(tǒng)資源是一個(gè)很嚴(yán)重的浪費(fèi)
    reply2:
    4K已是很大的一個(gè)數(shù)字了。
    我一般喜歡寫一個(gè)類。封裝用戶登陸后的一些信息。
    然后把這個(gè)類放在session中,取得直接用類的方法取相關(guān)信息,

    posted @ 2008-05-21 15:49 honzeland 閱讀(294) | 評(píng)論 (0)編輯 收藏

    Svn revision retrieve and logging to database

    最近接到兩個(gè)很小的tickets,兩個(gè)都是為了項(xiàng)目開(kāi)發(fā)時(shí)的方便:一是將logs寫入到數(shù)據(jù)庫(kù)中,以方便日志的查詢;一是在build時(shí),在war包加入svn revision info。
    1) logging to database
    經(jīng)過(guò)調(diào)查,決定采用log4j的org.apache.log4j.jdbc.JDBCAppender,于是采用:
    # logging to db
    log4j.logger.com.example=DEBUG, DATABASE
    log4j.additivity.com.example=false
    log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
    log4j.appender.DATABASE.url=jdbc:postgresql://localhost:5432/test
    log4j.appender.DATABASE.driver=org.postgresql.Driver
    log4j.appender.DATABASE.user=pguser
    log4j.appender.DATABASE.password=post
    log4j.appender.DATABASE.sql=INSERT INTO debug_log(created, logger, priority, message) VALUES (to_timestamp('%d{ISO8601}','YYYY-MM-DD HH:MI:SS.MS'),'%c.%M:%L','%p','%m')
    log4j.appender.DB.layout=org.apache.log4j.PatternLayout
    log4j.appender.DATABASE.layout.ConversionPattern=%d{ISO8601} %p %c.%M:%L %m
    很直觀,用起來(lái)還很方便,但是不久就出現(xiàn)了問(wèn)題,tomcat拋出了exception。只好把之前fixed ticket reopen,提交新的comments:Unfortunately, org.apache.log4j.jdbc.JDBCAppender that ships with the Log4j distribution is not able to process logging messages that have characters like ' (single quote) and , (comma) in it. When logging messages contains characters like single quote or comma, the program will throw an exception.
    重新google了,找到了一個(gè)plusjdbc,Looking further, I found an alternative JDBCAppender package (org.apache.log4j.jdbcplus.JDBCAppender) from http://www.dankomannhaupt.de/projects/index.html. It can solve this problem. 長(zhǎng)嘆了一下。

    最后采用:
    log4j.appender.DATABASE=org.apache.log4j.jdbcplus.JDBCAppender
    log4j.appender.DATABASE.url=jdbc:postgresql://localhost:5432/test
    log4j.appender.DATABASE.dbclass=org.postgresql.Driver
    log4j.appender.DATABASE.username=pguser
    log4j.appender.DATABASE.password=post
    log4j.appender.DATABASE.sql=INSERT INTO debug_log(created, logger, priority, message) VALUES (to_timestamp('@LAYOUT:1@', 'YYYY-MM-DD HH:MI:SS.MS'),'@LAYOUT:3@','@LAYOUT:2@','@LAYOUT:4@')
    log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
    log4j.appender.DATABASE.layout.ConversionPattern=%d{ISO8601}#%p#%c.%M:%L#%m
    log4j.appender.DATABASE.layoutPartsDelimiter=#
    log4j.appender.DATABASE.buffer=1
    log4j.appender.DATABASE.commit=true
    log4j.appender.DATABASE.quoteReplace=true
    問(wèn)題解決,但是中間有點(diǎn)小波折,在我的項(xiàng)目中,log4j.jar(>1.2.9)重復(fù)了,在$CATALINA_HOME/lib下有一份,在web工程下的WEB-INF/lib下也有一份,而plus-jdbc.jar放置在$CATALINA_HOME/lib下,結(jié)果啟動(dòng)Tomcat,出現(xiàn)
    log4j:ERROR A "org.apache.log4j.jdbcplus.JDBCAppender" object is not assignable to a "org.apache.log4j.Appender" variable.
    log4j:ERROR The class "org.apache.log4j.Appender" was loaded by
    log4j:ERROR [WebappClassLoader^M
      delegate: false^M
      repositories:^M
    ----------> Parent Classloader:^M
    org.apache.catalina.loader.StandardClassLoader@1ccb029^M
    ] whereas object of type
    log4j:ERROR "org.apache.log4j.jdbcplus.JDBCAppender" was loaded by [org.apache.catalina.loader.StandardClassLoader@1ccb029].
    log4j:ERROR Could not instantiate appender named "DATABASE".
    原來(lái)是兩個(gè)JDBCAppender實(shí)例不在同一個(gè)classlaoder里面,將WEB-INF/lib下的log4j.jar刪除掉,重啟就沒(méi)問(wèn)題了,按理,將$CATALINA_HOME/lib下的plus-jdbc.jar移到WEB-INF/lib下,應(yīng)該也沒(méi)問(wèn)題,沒(méi)有測(cè)試。

    2)Add build revision info in war file and read it on tomcat startup
    這個(gè)經(jīng)歷比較慘痛,兩個(gè)問(wèn)題,如何獲取revision? And how to read it when tomcat startup? 第二個(gè)問(wèn)題倒是沒(méi)什么,采用javax.servlet.ServletContextListener就可以實(shí)現(xiàn),很簡(jiǎn)單,走彎路的是第一個(gè)問(wèn)題,google后發(fā)現(xiàn)有兩種常見(jiàn)的實(shí)現(xiàn):
    As I have learned, there are totally two solutions to get svn revision info.

    First, retrieve the svn revision from local file($BASE_HOME/.svn/entries). Just parsing the xml file, get the revision property and write it to a properties file.(就是該死的xml,遠(yuǎn)在烏克蘭的同事,該文件卻不是xml的,也只怪自己調(diào)研不充分,還得折騰了半天,后來(lái)發(fā)現(xiàn),最新版的svn為了performance的考慮,采用meta data來(lái)實(shí)現(xiàn)entries)

    Second, retrieve the svn revision from the remote repository. The solution always use a svn client to perform a demand with remote server to retrieve the revision info. Installing a snv client and using SvnAnt? are most commonly used at present. SvnAnt? is an ant task that provides an interface to Subversion revision control system and encapsulates the svn client. It uses javahl - a native (JNI) java interface for the subversion api if it can find the corresponding library. javahl is platform-dependent.

    Because of needing interaction with the server(服務(wù)器在國(guó)外,更新很慢), now I employ the first solution. But I found a flaw of this method when i was going off duty. Generally, we may update our project with svn before committing. This may make a mismatch with svn revision between remote server and local file. Svn revision in local file is usually updated when we update our project. But when we take a commit after update, the svn revision in the remote server will change to a new one.

    So, the case is that if we update, commit, and then build, we may get a mismatch with the newest svn revision, and build the error revision into our ROOT.war. If we update , then build ,without commit, we can get right revision info.

    下面是第一版實(shí)現(xiàn):
        <!--  retrieve the svn revision from the remote repository
        <path id="svnant.lib" >
            <fileset dir="${lib.dir}">
                <include name="svnant.jar"/>
                <include name="svnClientAdapter.jar"/>
                <include name="svnjavahl.jar"/>
            </fileset>
        </path>
       
        <taskdef name="svn" classpathref="svnant.lib" classname="org.tigris.subversion.svnant.SvnTask" />
       
        <target name="get-svn-revision">
            <svn username="*******" password="******" javahl="true">
                    <status urlProperty="https://example.com" path="." revisionProperty="svn.revision" />
            </svn>
            <echo>svn revision: ${svn.revision}</echo>
        </target>   
        -->
       
        <!--  retrieve the svn revision from local file(.svn/entries). The file may contain several  'wc-entries.entry.revision' elements.
        The property will get several values seperated by ',' when using xmlproperty task.  Then the svn revison expected will be the
        max one of these property values.
         -->
        <property name="svn.revision.file" value=".svn/entries" />
        <!-- This property is used to run xmlproperty task successfully with a low version of svn client (under 1.3.1). Don't  sure whether it really makes sense -->
        <property name="build.id" value="foo" />
        <target name="get-svn-revision">
            <xmlproperty file="${svn.revision.file}" collapseAttributes="true"/>
            <echo>svn revision: ${wc-entries.entry.revision}</echo>
        </target>

        <!--
            If the file doesn't contain any 'wc-entries.entry.revision' element, the content of the property file will be: revision = ${wc-entries.entry.revision};
            If contain a 'wc-entries.entry.revision' element, mark this value as $revision_value, then  the content will be: revision = $revision_value;
            If contain several 'wc-entries.entry.revision' elements, mark these values as $value1, $value2, ..., respectively, then the content will be: revision = $value1,$value2,..., seperated by a ',';
        -->
        <property name="svn.revision.propertyfile" value="${build.dir}/revision.properties" />
        <target name="write-svn-revision-to-file" depends="get-svn-revision">
            <delete file="${svn.revision.propertyfile}"/>
            <propertyfile file="${svn.revision.propertyfile}" comment="record svn revision">
                <entry  key="revision" value="${wc-entries.entry.revision}"/>
            </propertyfile>
        </target>

    結(jié)果write-svn-revision-to-file這個(gè)在我這倒是可以獲取本地的svn revision,但是遠(yuǎn)方的同事可急了,build老失敗,只好把這部分build注釋了,還好,到周末了,可以在家好好研究一下,很快找了一個(gè)新的工具:
    It's my fault. In my version of svn, the entries file is xml formatted. So i parse it using ant task - 'xmlproperty'. Now i have fix this problem by using 'svnkit' tools, a pure java svn toolkit. Now there are two ways to retrieve svn revision. One is from remote repository server. For this one, before building, you should set your own username and password for the remote repository server('remote.repository.username' and 'remote.repository.password' properties in build.xml,respectively). Another one is retrieving revision from local working copy. If using this one, you should set 'local.repository' property in build.xml to your own directory.
    利用svnkit,從服務(wù)器上獲取revision大概是:
                repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded(urlStr));
                ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password);
                repository.setAuthenticationManager(authManager);
                headRevision = repository.getLatestRevision();
    從本地working copy獲取revision:
                SVNClientManager clientManager = SVNClientManager.newInstance();
                SVNWCClient wcClient = clientManager.getWCClient();   
                SVNInfo info = wcClient.doInfo(new File(fileUrl), SVNRevision.WORKING);
                headRevision = info.getRevision().getNumber(); 

    利用ant task將獲取的revision寫入到一個(gè)配置文件中(如revision.properties),在tomcat啟動(dòng)的時(shí)候加載進(jìn)來(lái),就可以了。   

    posted @ 2008-04-28 15:43 honzeland 閱讀(2180) | 評(píng)論 (2)編輯 收藏

    主站蜘蛛池模板: 亚洲乱妇熟女爽到高潮的片| 国产精品亚洲专区无码不卡| 污视频网站免费在线观看| 国产精品网站在线观看免费传媒| 野花高清在线电影观看免费视频 | 亚洲av日韩av永久在线观看| 久久最新免费视频| 成年女人免费视频播放体验区| 久久国产成人亚洲精品影院| 中文字幕 亚洲 有码 在线| 一级人做人爰a全过程免费视频| 精品熟女少妇av免费久久| 四只虎免费永久观看| 久久亚洲日韩看片无码| 男女污污污超污视频免费在线看| 亚洲免费在线观看视频| 久久久青草青青国产亚洲免观| wwwxxx亚洲| 日本免费中文字幕| 国产一区二区视频免费| 亚洲精品福利网泷泽萝拉| 理论片在线观看免费| 在线看免费观看AV深夜影院| 亚洲日本va中文字幕久久| 亚洲AV无码男人的天堂| 亚洲精品在线免费观看视频| 亚洲熟妇av一区二区三区| 亚洲AV无码一区二区一二区| 50岁老女人的毛片免费观看| 亚洲日本一区二区三区在线| 国产偷国产偷亚洲高清在线 | 区三区激情福利综合中文字幕在线一区亚洲视频1 | 亚洲成AⅤ人影院在线观看| 亚洲免费在线观看视频| 在线观看免费无码专区| 亚洲福利视频一区二区| 亚洲国产欧美国产综合一区| 免费看片在线观看| 亚洲AV无码日韩AV无码导航| 无码免费又爽又高潮喷水的视频| 毛片a级三毛片免费播放|