stone2083

          #

          關(guān)于cookie特殊字符的一點(diǎn)理解

          背景:
          加密的cookie信息中帶有特殊字符(“=”),導(dǎo)致讀cookie的時(shí)候,特殊符號(hào)丟失,解密失敗

          看了同事“關(guān)于cookie特殊字符”的說(shuō)明郵件,和網(wǎng)上對(duì)cookie特殊字符問題的解釋:

          我們?cè)趯?shí)際使用Cookie過程中要注意一些問題:

            1. Cookie的兼容性問題

            Cookie的格式有2個(gè)不同的版本,第一個(gè)版本,我們稱為Cookie Version 0,是最初由Netscape公司制定的,也被幾乎所有的瀏覽器支持。而較新的版本,Cookie Version 1,則是根據(jù)RFC 2109文檔制定的。為了確保兼容性,JAVA規(guī)定,前面所提到的涉及Cookie的操作都是針對(duì)舊版本的Cookie進(jìn)行的。而新版本的Cookie目前還不被Javax.servlet.http.Cookie包所支持。

            2. Cookie的內(nèi)容

            同樣的Cookie的內(nèi)容的字符限制針對(duì)不同的Cookie版本也有不同。在Cookie Version 0中,某些特殊的字符,例如:空格,方括號(hào),圓括號(hào),等于號(hào)(=),逗號(hào),雙引號(hào),斜杠,問號(hào),@符號(hào),冒號(hào),分號(hào)都不能作為Cookie的內(nèi)容。這也就是為什么我們?cè)诶又性O(shè)定Cookie的內(nèi)容為“Test_Content”的原因。

            雖然在Cookie Version 1規(guī)定中放寬了限制,可以使用這些字符,但是考慮到新版本的Cookie規(guī)范目前仍然沒有為所有的瀏覽器所支持,因而為保險(xiǎn)起見,我們應(yīng)該在Cookie的內(nèi)容中盡量避免使用這些字符。

          摘自:http://swingchen.bokee.com/6200015.html
          類似這樣的解釋,搜索出來(lái)的結(jié)果,挺多。

          但是,我去看了RFC2109(http://www.faqs.org/rfcs/rfc2109.html),其說(shuō)明如下:

          value中的token,是有一組非特殊字符,非空白字符。而它是在RFC 2068(http://www.faqs.org/rfcs/rfc2068.html)中制定的 (是對(duì)Header的規(guī)范),請(qǐng)看:


          也就是說(shuō),所謂的Cookie1,同樣有特殊字符的限制。
          同樣,在Cookie2(RFC2965)中,也如此。

          想想也是啊,如果沒有特殊字符的限制,解析Header的時(shí)候,還不亂套了?

          看了RFC之后,我們?cè)賮?lái)看看Tomcat中的實(shí)現(xiàn)(6.0.29版本),請(qǐng)看:
          org.apache.tomcat.util.http.Cookies

          1.類注釋:
          A collection of cookies - reusable and tuned for server side performance.
          Based on RFC2965 ( and 2109 )
          是基于RFC2965/RFC2109規(guī)范來(lái)實(shí)現(xiàn)的

          2.特殊字符的定義
          /*
              List of Separator Characters (see isSeparator())
              Excluding the '/' char violates the RFC, but 
              it looks like a lot of people put '/'
              in unquoted values: '/': ; //47 
              '\t':9 ' ':32 '\"':34 '(':40 ')':41 ',':44 ':':58 ';':59 '<':60 
              '=':61 '>':62 '?':63 '@':64 '[':91 '\\':92 ']':93 '{':123 '}':125
              
          */
              
          public static final char SEPARATORS[] = { '\t'' ''\"''('')'','
                  
          ':'';''<''=''>''?''@''[''\\'']''{''}' };
          根據(jù)規(guī)范,定義了特殊字符。除了“/”這個(gè)符號(hào)。因?yàn)榇蠖鄶?shù)人會(huì)直接使用“/”。

          3.針對(duì)“=”特殊處理
          /**
           * If true, cookie values are allowed to contain an equals character without
           * being quoted.
           
          */
          public static final boolean ALLOW_EQUALS_IN_VALUE;

          static {
              ALLOW_EQUALS_IN_VALUE 
          = Boolean.valueOf(System.getProperty(
                      
          "org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUALS_IN_VALUE",
                      
          "false")).booleanValue();
          }
          可以在catalina.properties中,添加這個(gè)配置項(xiàng) (或者啟動(dòng)過程中加上-D參數(shù)),使得cookie value中允許存在“=”符號(hào)。
          所以本文開頭提到的問題,可以使用這個(gè)方法得到解決

          4.解析過程
          /**
           * Parses a cookie header after the initial "Cookie:"
           * [WS][$]token[WS]=[WS](token|QV)[;|,]
           * RFC 2965
           * JVK
           
          */
          public final void processCookieHeader(byte bytes[], int off, int len){
              
          //詳細(xì)代碼,省略
          }


          備注:
          RFC沒有仔細(xì)看(時(shí)間有限,并且看E文挺累的),如理解有誤,請(qǐng)告知。


          posted @ 2010-11-03 13:27 stone2083 閱讀(7215) | 評(píng)論 (1)編輯 收藏

          爬取交通違章信息的腳本

               摘要: 會(huì)開車了,也慢慢不規(guī)矩起來(lái)了,于是乎,違章信息也慢慢多起來(lái)了,但是無(wú)法第一時(shí)間通知到自己。 雖說(shuō),有個(gè)網(wǎng)站:http://www.hzti.com/service/qry/violation_veh.aspx?pgid=&type=1&node=249 可以查詢非現(xiàn)場(chǎng)違章情況, 不過: 1.我是懶人,主動(dòng)去查詢的時(shí)候不太樂意做 2.車輛識(shí)別碼,永遠(yuǎn)記不住 3.每次輸驗(yàn)證...  閱讀全文

          posted @ 2010-10-29 18:30 stone2083 閱讀(3138) | 評(píng)論 (8)編輯 收藏

          關(guān)于java多線程的幾個(gè)小貼士

          原文地址:
          http://weblogs.java.net/blog/caroljmcdonald/archive/2009/09/17/some-java-concurrency-tips

          大綱:

          Prefer immutable objects/data
          盡可能使用不變對(duì)象/數(shù)據(jù)

          Threading risks for Web applications
          注意web應(yīng)用的線程安全問題

          Hold Locks for as short a time as possible
          持有鎖的時(shí)間盡可能短

          Prefer executors and tasks to threads
          盡可能使用JDK并發(fā)工具包提供的Executor框架,進(jìn)行多線程操作

          Prefer Concurrency utilities to wait and notify
          盡可能使用JDK并發(fā)工具包提供的工具進(jìn)行同步(等待和通知)

          • Concurrent Collections
            • ConcurrentMap
            • ConcurrentHashMap
            • COncurrentLinkedQueue
            • CopyOnWriteArrayList
          • BlockingQueue Implementations
            • ArrayBlockingQueue
            • LinkedBlockingQueue
            • PriorityBlockingQueue

          Producer Consumer Pattern
          了解生產(chǎn)者消費(fèi)者模式

          Synchronizers
          同步器

          • Semaphore
          • CountDownLatch
          • CyclicBarrier
          • Exchanger

          Multithreaded Lazy Initialization is tricky
          多線程環(huán)境下,lazy init是一件棘手的事情

          Prefer Normal initialization
          盡可能使用正常的初始化(盡可能不要使用lazy init)


          posted @ 2010-09-15 17:37 stone2083 閱讀(1928) | 評(píng)論 (2)編輯 收藏

          java反射效率

               摘要: java反射效率到底如何,花了點(diǎn)時(shí)間,做了一個(gè)簡(jiǎn)單的測(cè)試.供大家參考. 測(cè)試背景: 1. 測(cè)試簡(jiǎn)單Bean(int,Integer,String)的set方法 2. loop 1億次 3. 測(cè)試代碼盡可能避免對(duì)象的創(chuàng)建,復(fù)發(fā)方法的調(diào)用,僅僅測(cè)試set方法的耗時(shí) 測(cè)試結(jié)果:  場(chǎng)景 &...  閱讀全文

          posted @ 2010-09-15 14:04 stone2083 閱讀(8032) | 評(píng)論 (9)編輯 收藏

          IBatis下DAO單元測(cè)試另類思路

          在說(shuō)另類思路之前,先說(shuō)下傳統(tǒng)的測(cè)試方法:
          0.準(zhǔn)備一個(gè)干凈的測(cè)試數(shù)據(jù)庫(kù)環(huán)境
            這個(gè)是前提
          1.測(cè)試數(shù)據(jù)準(zhǔn)備
            使用文本,excel,或者wiki等,準(zhǔn)備測(cè)試sql以及測(cè)試數(shù)據(jù)
            利用dbfit,dbutil等工具將準(zhǔn)備的測(cè)試數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫(kù)中
          2.執(zhí)行dao方法
            執(zhí)行被測(cè)試的dao方法
          3.測(cè)試結(jié)果斷言
            利用dbfit,dbutil等工具,斷言測(cè)試結(jié)果數(shù)據(jù)和預(yù)計(jì)是否一致
          4.所有數(shù)據(jù)回滾

          其實(shí),對(duì)于這個(gè)流程來(lái)說(shuō),目前的dao測(cè)試框架,支持的已經(jīng)比較完美了
          但是此類測(cè)試方法,也有明顯的缺點(diǎn)(或者不能叫缺點(diǎn),叫使用比較麻煩的地方)
          如下:
          1.背上了一個(gè)數(shù)據(jù)庫(kù)環(huán)境.
            不輕量
            這是一個(gè)共享環(huán)境,誰(shuí)也無(wú)法確保環(huán)境數(shù)據(jù)是否真正的干凈
          2.測(cè)試數(shù)據(jù)準(zhǔn)備是一件麻煩的事情
            新表,10幾個(gè)字段毫不為奇;老表,50幾個(gè)字段甚至百來(lái)個(gè)字段,也偶有可見;無(wú)論是使用文本,excel,wiki,準(zhǔn)備工作量,都是巨大的.
            準(zhǔn)備的數(shù)據(jù),部分字段內(nèi)容可以是無(wú)意義的,部分字段內(nèi)容又是需要符合測(cè)試意圖(testcase設(shè)計(jì)目的),部分字段還是其他表的關(guān)聯(lián)字段.從而導(dǎo)致后續(xù)維護(hù)人員無(wú)法了解準(zhǔn)備數(shù)據(jù)意圖.
            (實(shí)踐中,也出現(xiàn)過,一同事在維護(hù)他人單元測(cè)試時(shí),由于無(wú)法了解測(cè)試數(shù)據(jù)準(zhǔn)備意圖,寧可重新刪除,自己準(zhǔn)備一份)
          3.預(yù)計(jì)結(jié)果數(shù)據(jù)準(zhǔn)備也是一件麻煩的事情
            理由如上

          所以,理論上是完美的測(cè)試方案,在實(shí)踐過程中,卻是一件麻煩的事情.導(dǎo)致DAO單元測(cè)試維護(hù)困難.


          分析了現(xiàn)狀,我們?cè)賮?lái)分析下,IBatis下DAO,程序員主要做了哪些編碼:
          1. 寫了一份sqlmap.xml配置文件
          2. 通過getSqlMapClientTemplate.doSomething($sqlID,$param), 執(zhí)行語(yǔ)句
          (當(dāng)然,沒有使用spring的同學(xué),也是使用了類似sqlMapClient.doSomething($sqlID,$param)方法)

          而步驟2其實(shí)是框架替我們做了的事情,按照MOCK的思想,其實(shí)這部分代碼可以被MOCK的,那么我們是否可以做如下假設(shè):
          只要sqlmap.xml中配置信息(主要包括resultmap和statement)是正確的,那么執(zhí)行結(jié)果也應(yīng)該是正確的.

          而我所謂的另類思路,就是基于這個(gè)假設(shè),得出的:
          IBatis下,DAO單元測(cè)試,我們拋棄背負(fù)的數(shù)據(jù)庫(kù)環(huán)境,只要根據(jù)不同的條件,斷言不同的sql即可.

          于是乎,封裝了一個(gè)IbatisSqlTester,可以根據(jù)sqlmap中的statement和傳入的條件參數(shù),生成sql語(yǔ)句.
          那么,DAO單元測(cè)試就簡(jiǎn)單了,脫離下數(shù)據(jù)庫(kù)環(huán)境:
          public class ScoreDAOTest extends TestCase {
           
              @SpringBeanByName
              
          private IbatisSqlTester ibatisSqlTester;  //通過spring配置,需要注入sqlmapclient對(duì)象
           
              @Test
              
          public void testListTpScores() {
                  Map
          <String, Object> param = new HashMap<String, Object>(1);
                  param.put(
          "memberIds"new String[] { "stone""stone2083" });
                  SqlStatement sql 
          = ibatisSqlTester.test("MS-LIST-SCORES", param);
                  
          // sql全部匹配
                  SqlAssert.isEqual("select * from score where member_id in ('stone','stone2083')", sql.toString());
                  
          // sql包含member_id,athena2002,stone關(guān)鍵詞
                  SqlAssert.keyWith(sql.toString(), "member_id""stone""stone2083");
                  
          // sql符合某個(gè) 正則
                  SqlAssert.regexWith(".* where member_id in .*", sql.toString());
                  
                  
          //其中,SqlAssert也可以換 成want.string()中的方法.
              }
          }

          優(yōu)勢(shì):
            脫離了數(shù)據(jù)庫(kù)環(huán)境
            脫離了表結(jié)構(gòu)數(shù)據(jù)準(zhǔn)備
            脫離了預(yù)計(jì)結(jié)果數(shù)據(jù)準(zhǔn)備
            讓單元測(cè)試變成sql的斷言,編寫相對(duì)更簡(jiǎn)單
          缺點(diǎn):
           
          row mapper過程無(wú)法被測(cè)試


          最后,附上兩個(gè)核心的代碼類(還未完成),供大家參考:
          SqlStatement.java
          /**
           * <pre>
           * SqlStatement:Sql語(yǔ)句對(duì)象.
           * 包含:
           *  1.sql語(yǔ)句,類似  select * from offer where id = ? and member_id = ?
           *  2.參數(shù)值,類似 [1,stone2083]
           *  
           *  toString方法,返回執(zhí)行的sql語(yǔ)句,如:
           *  select * from offer where id = '1' and member_id = 'stone2083'
           * </pre>
           * 
           * 
          @author Stone.J 2010-8-9 下午02:55:36
           
          */
          public class SqlStatement {

              
          //sql
              private String   sql;
              
          //sql參數(shù)
              private Object[] param;

              
          /**
               * <pre>
               * 輸出最終執(zhí)行的sql內(nèi)容.
               * 將sql和param進(jìn)行merge,產(chǎn)生最終執(zhí)行的sql語(yǔ)句
               * </pre>
               
          */
              @Override
              
          public String toString() {
                  
          return merge();
              }

              
          /**
               * <pre>
               * 將sql進(jìn)行格式化.
               * 
               * 目前只是簡(jiǎn)單進(jìn)行格式化.去除前后空格,已經(jīng)重復(fù)空格
               * TODO:請(qǐng)使用統(tǒng)一格式化標(biāo)準(zhǔn)規(guī),建議使用SqlFormater類,進(jìn)行處理
               * </pre>
               * 
               * 
          @param sql
               * 
          @return
               
          */
              
          protected String format(String sql) {
                  
          if (sql == null) {
                      
          return null;
                  }
                  
          return sql.toLowerCase().trim().replaceAll("\\s{1,}"" ");
              }

              
          /**
               * <pre>
               * 將sql和param進(jìn)行merge.
               * TODO:請(qǐng)嚴(yán)格按照SQL標(biāo)準(zhǔn),進(jìn)行merge sql內(nèi)容
               * </pre>
               
          */
              
          protected String merge() {
                  
          if (param == null || param.length == 0) {
                      
          return this.sql;
                  }
                  String ret 
          = sql;
                  
          for (Object p : param) {
                      ret 
          = ret.replaceFirst("\\?""'" + p.toString() + "'");
                  }
                  
          return ret;
              }

              
          public String getSql() {
                  
          return sql;
              }

              
          public void setSql(String sql) {
                  
          this.sql = format(sql);
              }

              
          public Object[] getParam() {
                  
          return param;
              }

              
          public void setParam(Object[] param) {
                  
          this.param = param;
              }
          }

          IbatisSqlTester.java
          /**
           * <pre>
           * IBtatis SQL 測(cè)試
           * 一般IBatis DAO單元測(cè)試,主要就是在測(cè)試ibatis的配置文件.
           * IbatisSqlTester將根據(jù)提供的Sql Map Id 和 對(duì)應(yīng)的參數(shù),返回 {
          @link SqlStatement}對(duì)象,提供最終執(zhí)行的sql語(yǔ)句
           * 通過外部SqlAssert對(duì)象,將預(yù)計(jì)Sql和實(shí)際產(chǎn)生的Sql進(jìn)行對(duì)比,判斷是否正確
           * </pre>
           * 
           * 
          @author Stone.J 2010-8-9 下午02:58:46
           
          */
          public class IbatisSqlTester {

              
          // sqlMapClient
              private ExtendedSqlMapClient sqlMapClient;

              
          /**
               * 根據(jù)提供的SqlMap ID,得到 {
          @link SqlStatement}對(duì)象
               * 
               * 
          @param sqlId: sql map id
               * 
          @return @see {@link SqlStatement}
               
          */
              
          public SqlStatement test(String sqlId) {
                  
          //得到MappedStatement對(duì)象
                  MappedStatement ms = sqlMapClient.getMappedStatement(sqlId);
                  
          if (ms == null) {
                      
          //TODO:建議封轉(zhuǎn)自己的異常對(duì)象
                      throw new RuntimeException("can't find MappedStatement.");
                  }

                  
          //按照Ibatis代碼,得到Sql和Param信息
                  RequestScope request = new RequestScope();
                  ms.initRequest(request);
                  Sql sql 
          = ms.getSql();
                  String sqlValue 
          = sql.getSql(request, null);

                  
          //組轉(zhuǎn)返回對(duì)象
                  SqlStatement ret = new SqlStatement();
                  ret.setSql(sqlValue);
                  
          return ret;
              }

              
          /**
               * 根據(jù)提供的SqlMap ID和對(duì)應(yīng)的param信息,得到 {
          @link SqlStatement}對(duì)象
               * 
               * 
          @param sqlId: sql map id
               * 
          @param param: 參數(shù)內(nèi)容
               * 
          @return @see {@link SqlStatement}
               
          */
              
          public SqlStatement test(String sqlId, Object param) {
                  
          //得到MappedStatement對(duì)象
                  MappedStatement ms = sqlMapClient.getMappedStatement(sqlId);
                  
          if (ms == null) {
                      
          //TODO:建議封轉(zhuǎn)自己的異常對(duì)象
                      throw new RuntimeException("can't find MappedStatement.");
                  }

                  
          //按照Ibatis代碼,得到Sql和Param信息
                  RequestScope request = new RequestScope();
                  ms.initRequest(request);
                  Sql sql 
          = ms.getSql();
                  String sqlValue 
          = sql.getSql(request, param);
                  Object[] sqlParam 
          = sql.getParameterMap(request, param).getParameterObjectValues(request, param);

                  
          //組轉(zhuǎn)返回對(duì)象
                  SqlStatement ret = new SqlStatement();
                  ret.setSql(sqlValue);
                  ret.setParam(sqlParam);
                  
          return ret;
              }

              
          /**
               * 設(shè)置SqlMapClient對(duì)象
               
          */
              
          public void setSqlMapClient(ExtendedSqlMapClient sqlMapClient) {
                  
          this.sqlMapClient = sqlMapClient;
              }

              
          /**
               * <pre>
               * 不推薦使用
               * 推薦使用: {
          @link IbatisSqlTester#setSqlMapClient(ExtendedSqlMapClient)}
               * TODO:請(qǐng)去除這個(gè)方法,或者增加初始化的方式
               * </pre>
               * 
               * 
          @param sqlMapConfig sqlMapConfig xml文件
               
          */
              
          public void setSqlMapConfig(String sqlMapConfig) {
                  InputStream in 
          = null;
                  
          try {
                      File file 
          = ResourceUtils.getFile(sqlMapConfig);
                      in 
          = new FileInputStream(file);
                      
          this.sqlMapClient = (ExtendedSqlMapClient) SqlMapClientBuilder.buildSqlMapClient(in);
                  } 
          catch (Exception e) {
                      
          throw new RuntimeException("sqlMapConfig init error.", e);
                  } 
          finally {
                      
          if (in != null) {
                          
          try {
                              in.close();
                          } 
          catch (IOException e) {
                          }
                      }
                  }
              }

          }


          最后的最后附上所有代碼(通過單元測(cè)試代碼,可以看如何使用).歡迎大家的討論.
          sqltester
          builder

          posted @ 2010-08-12 09:03 stone2083 閱讀(3536) | 評(píng)論 (9)編輯 收藏

          掃描classpath下類資源

          很早之前,為了簡(jiǎn)化配置信息,自己寫了一坨代碼,基于classpath掃描類信息,加載.
          其實(shí),在spring中,已經(jīng)提供了類似組件(后知后覺了...):

          org.springframework.core.io.support.PathMatchingResourcePatternResolver  資源解析器(基于路徑的正則表達(dá)式)
          org.springframework.core.type.classreading.MetadataReader ClassMeta信息解讀器

          于是乎,代碼就非常簡(jiǎn)單了:
           1 public class Test {
           2 
           3     /* 資源路徑 */
           4     private static final String                  PATH           = "classpath*:com/alibaba/javalab/t*/**/*.class";
           5     /* 資源解析器 */
           6     private static final ResourcePatternResolver RESOLVER       = new PathMatchingResourcePatternResolver();
           7     /* Meta信息Reader Factory.用于創(chuàng)建MetaReader */
           8     private static final MetadataReaderFactory   READER_FACTORY = new SimpleMetadataReaderFactory();
           9 
          10     public static void main(String[] args) throws Exception {
          11         //根據(jù)正則表達(dá)式,得到資源列表
          12         Resource[] resources = RESOLVER.getResources(PATH);
          13         for (Resource res : resources) {
          14             //通過 MetadataReader得到ClassMeta信息,打印類名
          15             MetadataReader meta = READER_FACTORY.getMetadataReader(res);
          16             System.out.println(meta.getClassMetadata().getClassName());
          17         }
          18     }
          19 }

          輸出結(jié)果:
          com.alibaba.javalab.tool.fetion.protocol.Config
          com.alibaba.javalab.tool.fetion.protocol.Fetion
          com.alibaba.javalab.tool.fetion.protocol.FetionHelper
          com.alibaba.javalab.tool.fetion.protocol.LoginSession
          com.alibaba.javalab.tool.trace.TimeTrace
          ...

          挺好使的一個(gè)工具 :)


          posted @ 2010-07-23 14:55 stone2083 閱讀(1193) | 評(píng)論 (0)編輯 收藏

          初識(shí)InheritableThreadLocal

          一直來(lái)只知道ThreadLocal,直到最近看slf4j MDC實(shí)現(xiàn)代碼的時(shí)候,才認(rèn)識(shí)了InheritableThreadLocal.
          InheritableThreadLocal顧名思義,可繼承的ThreadLocal.
          看類描述:
          This class extends <tt>ThreadLocal</tt> to provide inheritance of values
           * from parent thread to child thread: when a child thread is created, the
           * child receives initial values for all inheritable thread-local variables
           * for which the parent has values.

          測(cè)試代碼:
           1 public class Test {
           2 
           3     public static void main(String[] args) {
           4         //使用ThreadLocal,父子線程之間,不共享Value
           5         final ThreadLocal<String> tl = new ThreadLocal<String>();
           6         tl.set("ThreadLocal-VAL");
           7         System.out.println("Main-1:" + tl.get());
           8         new Thread() {
           9             public void run() {
          10                 System.out.println("Child-1:" + tl.get());
          11             };
          12         }.start();
          13 
          14         //使用InheritableThreadLocal,父線程Value可讓子線程共享
          15         final ThreadLocal<String> itl = new InheritableThreadLocal<String>();
          16         itl.set("InheritableThreadLocal-VAL");
          17         System.out.println("Main-2:" + itl.get());
          18         new Thread() {
          19             public void run() {
          20                 System.out.println("Child-2:" + itl.get());
          21             };
          22         }.start();
          23 
          24     }
          25 }

          輸出內(nèi)容:
          Main-1:ThreadLocal-VAL
          Main-2:InheritableThreadLocal-VAL
          Child-1:null
          Child-2:InheritableThreadLocal-VAL


          ......分隔符號(hào)......

          順帶著簡(jiǎn)單說(shuō)下MDC.(Mapped Diagnostic Context). 中文直譯太惡心了,我理解的意思是,和環(huán)境相關(guān)的上下文信息.
          比如在web應(yīng)用中,我們可以把用戶的ip,訪問url等放入到這個(gè)上下文中,log打印的時(shí)候,就能得到這個(gè)信息.

          在slf4j BasicMDCAdapter實(shí)現(xiàn)中,就是用了InheritableThreadLocal
          1 public class BasicMDCAdapter implements MDCAdapter {
          2 
          3   private InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal();
          4   
          5   //.
          6 
          7 }

          posted @ 2010-07-23 09:17 stone2083 閱讀(2592) | 評(píng)論 (0)編輯 收藏

          小談PropertyPlaceholderConfigurer

          背景:讓應(yīng)用在一個(gè)環(huán)境下,以多實(shí)例的方法運(yùn)行.
          Log問題,可以通過Log4j占位符實(shí)現(xiàn)(見前文:http://www.aygfsteel.com/stone2083/archive/2010/07/01/324935.html)
          其他Java組件代碼依賴了本地環(huán)境資源,怎么解決呢?

          對(duì)于使用Spring的組件來(lái)說(shuō),PropertyPlaceholderConfigurer能幫我們解決這一問題.

          PropertyPlaceholderConfigurer除了支持配置的properties文件外,還支持系統(tǒng)屬性(System.getProperties()).當(dāng)然,它有三種模式:
           1/** Never check system properties. */
           2public static final int SYSTEM_PROPERTIES_MODE_NEVER = 0;
           3 
           4/**
           5 * Check system properties if not resolvable in the specified properties.
           6 * This is the default.
           7 */
           8public static final int SYSTEM_PROPERTIES_MODE_FALLBACK = 1;
           9 
          10/**
          11 * Check system properties first, before trying the specified properties.
          12 * This allows system properties to override any other property source.
          13 */
          14public static final int SYSTEM_PROPERTIES_MODE_OVERRIDE = 2;

          對(duì)于使用本地環(huán)境資源的bean來(lái)說(shuō),只要配置:
           1 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
           2     <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
           3     <property name="locations">
           4         <list>
           5             <value>classpath*:spring/env.properties</value> <!--無(wú)需配置node-->
           6         </list>
           7     </property>
           8 </bean>
           9 
          10 <bean id="javaBean" class="com.alibaba.javalab.spring.JavaBean">
          11      <property name="lockFile" value="/home/stone/base/${node}/lock" />
          12 </bean>


          在啟動(dòng)腳本中,只要加入-Dnode=instanceX即可.

          總結(jié):
          PropertyPlaceholderConfigurer支持properties文件和系統(tǒng)屬性.并且存在三種覆蓋策略.

          posted @ 2010-07-23 08:51 stone2083 閱讀(1281) | 評(píng)論 (0)編輯 收藏

          新人破冰問題(挺搞笑,挺惡毒)

          轉(zhuǎn)自:http://blog.renren.com/blog/226112318/452978694


          1. 初次訪問發(fā)生在幾點(diǎn)幾分?
          2. 完全打開首頁(yè)花費(fèi)多少時(shí)間?
          3. 是否瀏覽完整個(gè)首頁(yè)后再去找login入口?
          4. 找login入口花了多少時(shí)間?
          5. 是否在服務(wù)器提示下找到入口?
          6. 在找到真正login頁(yè)面之前,是否誤入后臺(tái)login頁(yè)面?
          7. 是否使用XX助手找到入口?
          8. 輸錯(cuò)了幾次密碼后成功登陸?
          9. 在第一次成功登陸的時(shí)候,是否使用https(安全連接)?
          10. 登陸之前購(gòu)買了多少份https證書?
          11. 是否由于服務(wù)器帶寬太小導(dǎo)致登入很慢?
          12. 登陸成功后服務(wù)器是否發(fā)出提示音?
          13. 登陸之后產(chǎn)生了多少PV才最終下單?
          14. 服務(wù)器是否在初次下單后給出紅色回執(zhí)?
          15. 下單之后留在處于登陸狀態(tài)幾分鐘才離開?
          16. 整個(gè)訪問過程一共產(chǎn)生了幾個(gè)session?
          17. 平均session時(shí)長(zhǎng)是幾分鐘?
          18. 當(dāng)日訪問的cookie類型是cookie2.2還是3.1?
          19. 當(dāng)日一共下了多少單?
          20. 在之后的30日內(nèi)的活躍度類型(5次-18次屬于中度活躍度)


          實(shí)踐經(jīng)驗(yàn):
          1. 對(duì)于封閉式題目(回答是與否),比較沒勁:問問題的人描述了半天,回答者只回答一個(gè)是否者否.對(duì)于此類問題,要做改進(jìn)
          2. 有些問題,都不好意思問出口
          3. 千萬(wàn)要根據(jù)新人的性格,決定是否是否這套模板,切忌切忌

          posted @ 2010-07-23 08:32 stone2083 閱讀(8677) | 評(píng)論 (0)編輯 收藏

          Java Exception性能問題

               摘要: 背景: 大學(xué)里學(xué)java,老師口口聲聲,言之鑿鑿,告誡我們,Java千萬(wàn)別用異??刂茦I(yè)務(wù)流程,只有系統(tǒng)級(jí)別的問題,才能使用異常; (當(dāng)時(shí),我們都不懂為什么不能用異常,只知道老師這么說(shuō),我們就這么做,考試才不會(huì)錯(cuò) :) ) 公司里,有兩派.異常擁護(hù)者說(shuō),使用業(yè)務(wù)異常,代碼邏輯更清晰,更OOP;反之者說(shuō),使用異常,性能非常糟糕; (當(dāng)然,我是擁護(hù)者) 論壇上,爭(zhēng)論得更多,仁者見仁智者見智,口...  閱讀全文

          posted @ 2010-07-09 14:30 stone2083 閱讀(13759) | 評(píng)論 (16)編輯 收藏

          僅列出標(biāo)題
          共10頁(yè): 上一頁(yè) 1 2 3 4 5 6 7 8 9 下一頁(yè) Last 
          主站蜘蛛池模板: 江川县| 赣州市| 吴忠市| 密云县| 肇东市| 柞水县| 平阳县| 封开县| 玛曲县| 屯门区| 玛纳斯县| 广水市| 来宾市| 黎平县| 鲜城| 祥云县| 电白县| 临江市| 塔城市| 射洪县| 海盐县| 榆中县| 和平县| 喀喇沁旗| 东港市| 田阳县| 清苑县| 湖南省| 湟中县| 嘉祥县| 宜兰县| 繁昌县| 阳江市| 富蕴县| 海城市| 靖边县| 通榆县| 浮梁县| 溧水县| 尼勒克县| 昂仁县|