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

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

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

    konhon

    忘掉過去,展望未來。找回自我,超越自我。
    逃避不一定躲的過, 面對不一定最難過, 孤單不一定不快樂, 得到不一定能長久, 失去不一定不再擁有, 可能因為某個理由而傷心難過, 但我卻能找個理由讓自己快樂.

    Google

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      203 Posts :: 0 Stories :: 61 Comments :: 0 Trackbacks

    #

    很多人 特別是新手 做j2ee 項目中
    總能受困于 這樣或那樣的編碼問題

    這里討論下 新手學習,高手指教 一起研究下
    (以 tomcat mysql 做例子 我推薦所有的編碼采用utf-8)

    1 工程
    工程內所有的 .java .jsp .xml .txt 都有默認的編碼 默認的是系統環境的編碼
    我們中文系統通常是GBK 推薦都采用utf-8
    utf-8 的時候 你編譯 生成doc 可能會遇到亂碼(特別是采用ant 的時候,生成doc你幾乎100%會遇到)

    解決方法 以ant 為例子
    編譯 注意 encoding 參數
    <target name="build" >
    ? ? ? ?<mkdir dir="${build.dir}" />
    ? ? ? ?<javac encoding="utf-8" destdir="${build.dir}" target="1.3" debug="true" deprecation="false" optimize="false" failonerror="true">
    ? ? ? ? ? ?<src path="${src.dir}" />
    ? ? ? ? ? ?<classpath refid="master-classpath" />
    ? ? ? ?</javac>
    ? ?</target>

    生成doc 注意 encoding 和 charset
    <target name="doc">
    <mkdir dir="doc" />
    <javadoc charset="utf-8" encoding="utf-8" packagenames="${packages}" sourcepath="src" destdir="doc" author="true" version="true" use="true" splitindex="true" >
    <classpath refid="master-classpath" />
    </javadoc>
    </target>

    這里 的encoding 就是指的你 java 文件的編碼格式 javac 和javadoc 都有這個參數
    charset 指的是 生成 doc 后的編碼方式 javadoc 的參數

    2 數據庫
    mysql 的編碼最復雜 從4以后 mysql 號稱支持多編碼 它更靈活了 我們也更麻煩了
    mysql 有4個級別的編碼
    系統級
    庫級
    表級
    sql語句級
    請保持采用統一的編碼 推薦utf-8
    其它數據庫要簡單的多 一般都是一種編碼

    3 web server
    tomcat 為例
    tomcat server.xml 中一個參數
    <Connectorport="8080" maxHttpHeaderSize="8192"
    maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
    enableLookups="false" redirectPort="8443" acceptCount="100"
    connectionTimeout="20000" disableUploadTimeout="true" URIncoding="utf-8"/>
    經測試 這個URIncoding 參數主要是 get 方法中采用編碼

    4 jsp 顯示層
    第1條中說明了 jsp 文件本身的格式
    很多朋友采用eclipse +myeclipse 生成jsp
    它自動生成一個頭<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    不要誤解 這句話不能保證你在ie里看到的不是亂碼
    pageEncoding它的意思是 這個頁面本身采用的是 utf-8 (似乎只在eclipse 里有效果 ,我不確定)
    為了在ie 里不亂碼 ?你還得加一句 <%@ page contentType="text/html; charset=UTF-8"%>
    它不能在(myeclispe)自動生成 ?推薦修改 myeclipse的模板 在下邊的目錄里
    MyEclipse\eclipse\plugins\com.genuitec.eclipse.wizards_4.0.1\Templates
    里邊的jsp模版 你加上<%@ page contentType="text/html; charset=${encoding}"%>

    5 filter
    自從tomcat 4 以后 網上就流傳了一個SetCharacterEncodingFilter 過濾器 搜一下有很多
    很好用 web.xml 中加入
    <filter>
     <filter-name>Set Character Encoding</filter-name>
     <filter-class>filters.SetCharacterEncodingFilter</filter-class>
     <init-param>
     <param-name>encoding</param-name>
     <param-value>utf-8</param-value>
     </init-param>
    </filter>
     <filter-mapping>
     <filter-name>Set Character Encoding</filter-name>
     <url-pattern>/*</url-pattern>
     </filter-mapping>

    6 資源文件
    首先保證 文件本身是utf-8
    然后部署的時候用 native2ascii 轉換
    這里給出 ant 里的例子
    <native2ascii encoding="utf-8" dest="${web.dir}/WEB-INF/classes" src="${src.dir}" includes="**/*.properties" />

    總結
    到這里 你應該徹底解決了亂碼了 嘿嘿
    寫的有點亂 還請高手們多指點
    posted @ 2006-06-13 19:25 konhon 優華 閱讀(467) | 評論 (0)編輯 收藏

    重要區別:

    重音發在第二個音節時一般是動詞
    重音發在第一個音節時一般是名詞或形容詞


    Welcome to Daily Tips on Learning English. Today’s tip is on how syllable stress can affect the meaning of words.
    Remenber that stressed syllables are said louder and are lengthened, and unstressed syllables are pronounced more softly, and often have the vowel sounds reduced.
    Sometimes, this difference can be the difference between a verb and a noun, or an adjective.
    There are at least 14 pairs of words in which syllable stress alone makes this difference. Some examples include `addict, a`ddict, `convict, con`vict, `perfect, per`fect. Each time the second syllable is stressed, the word is a verb. When the first syllable is stressed, the word is either a noun or an adjective. Let’s look some examples more closely. `Permit, per`mit, a `permit is a noun, it is a piece of paper which authorizes you to do something. For instance, a fishing `permit allows you to go fishing. Per`mit is a verb. It means to allow. For instence, fishing isn’t per`mitted here without a `permit.
    Another example is `perfect, per`fect. `Perfect is an adjective. It means 100% correct, no mistakes or errors. The verb is per`fect, it means to make something perfect. For example, “I want to per`fect my English” means “I want to make my English perfect”. Make sure you stress the right syllable. It can be the differece between different parts of speech. This has been today’s daily tip. Till then, tomorrow, for another tip on learning English.

    posted @ 2006-06-05 18:53 konhon 優華 閱讀(408) | 評論 (0)編輯 收藏

    最重要區別:?
    發音時如果表示can 則把重音放在 can 後面的動詞上
    如果表示Can't則把重音入在Can't上.
    仔細看看下這面這段話.
    ?
    Welcome to Daily tips on Learning English. Today's tip is on distinguishing "can" and "cannot" in spoken American English.

    "Cannot" is usually contracted to "can't". So many learners of English assume that in order to distinguish between "can" and "can't", one must listen for the final "t" sound /t/. And when speaking, one must pronounce final 't' sound /t/ clearly. However, this is not in fact how native speakers distinguish "can" and "can't". People do not say 'I `can drive a car, but I can't drive a motorcycle.' People say 'I can `drive a car', but I `can't drive a motorcycle.' The difference between "can" and "can't" is in stress. "Can" is not stressed, the verb after it is. "Can't" is stressed. The verb after it is not.

    Also since 'can' is not stressed, the vowel is reduced to /a/, so "can" is actually pronounced "can". Listen to another example. "I `can't go on Saturday, but I can `go on Sunday." Did you hear the 't' sound? Did you notice the difference words being stressed? Listening again. "I `can't go on Saturday, but I can `go on Sunday." If you want to understand whether someone is saying he can or can't do something, you have to be listening for a stressed "can't" or a verb stressed after "can". What does this mean? "I can `speak Japanese, but I `can't speak Taiwanese." That's right, I can speak Japanese, but I cannot speak Taiwanese. When you are speaking it is very important that you follow this rule too. When learners of English say I `can help you, native speakers often unsure what is meant because of improper stress. So remember, you can stress "can't", but you `can't stress "can".

    This has been today's tip on learning English. Tune in tomorrow for another tip.

    posted @ 2006-06-05 01:15 konhon 優華 閱讀(3010) | 評論 (0)編輯 收藏

    Sun 官方的中文版 Java API 文檔發布了,地址為:http://gceclub.sun.com.cn/download/Java_Docs/html_zh_CN.zip, 下載后請參考如下步驟配合 eclipse3.1 使用

    1. 點擊菜單 <窗口> -?> <設定>
    2. 點擊左邊項目列表中的 <Java> ->? <已安裝的 JRE>
    3. 選中你已經安裝好的 JRE5.0 ,單擊右邊的編輯
    4. 點擊對話框下邊的庫列表中的 rt.jar 左邊的加號 “+”,展開 rt.jar 的配置
    5. 選中第二項,JavaDoc Location ,單擊右邊的編輯,如果右邊的編輯是灰色的,將庫列表上邊的“使用默認的系統庫” (use default system libraries) 的復選框取消選擇。
    6. 在彈出的對象框中,上邊是使用解壓后的文件來進行幫助,下面使用未解壓的壓縮包幫助。
    7. 我們使用未解壓的壓縮包,選擇下面的 javaDoc in Archive.
    8. 需要輸入兩個內容,一個是壓縮包所在的位置 (Archive Path ), 可以選擇右邊的瀏覽選擇,第二個是壓縮包里面的路徑 ( Paht within Archive),也可以使用右邊的瀏覽進行選擇,一直到 api 文件夾為止。完成后,在瀏覽的下面有一個檢驗的按鈕 (validate) 可以進行檢查。
    9. 完成后,確定關閉。

    現在,在 Java 編輯器中選中一個系統的方法,按 F1 即可在幫助窗口中看到對應的 JavaDoc 的幫助入口,點擊后,就可以直接看到對應的 JavaAPI 的 Doc 了。
    posted @ 2006-06-04 19:41 konhon 優華 閱讀(552) | 評論 (0)編輯 收藏

    使用高效的日志工具—Log4J (1)??
    作者:趙科 發文時間:2002.11.13 09:52:21

    大家在編程時經常不可避免地要使用到一些日志操作,比如開發階段的調試信息、運行時的日志記錄及審計。調查顯示,日志代碼占代碼總量的4%。通常大家可以簡單地使用System.out.println()語句輸出日志信息,但是往往會有一些判斷,比如:

    if (someCondition) {
    System.out.println("some information.");
    }



    這些判斷造成正常的程序邏輯中混雜了大量的輸出語句。而在開發階段寫下的這些判斷僅為了調試的語句,在開發完成時需要查找并移除。部署運行后,尤其是在一些企業應用系統中,還經常需要進一步調試,這時就遇到了更大的麻煩。所以,我們需要一套完備的、靈活的、可配置的日志工具。Log4J就是優秀的選擇。

    Log4J是Apache軟件基金會Jakarta項目下的一個子項目,是用Java編寫的優秀日志工具包。通過Log4J可以在不修改代碼的情況下,方便、靈活地控制任意粒度的日志信息的開啟或關閉,然后使用定制的格式,把日志信息輸出到一個或多個需要的地方。并且,Log4J還有一條平滑的學習曲線,在三分鐘內就可學會它的簡單使用。隨著使用深入,你會發現Log4J功能的強大,幾乎可以滿足日志方面的所有需要。


    快速入門


    先看一段代碼,看看Log4J是多么易于上手,代碼如下:

    package org.javaresearch.log4j;
    import org.apache.log4j.*;
    public class TestLog4J {
    static Logger log = Logger.getLogger(TestLog4J.class.getName());
    public static void main(String args[]) {
    ??BasicConfigurator.configure();
    ??// logging的各種方法
    ??cat.debug("Start of main()");
    ??cat.info("Just testing a log message with priority set to INFO");
    ??cat.warn("Just testing a log message with priority set to WARN");
    ??cat.error("Just testing a log message with priority set to ERROR");
    ??cat.fatal("Just testing a log message with priority set to FATAL");
    ??// 另一種不方便的格式
    ??cat.log(Priority.DEBUG, "Testing a log message use a alternate form");
    ??log.debug("End of main().");
    }
    }



    把這段代碼保存在一個目錄下,編譯運行(注意要把log4j-1.2.7.jar包含入類路徑中),程序輸出如下:

    0 [main] DEBUG TestLog4J??- Start of main()
    10 [main] INFO TestLog4J??- Just testing a log message with priority set to INFO
    20 [main] WARN TestLog4J??- Just testing a log message with priority set to WARN
    30 [main] ERROR TestLog4J??- Just testing a log message with priority set to ERROR
    30 [main] FATAL TestLog4J??- Just testing a log message with priority set to FATAL
    40 [main] DEBUG TestLog4J??- Testing a log message use a alternate form
    50 [main] DEBUG TestLog4J??- End of main().



    首先解釋一下上面輸出結果的意義。第一個數字是指程序開始運行到運行該日志語句所經歷的毫秒數(用來做一點運行效率分析也不錯),“[main]”是日志事件發生的線程,隨后的“DEBUG”、“INFO”等信息是相應日志信息的優先級別,“TestLog4”是當前Logger的實例名,最后是日志信息。

    在這段程序中,使用了Log4J提供的一個基本配置類BasicConfigurator對Log4J進行初始化。但在實際使用時通常不這么做,因為這多少有點“硬”編碼。今后如果要修改Log4J的配置,就需要修改、重新編譯代碼,這通常不是大家所希望的。通常,我們都提供一個名為log4j.properties的文件,在第一次調用到Log4J時,Log4J會在類路徑中定位這個文件,并讀入這個文件完成的配置。這個配置文件告訴Log4J以什么樣的格式、把什么樣的信息、輸出到什么地方。我們來看一個簡單的log4j.properties配置文件的示例,代碼如下:

    log4j.rootLogger=DEBUG, A1
    log4j.appender.A1=org.apache.log4j.ConsoleAppender
    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
    log4j.appender.A1.layout.ConversionPattern= "%-4r [%t] %-5p %c %x - %m%n



    把上面的內容存儲為log4j.properties,并放到和TestLog4J.class同一目錄下(當然也可以放到其它任何目錄,只要該目錄被包含到類路徑中即可)。具體這些配置文件中每行的意義,在以后章節會有詳細的說明,現在可以先跳過。現在你可以注釋掉上面程序中的“BasicConfigurator. configure();”語句,然后使用log4j.properties屬性文件完成Log4J的配置,重新編譯、運行,就得到和上面一樣的結果。

    這樣做有什么好處呢?現在就初步領略一些Log4J的靈活、強大功能。比如系統要上線了,希望輸出一些警告和錯誤信息,這時僅需要修改log4j.properties文件中的“log4j.rootCategory=DEBUG, A1”即可,然后設置日志輸出的最低級別是WARN,設置為“log4j.root Category=WARN, A1”。此時不需要修改任何代碼,重新運行系統,輸出結果就變成了:

    20 [main] WARN TestLog4J??- Just testing a log message with priority set to WARN
    30 [main] ERROR TestLog4J??- Just testing a log message with priority set to ERROR
    30 [main] FATAL TestLog4J??- Just testing a log message with priority set to FATAL




    原理分析


    Log4J有三個主要部件,它們是記錄器(Loggers)、輸出源(Appenders)和布局(Logouts)。記錄器按照布局中指定的格式把日志信息寫入一個或多個輸出源。輸出源可以是控制臺、文本文件、XML文件或Socket,甚至還可以把信息寫入到Windows事件日志或通過電子郵件發送,這都需要相應的類來處理,這些相關的類是ConsoleAppender、FileAppender、SocketAppender、NtEventLogAppender和JMSAppender。

    記錄器(Logger)

    首先讓我們看Logger類,代碼如下:

    package org.apache.log4j;
    public class Logger {
    //創建和恢復方法
    public static Logger getRootLogger();
    public static Logger getLogger(String name);
    public static Logger getLogger(Class clazz);
    // 打印方法
    public void debug(Object message);
    public void info(Object message);
    public void warn(Object message);
    public void error(Object message);
    public void fatal(Object message);
    // 常用打印方法
    public void log(Level l, Object message);
    }



    從這段代碼中可以看出Logger的基本使用。首先需要獲取一個Logger對象,獲取Logger對象的語句為:

    Logger logger = Logger.getLogger(JavaLoggingExample.class.getName());



    有了這個Logger對象,就可以在需要的地方方便地輸出日志信息。對于這些信息是否輸出、輸出的格式等,都可以通過配置文件方便地配置,而不需要修改代碼,這就是Log4J帶來的方便之處。

    記錄器的層次結構

    使用Log4J的Logger.getLogger()方法時會得到一個Logger的實例。如果一個應用中包含了上千個類,那么也幾乎需要上千個Logger實例。如何對這上千個Logger實例進行方便地配置,就是一個很重要的問題。Log4J采用了一種樹狀的繼承層次巧妙地解決了這個問題。在Log4J中Logger是具有層次關系的。它有一個共同的根,位于最上層,其它Logger遵循類似包的層次,比如:

    static Logger root = Logger.getRootLogger();
    static Logger log1 = Logger.getLogger("org");
    static Logger log2 = Logger.getLogger("org.javaresearch");
    static Logger log3 = Logger.getLogger("org.javaresearch.log4j.TestLog4J");



    上面代碼中,log1是log2的父親,是log3的祖先,而root是所有log1、log2、log3的祖先,它們都從root中繼承。所以,一般情況下,僅需要配置好rootLogger,其它子記錄器都會從中繼承rootLogger的配置。如果修改了rootLogger的配置,其它所有的子記錄器也會繼承這種變化。這樣就大大地方便了配置。現在回頭看看在“快速入門”中的配置文件,我們僅配置了rootLogger,就可以控制所有的Logger的行為。

    級別(Level)

    Log4J中的一個核心概念是日志級別是有序的。Log4J內置了5種日志級別為:

    DEBUG??<??INFO??<??WARN??<??ERROR??<??FATAL



    右邊的級別比左邊的高。每一個Logger實例都有一個日志級別,上面的5種輸出方法就是對應于5種不同級別的日志請求。比如,如果c是一個Logger實例,c.info("some information")就是一個INFO級別的日志請求。一個日志請求會不會輸出,取決于該Logger實例的日志級別和該日志請求級別的比較。規則如下:

    假如在一個級別為p的Logger實例中發生一個級別為q的日志請求,則當q >= p時請求才會啟用。

    我們先來看實例2代碼如下:

    // 得到一個logger 實例 "com.foo"
    Logger??logger = Logger.getLogger("com.foo")
    // 現在設置logger的級別,但正常情況是不需要刻意設置lgger級別的,因為它已經在配置文件中完成了
    logger.setLevel(Level.INFO);
    Logger barlogger = Logger.getLogger("com.foo.Bar");
    //因為 WARN >= INFO,這個請求是可以實現的
    logger.warn("Low fuel level.");
    // 因為DEBUG < INFO,所以這個請求是無法實現的
    logger.debug("Starting search for nearest gas station.");
    // logger實例"com.foo.Bar"將從"com.foo"繼承級別,這樣,因為INFO >=
    INFO,所以可以實現下面的請求
    barlogger.info("Located nearest gas station.");
    //因為DEBUG < INFO,這個請求是不能實現的
    barlogger.debug("Exiting gas station search");



    布局(Layout)

    Log4J采用類似C語言中的printf函數的打印格式格式化日志信息,打印參數見表1如下:


    %m 輸出代碼中指定的消息
    %p 輸出優先級,即DEBUG,INFO,WARN,ERROR,FATAL
    %r 輸出自應用啟動到輸出該log信息耗費的毫秒數
    %c 輸出所屬的類目,通常就是所在類的全名
    %t 輸出產生該日志事件的線程名
    %n 輸出一個回車換行符,Windows平臺為“\r\n”,Unix平臺為“\n”
    %d 輸出日志時間點的日期或時間,默認格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921
    %l 輸出日志事件的發生位置,包括類目名、發生的線程,以及在代碼中的行數。舉例:Testlog4.main(TestLog4.java:10)


    使用高效的日志工具—Log4J (2)??
    作者:趙科 發文時間:2002.11.13 09:52:21

    基本應用
    Log4J的配置

    現在來看log4j.properties配置文件的意義。第一行指定了根Logger的級別是DEBUG,并將此指定輸出到A1。A1就是第二行定義的org.apache.log4j.ConsoleAppender,此行表示將A1輸出到控制臺。第三行規定了輸出到A1的格式為org.apache.log4j.PatternLayout。第四行規定了輸出到A1格式的轉換模式為org.javaresearch.log4j.TestLog4J。

    很多成熟的服務器類的軟件日志信息會輸出到控制臺,同時輸出到日志文件備查。使用Log4J可以在不改變任何代碼的情況下,僅通過修改配置文件就可以輕松地完成這項功能。相關配置文件如下:


    #### Use two appenders, one to log to console, another to log to a file
    log4j.rootCategory=debug, stdout, R

    # Print only messages of priority WARN or higher for your category
    log4j.category.your.category.name=WARN

    #### First appender writes to console
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

    # Pattern to output the caller&#39;s file name and line number.
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

    #### Second appender writes to a file
    log4j.appender.R=org.apache.log4j.RollingFileAppender
    log4j.appender.R.File=example.log

    # Control the maximum log file size
    log4j.appender.R.MaxFileSize=100KB
    # Archive log files (one backup file here)
    log4j.appender.R.MaxBackupIndex=1

    log4j.appender.R.layout=org.apache.log4j.PatternLayout
    log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n




    這個配置文件指定了兩個輸出源stdout和R。前者把日志信息輸出到控制臺,后者是一個輪轉日志文件。最大的文件是100KB,當一個日志文件達到最大尺寸時,Log4J會自動把example.log重命名為example.log.1,然后重建一個新的example.log文件,依次輪轉。

    在Web應用中使用

    在Web應用中,應該在哪兒對Log4J進行配置呢?首先要明確,Log4J必須在應用的其它代碼執行前完成初始化。因為Servlet是在Web服務器啟動時立即裝入的,所以,在Web應用中一般使用一個專門的Servlet來完成Log4J的配置,并保證在web.xml的配置中,這個Servlet位于其它Servlet之前。下面是一個例子,代碼如下:


    package org.javaresearch.log4j;
    import java.io.*;
    import javax.servlet.*;
    import org.apache.log4j.*;
    public class Log4JInit extends HttpServlet {
    public void init() throws ServletException {
    ??String prefix = getServletContext().getRealPath("/");
    ??String file = getServletConfig().getInitParameter("log4j-config-file");
    ??// 從Servlet參數讀取log4j的配置文件
    ??if (file != null) {
    ?? PropertyConfigurator.configure(prefix + file);
    ??}
    }
    public void doGet(HttpServletRequest request,HttpServletResponse response)throws
    IOException, ServletException {}
    public void doPost(HttpServletRequest request,HttpServletResponse response)throws
    IOException, ServletException {}
    }





    <servlet>
    ??<servlet-name>log4jinit</servlet-name>
    ?? <servlet-class>org.javaresearch. log4j.Log4JInit</servlet-class>??????????????????
    ?? <init-param>
    ?? <param-name> log4j-config-file </param-name>
    ????????<param-value>/properties/log4j.properties</param-value>
    ?? </init-param>
    ?? <load-on-startup>1</load-on-startup>
    ??</servlet>




    注意:上面的load-on-startup應設為1,以便在Web容器啟動時即裝入該Servlet。log4j.properties文件放在根的properties子目錄中,也可以把它放在其它目錄中。應該把.properties文件集中存放,這樣方便管理。


    高級話題


    性能

    在記錄一些日志信息時,會一定程度地影響系統的運行效率,這時日志工具是否高效就是一個關鍵。Log4J的首要設計目標就是高效,一些關鍵組件都重寫過很多次以不斷提高性能。根據Log4J項目小組的報告,在AMD Duron 800MHz + JDK1.3.1的環境下,Log4J判斷一條日志語句是否需要輸出僅需要5納秒。實際的日志語句執行的也非常快速,從使用SimpleLayout的21微秒(幾乎與System.out.println一樣快),到使用TTCCLayout的37微秒不等。

    嵌套診斷環境NDC

    在多用戶并發的環境下,通常是由不同的線程分別處理不同的客戶端請求。此時要在日志信息中區分出不同的客戶端,你可以為每一個線程生成一個Logger,從而從一堆日志信息中區分出哪些信息是屬于哪個線程的,但這種方式并不高效。Log4J巧妙地使用了Neil Harrison提出的“NDC(嵌套診斷環境)”機制來解決這個問題。Log4J為同一類別的線程生成一個Logger,多個線程共享使用,而它僅在日志信息中添加能夠區分不同線程的信息。NDC是什么?舉例來說,如果一個Servlet接到并發請求時,為每一個客戶端創建一個新的線程,然后分配一個用于保存該請求上下文的NDC堆棧。該上下文可能是發出請求的主機名、IP地址或其它任何可以用于標識該請求的信息。這樣,由于不同的客戶端處理線程具有不同的NDC堆棧,即使這個Servlet同時生成多個線程處理不同的請求,這些日志信息仍然可以區分出來,就好像Log4J為每一個線程都單獨生成了一個Logger實例一樣。在Log4J中是通過org.apache.log4j.NDC實現這種機制的。使用NDC的方法也很簡單,步驟如下:

    1. 在進入一個環境時調用NDC.push(String),然后創建一個NDC;

    2. 所做的日志操作輸出中包括了NDC的信息;

    3. 離開該環境時調用NDC.pop方法;

    4. 當從一個線程中退出時調用NDC.remove方法,以便釋放資源。

    下面是一個模擬記錄來自不同客戶端請求事件的例子,代碼如下:

    import org.apache.log4j.Logger;
    import org.apache.log4j.NDC;
    public class TestNDC {
    static Logger log = Logger.getLogger(TestNDC.class.getName());
    public static void main(String[] args) {
    ??log.info("Make sure %x is in your layout pattern!");
    ??// 從客戶端獲得IP地址的例子
    ??String[] ips = {"192.168.0.10","192.168.0.27"};
    ??for (int i = 0; i<ips.length ; i++)??// 模擬一個運行方法
    ??{
    ?? // 將IP放進 NDC中
    ?? NDC.push(ips[i]);
    ?? log.info("A NEW client connected, who&#39;s ip should appear in this log message.");
    ?? NDC.pop();
    ??}
    ??NDC.remove();
    ??log.info("Finished.");
    }
    }



    注意配置文件中的布局格式中一定要加上%x。系統輸出如下:

    INFO?? - Make sure %x is in your layout pattern!
    INFO??192.168.0.10 - A NEW client connected, who&#39;s ip should appear in this log
    message.
    INFO??192.168.0.27 - A NEW client connected, who&#39;s ip should appear in this log
    message.
    INFO?? - Finished.



    使用Log4J還是JDK logging API

    從JDK 1.4.0開始,引入了java.util.logging包。雖然Log4J小組曾竭力游說JCP(Java Community Process)采用Log4J作為JDK 1.4的“標準”日志API,雖然最終因Sun的日志API規范的負責人Graham Hamilton的一句“Merlin的開發已經到了最后階段,這時不允許再對主要API做出改變”而沒有被采納,但Log4J還是對新的日志API產生了重要影響。那么,我們到底應該采用Log4J還是java.util.logging包呢?下面僅對兩者做一簡單的比較。

    1. Log4J更加成熟,從1999年10月開始至今已經有3年的時間,并且已經在許多項目中有著成熟的應用。而JDK中的logging包是在1.4之后才引入的,并且不能運行于JDK 1.3之前的版本。Log4J則可以良好地運行于JDK 1.1之后的所有版本。

    2. Log4J已經被移植到多種環境下,包括log4c(C)、log4cpp(C++)、log4perl(Perl)、log4net(.net)等。在這些環境下,可以感受到幾乎一致的配置和使用方式。這是JDK中的logging API所不能比擬的。

    3. Log4J還具有更加強力的格式化系統,可以使記錄輸出時實現簡單的模式。但是,它不會增加類而導致格式化工具的擴展。眾多的附加程序和處理器使得Log4J數據包成為一個絕佳的選擇,所有你所需要的都可能加以實現。

    4. Log4J在性能上做了最大的優化。

    Logging API對于簡單的使用是足夠的,但它缺少了許多Log4J所具有的功能。所以,如果你需要一個強力的logging機制,就應堅持使用Log4J;而如果只是需要一些簡單的控制或文件記錄,那么可以使用已經內建在JDK之中的logging API。

    雖然Log4J和JDK logging API是一種競爭關系,但在logging API還在JCP中討論(JSR47)時,兩者之間就已經開始相互影響了。

    FAQ

    1. 如何讓Log4J使用指定的配置文件

    在啟動你的應用時植入系統屬性。例如,可以把上面的log4j.properties文件放到\properties的相對路徑下,并改名為log.properties,此時如果讓Log4J能夠找到這個配置文件并正確地初始化,需要這樣運行程序:

    D:\..\java -Dlog4j.configuration=. \properties\log.properties YourAppName



    為什么一定要使用系統屬性,而不在配置文件中指定呢?很顯然,如果把它寫入配置文件,那么,Log4J讀到它時已經遲了。

    2. 如何查看到Log4J的配置過程

    可以類似1中的那樣,設置系統屬性log4j.debug=true,從而打開Log4J的Verbose模式,此時會輸出Log4J的初始化過程,這樣就會對Log4J的啟動有一個更詳細的了解。下面是Log4J啟動信息的一個示例:

    log4j: Trying to find [log4j.xml] using context classloader
    sun.misc.Launcher$AppClassLoader@92e78c.
    log4j: Trying to find [log4j.xml] using sun.misc.Launcher$ExtClassLoader@9fbe93class
    loader.
    log4j: Trying to find [log4j.xml] using ClassLoader.getSystemResource().
    log4j: Trying to find [log4j.properties] using context classloader
    sun.misc.Launcher$AppClassLoader@92e78c.
    log4j: Using URL [file:/D:/java/logging/src/log4j.properties] for automatic log4j
    configuration.
    log4j: Reading configuration from URL file:/E:/java/logging/src/log4j.properties
    log4j: Parsing for [root] with value=[DEBUG, A1].
    log4j: Level token is [DEBUG].
    log4j: Category root set to DEBUG
    log4j: Parsing appender named "A1".
    log4j: Parsing layout options for "A1".
    log4j: Setting property [conversionPattern] to [%d %l %-5p %c [%t] - %m%n].
    log4j: End of parsing for "A1".
    log4j: Parsed "A1" options.
    log4j: Finished configuring.
    ......??// 下面就是應用的日志信息,省略。
    posted @ 2006-05-30 07:17 konhon 優華 閱讀(688) | 評論 (0)編輯 收藏

    Spring是一個服務于所有層面的application framework:提供了bean的配置基礎,AOP的支持,JDBC的提取框架,抽象事務支持,等等。它有一個非常顯著的特點:在某個層面上如果你不需要Spring的支持,你就可以不使用String的class,只使用它的某一部分的功能。從它的設計理念,你可以看到String幫助你實現了真正的邏輯層和web層的分離。

      相對于EJB來說,Spring是一個輕量級的J2EE應用開發框架。這里提到的輕量級指的是Spring框架本身,而不是說Spring只能適用于輕量級的應用開發。Spring的輕盈體現在其框架本身的基礎結構以及對其他應用工具的支持和裝配能力,與EJB這種龐然大物相比,Spring使我們把各個技術層次之間的風險降低。EJB的內聚性較強,比如數據持久層管理、事務管理、生命周期管理都全部交給了EJB容器中管理,內聚性的白盒特征使我們必須放棄一部分可控性而去信任容器能力。而Spring則是考慮如何“不造輪子”,如何更好的組裝這些輪子,讓他們更好的轉動。比如數據持久層管理可以使用hibernate,日志管理可以使用jakartacommonlogging。一個比較恰當的比喻就是“我們要釘幾個釘子,為了完成這個目的,錘子生產商生產了大大小小一系列的錘子,每個錘子都有一套復雜的使用方法,用來釘某種特別的釘子,結果令我們頭疼不堪。解決錘子過多的問題,通過spring,我們可以使用幾種錘子,但用起來象是只有一個錘子”。(注:這段話是在網上看見的,這里引用這個比喻,我個人覺得很生動)關于這個框架也有一些簡單的總結:“Spring有幾個主要的部分:Bean+ApplicationContext,以一種統一的、IoC的方式查找、管理、組裝、使用系統的組件,取代一切工廠;持久化框架;web框架。“J2EE框架”是RodJohnson的愿景,他希望Spring為J2EE輕量級解決方案提供自底至頂的全面基礎設施支持。”
      上面是關于一個新的Framework的簡單介紹,據說是未來J2EE發展的方向。以前在論壇上有關于J2EE最佳組合的討論,聽說這個JSTL+Struts(或webwork)+Spring+Hibernate的組合很被看好,如果你感興趣的話,可以到SpringFramework中文論壇上看看。下面轉入本文的正題。

      Spring 標記庫介紹及用法:

      本文將重點介紹Spring 提供的標記庫及其用法:

      當你在項目中用Spring Framework的時候,表現層可以選擇Spring Framework自帶的標記庫。當然,這不是你唯一的選擇。你可以選擇其它標記庫或模板替換技術。Spring Framework 并沒有為應用提供非常豐富的標記庫。Spring Framework 提供的標記庫僅僅是為了夠用就行,它并不是無所不包的。呵呵,這點與Struts豐富的標記庫不一樣。其實這點符合RodJohnson的出發點,既“不造輪子”。當然,Spring Framework標記庫有它自身的特點,可以說是個有益的補充吧。

      Spring 標記庫分類如下:

      1、spring:hasBindErrors

      2、spring:bind

      3、spring:transform

      4、spring:message

      5、spring:htmlEscape

      6、spring:theme

      下面我們來具體介紹一下用法:

      1、spring:hasBindErrors

      對應org.springframework.web.servlet.tags.BindErrorsTag標記庫處理類。

      這個標記提供用于綁定對象的errors,如果這個標記被用到的話,那么關于這個對象的錯誤將在頁面上顯示出來。使用這個標記的前提條件是要先使用<spring:bind>標記,并且<spring:hasBindErrors>這個標記不能用來表示對象的狀態,它僅僅可以綁定對象本身和對象的屬性。 具體用法如下:

    <spring:hasBindErrors name="priceIncrease"> <b>Please fix all errors!</b> </spring:hasBindErrors>

      通過這個簡單的例子,我來具體說一下這個標記的屬性吧。

      name:是要被檢查的Bean的名字。這個屬性是必需要的。

      這里是簡單用法,所以就不介紹它包含的errors變量了。具體看英語文檔。下同。

      2、spring:bind

      對應org.springframework.web.servlet.tags.BindTag標記庫處理類

      這個標記用來為某個bean或bean 的屬性賦值,通常和form一起用,相當于action的作用。它指明表單要提交到那個類或類的屬性中去。

      其中path屬性是必須的,指明轉到的類的路徑。舉例如下:

    <form method="post">
    <table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0" cellpadding="5">
    <tr>
    <td alignment="right" width="20%">Increase (%):</td>
    <spring:bind path="priceIncrease.percentage">
    <td width="20%">
    <input type="text" name="percentage" value="<c:out value="${status.value}"/>">
    </td>
    <td width="60%">
    <font color="red"><c:out value="${status.errorMessage}"/></font>
    </td>
    </spring:bind>
    </tr>
    </table>
    <br>
    ……………………省略
    </form>

     3、spring:transform

      對應org.springframework.web.servlet.tags.TransformTag標記庫處理類,這個標記用來轉換表單中不與bean中的屬性一一對應的那些屬性,通常和<spring:bind>一起使用。<spring:transform>標記為<spring:bind>使用提供了更好的支持。

      屬性如下:

      value:必需要的。和當前<spring:bind>標記指向的bean類相同。就是你要轉換的實體類名。

      var:不是必需的。這個字符串被用來綁定輸出結果到page,request, session或application scope.默認情況輸出到jsp中。

      scope:不是必需的。前提條件var必須設置的情況下。它的值可以是page,request, session或application。

      4、spring:message 對應org.springframework.web.servlet.tags.MessageTag標記庫處理類

      這個標記用來幫助springframework支持國際化。和JSTL的fmt:message標記類似。當然這個標記可以很好的工作的本地的springframework框架下。

      屬性如下:

      code:不是必需的。用來查找message,如果沒有被使用的話,text將被使用。

      text:不是必需的。假如code不存在的話,默認是text輸出。當code和text都沒有設置的話,標記將輸出為null.

      var:不是必需的。這個字符串被用來綁定輸出結果到page,request, session或application scope.默認情況輸出到jsp中。

      scope:不是必需的。前提條件var必須設置的情況下。它的值可以是page,request, session或application。

      5、spring:htmlEscape

      對應org.springframework.web.servlet.tags.HtmlEscapeTag標記庫處理類

      不常用,這里省略

      6、spring:theme

      對應org.springframework.web.servlet.tags.ThemeTag標記庫處理類

      不常用,這里省略

      學習完這些用法后,讓我們來看個具體的例子吧。

      配置步驟如下:

      目錄結構圖:

    -spirngapp
    -WEB-INF
    -classes
    -lib
    -src
    -war

      1、將spring.tld拷貝到WEB-INF目錄。

      2、將spring.jar拷貝到WEB-INF\lib包下

      舉例如下:

      在web.xml中配置好taglib屬性,代碼如下:

    <?xml?version="1.0"?encoding="UTF-8"?>?
    <!DOCTYPE?web-app?PUBLIC?'-//Sun?Microsystems,?Inc.//DTD?Web?Application?2.3//EN'?'http://java.sun.com/dtd/web-app_2_3.dtd'>?
    <web-app>?
    <servlet>?
    <servlet-name>springapp</servlet-name>?
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>?
    <load-on-startup>1</load-on-startup>?
    </servlet>?
    <servlet-mapping>?
    <servlet-name>springapp</servlet-name>?
    <url-pattern>*.htm</url-pattern>?
    </servlet-mapping>?
    <welcome-file-list>?
    <welcome-file>?index.jsp?</welcome-file>?
    </welcome-file-list>?
    <taglib>?
    <taglib-uri>/spring</taglib-uri>?
    <taglib-location>/WEB-INF/spring.tld</taglib-location>?
    </taglib>?
    </web-app>?

      jsp頁面代碼如下:

    <%@?include?file="/WEB-INF/jsp/include.jsp"?%>?
    <%@?taglib?prefix="spring"?uri="/spring"?%>?
    <html>?
    <head>?
    <title><fmt:message?key="title"/></title>?
    </head>?
    <body>?
    <h1>?
    <fmt:message?key="priceincrease.heading"/>?
    </h1>?
    <form?method="post">?
    <table?width="95%"?bgcolor="f8f8ff"?border="0"?cellspacing="0"?cellpadding="5">?
    <tr>?
    <td?alignment="right"?width="20%">Increase?(%):</td>?
    <spring:bind?path="priceIncrease.percentage">?
    <td?width="20%">?
    <input?type="text"?name="percentage"?value="<c:out?value="${status.value}"/>">?
    </td>?
    <td?width="60%">?
    <font?color="red">?
    <c:out?value="${status.errorMessage}"/>?
    </font>?
    </td>?
    </spring:bind>?
    </tr>?
    </table>?
    <br>?
    <spring:hasBindErrors?name="priceIncrease">?
    <b>Please?fix?all?errors!</b>?
    </spring:hasBindErrors>?<br><br>?
    <input?type="submit"?alignment="center"?value="Execute">?
    </form>?
    <a?href="<c:url?value="hello.htm"/>">Home</a>?
    </body>?
    </html>?

      <spring:bind>標記經常用來綁定<input>表單元素以便提交給PriceIncrease.java,其實PriceIncrease.java中就是包含一些getter和setter的方法的類。當用戶按下按鈕提交的時候,其表單中的值實際上就被framework放到了PriceIncrease.java中。<spring:bind>經常和form一起使用.這個${status.errorMessage}和${status.value}是一個framework定義的特殊變量,它們被用來顯示錯誤信息和當前表單中的數據。呵呵,今天就到此為止吧,關于Spring Framework標記庫的詳細用法,請參考其文檔。
    posted @ 2006-05-28 20:11 konhon 優華 閱讀(397) | 評論 (0)編輯 收藏

    ?

    熱鍵篇:
    TemplateAlt + /
    修改處:窗口->喜好設定->工作臺->按鍵->編輯->內容輔助。
    個人習慣:Shift+SPACE(空白)
    簡易說明:編輯程序代碼時,打sysout +Template啟動鍵,就
    會自動出現:System.out.println();
    設定Template的格式:窗口->喜好設定->Java->編輯器->模板。

    程序代碼自動排版:Ctrl+Shift+F
    修改處:窗口->喜好設定->工作臺->按鍵->程序代碼->格式。
    個人習慣:Alt+Z
    自動排版設定:窗口->喜好設定->Java->程序代碼格式制作程序。
    樣式頁面->將插入tab(而非空格鍵)以內縮,該選項取消勾選
    ,下面空格數目填4,這樣在自動編排時會以空格4作縮排。

    快速執行程序:Ctrl + F11
    個人習慣:ALT+X
    修改處:窗口->喜好設定->工作臺->按鍵->執行->啟動前一次的啟動作業。
    簡易說明:第一次執行時,它會詢問您執行模式,
    設置好后,以后只要按這個熱鍵,它就會快速執行。
    <ALT+Z(
    排版完)ATL+X(執行)>..我覺得很順手^___^

    自動匯入所需要的類別:Ctrl+Shift+O
    簡易說明:
    假設我們沒有Import任何類別時,當我們在程序里打入:

    BufferedReader buf =
    new BufferedReader(new InputStreamReader(System.in));

    此時Eclipse會警示說沒有匯入類別,這時我們只要按下Ctrl+Shift+O
    ,它就會自動幫我們Import類別。

    查看使用類別的原始碼:Ctrl+鼠標左鍵點擊
    簡易說明:可以看到您所使用類別的原始碼。

    將選取的文字批注起來:Ctrl+/
    簡易說明:Debug時很方便。
    修改處:窗口->喜好設定->工作臺->按鍵->程序代碼->批注

    視景切換:Ctrl+F8
    個人習慣:Alt+S
    修改處:窗口->喜好設定->工作臺->按鍵->窗口->下一個視景。
    簡易說明:可以方便我們快速切換編輯、除錯等視景。

    密技篇:
    一套Eclipse可同時切換,英文、繁體、簡體顯示:
    1.
    首先要先安裝完中文化包。
    2.
    在桌面的快捷方式后面加上參數即可,
    英文-> -nl "zh_US"
    繁體-> -nl "zh_TW"
    簡體-> -nl "zh_CN"
    (
    其它語系以此類推)
    像我2.1.2中文化后,我在我桌面的Eclipse快捷方式加入參數-n1 "zh_US"
    "C:\Program Files\eclipse\eclipse.exe" -n "zh_US"
    接口就會變回英文語系嚕。

    利用Eclipse,在Word編輯文書時可不必將程序代碼重新編排:
    Eclipse程序編輯區的程序代碼整個復制下來(Ctrl+C),直接貼(Ctrl+V)
    Word
    WordPad上,您將會發現在Word里的程序代碼格式,跟Eclipse
    所設定的完全一樣,包括字型、縮排、關鍵詞顏色。我曾試過JBuilder
    GELNetBeans...使用復制貼上時,只有縮排格式一樣,字型、顏
    色等都不會改變。

    外掛篇:
    外掛安裝:將外掛包下載回來后,將其解壓縮后,您會發現features
    plugins
    2個數據夾,將里面的東西都復制或移動到Eclipsefeatures
    plugins數據夾內后,重新啟動Eclipse即可。

    Eclipse可以像JBuilderX一樣使用拖拉方式建構GUI的外掛:
    1.Jigloo SWT/Swing GUI Builder

    http://cloudgarden.com/jigloo/index.html
    下載此版本:Jigloo plugin for Eclipse (using Java 1.4 or 1.5)
    安裝后即可由檔案->新建->其它->GUI Form選取要建構的GUI類型。

    2.Eclipse Visual Editor Project

    http://www.eclipse.org/vep/
    點選下方Download Page,再點選Latest Release 0.5.0進入下載。
    除了VE-runtime-0.5.0.zip要下載外,以下這2個也要:
    EMF build 1.1.1: (build page) (download zip)
    GEF Build 2.1.2: (build page) (download zip)

    3.0 M8
    版本,請下載:
    EMF build I200403250631
    GEF Build I20040330
    VE-runtime-1.0M1

    安裝成功后,便可由File->New->Visual Class開始UI設計。
    安裝成功后,即可由新建->Java->AWTSwing里選擇
    所要建構的GUI類型開始進行設計。VE必須配合著對應
    版本,才能正常使用,否則即使安裝成功,使用上仍會
    有問題。

    使用Eclipse來開發JSP程序:
    外掛名稱:lomboz(下載頁面)
    http://forge.objectweb.org/project/showfiles.php?group_id=97
    請選擇適合自己版本的lomboz下載,lomboz.212.p1.zip表示2.1.2版,
    lomboz.3m7.zip
    表示M7版本....以此類推。
    lomboz
    安裝以及設置教學:
    Eclipse開發JSP-教學文件

    Java
    exe篇:
    實現方式:Eclipse搭配JSmooth(免費)
    1.
    先由Eclipse制作包含ManifestJAR
    制作教學
    2.
    使用JSmooth將做好的JAR包裝成EXE
    JSmooth
    下載頁面:
    http://jsmooth.sourceforge.net/index.php
    3.
    制作完成的exe文件,可在有裝置JREWindows上執行。

    Eclipse-Java
    編輯器最佳設定:
    編輯器字型設定:工作臺->字型->Java編輯器文字字型。
    (
    建議設定Courier New -regular 10)

    編輯器相關設定:窗口->喜好設定->Java->編輯器

    外觀:顯示行號、強調對稱顯示的方括號、強調顯示現行行、
    顯示打印邊距,將其勾選,Tab寬度設4,打印編距字段設80
    程序代碼協助:采預設即可。
    語法:可設定關鍵詞、字符串等等的顯示顏色。
    附注:采預設即可。
    輸入:全部字段都勾選。
    浮動說明:采預設即可。
    導覽:采預設即可。

    使自動排版排出來的效果,最符合Java設計慣例的設定:
    自動排版設定:窗口->喜好設定->Java->程序代碼制作格式。

    換行:全部不勾選。
    分行:行長度上限設:80
    樣式:只將強制轉型后插入空白勾選。
    內縮空格數目:設為4

    Eclipse
    的教學文件:
    Eclipse 3.0系列熱鍵表 - 中英對照解說版 (by sungo) ~New~
    Window+GCC+CDT用Eclipse開發C、C++ (by sungo) ~New~

    其它:
    擴充Eclipse的Java 開發工具(中文)
    使用Eclipse開發J2EE 應用程序(中文)
    使用Eclipse平臺進行除錯(中文)
    用Eclipse進行XML 開發(中文)
    開發Eclipse外掛程序(中文)
    國際化您的Eclipse外掛程序(英文)
    將Swing編輯器加入Eclipse(英文)
    如何測試你的Eclipse plug-in符合國際市場需求(英文)

    Eclipse
    的相關網站:
    http://eclipse-plugins.2y.net/eclipse/index.jsp
    http://www.eclipseplugincentral.com/
    Eclipse相關教學[簡體]

    posted @ 2006-05-26 03:37 konhon 優華 閱讀(484) | 評論 (0)編輯 收藏

    我們經常為每一個Action撰寫一個Controller類別,很快的,您發現到您的Web應用程式下越來越多的Controller類別,而事實上當中的方法是可以組織在一起成為一個類別檔案,例如與資料庫操作相關的list()、add()、delete()等方法,就可以組織為一個類別。

     要將相關的方法組織在一個檔案中,只使用一個handleRequest()方法似乎是不夠的,我們希望同一個Controller中可以根據我們的指定來Action中的某個方法,而不只是使用handleRequest()方法。

     作為org.springframework.web.servlet.mvc.AbstractController下的另一個子類別:org.springframework.web.servlet.mvc.multiaction.MultiActionController,它可以讓我們在一個Controller類別中定義多個方法,並根據我們的請求來呼叫當中的某個方法來執行。

     如果您瞭解Struts,其DispatchAction就類似於Spring的MultiActionController類別,所不同的是,MultiActionController擁有比Struts的DispatchAction更多樣化的方式來參數化與組織這些Action。

     要使用MultiActionController,您要配合一個MethodNameResolver的實例,MultiActionController預設是InternalPathMethodNameResolver,這是最簡單的方式,根據您所給的網址最後的檔案名稱來判斷要執行Action中的哪一個方法,但通常我們不會使用InternalPathMethodNameResolver,因為這就失去了使用MultiActionController的一些優點,像是依請求參數來決定要呼叫的方法。

     我們通常會使用ParameterMethodNameResolver或PropertiesMethodNameResolver,在一個網址上結合請求參數,以參數來決定要執行哪一個Action,這邊以ParameterMethodNameResolver為例,首先,我們可以在bean定義檔中這麼撰寫:

    <?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN""http://www.springframework.org/dtd/spring-beans.dtd"> 
    <beans> 
        <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 
            <property name="mappings"> 
                <props> 
                    <prop key="/book.do">bookAction</prop> 
                </props> 
            </property> 
        </bean> 
        
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
            <property name="viewClass"> 
                <value>org.springframework.web.servlet.view.InternalResourceView</value> 
            </property> 
            <property name="prefix"> 
                <value>/WEB-INF/jsp/</value> 
            </property> 
            <property name="suffix"> 
                <value>.jsp</value> 
            </property> 
        </bean> 
    
        <bean id="paraMethodResolver" 
            class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver"> 
            <property name="paramName"><value>method</value></property> 
            <property name="defaultMethodName"><value>list</value></property> 
        </bean> 
            
        <bean id="bookAction" class="onlyfun.caterpillar.GuestBookAction"> 
            <property name="methodNameResolver"> 
                <ref bean="paraMethodResolver"/> 
            </property> 
            <property name="testPage"> 
                <value>test</value> 
            </property> 
        </bean> 
    </beans>

     在paraMethodResolver中,我們使用paramName定義在http請求中使用method參數來指定要呼叫的方法,若是請求中沒有指定method參數,則會使用defaultMethodName所指定的方法,這邊指定的是list()方法。

     GuestBookAction是個繼承MultiActionController的類別,當中我們可以定義我們在method參數指定下所要呼叫的方法,例如:

    GuestBookAction.java
    package onlyfun.caterpillar; 
    
    import javax.servlet.http.*; 
    import org.springframework.web.servlet.ModelAndView; 
    import org.springframework.web.servlet.mvc.multiaction.MultiActionController; 
    
    public class GuestBookAction extends MultiActionController { 
        privateString testPage; 
        
        public ModelAndView list(HttpServletRequest req, HttpServletResponse res) { 
            returnnew ModelAndView(this.getTestPage(),"executed", "list"); 
        } 
        
        public ModelAndView add(HttpServletRequest req, HttpServletResponse res) { 
            returnnew ModelAndView(this.getTestPage(),"executed", "add"); 
        } 
        
        public ModelAndView delete(HttpServletRequest req, HttpServletResponse res) { 
            returnnew ModelAndView(this.getTestPage(),"executed", "delete"); 
        } 
        
        publicString getTestPage() { 
            return testPage; 
        } 
        
        public void setTestPage(String testPage) { 
            this.testPage = testPage; 
        } 
    }

     注意到我們的方法必須包括HttpServletRequest與HttpServletResponse作為參數,您也可以使用帶有第三個參數HttpSession的版本。

     上面的類別只是一個簡單的範例,用於測試MultiActionController的運作,我們測試用的JSP網頁如下:

    <html> 
    <head><title>Test</title></head> 
    <body> 
        <H1> "${executed}" method is executed.</H2> 
    </body> 
    </html>

     當您使用以下的網址請求資源時:
    http://localhost:8080/springapp/book.do?method=add

     我們的測試網頁將傳回以下的內容:

    <html> 
    <head><title>Test</title></head> 
    <body> 
        <H1> "add" method is executed.</H2> 
    </body> 
    </html>

     您也可以將所有相對應的方法專門組織在一個委託(delegate)物件中,而不是撰寫在Controller類別中,當請求來到時,將委託給這個物件來執行指定的方法,您只要定義MultiActionController的delegate屬性即可,例如我們的委託物件如下:

    BookActionDelegate.java
    package onlyfun.caterpillar; 
    
    import javax.servlet.http.*; 
    import org.springframework.web.servlet.ModelAndView; 
    
    public class BookActionDelegate { 
        privateString testPage; 
        
        public ModelAndView list(HttpServletRequest req, HttpServletResponse res) { 
            returnnew ModelAndView(this.getTestPage(),"executed", "list"); 
        } 
        
        public ModelAndView add(HttpServletRequest req, HttpServletResponse res) { 
            returnnew ModelAndView(this.getTestPage(),"executed", "add"); 
        } 
        
        public ModelAndView delete(HttpServletRequest req, HttpServletResponse res) { 
            returnnew ModelAndView(this.getTestPage(),"executed", "delete"); 
        } 
        
        publicString getTestPage() { 
            return testPage; 
        } 
        
        public void setTestPage(String testPage) { 
            this.testPage = testPage; 
        } 
    }

     現在我們不用定義GuestBookAction了,直接使用MultiActionController,只要定義Bean定義檔就好了:

    <?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN""http://www.springframework.org/dtd/spring-beans.dtd"> 
    <beans> 
        <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 
            <property name="mappings"> 
                <props> 
                    <prop key="/book.do">bookAction</prop> 
                </props> 
            </property> 
        </bean> 
        
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
            <property name="viewClass"> 
                <value>org.springframework.web.servlet.view.InternalResourceView</value> 
            </property> 
            <property name="prefix"> 
                <value>/WEB-INF/jsp/</value> 
            </property> 
            <property name="suffix"> 
                <value>.jsp</value> 
            </property> 
        </bean> 
    
        <bean id="paraMethodResolver" 
            class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver"> 
            <property name="paramName"><value>method</value></property> 
            <property name="defaultMethodName"><value>list</value></property> 
        </bean> 
    
        <bean id="bookActionDelegate" class="onlyfun.caterpillar.BookActionDelegate"> 
            <property name="testPage"> 
                <value>test</value> 
            </property> 
        </bean> 
        
        <bean id="bookAction" class="org.springframework.web.servlet.mvc.multiaction.MultiActionController"> 
            <property name="methodNameResolver"> 
                <ref bean="paraMethodResolver"/> 
            </property> 
            <property name="delegate"> 
                <ref bean="bookActionDelegate"/> 
            </property> 
        </bean>    
    </beans>

     測試的結果與上面是相同的。

     以上說明的是ParameterMethodNameResolver,而PropertiesMethodNameResolver的設定方法是類似的,有興趣的話,可以看一下Spring參考手冊中有關MultiActionController的說明,當中也有個簡明的設定範例。

    posted @ 2006-05-25 20:07 konhon 優華 閱讀(990) | 評論 (0)編輯 收藏

    Hibernate3提供了DetachedCriteria,使得我們可以在Web層構造detachedCriteria,然后調用業務層Bean,進行動態條件查詢,根據這一功能,我設計了通用的抽象Bean基類和分頁類支持,代碼來自于Quake Wang的javaeye-core包的相應類,然后又做了很多修改。

    分頁支持類:
    package?com.javaeye.common.util;?

    import?java.util.List;?

    public?class?PaginationSupport?{?

    ????????
    public?final?static?int?PAGESIZE?=?30;?

    ????????
    private?int?pageSize?=?PAGESIZE;?

    ????????
    private?List?items;?

    ????????
    private?int?totalCount;?

    ????????
    private?int[]?indexes?=?new?int[0];?

    ????????
    private?int?startIndex?=?0;?

    ????????
    public?PaginationSupport(List?items,?int?totalCount)?{?
    ????????????????setPageSize(PAGESIZE);?
    ????????????????setTotalCount(totalCount);?
    ????????????????setItems(items);????????????????
    ????????????????setStartIndex(
    0);?
    ????????}?

    ????????
    public?PaginationSupport(List?items,?int?totalCount,?int?startIndex)?{?
    ????????????????setPageSize(PAGESIZE);?
    ????????????????setTotalCount(totalCount);?
    ????????????????setItems(items);????????????????
    ????????????????setStartIndex(startIndex);?
    ????????}?

    ????????
    public?PaginationSupport(List?items,?int?totalCount,?int?pageSize,?int?startIndex)?{?
    ????????????????setPageSize(pageSize);?
    ????????????????setTotalCount(totalCount);?
    ????????????????setItems(items);?
    ????????????????setStartIndex(startIndex);?
    ????????}?

    ????????
    public?List?getItems()?{?
    ????????????????
    return?items;?
    ????????}?

    ????????
    public?void?setItems(List?items)?{?
    ????????????????
    this.items?=?items;?
    ????????}?

    ????????
    public?int?getPageSize()?{?
    ????????????????
    return?pageSize;?
    ????????}?

    ????????
    public?void?setPageSize(int?pageSize)?{?
    ????????????????
    this.pageSize?=?pageSize;?
    ????????}?

    ????????
    public?int?getTotalCount()?{?
    ????????????????
    return?totalCount;?
    ????????}?

    ????????
    public?void?setTotalCount(int?totalCount)?{?
    ????????????????
    if?(totalCount?>?0)?{?
    ????????????????????????
    this.totalCount?=?totalCount;?
    ????????????????????????
    int?count?=?totalCount?/?pageSize;?
    ????????????????????????
    if?(totalCount?%?pageSize?>?0)?
    ????????????????????????????????count
    ++;?
    ????????????????????????indexes?
    =?new?int[count];?
    ????????????????????????
    for?(int?i?=?0;?i?<?count;?i++)?{?
    ????????????????????????????????indexes[i]?
    =?pageSize?*?i;?
    ????????????????????????}?
    ????????????????}?
    else?{?
    ????????????????????????
    this.totalCount?=?0;?
    ????????????????}?
    ????????}?

    ????????
    public?int[]?getIndexes()?{?
    ????????????????
    return?indexes;?
    ????????}?

    ????????
    public?void?setIndexes(int[]?indexes)?{?
    ????????????????
    this.indexes?=?indexes;?
    ????????}?

    ????????
    public?int?getStartIndex()?{?
    ????????????????
    return?startIndex;?
    ????????}?

    ????????
    public?void?setStartIndex(int?startIndex)?{?
    ????????????????
    if?(totalCount?<=?0)?
    ????????????????????????
    this.startIndex?=?0;?
    ????????????????
    else?if?(startIndex?>=?totalCount)?
    ????????????????????????
    this.startIndex?=?indexes[indexes.length?-?1];?
    ????????????????
    else?if?(startIndex?<?0)?
    ????????????????????????
    this.startIndex?=?0;?
    ????????????????
    else?{?
    ????????????????????????
    this.startIndex?=?indexes[startIndex?/?pageSize];?
    ????????????????}?
    ????????}?

    ????????
    public?int?getNextIndex()?{?
    ????????????????
    int?nextIndex?=?getStartIndex()?+?pageSize;?
    ????????????????
    if?(nextIndex?>=?totalCount)?
    ????????????????????????
    return?getStartIndex();?
    ????????????????
    else?
    ????????????????????????
    return?nextIndex;?
    ????????}?

    ????????
    public?int?getPreviousIndex()?{?
    ????????????????
    int?previousIndex?=?getStartIndex()?-?pageSize;?
    ????????????????
    if?(previousIndex?<?0)?
    ????????????????????????
    return?0;?
    ????????????????
    else?
    ????????????????????????
    return?previousIndex;?
    ????????}?

    }

    抽象業務類
    java代碼:?
    /**?
    *?Created?on?2005-7-12?
    */?
    package?com.javaeye.common.business;?

    import?java.io.Serializable;?
    import?java.util.List;?

    import?org.hibernate.Criteria;?
    import?org.hibernate.HibernateException;?
    import?org.hibernate.Session;?
    import?org.hibernate.criterion.DetachedCriteria;?
    import?org.hibernate.criterion.Projections;?
    import?org.springframework.orm.hibernate3.HibernateCallback;?
    import?org.springframework.orm.hibernate3.support.HibernateDaoSupport;?

    import?com.javaeye.common.util.PaginationSupport;?

    public?abstract?class?AbstractManager?extends?HibernateDaoSupport?{?

    ????????
    private?boolean?cacheQueries?=?false;?

    ????????
    private?String?queryCacheRegion;?

    ????????
    public?void?setCacheQueries(boolean?cacheQueries)?{?
    ????????????????
    this.cacheQueries?=?cacheQueries;?
    ????????}?

    ????????
    public?void?setQueryCacheRegion(String?queryCacheRegion)?{?
    ????????????????
    this.queryCacheRegion?=?queryCacheRegion;?
    ????????}?

    ????????
    public?void?save(final?Object?entity)?{?
    ????????????????getHibernateTemplate().save(entity);?
    ????????}?

    ????????
    public?void?persist(final?Object?entity)?{?
    ????????????????getHibernateTemplate().save(entity);?
    ????????}?

    ????????
    public?void?update(final?Object?entity)?{?
    ????????????????getHibernateTemplate().update(entity);?
    ????????}?

    ????????
    public?void?delete(final?Object?entity)?{?
    ????????????????getHibernateTemplate().delete(entity);?
    ????????}?

    ????????
    public?Object?load(final?Class?entity,?final?Serializable?id)?{?
    ????????????????
    return?getHibernateTemplate().load(entity,?id);?
    ????????}?

    ????????
    public?Object?get(final?Class?entity,?final?Serializable?id)?{?
    ????????????????
    return?getHibernateTemplate().get(entity,?id);?
    ????????}?

    ????????
    public?List?findAll(final?Class?entity)?{?
    ????????????????
    return?getHibernateTemplate().find("from?"?+?entity.getName());?
    ????????}?

    ????????
    public?List?findByNamedQuery(final?String?namedQuery)?{?
    ????????????????
    return?getHibernateTemplate().findByNamedQuery(namedQuery);?
    ????????}?

    ????????
    public?List?findByNamedQuery(final?String?query,?final?Object?parameter)?{?
    ????????????????
    return?getHibernateTemplate().findByNamedQuery(query,?parameter);?
    ????????}?

    ????????
    public?List?findByNamedQuery(final?String?query,?final?Object[]?parameters)?{?
    ????????????????
    return?getHibernateTemplate().findByNamedQuery(query,?parameters);?
    ????????}?

    ????????
    public?List?find(final?String?query)?{?
    ????????????????
    return?getHibernateTemplate().find(query);?
    ????????}?

    ????????
    public?List?find(final?String?query,?final?Object?parameter)?{?
    ????????????????
    return?getHibernateTemplate().find(query,?parameter);?
    ????????}?

    ????????
    public?PaginationSupport?findPageByCriteria(final?DetachedCriteria?detachedCriteria)?{?
    ????????????????
    return?findPageByCriteria(detachedCriteria,?PaginationSupport.PAGESIZE,?0);?
    ????????}?

    ????????
    public?PaginationSupport?findPageByCriteria(final?DetachedCriteria?detachedCriteria,?final?int?startIndex)?{?
    ????????????????
    return?findPageByCriteria(detachedCriteria,?PaginationSupport.PAGESIZE,?startIndex);?
    ????????}?

    ????????
    public?PaginationSupport?findPageByCriteria(final?DetachedCriteria?detachedCriteria,?final?int?pageSize,?
    ????????????????????????
    final?int?startIndex)?{?
    ????????????????
    return?(PaginationSupport)?getHibernateTemplate().execute(new?HibernateCallback()?{?
    ????????????????????????
    public?Object?doInHibernate(Session?session)?throws?HibernateException?{?
    ????????????????????????????????Criteria?criteria?
    =?detachedCriteria.getExecutableCriteria(session);?
    ????????????????????????????????
    int?totalCount?=?((Integer)?criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();?
    ????????????????????????????????criteria.setProjection(
    null);?
    ????????????????????????????????List?items?
    =?criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();?
    ????????????????????????????????PaginationSupport?ps?
    =?new?PaginationSupport(items,?totalCount,?pageSize,?startIndex);?
    ????????????????????????????????
    return?ps;?
    ????????????????????????}?
    ????????????????},?
    true);?
    ????????}?

    ????????
    public?List?findAllByCriteria(final?DetachedCriteria?detachedCriteria)?{?
    ????????????????
    return?(List)?getHibernateTemplate().execute(new?HibernateCallback()?{?
    ????????????????????????
    public?Object?doInHibernate(Session?session)?throws?HibernateException?{?
    ????????????????????????????????Criteria?criteria?
    =?detachedCriteria.getExecutableCriteria(session);?
    ????????????????????????????????
    return?criteria.list();?
    ????????????????????????}?
    ????????????????},?
    true);?
    ????????}?

    ????????
    public?int?getCountByCriteria(final?DetachedCriteria?detachedCriteria)?{?
    ????????????????Integer?count?
    =?(Integer)?getHibernateTemplate().execute(new?HibernateCallback()?{?
    ????????????????????????
    public?Object?doInHibernate(Session?session)?throws?HibernateException?{?
    ????????????????????????????????Criteria?criteria?
    =?detachedCriteria.getExecutableCriteria(session);?
    ????????????????????????????????
    return?criteria.setProjection(Projections.rowCount()).uniqueResult();?
    ????????????????????????}?
    ????????????????},?
    true);?
    ????????????????
    return?count.intValue();?
    ????????}?
    }?
    用戶在web層構造查詢條件detachedCriteria,和可選的startIndex,調用業務bean的相應findByCriteria方法,返回一個PaginationSupport的實例ps。

    ps.getItems()得到已分頁好的結果集
    ps.getIndexes()得到分頁索引的數組
    ps.getTotalCount()得到總結果數
    ps.getStartIndex()當前分頁索引
    ps.getNextIndex()下一頁索引
    ps.getPreviousIndex()上一頁索引

    ?

    ?

    posted @ 2006-04-06 21:37 konhon 優華 閱讀(1529) | 評論 (1)編輯 收藏

    那與jdk的版本沒關系吧.

    那是Eclipse提供這個提示功能給你吧.
    你點它warning的icon兩下Eclipse就會自動給定.
    如果你不喜歡,可以把它關掉,
    windows -> preferences -> compiler -> Error/Warnings
    -> Potential Programming problems
    將Serializable class without serialVersionUID的warning改成ignore.

    其實如果你沒有考慮到兼容性問題時,那就把它關掉吧.
    其實有這個功能是好的.
    只要任何類別實作了Serializable這個介面,
    如果沒有加入serialVersionUID,Eclipse都會給你warning提示,
    這個serialVersionUID為了讓該類別Serializable後兼容.

    考慮一下,如果今天你的類Serialized存到硬碟里,
    可是後來你卻更改了類別的field(增加或減少或改名).
    當你Deserialize時,就會出現Exception.這樣就會做成不兼容性的問題.

    但當serialVersionUID相同時,它就會將不一樣的field以type的預設值Deserialize.
    這個可以避開不兼容性的問題.

    自於你說內存的問題,我覺得沒差多少吧.
    posted @ 2006-04-06 20:03 konhon 優華 閱讀(4419) | 評論 (0)編輯 收藏

    僅列出標題
    共21頁: First 上一頁 2 3 4 5 6 7 8 9 10 下一頁 Last 
    主站蜘蛛池模板: 国内精品乱码卡1卡2卡3免费| 亚洲国产精品一区二区第一页免| 亚洲成a人片在线不卡一二三区| 免费欧洲美女牲交视频| a在线视频免费观看| 亚洲午夜成激人情在线影院 | 91禁漫免费进入| 亚洲国产精品成人午夜在线观看 | 女人张开腿给人桶免费视频 | 亚洲男人在线无码视频| 97在线视频免费| 国产亚洲精品欧洲在线观看| 久久久亚洲精品无码| 成人性生交大片免费看无遮挡 | 很黄很污的网站免费| 亚洲精品无码人妻无码| 亚洲精品无码久久一线| 精品久久久久久久免费人妻| 暖暖免费在线中文日本| 羞羞网站免费观看| 亚洲精品国产第1页| 国产av无码专区亚洲国产精品| 人成午夜免费视频在线观看| 99久久免费国产精精品| 亚洲youwu永久无码精品| 亚洲自偷自拍另类图片二区| 国产精品亚洲高清一区二区| 亚洲成在人线aⅴ免费毛片| 大片免费观看92在线视频线视频| 人人爽人人爽人人片av免费| 亚洲愉拍一区二区三区| 亚洲精品国产成人99久久| 国产亚洲一区区二区在线| 国产精品va无码免费麻豆| 久久成人免费播放网站| 国产偷国产偷亚洲高清在线 | 久久精品国产亚洲AV网站| 国产成人免费A在线视频| 在线精品一卡乱码免费| 中文在线免费观看| 国产偷国产偷亚洲高清在线|