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

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

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

    隨筆 - 3, 文章 - 152, 評論 - 17, 引用 - 0
    數據加載中……

    Spring學習筆記

    *******************************************************

    作者:陳剛,程序員,廣西省桂林人,廣西師范大學數學系97屆畢業。

    blog:http://blog.csdn.net/glchengang

    Email:glchengang@yeah.net 

    ******************************************************* 

    1、概念理解

    對Spring耳聞已久,但一直沒有時間和心情去看它,最近它的聲音是越來越大了,Java視線http://forum.javaeye.com/有不高手在談論它。于是趁著有空閑時間,我也花了兩個晚上看了看Spring,看的是夏昕的<Spring開發指南>http://www.xiaxin.net/Spring_Dev_Guide.rar,文章寫得不錯。以下談談我的學習感受

    一、Spring的IoC(Inversion of Control)。
    這是Spring中得有特點的一部份。IoC又被翻譯成“控制反轉”,也不知道是誰翻譯得這么別扭,感覺很深奧的詞。其實,原理很簡單,用一句通俗的話來說:就是用XML來定義生成的對象。IoC其實是一種設計模式,Spring只是實現了這種設計模式。

    這種設計模式是怎么來的呢?是實踐中逐漸形成的。

    第一階段:用普通的無模式來寫Java程序。一般初學者都要經過這個階段。
    第二階段:頻繁的開始使用接口,這時,接口一般都會伴隨著使用工廠模式。
    第三階段:使用IoC模式。工廠模式還不夠好:(1)因為的類的生成代碼寫死在程序里,如果你要換一個子類,就要修改工廠方法。(2)一個接口常常意味著一個生成工廠,會多出很多工廠類。
        可以把IoC模式看做是工廠模式的升華,可以把IoC看作是一個大工廠,只不過這個大工廠里要生成的對象都是在XML文件中給出定義的,然后利用Java的“反射”編程,根據XML中給出的類名生成相應的對象。從實現來看,IoC是把以前在工廠方法里寫死的對象生成代碼,改變為由XML文件來定義,也就是把工廠和對象生成這兩者獨立分隔開來,目的就是提高靈活性和可維護性。

        IoC中最基本的Java技術就是“反射”編程。反射又是一個生澀的名詞,通俗的說反射就是根據給出的類名(字符串)來生成對象。這種編程方式可以讓對象在生成時才決定要生成哪一種對象。我在最近的一個項目也用到了反射,當時是給出一個.properties文本文件,里面寫了一些全類名(包名+類名),然后,要根據這些全類名在程序中生成它們的對象。反射的應用是很廣泛的,象Hibernate、String中都是用“反射”做為最基本的技術手段。

        在過去,反射編程方式相對于正常的對象生成方式要慢10幾倍,這也許也是當時為什么反射技術沒有普通應用開來的原因。但經SUN改良優化后,反射方式生成對象和通常對象生成方式,速度已經相差不大了(但依然有一倍以上的差距)。


        所以要理解IoC,你必須先了解工廠模式和反射編程,否則對它產生的前因后果和實現原理都是無法理解透徹的。只要你理解了這一點,你自己也完全可以自己在程序中實現一個IoC框架,只不是這還要涉及到XML解析等其他知識,稍微麻煩一些。


        IoC最大的好處是什么?因為把對象生成放在了XML里定義,所以當我們需要換一個實現子類將會變成很簡單(一般這樣的對象都是現實于某種接口的),只要修改XML就可以了,這樣我們甚至可以實現對象的熱插撥(有點象USB接口和SCIS硬盤了)。

        IoC最大的缺點是什么?(1)生成一個對象的步驟變復雜了(其實上操作上還是挺簡單的),對于不習慣這種方式的人,會覺得有些別扭和不直觀。(2)對象生成因為是使用反射編程,在效率上有些損耗。但相對于IoC提高的維護性和靈活性來說,這點損耗是微不足道的,除非某對象的生成對效率要求特別高。(3)缺少IDE重構操作的支持,如果在Eclipse要對類改名,那么你還需要去XML文件里手工去改了,這似乎是所有XML方式的缺憾所在。

        總的來說IoC無論原理和實現都還算是很簡單的。一些人曾認為IoC沒什么實際作用,這種說法是可以理解的,因為如果你在編程中很少使用接口,或很少使用工廠模式,那么你根本就沒有使用IoC的強烈需要,也不會體會到IoC可貴之處。有些人也說要消除工廠模式、單例模式,但是都語焉不詳、人云亦云。但如果你看到IoC模式和用上Spring,那么工廠模式和單例模式的確基本上可以不用了。但它消失了嗎?沒有!Spring的IoC實現本身就是一個大工廠,其中也包含了單例對象生成方式,只要用一個設置就可以讓對象生成由普通方式變單一實例方式,非常之簡單。

       總結:
       (1)IoC原理很簡單,作用的針對性也很強,不要把它看得很玄乎。
       (2)要理解IoC,首先要了解“工廠、接口、反射”這些概念。


    二、Spring的MVC

    如果你已經熟悉Struts,那么不必把MVC做為重點學習內容。基本上我認為Spring  MVC是一個雞肋,它的技術上很先進,但易用性上沒有Struts好。而且Struts有這么多年的基礎了,Spring很難取代Struts的地位。這就是先入為主的優秀,一個項目經理選用一種框架,不能單純的從它的技術上考慮,還有開發效率,人員配置等都是考慮因素。但做為研究性的學習,Spring的MVC部份還是蠻有價值的。


    三、數據庫層的模板
    Spring主要是提供了一些數據庫模板(模板也是一種Java設計模式),讓數據部分的代碼更簡潔,那些try...catch都可以不見了。這個的確是個好東東。


    四、AOP

    AOP又稱面向方面編程,它的實現原理還是用了反射:通過對某一個種類的方法名做監控來實現統一處理。比如:監控以“insert”字符串開頭的方法名,在這種方法執行的前后進行某種處理(數據庫事務等)。但這里我有一個疑問?不一定所有以insert開頭的方法都是數據庫操作,哪么當某個insert開頭的方法不是數據庫操作,你又對它進行了數據事務的操作,這樣的錯誤如何防止???我對這方面了解不深,還是只知道一個大概。


    曾看過一個程序員發出這樣的感慨:“框架一個接一個,學也學不完,而且有必要嗎?這樣一層層的加上框架,還不如直接寫JSP來得直接,效率還高”。我想這種困惑很多人都有吧?但如果你經過的項目漸多,就會發現,維護項目要比開發項目更艱難,代價更大。那種用JSP直接來寫,層次又不清楚的開發,往往最后得到一個不可再修改的軟件,一團亂麻,移一發而動全身。但軟件不象電視機,做好了就不會改動了,軟件是一個變化的事物,用戶的需求隨時會改變,這時你會體會到分層和使用框架的好處了,它們為你做了軟件中很多和業務無關的工作,你可以只關注業務,并減少代碼量。唯一缺點就是有一個學習的代價,框架配置上也較麻煩。


    學習框架,我認為應該:第一步,了解這個框架中的一些關鍵概念,它的具體含義是什么。第二步,了解這個框架的精華在哪里,它能對開發起到什么樣的作用,最好能對它的原理有一定的了解。第三步,用這個框架來寫幾個例子,實際體會一下。我現在還是剛剛大概完成了前兩步,這幾天會再看看Spring的文檔并用Spring寫幾個例子,到時一起發出來。

    另外,很贊賞<Spring開發指南>的作者夏昕的觀點,將自已的經驗寫成文檔公開出來,不過一個人的力量終究太弱。最好能夠形成一個組織,對一種新技術,由一兩個人出一個大綱,大家把它分了,更寫一章,然后由兩三個人總集起。我個人感覺,由于英文語言的關系,新技術引進到國內的還是太慢了,至少要比國外慢上一年以上,成立一個開源文檔組織還是很有意義的事。

    第一章  Spring的下載和安裝

    下載主頁http://www.springframework.org/download.html ,或者直接使用鏈接地址:http://voxel.dl.sourceforge.net/sourceforge/springframework/spring-framework-1.1.4-with-dependencies.zip

    Spring的下載包有兩種:spring-framework-1.1.4-with-dependencies.zipspring-framework-1.1.4.zip,上面的第二個鏈接就是下載前者,建議你也下載前者,因為前者比后者多了一些Spring要用到的第三方包,如hibernatej2eedom4jaopalliancejakarta-commons等。下載包名稱的dependencies就是“依賴”的意思。

    1、解壓后的目錄結構如下:

     

    目錄說明:

    l           dist  Spring自已的核心庫

    l           docs    有一些文檔。

    l           lib   是一些用到的第三方庫。

    l           mock  仿制品?????????????我也不知道

    l           samples 一些項目例子

    l           src  Spring的源代碼

    l           test  測試用例

     

    2、新建一個Eclipse項目

    1)項目名myspring

     

    2)直接單擊“下一步”,再單擊“完成”

    3)在項目下創建一個lib目錄

     

    4)將Spring的解壓縮目錄distlib都復制到這個lib目錄中,然后前者改名成spring,后者先暫時不動吧,以后用到時才管它。

     

    3、將spring庫加入到庫引用

    spring庫加入到庫引用中,有如下兩種方法。

    方法一:單擊“添加JAR”把spring的核心包加入。

     

    方法二:上面的“方法一”簡單易行,但如果一個項目要引入的包種類很多,那么就顯示得較亂。還有一種操作麻煩,但較清晰一些的方法。這種方法是使用Eclipse中的“用戶庫”的方式,如下圖所示:

     

     

    最后的結果如下圖所示,然后單擊“確定”


     

    返回上一界面后,再單擊“完成”,得到如下圖所示的效果

     

    最后,項目里的spring包的引用都在一個目錄下,顯示層次感強很多。

     

    以后如果要引入myspring/lib/lib目錄下的第三方包,也按方法二較好:將第三方包的目錄復制到myspring/lib下,再參照方法二,將其加入庫引用中即可

    4、設置日志包的庫引用

    jakarta-commonslog4j包主要是做為Spring的運行時輸出log(日志)用,如果不設置日志包,那么日志就沒法輸出到控制臺,不利于開發和調試。設置方式如下:

    1)就照上面的方法,放myspring/lib/lib目錄下的log4j目錄和jakarta-commons目錄往上移一層到myspring/lib目錄下。最后設置的結果如下圖所示,這里我們把log4j移到了others目錄,因為log4j就一個JAR包,專門為它象jakarta-commons創建一個目錄和用戶庫太不值了,以后可能還會有這種引用單個包的時候,到時都放到others目錄里好了。

    2)日志的庫引用完成之后,還要創建一個日志的配置文件:log4j.properties,其文件內容如下:

    log4j.rootLogger=DEBUG, stdout

    log4j.appender.stdout=org.apache.log4j.ConsoleAppender

    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

    log4j.appender.stdout.layout.ConversionPattern=%c{1} - %m%n

     

    log4j.properties文件的創建位置在src目錄下,如下圖所示:

     

    如果沒有設置日志設置或設置不對,在使用控制臺時會出現下面所示的紅字。

    java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

    第二章  SpringIoC的入門實例

    Spring的模塊化是很強的,各個功能模塊都是獨立的,我們可以選擇的使用。這一章先從SpringIoC開始。所謂IoC就是一個用XML來定義生成對象的模式,我們看看如果來使用的。

    1、數據模型。

    1、如下圖所示有三個類,Human(人類)是接口,Chinese(中國人)是一個子類,American(美國人)是另外一個子類。

    源代碼如下:

    package cn.com.chengang.spring;

    public interface Human {

           void eat();

           void walk();

    }

     

    package cn.com.chengang.spring;

    public class Chinese implements Human {

        /* (非 Javadoc

         * @see cn.com.chengang.spring.Human#eat()

         */

        public void eat() {

            System.out.println("中國人對吃很有一套");

        }

     

        /* (非 Javadoc

         * @see cn.com.chengang.spring.Human#walk()

         */

        public void walk() {

            System.out.println("中國人行如飛");

        }

    }

     

    package cn.com.chengang.spring;

    public class American implements Human {

        /* (非 Javadoc

         * @see cn.com.chengang.spring.Human#eat()

         */

        public void eat() {

            System.out.println("美國人主要以面包為主");

        }

     

        /* (非 Javadoc

         * @see cn.com.chengang.spring.Human#walk()

         */

        public void walk() {

            System.out.println("美國人以車代步,有四肢退化的趨勢");

        }

    }

     

    2、對以上對象采用工廠模式的用法如下

    創建一個工廠類Factory,如下。這個工廠類里定義了兩個字符串常量,所標識不同的人種。getHuman方法根據傳入參數的字串,來判斷要生成什么樣的人種。

    package cn.com.chengang.spring;

    public class Factory {

        public final static String CHINESE = "Chinese";

        public final static String AMERICAN = "American";

     

        public Human getHuman(String ethnic) {

            if (ethnic.equals(CHINESE))

                return new Chinese();

            else if (ethnic.equals(AMERICAN))

                return new American();

            else

                throw new IllegalArgumentException("參數(人種)錯誤");

        }

    }

     

    下面是一個測試的程序,使用工廠方法來得到了不同的“人種對象”,并執行相應的方法。

    package cn.com.chengang.spring;

    public class ClientTest {

        public static void main(String[] args) {

            Human human = null;

            human = new Factory().getHuman(Factory.CHINESE);

            human.eat();

            human.walk();

            human = new Factory().getHuman(Factory.AMERICAN);

            human.eat();

            human.walk();

        }

    }

     

    控制臺的打印結果如下:

     

    3、采用Spring的IoC的用法如下:

    1、在項目根目錄下創建一個bean.xml文件

    <?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="Chinese" class="cn.com.chengang.spring.Chinese"/>

           <bean id="American" class="cn.com.chengang.spring.American"/>

    </beans>

    bean.xml的位置如下圖,注意不要看花眼把它看成是lib目錄下的了,它是在myspring目錄下的。

     

    2、修改ClientTest程序如下:

    package cn.com.chengang.spring;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.FileSystemXmlApplicationContext;

    public class ClientTest {

        public final static String CHINESE = "Chinese";

        public final static String AMERICAN = "American";

     

        public static void main(String[] args) {

            //        Human human = null;

            //        human = new Factory().getHuman(Factory.CHINESE);

            //        human.eat();

            //        human.walk();

            //        human = new Factory().getHuman(Factory.AMERICAN);

            //        human.eat();

            //        human.walk();

     

            ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");

            Human human = null;

            human = (Human) ctx.getBean(CHINESE);

            human.eat();

            human.walk();

            human = (Human) ctx.getBean(AMERICAN);

            human.eat();

            human.walk();

        }

    }

    從這個程序可以看到,ctx就相當于原來的Factory工廠,原來的Factory就可以刪除掉了。然后又把Factory里的兩個常量移到了ClientTest類里,整個程序結構基本一樣。

    再回頭看原來的bean.xml文件的這一句

    <bean id="Chinese" class="cn.com.chengang.spring.Chinese"/>

    id就是ctx.getBean的參數值,一個字符串。class就是一個類(包名+類名)。然后在ClientTest類里獲得Chinese對象就是這么一句

    human = (Human) ctx.getBean(CHINESE);

    因為getBean方法返回的是Object類型,所以前面要加一個類型轉換。

     

    4、總結

    1)也許有人說,IoC和工廠模式不是一樣的作用嗎,用IoC好象還麻煩一點。

           舉個例子,如果用戶需求發生變化,要把Chinese類修改一下。那么前一種工廠模式,就要更改Factory類的方法,并且重新編譯布署。而IoC只需要將class屬性改變一下,并且由于IoC利用了Java反射機制,這些對象是動態生成的,這時我們就可以熱插撥Chinese對象(不必把原程序停止下來重新編譯布署)

     

           2)也許有人說,即然IoC這么好,那么我把系統所有對象都用IoC方式來生成。

           注意,IoC的靈活性是有代價的:設置步驟麻煩、生成對象的方式不直觀、反射比正常生成對象在效率上慢一點。因此使用IoC要看有沒有必要,我認為比較通用的判斷方式是:用到工廠模式的地方都可以考慮用IoC模式。

     

           3)在上面的IoC的方式里,還有一些可以變化的地方。比如,bean.xml不一定要放在項目錄下,也可以放在其他地方,比如cn.com.chengang.spring包里。不過在使用時也要變化一下,如下所示:

    new FileSystemXmlApplicationContext("src/cn/com/chengang/spring/bean.xml");

    另外,bean.xml也可以改成其他名字。這樣我們在系統中就可以分門別類的設置不同的bean.xml

     

    4)關于IoC的低侵入性。

    什么是低侵入性?如果你用過StrutsEJB就會發現,要繼承一些接口或類,才能利用它們的框架開發。這樣,系統就被綁定在StrutsEJB上了,對系統的可移植性產生不利的影響。如果代碼中很少涉及某一個框架的代碼,那么這個框架就可以稱做是一個低侵入性的框架。

    Spring的侵入性很低,Humen.javaChinese.java等幾個類都不必繼承什么接口或類。但在ClientTest里還是有一些Spring的影子:FileSystemXmlApplicationContext類和ctx.getBean方式等。

    現在,低侵入性似乎也成了判定一個框架的實現技術好壞的標準之一。

     

    5)關于bean.xml的用法

    bean.xml的用法還有很多,其中內容是相當豐富的。假設Chinese類里有一個humenName屬性(姓名),那么原的bean.xml修改如下。此后生成Chinese對象時,“陳剛”這個值將自動設置到Chinese類的humenName屬性中。而且由于singletontrue這時生成Chinese對象將采用單例模式,系統僅存在一個Chinese對象實例。

    <?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="Chinese" class="cn.com.chengang.spring.Chinese"  singleton="true">

                  <property name="humenName">

                         <value>陳剛</value>

                  </property>

           </bean>

           <bean id="American" class="cn.com.chengang.spring.American"/>

    </beans>

     

    關于bean.xml的其它用法,不再詳細介紹了,大家自己拿Spring的文檔一看就明白了。

    第三章  IoC中的國際化(CVS版本:V002

    從這一章開始,我將把實例的項目打開一個CVS版本,不知誰能提供一個FTP空間?

    3.1        前言

    標題準確來說應該是“使用Spring中的IoC功能來實現我們所開發項目系統的國際化”,國際化不是針對IoC的,而是針對你開發的整個系統。

    如果你使用過Eclipse的國際化,或者用過Eclipse的“外部化字符串”向導(Eclipse主菜單:源代碼->外部化字符串),那么對Spring提供的國際化功能應該是非常容易理解,兩者基本一樣,或者說各種Java程序的國際化方式都基本一樣。

    先談談Eclipse國際化的兩個組成部分:*.properties的資源文件、獲取資源文件內容的Message類。

    Spring則和Eclipse的處理類似:資源文件兩者是一樣的,不同語言的翻譯放在不同的資源文件里,連起名規則都一樣;EclipseMessage類要自己寫(代碼通用,復制以前項目的即可,或用Eclipse的向導生成一個也行),Spring則已經有寫好的Message類,我們在IoCxml文件里注冊一下即可使用(也可以實現SpringMessageSource接口,自己來寫一個Message類,代碼并不復雜,不過這沒什么必要,用Spring提供的就行了)。

    無論是EclipseMessage類,還是Spring的自帶的Message類,或是我們自己寫一個Message類,都是使用JDKjava.util.ResourceBundle類來實現*.properties文件的讀取。

    下面用實例來體會一下,先給出本章完成之后的項目結構的截圖:

    3.2  簡單實例

    假設我們有如下程序,程序的作用是打印出一個字符串

    package cn.com.chengang.spring;

    public class MessageTest {

        public static void main(String[] args) {

            String str = "ChenGang";

            System.out.println(str);

        }

    }

    現在,我們要讓這個程序能夠根據使用者的語言情況輸出不同的字符,比如:對英文使用者輸出“ChenGang”,對中文使用者輸出“陳剛”,對臺灣使用輸出“陳剛”等等。這個需求的實現方法如下:

    1、創建一系列的資源文件

    cn.com.chengang.spring包下創建以下文件:

    1messages.properties(默認:英文),內容僅一句,如下

    chengang=Giles

    chengang”是鍵值,Giles是要輸出的英文字符串

    2messages_zh_CN.properties(簡體中文)

    chengang=\u9648\u521A

    \u9648\u521A”是UNICODE碼,對應的中文是“陳剛”

    3messages_ zh_TW.properties(繁體中文)

    chengang=\u9673\u525B

    \u9673\u525B”對應的中文是“陳剛”

     

    附注:由于中文是要轉換成UNICODE碼,在編輯和閱讀上有諸多不便,如果是用EclipseIDE,則有一個編輯資源文件的插件jinto,下載網址是http://www.guh-software.de/,用它打開的資源文件如下圖所示,可以看到三個資源在一個界面反映了出來。

    如果你不用Eclipse,而是用EditplugsJDK的方式來編程(現在還有這樣的原始人嗎?),你也可以用JDK自帶的native2ascii.exe程序來將中文字串轉成UNICODE碼。Ant中還提供了一個相應的任務:<native2ascii encoding="GBK" src="${src}" dest="${build}"/>,其中GBK是一個中國的字符集。

     

    2、修改bean.xml

    Spring自帶的org.springframework.context.support.ResourceBundleMessageSource類注冊到bean.xml中,這個類的作用是獲取資源文件的內容,注冊到IoCbean.xml文件中是為了自動獲得此類的對象(Spring做了一些簡化編程的處理)。

    <?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="Chinese" class="cn.com.chengang.spring.Chinese"/>

           <bean id="American" class="cn.com.chengang.spring.American"/>

           <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

                  <property name="basenames">

                         <list>

                                <value>cn.com.chengang.spring.messages</value>

                         </list>

                  </property>

           </bean>

    </beans>

    代碼說明:

    l           id="messageSource" 的設置是不變的、必須的。

    l           ResourceBundleMessageSourceSpring的一個Message類。這里還有一個選擇,用ReloadableResourceBundleMessageSource類,此類可以提供不用重啟即可重新加載資源文件的特性(前者對資源文件只加載一次)。對于那種有熱修改資源文件的需求,后者比較合適,只是后者在效率上有可能有損耗,因為至少要多一些檢查資源文件是否改變的代碼(這只是我的猜測,我沒有仔佃去讀這段的源碼)。

    l           basenames”是不變的、必須的。它是ResourceBundleMessageSource的一個屬性,在源代碼中的定義是“private String[] basenames;”,可見它是一個字符串數組。

    l           cn.com.chengang.spring.messages”是把資源文件的位置傳入到basenames屬性中。注意:三個資源文件只需要將共同的主名(紅色字體)傳入:messages.propertiesmessages_zh_CN.propertiesmessages_zh_TW.properties

     

    3、使用。修改MessageTest類,如下

    package cn.com.chengang.spring;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.FileSystemXmlApplicationContext;

    public class MessageTest {

        public static void main(String[] args) {

            ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");

            String str = ctx.getMessage("chengang", null, null);

            System.out.println(str);

        }

    }

    代碼說明:

    1main方法里

    l           第一句取得bean.xml文件的配置信息。

    l           第二句從資源文件里得到鍵值chengang對應的字符串。

    l           第三句將字符串打印出來,結果是打印的是“陳剛”,說明讀取的是messages_zh_CN.properties資源文件。

    2ctx.getMessage("chengang", null, null);有三個參數:

    l           第一個是資源文件的鍵值;

    l           第二個是資源文件字符串的參數,由于本字符串沒有參數,所以用一個null(后面給出了一個用到字符串參數的實例);

    l           第三個是一個java.util. Locale類型的參數。參數為null,則表示根據使用者的語言環境來選擇Locale,因為我用的是中文版的windows,所以在取字符串時它自動選擇了messages_zh_CN.properties資源文件。
       
    這其中還有一個控制點在JVMJVM會根據當前操作系統的語言環境進行相應處理,我們可以通過在JVM啟動參數中追加“-Duser.language=zh_TW”來設定當前JVM語言類型,通過JVM級的設定,也可以實現自動切換所使用的資源文件類型。
       
    所以這里面的控制語言的方式有三種:從最低層的操作系統的Locale設定,到更上一層的JVMLocale設定,再到程序一級的Locale設定。

    3.3  資源文件的其他使用方式:

    package cn.com.chengang.spring;

    import java.util.Locale;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.FileSystemXmlApplicationContext;

    import org.springframework.context.support.ResourceBundleMessageSource;

    public class MessageTest {

        public static void main(String[] args) {

            ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");

            String str = ctx.getMessage("chengang", null, null);

            System.out.println(str); //輸出“陳剛”

            /*

             * 使用了messages.properties

             */

            str = ctx.getMessage("chengang", null, new Locale(""));

            System.out.println(str);//輸出“Giles

            /*

             * 使用了messages_zh_CN.properties

             */

            str = ctx.getMessage("chengang", null, new Locale("zh", "CN"));

            System.out.println(str);//輸出“陳剛”

            /*

             * 使用了messages_zh_TW.properties

             */

            str = ctx.getMessage("chengang", null, new Locale("zh", "TW"));

            System.out.println(str);//輸出“陳剛”

            /*

             * 使用了messages_zh_TW.properties,從這里可見資源文件的起名可以很隨意,

             * 比如我們建立一個messages_123.properties,在傳參數時候就可以這樣:

             * new Locale("123"),一樣也可以取出messages_123.properties中的值

             */

            str = ctx.getMessage("chengang", null, new Locale("zh_TW"));

            System.out.println(str);//輸出“陳剛”

            /*

             * 當找不到相應的資源文件時,使用了messages_zh_CN.properties

             */

            str = ctx.getMessage("chengang", null, new Locale("abcd"));

            System.out.println(str);//輸出“陳剛”

             /**

             * 不通過IoC注冊,直接使用ResourceBundleMessageSource類的寫法。

             */

            ResourceBundleMessageSource s = new ResourceBundleMessageSource();

            s.setBasename("cn.com.chengang.spring.messages");

            str = s.getMessage("chengang", null, null);

            System.out.println(str);//輸出“陳剛”

        }

    }

    代碼說明:

    前面說過控制語言的方式有三種:從最低層的操作系統的Locale設定,到更上一層的JVMLocale設定,再到程序一級的Locale設定。我認為最佳的方法是在程序一級進行控制:定義一個統一的Locale靜態變量,然后整個系統中只使用這一個變量,以后就可以通過界面操作設置此Locale變量的值,讓用戶來選擇他所需的軟件語言。而且我們也可以將此靜態變量設成null值,來自動選擇資源文件。

    另外,Locale里也定義了一些常量,我們可以直接使用而不必去new一個Locale對象,如:“Locale.ENGLISH”。

     

    3.4  再一個實例

    這個實例演示了如何使用多個資源文件,以及如何使用字符串參數

    1)在cn.com.chengang.spring包下再創建一個資源文件messagesOther_zh_CN.properties

    chengang.info=\u9648\u521A\uFF0C\u7F51\u540D\uFF1A{0}\uFF0C\u82F1\u6587\u540D\uFF1A{1}\uFF0CBlog\uFF1A{2}

    其中UNICODE字符串對應的中文是:“陳剛,網名:{0},英文名:{1}Blog{2}”,這個字符串一共有三個參數。

    2)修改 bean.xml文件

    因為basenames屬性是一個數組,當然也就可以接收多個資源文件設定。具體修改如下面的紅字部份

    <?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="Chinese" class="cn.com.chengang.spring.Chinese"/>

           <bean id="American" class="cn.com.chengang.spring.American"/>

           <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

                  <property name="basenames">

                         <list>

                                <value>cn.com.chengang.spring.messages</value>

                                <value>cn.com.chengang.spring.messagesOther</value>

                         </list>

                  </property>

           </bean>

    </beans>

     

    3)修改MessageTest類,加入幾行使用的代碼

            String[] strArgs = new String[3];

            strArgs[0]="混北民工";

            strArgs[1]="Giles";

            strArgs[2]="http://blog.csdn.net/glchengang";

            str = ctx.getMessage("chengang.info", strArgs, null);

            System.out.println(str);

    打印出來的結果就是:“陳剛,網名:混北民工,英文名:GilesBloghttp://blog.csdn.net/glchengang

     

    3.5  國際化的實踐建議

    l           建議一個包對應一個資源文件。不要整個系統都使用一個資源文件來翻譯,這樣單個文檔的體積就太大了,不利于維護;當然,也不必一個類對應一個資源文件,這樣資源文件又太多了。

    l           建議資源文件和其翻譯類/包在同一目錄下。不過,如果是要將軟件打成一外JAR包或WAR包,建議把資源文件分離出來,這樣可以修改資源文件,而不必再次打包。

    l           建議字符串項的鍵值上加上其所在的類名。比如:上面的chengangchengang.info最好是取名成MessageTest.chengangMessageTest.chengang.info。這樣查找使用此鍵值的類會方便很多。

     

     

    參考文獻

    l           夏昕的<<Spring開發指南>>  http://www.xiaxin.net/Spring_Dev_Guide.rar 

    posted on 2005-03-05 14:20 閱讀(2083) 評論(2)  編輯  收藏 所屬分類: J2ee

    評論

    # re: Spring學習筆記[未登錄]  回復  更多評論   

    如果只是少數幾個開發的話,或是自己開發的話,springmvc+spring 比strut +spring 光配置使用上就要簡單一倍,而且不存在整合問題。比struts要自由了許多,不需要局限于FormBean,sturts標簽,可以用任何你喜歡的方式來實現。spingmvc 能做的遠比文檔上寫的要多的多, 慢慢的深入研究可以把它變成屬于你自己的mvc。
    2008-10-16 17:54 | alex

    # re: Spring學習筆記  回復  更多評論   

    spring代碼下載:http://www.zuidaima.com/share/search.htm?key=spring
    2014-06-18 22:52 | zuidaima
    主站蜘蛛池模板: 亚洲综合一区国产精品| 亚洲人成在线精品| 日本视频免费观看| 五月天婷亚洲天综合网精品偷| 亚洲午夜理论片在线观看| 黄色成人网站免费无码av| 亚洲伦理中文字幕| 99久久免费精品国产72精品九九| 亚洲制服丝袜中文字幕| 成年人在线免费观看| 亚洲精品无码专区在线播放| 国产人成免费视频| AAAAA级少妇高潮大片免费看| 亚洲狠狠婷婷综合久久久久| 久9久9精品免费观看| 亚洲综合亚洲国产尤物| 性xxxx视频播放免费| 国产亚洲漂亮白嫩美女在线| 亚洲午夜福利在线观看| 亚欧免费一级毛片| 亚洲AV成人一区二区三区在线看| 啦啦啦在线免费视频| 一个人看的免费视频www在线高清动漫| 亚洲一级特黄大片无码毛片| 国产免费网站看v片在线| 亚洲综合久久久久久中文字幕| 好男人www免费高清视频在线| 亚洲AV综合色区无码一二三区 | 亚洲VA中文字幕无码毛片| 99精品视频免费观看| 色婷五月综激情亚洲综合| 免费又黄又爽又猛的毛片| a在线视频免费观看| 亚洲一级在线观看| 九月婷婷亚洲综合在线| 一区二区在线免费观看| 亚洲国产精品无码久久久秋霞1| 亚洲日韩激情无码一区| 毛片免费全部免费观看| 色www永久免费| 亚洲AV永久无码精品网站在线观看|