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

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

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

    潛心學(xué)習(xí) 技術(shù)強(qiáng)身

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      14 隨筆 :: 0 文章 :: 8 評(píng)論 :: 0 Trackbacks

    2009年8月5日 #

    轉(zhuǎn)自:http://m.tkk7.com/Unmi/archive/2007/12/04/165035.html
    一:要解決的問(wèn)題

    我們?cè)趪L鮮 JDK1.5 的時(shí)候,相信不少人遇到過(guò) Unsupported major.minor version 49.0 錯(cuò)誤,當(dāng)時(shí)定會(huì)茫然不知所措。因?yàn)閯傞_(kāi)始那會(huì)兒,網(wǎng)上與此相關(guān)的中文資料還不多,現(xiàn)在好了,網(wǎng)上一找就知道是如何解決,大多會(huì)告訴你要使用 JDK 1.4 重新編譯。那么至于為什么,那個(gè) major.minor 究竟為何物呢?這就是本篇來(lái)講的內(nèi)容,以使未錯(cuò)而先知。

    我覺(jué)得我是比較幸運(yùn)的,因?yàn)樵谟龅侥莻€(gè)錯(cuò)誤之前已研讀過(guò)《深入 Java 虛擬機(jī)》第二版,英文原書名為《Inside the Java Virtual Machine》( Second Edition),看時(shí)已知曉 major.minor 藏匿于何處,但沒(méi)有切身體會(huì),待到與 Unsupported major.minor version 49.0 真正會(huì)面試,正好是給我驗(yàn)證了一個(gè)事實(shí)。

    首先我們要對(duì) Unsupported major.minor version 49.0 建立的直接感覺(jué)是:JDK1.5 編譯出來(lái)的類不能在 JVM 1.4 下運(yùn)行,必須編譯成 JVM 1.4 下能運(yùn)行的類。(當(dāng)然,也許你用的還是 JVM 1.3 或 JVM 1.2,那么就要編譯成目標(biāo) JVM 能認(rèn)可的類)。這也解決問(wèn)題的方向。

    二:major.minor 棲身于何處

    何謂 major.minor,且又居身于何處呢?先感性認(rèn)識(shí)并找到 major.minor 來(lái)。

    寫一個(gè) Java Hello World! 代碼,然后用 JDK 1.5 的編譯器編譯成,HelloWorld.java
     1package com.unmi;
     2
     3public class HelloWorld
     4{
     5    public static void main(String[] args)
     6    {
     7        System.out.println("Hello, World!");
     8    }

     9}

    10
    用 JDK 1.5 的 javac -d .  HelloWorld.java 編譯出來(lái)的字節(jié)碼 HelloWorld.class 用 UltraEdit 打開(kāi)來(lái)的內(nèi)容如圖所示:

    HelloWorldClassUnmi.jpg


    從上圖中我們看出來(lái)了什么是 major.minor version 了,它相當(dāng)于一個(gè)軟件的主次版本號(hào),只是在這里是標(biāo)識(shí)的一個(gè) Java Class 的主版本號(hào)和次版本號(hào),同時(shí)我們看到 minor_version 為 0x0000,major_version 為 0x0031,轉(zhuǎn)換為十制數(shù)分別為0 和 49,即 major.minor 就是 49.0 了。

    三:何謂 major.minor 以及何用

    Class 文件的第 5-8 字節(jié)為 minor_version 和 major_version。Java class 文件格式可能會(huì)加入新特性。class 文件格式一旦發(fā)生變化,版本號(hào)也會(huì)隨之變化。對(duì)于 JVM 來(lái)說(shuō),版本號(hào)確定了特定的 class 文件格式,通常只有給定主版本號(hào)和一系列次版本號(hào)后,JVM 才能夠讀取 class 文件。如果 class 文件的版本號(hào)超出了 JVM 所能處理的有效范圍,JVM 將不會(huì)處理該 class 文件。

    在 Sun 的 JDK 1.0.2 發(fā)布版中,JVM 實(shí)現(xiàn)支持從 45.0 到 45.3 的 class 文件格式。在所有 JDK 1.1 發(fā)布版中的 JVM 都能夠支持版本從 45.0 到 45.65535 的 class 文件格式。在 Sun 的 1.2 版本的 SDK 中,JVM 能夠支持從版本 45.0 到46.0 的 class 文件格式。

    1.0 或 1.2 版本的編譯器能夠產(chǎn)生版本號(hào)為 45.3 的 class 文件。在 Sun 的 1.2 版本 SDK 中,Javac 編譯器默認(rèn)產(chǎn)生版本號(hào)為 45.3  的 class 文件。但如果在 javac 命令行中指定了 -target 1.2 標(biāo)志,1.2 版本的編譯器將產(chǎn)生版本號(hào)為 46.0 的 class 文件。1.0 或 1.1 版本的 JVM 上不能運(yùn)行使用-target 1.2 標(biāo)志所產(chǎn)生的 class 文件。

    JVM 實(shí)現(xiàn)的 第二版中修改了對(duì) class 文件主版本號(hào)和次版本號(hào)的解釋。對(duì)于第二版而言,class 文件的主版本號(hào)與 Java 平臺(tái)主發(fā)布版的版本號(hào)保持一致(例如:在 Java 2 平臺(tái)發(fā)布版上,主版本號(hào)從 45 升至 46),次版本號(hào)與特定主平臺(tái)發(fā)布版的各個(gè)發(fā)布版相關(guān)。因此,盡管不同的 class 文件格式可以由不同的版本號(hào)表示,但版本號(hào)不一樣并不代表 class 文件格式不同。版本號(hào)不同的原因可能只是因?yàn)?class 文件由不同發(fā)布版本的 java 平臺(tái)產(chǎn)生,可能 class 文件的格式并沒(méi)有改變。

    上面三段節(jié)選自《深入 Java 虛擬機(jī)》,啰嗦一堆,JDK 1.2 開(kāi)啟了 Java 2 的時(shí)代,但那個(gè)年代仍然離我們很遠(yuǎn),我們當(dāng)中很多少直接跳在 JDK 1.4 上的,我也差不多,只是項(xiàng)目要求不得不在一段時(shí)間里委屈在 JDK 1.3 上。不過(guò)大致我們可以得到的信息就是每個(gè)版本的 JDK 編譯器編譯出的 class 文件中都帶有一個(gè)版本號(hào),不同的 JVM 能接受一個(gè)范圍 class 版本號(hào),超出范圍則要出錯(cuò)。不過(guò)一般都是能向后兼容的,知道 Sun 在做 Solaris 的一句口號(hào)嗎?保持對(duì)先前版本的 100% 二進(jìn)制兼容性,這也是對(duì)客戶的投資保護(hù)。

    四:其他確定 class 的 major.minor version 辦法

    1)Eclipse 中查看
          Eclipse 3.3 加入的新特征,當(dāng)某個(gè)類沒(méi)有關(guān)聯(lián)到源代碼,打開(kāi)它會(huì)顯示比較詳細(xì)的類信息,當(dāng)然還未到源碼級(jí)別了,看下圖是打開(kāi) 2.0 spring.jar 中 ClasspathXmlApplicationContext.class 顯示的信息

    eclipseclass1.jpg

    2)命令 javap -verbose
           對(duì)于編譯出的 class 文件用 javap -verbose 能顯示出類的 major.minor 版本,見(jiàn)下圖:

    JavapVerboseUnmi.jpg

    3)  MANIFEST 文件
          把 class 打成的 JAR 包中都會(huì)有文件 META-INF\MANIFEST,這個(gè)文件一般會(huì)有編譯器的信息,下面列幾個(gè)包的 META-INF\MANIFEST 文件內(nèi)容大家看看
          ·Velocity-1.5.jar 的 META-INFO\MANIFEST 部份內(nèi)容
                      Manifest-Version: 1.0
                      Ant-Version: Apache Ant 1.7.0
                      Created-By: Apache Ant
                      Package: org.apache.velocity
                      Build-Jdk: 1.4.2_08
                      Extension-Name: velocity
                我們看到是用 ant 打包,構(gòu)建用的JDK是 1.4.2_08,用 1.4 編譯的類在 1.4 JVM 中當(dāng)然能運(yùn)行。如果那人用 1.5 的 JDK 來(lái)編譯,然后用 JDK 1.4+ANT 來(lái)打包就太無(wú)聊了。
          ·2.0 spring.jar 的 META-INFO\MANIFEST 部份內(nèi)容
                      Manifest-Version: 1.0
                      Ant-Version: Apache Ant 1.6.5
                      Created-By: 1.5.0_08-b03 (Sun Microsystems Inc.)
                      Implementation-Title: Spring Framework
               這下要注意啦,它是用的 JDK 1.5 來(lái)編譯的,那么它是否帶了 -target 1.4 或 -target 1.3 來(lái)編譯的呢?確實(shí)是的,可以查看類的二進(jìn)制文件,這是最保險(xiǎn)的。所在 spring-2.0.jar 也可以在 1.4 JVM 中加載執(zhí)行。
          ·自已一個(gè)項(xiàng)目中用 ant 打的 jar 包的 META-INFO\MANIFEST
                      Manifest-Version: 1.0
                      Ant-Version: Apache Ant 1.7.0
                      Created-By: 1.4.2-b28 (Sun Microsystems Inc.)
                用的是 JDK 1.4 構(gòu)建打包的。

    第一第二種辦法能明確知道 major.minor version,而第三種方法應(yīng)該也沒(méi)問(wèn)題,但是碰到變態(tài)構(gòu)建就難說(shuō)了,比如誰(shuí)把那個(gè) META-INFO\MANIFEST 打包后換了也未可知。直接查看類的二進(jìn)制文件的方法可以萬(wàn)分保證,準(zhǔn)確無(wú)誤,就是工具篡改我也認(rèn)了。

    五:編譯器比較及癥節(jié)之所在

    現(xiàn)在不妨從 JDK 1.1 到 JDK 1.7 編譯器編譯出的 class 的默認(rèn) minor.major version 吧。(又走到 Sun 的網(wǎng)站上翻騰出我從來(lái)都沒(méi)用過(guò)的古董來(lái))

    JDK 編譯器版本 target 參數(shù) 十六進(jìn)制 minor.major 十進(jìn)制 minor.major
    jdk1.1.8 不能帶 target 參數(shù) 00 03   00 2D 45.3
    jdk1.2.2 不帶(默認(rèn)為 -target 1.1) 00 03   00 2D 45.3
    jdk1.2.2 -target 1.2 00 00   00 2E 46.0
    jdk1.3.1_19 不帶(默認(rèn)為 -target 1.1) 00 03   00 2D 45.3
    jdk1.3.1_19 -target 1.3 00 00   00 2F 47.0
    j2sdk1.4.2_10 不帶(默認(rèn)為 -target 1.2) 00 00   00 2E 46.0
    j2sdk1.4.2_10 -target 1.4 00 00   00 30 48.0
    jdk1.5.0_11 不帶(默認(rèn)為 -target 1.5) 00 00   00 31 49.0
    jdk1.5.0_11 -target 1.4 -source 1.4 00 00   00 30 48.0
    jdk1.6.0_01 不帶(默認(rèn)為 -target 1.6) 00 00   00 32 50.0
    jdk1.6.0_01 -target 1.5 00 00   00 31 49.0
    jdk1.6.0_01 -target 1.4 -source 1.4 00 00   00 30 48.0
    jdk1.7.0 不帶(默認(rèn)為 -target 1.6) 00 00   00 32 50.0
    jdk1.7.0 -target 1.7 00 00   00 33 51.0
    jdk1.7.0 -target 1.4 -source 1.4 00 00   00 30 48.0
    Apache Harmony 5.0M3 不帶(默認(rèn)為 -target 1.2) 00 00   00 2E 46.0
    Apache Harmony 5.0M3 -target 1.4 00 00   00 30 48.0

    上面比較是 Windows 平臺(tái)下的 JDK 編譯器的情況,我們可以此作些總結(jié):

    1) -target 1.1 時(shí) 有次版本號(hào),target 為 1.2 及以后都只用主版本號(hào)了,次版本號(hào)為 0
    2) 從 1.1 到 1.4 語(yǔ)言差異比較小,所以 1.2 到 1.4 默認(rèn)的 target 都不是自身相對(duì)應(yīng)版本
    3) 1.5 語(yǔ)法變動(dòng)很大,所以直接默認(rèn) target 就是 1.5。也因?yàn)槿绱擞?1.5 的 JDK 要生成目標(biāo)為 1.4 的代碼,光有 -target 1.4 不夠,必須同時(shí)帶上 -source 1.4,指定源碼的兼容性,1.6/1.7 JDk 生成目標(biāo)為 1.4 的代碼也如此。
    4) 1.6 編譯器顯得較為激進(jìn),默認(rèn)參數(shù)就為 -target 1.6。因?yàn)?nbsp;1.6 和 1.5 的語(yǔ)法無(wú)差異,所以用 -target 1.5 時(shí)無(wú)需跟著 -source 1.5。
    5) 注意 1.7 編譯的默認(rèn) target 為 1.6
    6) 其他第三方的 JDK 生成的 Class 文件格式版本號(hào)同對(duì)應(yīng) Sun 版本 JDK
    7) 最后一點(diǎn)最重要的,某個(gè)版本的 JVM 能接受 class 文件的最大主版本號(hào)不能超過(guò)對(duì)應(yīng) JDK 帶相應(yīng) target 參數(shù)編譯出來(lái)的 class 文件的版本號(hào)

    上面那句話有點(diǎn)長(zhǎng),一口氣讀過(guò)去不是很好理解,舉個(gè)例子:1.4 的 JVM 能接受最大的 class 文件的主版本號(hào)不能超過(guò)用 1.4 JDK 帶參數(shù) -target 1.4 時(shí)編譯出的 class 文件的主版本號(hào),也就是 48。

    因?yàn)?1.5 JDK 編譯時(shí)默認(rèn) target 為 1.5,出來(lái)的字節(jié)碼 major.minor version 是 49.0,所以 1.4 的 JVM 是無(wú)法接受的,只有拋出錯(cuò)誤。

    那么又為什么從 1.1 到 1.2、從 1.2 到 1.3 或者從 1.3 到 1.4 的 JDK 升級(jí)不會(huì)發(fā)生 Unsupported major.minor version 的錯(cuò)誤呢,那是因?yàn)?1.2/1.3/1.4 都保持了很好的二進(jìn)制兼容性,看看 1.2/1.3/1.4 的默認(rèn) target 分別為 1.1/1.1/1.2 就知道了,也就是默認(rèn)情況下1.4 JDK 編譯出的 class 文件在 JVM 1.2 下都能加載執(zhí)行,何況于 JVM 1.3 呢?(當(dāng)然要去除使用了新版本擴(kuò)充的 API 的因素)

    六:找到問(wèn)題解決的方法

    那么現(xiàn)在如果碰到這種問(wèn)題該知道如何解決了吧,還會(huì)像我所見(jiàn)到有些兄弟那樣,去找個(gè) 1.4 的 JDK 下載安裝,然后用其重新編譯所有的代碼嗎?其實(shí)大可不必如此費(fèi)神,我們一定還記得 javac 還有個(gè) -target 參數(shù),對(duì)啦,可以繼續(xù)使用 1.5 JDK,編譯時(shí)帶上參數(shù) -target 1.4 -source 1.4 就 OK 啦,不過(guò)你一定要對(duì)哪些 API 是 1.5 JDK 加入進(jìn)來(lái)的了如指掌,不能你的 class 文件拿到 JVM 1.4 下就會(huì) method not found。目標(biāo) JVM 是 1.3 的話,編譯選項(xiàng)就用 -target 1.3 -source 1.3 了。

    相應(yīng)的如果使用 ant ,它的 javac 任務(wù)也可對(duì)應(yīng)的選擇 target 和 source

    <javac target="1.4" source="1.4" ............................/>

    如果是在開(kāi)發(fā)中,可以肯定的是現(xiàn)在真正算得上是 JAVA IDE 對(duì)于工程也都有編譯選項(xiàng)設(shè)置目標(biāo)代碼的。例如 Eclipse 的項(xiàng)目屬性中的 Java Compiler 設(shè)置,如圖

    EclipseCompiler.JPG


    自已設(shè)定編譯選項(xiàng),你會(huì)看到選擇不同的 compiler compliance level 是,Generated class files compatibility 和 Source compatibility 也在變,你也可以手動(dòng)調(diào)整那兩項(xiàng),手動(dòng)設(shè)置后你就不用很在乎用的什么版本的編譯器了,只要求他生成我們希望的字節(jié)碼就行了,再引申一下就是即使源代碼是用 VB 寫的,只要能編譯成 JVM 能執(zhí)行的字節(jié)碼都不打緊。在其他的 IDE 也能找到相應(yīng)的設(shè)置對(duì)話框的。

    其他時(shí)候,你一定要知道當(dāng)前的 JVM 是什么版本,能接受的字節(jié)碼主版本號(hào)是多少(可對(duì)照前面那個(gè)表)。獲息當(dāng)前 JVM 版本有兩種途徑:

    第一:如果你是直接用 java 命令在控制臺(tái)執(zhí)行程序,可以用 java -version 查看當(dāng)前的 JVM 版本,然后確定能接受的 class 文件版本

    第二:如果是在容器中執(zhí)行,而不能明確知道會(huì)使用哪個(gè) JVM,那么可以在容器中執(zhí)行的程序中加入代碼 System.getProperty("java.runtime.version"); 或 System.getProperty("java.class.version"),獲得 JVM 版本和能接受的 class 的版本號(hào)。

    最后一絕招,如果你不想針對(duì)低版本的 JVM 用 target 參數(shù)重新編譯所有代碼;如果你仍然想繼續(xù)在代碼中用新的 API 的話;更有甚者,你還用了 JDK 1.5 的新特性,譬如泛型、自動(dòng)拆裝箱、枚舉等的話,那你用 -target 1.4 -source 1.4 就沒(méi)法編譯通過(guò),不得不重新整理代碼。那么告訴你最后一招,不需要再?gòu)脑创a著手,直接轉(zhuǎn)換你所正常編譯出的字節(jié)碼,繼續(xù)享用那些新的特性,新的 API,那就是:請(qǐng)參考之前的一篇日志:Retrotranslator讓你用JDK1.5的特性寫出的代碼能在JVM1.4中運(yùn)行,我就是這么用的,做好測(cè)試就不會(huì)有問(wèn)題的。

    七:再議一個(gè)實(shí)際發(fā)生的相關(guān)問(wèn)題

    這是一個(gè)因?yàn)榭截?Tomcat 而產(chǎn)生的 Unsupported major.minor version 49.0 錯(cuò)誤。情景是:我本地安裝的是 JDK 1.5,然后在網(wǎng)上找了一個(gè) EXE 的 Tomcat 安裝文件安裝了并且可用。后來(lái)同事要一個(gè) Tomcat,不想下載或安裝,于是根據(jù)我以往的經(jīng)驗(yàn)是把我的 Tomcat 整個(gè)目錄拷給他應(yīng)該就行了,結(jié)果是拿到他那里瀏覽 jsp 文件都出現(xiàn) Unsupported major.minor version 49.0 錯(cuò)誤,可以確定的是他安裝的是 1.4 的 JDK,但我還是有些納悶,先前對(duì)這個(gè)問(wèn)題還頗有信心的我傻眼了。慣性思維是編譯好的 class 文件拿到低版本的 JVM 會(huì)出現(xiàn)如是異常,可現(xiàn)并沒(méi)有用已 JDK 1.5 編譯好的類要執(zhí)行啊。

    后來(lái)仔細(xì)看異常信息,終于發(fā)現(xiàn)了 %TOMCAT_HOME%\common\lib\tools.jar 這一眉目,因?yàn)?jsp 文件需要依賴它來(lái)編譯,打來(lái)這個(gè) tools.jar 中的一個(gè) class 文件來(lái)看看,49.0,很快我就明白原來(lái)這個(gè)文件是在我的機(jī)器上安裝 Tomcat 時(shí)由 Tomcat 安裝程序從 %JDK1.5%\lib 目錄拷到 Tomcat 的 lib 目錄去的,造成在同事機(jī)器上編譯 JSP 時(shí)是 1.4 的 JVM 配搭著 49.0 的 tools.jar,那能不出錯(cuò),于是找來(lái) 1.4  JDK 的 tools.jar 替換了 Tomcat 的就 OK 啦。

    八:小結(jié)

    其實(shí)理解 major.minor 就像是我們可以這么想像,同樣是微軟件的程序,32 位的應(yīng)用程序不能拿到 16 位系統(tǒng)中執(zhí)行那樣。

    如果我們發(fā)布前了解到目標(biāo) JVM 版本,知道怎么從 java class 文件中看出 major.minor 版本來(lái),就不用等到服務(wù)器報(bào)出異常才著手去解決,也就能預(yù)知到可能發(fā)生的問(wèn)題。

    其他時(shí)候遇到這個(gè)問(wèn)題應(yīng)具體解決,總之問(wèn)題的根由是低版本的  JVM 無(wú)法加載高版本的 class 文件造成的,找到高版本的 class 文件處理一下就行了。

    posted @ 2009-08-05 16:27 平濤 閱讀(402) | 評(píng)論 (0)編輯 收藏

    2009年8月1日 #

         摘要: VO(value object) 值對(duì)象     通常用于業(yè)務(wù)層之間的數(shù)據(jù)傳遞,和PO一樣也是僅僅包含數(shù)據(jù)而已。但應(yīng)是抽象出的業(yè)務(wù)對(duì)象,可以和表對(duì)應(yīng),也可以不,這根據(jù)業(yè)務(wù)的需要.個(gè)人覺(jué)得同DTO(數(shù)據(jù)傳輸對(duì)象),在web上傳遞。     對(duì)于數(shù)據(jù)庫(kù)而言,每一個(gè)VO對(duì)象可以表示出一張表中的一行記錄,此類的名稱要與表的名稱一致。 B...  閱讀全文
    posted @ 2009-08-01 11:12 平濤 閱讀(521) | 評(píng)論 (1)編輯 收藏

    2009年7月31日 #

           有許多標(biāo)準(zhǔn)和實(shí)踐準(zhǔn)則可適用于Java開(kāi)發(fā)者,但此處要說(shuō)的,是每個(gè)Java開(kāi)發(fā)者需堅(jiān)守的基本原則。

      一、為代碼加注釋。雖然每個(gè)人都知道這點(diǎn),但有時(shí)卻不自覺(jué)忘了履行,今天你“忘了”加注釋了嗎?雖然注釋對(duì)程序的功能沒(méi)什么“貢獻(xiàn)”,但過(guò)一段時(shí)間,比如說(shuō)兩星期之后或者更長(zhǎng),回過(guò)頭來(lái)看看自己的代碼,說(shuō)不定已經(jīng)記不住它是干什么的了。如果這些代碼是你個(gè)人的,那還算是走運(yùn)了,不幸的是,當(dāng)然了,大多數(shù)時(shí)候都是別人的不幸,很多時(shí)候大家都是在為公司寫代碼,寫代碼的人也許早已經(jīng)離開(kāi)了公司,但別忘了一句古話,有來(lái)有往嘛,為他人,也為我們自己,請(qǐng)為你的代碼加上注釋。

      二、不要讓事情復(fù)雜化。程序員有時(shí)候總是對(duì)簡(jiǎn)單問(wèn)題想出復(fù)雜的解決方案,比如說(shuō),在只有五個(gè)用戶的程序中引入EJB、對(duì)程序?qū)崿F(xiàn)了并不需要的框架(framework),之類的還有屬性文件、面向?qū)ο蠼鉀Q方案、多線程等等。為什么要這樣做呢?也許我們并不知道是否這樣會(huì)更好,但這樣做也許可以學(xué)到一些新東西,或者讓自己更感興趣一些。如果是不知道為什么這樣做,建議多請(qǐng)教經(jīng)驗(yàn)豐富的程序員,如果是為了個(gè)人的目的,麻煩讓自己更專業(yè)一點(diǎn)。

      三、始終牢記——“少即是好(Less is more)并不總是對(duì)的”。代碼效率雖然很重要,但在許多解決方案中,編寫更少的代碼并不能改善這些代碼的效率,請(qǐng)看下面這個(gè)簡(jiǎn)單的例子:

    if(newStatusCode.equals("SD") && (sellOffDate == null ||
    todayDate.compareTo(sellOffDate)<0 || (lastUsedDate != null &&
    todayDate.compareTo(lastUsedDate)>0)) ||
    (newStatusCode.equals("OBS") && (OBSDate == null ||
    todayDate.compareTo(OBSDate)<0))){
    newStatusCode = "NYP"; 
    }

      能看明白if條件語(yǔ)句是干什么的嗎?能想出來(lái)是誰(shuí)寫的這段代碼嗎?如果把它分成兩段獨(dú)立的if語(yǔ)句,是不是更容易理解呢,下面是修改后的代碼:

    if(newStatusCode.equals("SD") && (sellOffDate == null ||
    todayDate.compareTo(sellOffDate)<0 || (lastUsedDate != null &&
    todayDate.compareTo(lastUsedDate)>0))){
    newStatusCode = "NYP"; 
    }else
    if(newStatusCode.equals("OBS") && (OBSDate == null ||
    todayDate.compareTo(OBSDate)<0))
    {
    newStatusCode = "NYP"; 
    }

      是不是讀起來(lái)容易多了呢,在此只是多加了一個(gè)if和兩個(gè)花括號(hào),但代碼的可讀性與可理解性就一下子提高了一大截。

      四、請(qǐng)不要硬編碼。開(kāi)發(fā)者經(jīng)常有意“忘記”或忽略掉這點(diǎn),因?yàn)橛行r(shí)候開(kāi)發(fā)日程逼得實(shí)在太緊。其實(shí),多寫一行定義靜態(tài)變量的代碼能花多少時(shí)間呢?

    public class A {
    public static final String S_CONSTANT_ABC = "ABC"; 
    public boolean methodA(String sParam1){
    if (A.S_CONSTANT_ABC.equalsIgnoreCase(sParam1)){
    return true; 
    }
    return false; 
    }
    }

     

      現(xiàn)在,每次需要將“ABC”與其他變量進(jìn)行比較時(shí),不必記住實(shí)際代碼,直接引用A.S_CONSTANT_ABC就行了,而且在今后需要進(jìn)行修改時(shí),也可在一處修改,不會(huì)翻遍整個(gè)源代碼逐個(gè)修改了。

      五、不要“創(chuàng)造”自己的框架(framework)。確切來(lái)說(shuō),有數(shù)以千計(jì)的各種框架存在,而且大多數(shù)是開(kāi)源的,這些框架都是優(yōu)秀的解決方案,可用于日常程序開(kāi)發(fā)中,我們只需使用這些框架的最新版本就行了,至少表面上要跟上形勢(shì)吧。被大家廣為接受的最為明顯的一個(gè)例子就是Struts了,這個(gè)開(kāi)源web框架非常適合用在基于web的應(yīng)用程序中。是不是想開(kāi)發(fā)出自己的Struts呢,還是省點(diǎn)力氣吧,回頭看看第二條——不要讓事情復(fù)雜化。另外,如果正在開(kāi)發(fā)的程序只有3個(gè)窗口,就不要使用Struts了,對(duì)這種程序來(lái)說(shuō),不需要那么多的“控制”。

      六、不要使用println及字符串連接。通常為了調(diào)試方便,開(kāi)發(fā)者喜歡在可能的所有地方都加上System.out.println,也許還會(huì)提醒自己回過(guò)頭來(lái)再來(lái)刪除,但有些時(shí)候,經(jīng)常會(huì)忘了刪除或者不愿意刪除它們。既然使用System.out.println是為了測(cè)試,那么測(cè)試完之后,為什么還要留著它們呢,因?yàn)樵趧h除時(shí),很可能會(huì)刪除掉真正有用的代碼,所以不能低估System.out.println危害啊,請(qǐng)看下面的代碼:

    public class BadCode {
    public static void calculationWithPrint(){
    double someValue = 0D; 
    for (int i = 0; i <10000; i++) {
    System.out.println(someValue = someValue + i); 
    }
    }
    public static void calculationWithOutPrint(){
    double someValue = 0D; 
    for (int i = 0; i < 10000; i++) {
    someValue = someValue + i; 
    }
    }
    public static void main(String [] n) {
    BadCode.calculationWithPrint(); 
    BadCode.calculationWithOutPrint(); 
    }
    }

      從測(cè)試中可以發(fā)現(xiàn),方法calculationWithOutPrint()執(zhí)行用了0.001204秒,作為對(duì)比,方法calculationWithPrint()執(zhí)行可是用了10.52秒。

      要避免浪費(fèi)CPU時(shí)間,最好的方法是引入像如下的包裝方法:

    public class BadCode {
    public static final int DEBUG_MODE = 1; 
    public static final int PRODUCTION_MODE = 2; 
    public static void calculationWithPrint(int logMode){
    double someValue = 0D; 
    for (int i = 0; i < 10000; i++) {
    someValue = someValue + i; 
    myPrintMethod(logMode, someValue); 
    }
    }
    public static void myPrintMethod(int logMode, double value) {
    if (logMode > BadCode.DEBUG_MODE) { return; }
    System.out.println(value); 
    }
    public static void main(String [] n) {
    BadCode.calculationWithPrint(BadCode.PRODUCTION_MODE); 
    }
    }

     

      另外,字符串連接也是浪費(fèi)CPU時(shí)間的一個(gè)大頭,請(qǐng)看下面的示例代碼:

    public static void concatenateStrings(String startingString) {
    for (int i = 0; i < 20; i++) {
    startingString = startingString + startingString; 
    }
    }
    public static void concatenateStringsUsingStringBuffer(String startingString) {
    StringBuffer sb = new StringBuffer(); 
    sb.append(startingString); 
    for (int i = 0; i < 20; i++) {
    sb.append(sb.toString()); 
    }
    }

      在測(cè)試中可發(fā)現(xiàn),使用StringBuffer的方法只用了0.01秒執(zhí)行完畢,而使用連接的方法則用了0.08秒,選擇顯而易見(jiàn)了。

      七、多關(guān)注GUI(用戶界面)。再三強(qiáng)調(diào),GUI對(duì)商業(yè)客戶來(lái)說(shuō),與程序的功能及效率同等重要,GUI是一個(gè)成功程序的最基本部分,而很多IT經(jīng)理往往都沒(méi)注意到GUI的重要性。在現(xiàn)實(shí)生活中,許多公司可能為了節(jié)省開(kāi)支,沒(méi)有雇用那些有著設(shè)計(jì)“用戶友好”界面豐富經(jīng)驗(yàn)的網(wǎng)頁(yè)設(shè)計(jì)者,此時(shí)Java開(kāi)發(fā)者只能依賴他們自身的HTML基本功及在此領(lǐng)域有限的知識(shí),結(jié)果,很多開(kāi)發(fā)出來(lái)的程序都是“計(jì)算機(jī)友好”甚于“用戶友好”。很少有開(kāi)發(fā)者同時(shí)精通軟件開(kāi)發(fā)及GUI設(shè)計(jì),如果你在公司“不幸”被分配負(fù)責(zé)程序界面,就應(yīng)該遵守下面三條原則:

      1、 不要再發(fā)明一次輪子,即不做無(wú)用功。現(xiàn)有的程序可能會(huì)有類似的界面需求。
      2、 先創(chuàng)建一個(gè)原型。這是非常重要一步,用戶一般想看到他們將使用的東西,而且可以先利用這個(gè)原型征求用戶的意見(jiàn),再慢慢修改成用戶想要的樣子。
      3、 學(xué)會(huì)換位思考。換句話來(lái)說(shuō),就是從用戶的角度來(lái)審查程序的需求。舉例來(lái)講,一個(gè)匯總的窗口可以跨頁(yè)或者不跨頁(yè),作為一個(gè)軟件開(kāi)發(fā)者,可能會(huì)傾向于不跨頁(yè),因?yàn)檫@樣簡(jiǎn)單一些。但是,從用戶的角度來(lái)看,可能不希望看到上百行數(shù)據(jù)都擠在同一頁(yè)上。

      八、文檔需求不放松。每個(gè)商業(yè)需求都必須記錄在案,這可能聽(tīng)上去像童話,似乎在現(xiàn)實(shí)生活中很難實(shí)現(xiàn)。而我們要做的是,不管開(kāi)發(fā)時(shí)間多緊迫,不管最終期限多臨近,對(duì)每個(gè)商業(yè)需求都必須記錄在案。

       九、單元測(cè)試、單元測(cè)試、單元測(cè)試。關(guān)于什么是單元測(cè)試的最好方法,在此不便細(xì)說(shuō),只是強(qiáng)調(diào),單元測(cè)試一定要完成,這也是編程中最基本的原則。當(dāng)然了,如果有人幫你做單元測(cè)試自然是最好,如果沒(méi)有,就自己來(lái)做吧,當(dāng)創(chuàng)建一個(gè)單元測(cè)試計(jì)劃時(shí),請(qǐng)遵守以下三條最基本的原則:

      1、 先于編寫類代碼之前編寫單元測(cè)試。
      2、 記錄單元測(cè)試中的代碼注釋。
      3、 測(cè)試所有執(zhí)行關(guān)鍵功能的公有方法,這里不是指set和get方法,除非它們是以自己獨(dú)特方式執(zhí)行set和get方法。

      十、質(zhì)量,而不是數(shù)量。有些時(shí)候因?yàn)楫a(chǎn)品問(wèn)題、期限緊迫、或一些預(yù)料之外的事情,導(dǎo)致常常不能按時(shí)下班,但一般而言,公司不會(huì)因?yàn)楣蛦T經(jīng)常加班而對(duì)之表?yè)P(yáng)和獎(jiǎng)勵(lì),公司只看重高質(zhì)量的工作。如果遵守了前九條原則,你會(huì)發(fā)現(xiàn)自己寫出的代碼bug少且可維護(hù)性高,無(wú)形中質(zhì)量提高了一大步。

    posted @ 2009-07-31 15:38 平濤 閱讀(169) | 評(píng)論 (0)編輯 收藏

    2009年7月30日 #

        Tomcat5 及 Tomcat6 下CP配置。
        主要是根據(jù)MLDN的一個(gè)實(shí)例進(jìn)行配置的。實(shí)例中用的是Tomcat5.5,所以他的CP配置如下:
        第一:將jdbc驅(qū)動(dòng)的jar包,如:MySQL、Oracle的jdbc驅(qū)動(dòng),拷貝到tomcat中l(wèi)ib下。
        注意:必須是tomcat中l(wèi)ib下,如:D:\Tomcat 6.0\lib,但不能是項(xiàng)目中的WEB-INF/lib下,因?yàn)檫@時(shí)tomcat解析不到此類目錄。
        第二:在Tomcat的安裝目錄下conf下找到server.xml,在<host></host>之間加上如下代碼:
     1<Context path="/zhinangtuan" docBase="F:\Eclipse\MyZNTProject\MyZhiNangTuanDemo\WebRoot"
     2        debug="5" reloadable="true" crossContext="true">
     3 
     4     <Logger className="org.apache.catalina.logger.FileLogger"
     5                 prefix="localhost_MysqlTest_log." suffix=".txt"
     6                 timestamp="true"/>
     7                 
     8    <Resource name="jdbc/mldn"  auth="Container" type="javax.sql.DataSource"/>
     9    
    10    <ResourceParams name="jdbc/mldn">
    11        <parameter>
    12            <name>factory</name>
    13            <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
    14        </parameter>
    15        <parameter>
    16            <name>maxActive</name>
    17            <value>100</value>
    18        </parameter>
    19        <parameter>
    20            <name>maxIdle</name>
    21            <value>30</value>
    22        </parameter>
    23        <parameter>
    24            <name>maxWait</name>
    25            <value>5000</value>
    26        </parameter>
    27        <parameter>
    28            <name>username</name>
    29            <value>root</value>
    30        </parameter>
    31        <parameter>
    32            <name>password</name>
    33            <value>mysqladmin</value>
    34        </parameter>
    35        <parameter>
    36            <name>driverClassName</name>
    37            <value>org.gjt.mm.mysql.Driver</value>
    38        </parameter>
    39        <parameter>
    40            <name>url</name>
    41            <value>jdbc:mysql://localhost:3306/mldn</value>
    42        </parameter>
    43      </ResourceParams>
    44    </Context>
        第一部分為項(xiàng)目的發(fā)布路徑。其他的就是數(shù)據(jù)庫(kù)的配置了。
        第三:在Spring的配置文件applicationContext.xml中加上如下代碼:
    1<bean id="dataSource"
    2        class="org.springframework.jndi.JndiObjectFactoryBean"
    3        destroy-method="close">
    4        <property name="jndiName">
    5            <value>java:comp/env/jdbc/mldn</value>
    6        </property>
    7    </bean>

        而我用的Tomcat是6.0.18,在根據(jù)這個(gè)配置后就會(huì)出現(xiàn)javax.naming.NameNotFoundException: Name jdbc is not bound in this Context的錯(cuò)誤。原因是,Tomcat5和Tomcat6的配置有所區(qū)別:
        第一:將jdbc驅(qū)動(dòng)的jar包,拷貝到Tomcat的lib下
        第二:在tomcat中conf下的context.xml文件中<context>與</context>之間加入以下部分:
     1<Resource name="jdbc/mldn"   
     2        auth="Container"       
     3         type="javax.sql.DataSource"
     4         factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
     5         driverClassName="com.mysql.jdbc.Driver"       
     6         url="jdbc:mysql://localhost:3306/mldn?useUnicode=true&amp;characterEncoding=utf-8"       
     7         username="root"       
     8         password="123"       
     9         maxActive="100"       
    10         maxIdle="30"       
    11        maxWait="10000" />
        同時(shí)在項(xiàng)目的web.xml中加入如下代碼(網(wǎng)上說(shuō)可以加也可以不加)
    1<resource-ref>       
    2     <description>DB Connection</description>       
    3     <res-ref-name>jdbc/mldn</res-ref-name>       
    4      <res-type>javax.sql.DataSource</res-type>       
    5      <res-auth>Container</res-auth>       
    6    </resource-ref>

        第三:在Spring的配置文件applicationContext.xml中加上如下代碼:
    1<bean id="dataSource"
    2        class="org.springframework.jndi.JndiObjectFactoryBean"
    3        destroy-method="close">
    4        <property name="jndiName">
    5            <value>java:comp/env/jdbc/mldn</value>
    6        </property>
    7    </bean>

        這樣,Tomcat6下的CP才能正常的運(yùn)行起來(lái)。
    posted @ 2009-07-30 01:21 平濤 閱讀(1760) | 評(píng)論 (4)編輯 收藏

    2009年7月23日 #

        主要是mysql數(shù)據(jù)庫(kù)亂碼問(wèn)題,關(guān)于網(wǎng)頁(yè)中的亂碼(JSP頁(yè)面亂碼,action亂碼)都好解決,只要頁(yè)面的編碼統(tǒng)一就可以了。我比較喜歡用UTF-8編碼,不是很喜歡GBK或GB2312編碼。
          關(guān)于JSP頁(yè)面及action只需添加一個(gè)EncodingFilter就可以了,代碼如下:
     1package cn.zhang.myznt.filter;
     2
     3import java.io.IOException;
     4
     5import javax.servlet.Filter;
     6import javax.servlet.FilterChain;
     7import javax.servlet.FilterConfig;
     8import javax.servlet.ServletException;
     9import javax.servlet.ServletRequest;
    10import javax.servlet.ServletResponse;
    11
    12public class EncodingFilter implements Filter {
    13    private String charset = null;
    14    public void destroy() {
    15
    16    }

    17
    18    public void doFilter(ServletRequest request, ServletResponse response,
    19            FilterChain chain) throws IOException, ServletException {
    20        request.setCharacterEncoding(this.charset);
    21        chain.doFilter(request, response);
    22
    23    }

    24
    25    public void init(FilterConfig arg0) throws ServletException {
    26        this.charset = arg0.getInitParameter("charset");
    27    }

    28
    29}

    30

    在web.xml中注冊(cè)這個(gè)Filter,注意他的位置必須放在需要調(diào)用action及jsp或其他頁(yè)面聲明之前
     1<filter>
     2        <filter-name>encoding</filter-name>
     3        <filter-class>cn.zhang.myznt.filter.EncodingFilter</filter-class>
     4        <init-param>
     5            <param-name>charset</param-name>
     6            <param-value>UTF-8</param-value>
     7        </init-param>
     8    </filter>
     9    <filter-mapping>
    10        <filter-name>encoding</filter-name>
    11        <url-pattern>/*</url-pattern>
    12    </filter-mapping>

    同時(shí)在連接mysql數(shù)據(jù)庫(kù)的時(shí)候也要改為jdbc:mysql://localhost:3306/mldn?useUnicode=true&amp;characterEncoding=utf-8 如果連接在java代碼中使用,請(qǐng)使用&,如果是在xml中使用請(qǐng)寫成&amp;

        關(guān)于mysql的collation字符集和mysql的characterSet字符集問(wèn)題,查了很多資料都說(shuō)要設(shè)置成一樣,我想那只是針對(duì)如果你選GBK作為數(shù)據(jù)庫(kù)編碼的時(shí)候所用,但如果選用UTF8作為數(shù)據(jù)庫(kù)編碼的時(shí)候就不一定正確了。
        今天根據(jù)網(wǎng)上的資料將所有的characterSet設(shè)置成utf8(可用mysql> SHOW VARIABLES LIKE 'character_set_%';查看),一直在測(cè)試亂碼問(wèn)題解決沒(méi)有。在測(cè)試過(guò)程發(fā)現(xiàn)傳遞的中文都是正確的,可就是在MySQL Client中查看的是亂碼,所以繼續(xù)找方法解決,但其實(shí)這個(gè)時(shí)候你插進(jìn)去的中文已經(jīng)是正常的了,只是在MySQL Client中顯示是亂碼。那么為什么會(huì)這樣?MySQL Client設(shè)置成UTF8的時(shí)候中文不能正常顯示,此時(shí)我們應(yīng)該將charact_set_client :設(shè)置成gbk,這樣就可以正常顯示中文了。
        可以在my.ini中

    [mysql]

    default-character-set=gbk


    而下面的default-character-set=utf8,兩個(gè)default-character-set的設(shè)置是不一樣的。當(dāng)然如果你選用gbk作為數(shù)據(jù)庫(kù)編碼,是需要設(shè)置成一樣的。
    posted @ 2009-07-23 17:40 平濤 閱讀(522) | 評(píng)論 (0)編輯 收藏

    tomcat下jsp出現(xiàn)getOutputStream() has already been called for this response異常的原因和解決方法

    在tomcat下jsp中出現(xiàn)此錯(cuò)誤一般都是在jsp中使用了輸出流(如輸出圖片驗(yàn)證碼,文件下載等),
    沒(méi)有妥善處理好的原因。
    具體的原因就是
    在tomcat中jsp編譯成servlet之后在函數(shù)_jspService(HttpServletRequest request, HttpServletResponse response)的最后
    有一段這樣的代碼
    finally {
          if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
        }
    這里是在釋放在jsp中使用的對(duì)象,會(huì)調(diào)用response.getWriter(),因?yàn)檫@個(gè)方法是和
    response.getOutputStream()相沖突的!所以會(huì)出現(xiàn)以上這個(gè)異常。

    然后當(dāng)然是要提出解決的辦法,其實(shí)挺簡(jiǎn)單的(并不是和某些朋友說(shuō)的那樣--
    將jsp內(nèi)的所有空格和回車符號(hào)所有都刪除掉),

    在使用完輸出流以后調(diào)用以下兩行代碼即可:
    out.clear();
    out = pageContext.pushBody();

    最后這里是一個(gè)輸出彩色驗(yàn)證碼例子(這樣的例子幾乎隨處可見(jiàn))
    imag.jsp

    <%@ page  import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %>
    <%@ page import="java.io.OutputStream" %>
    <%!
    Color getRandColor(int fc,int bc){
    Random random = new Random();
    if(fc>255) fc=255;
    if(bc>255) bc=255;
    int r=fc+random.nextInt(bc-fc);
    int g=fc+random.nextInt(bc-fc);
    int b=fc+random.nextInt(bc-fc);
    return new Color(r,g,b);
    }
    %>
    <%
    try{
    response.setHeader("Pragma","No-cache");
    response.setHeader("Cache-Control","no-cache");
    response.setDateHeader("Expires", 0);
    int width=60, height=20;
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    OutputStream os=response.getOutputStream();
    Graphics g = image.getGraphics();
    Random random = new Random();
    g.setColor(getRandColor(200,250));
    g.fillRect(0, 0, width, height);

    g.setFont(new Font("Times New Roman",Font.PLAIN,18));
    g.setColor(getRandColor(160,200));
    for (int i=0;i<155;i++)
    {
    int x = random.nextInt(width);
    int y = random.nextInt(height);
    int xl = random.nextInt(12);
    int yl = random.nextInt(12);
    g.drawLine(x,y,x+xl,y+yl);
    }
    String sRand="";
    for (int i=0;i<4;i++){
    String rand=String.valueOf(random.nextInt(10));
    sRand+=rand;
    g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
    g.drawString(rand,13*i+6,16);
    }
    session.setAttribute("rand",sRand);
    g.dispose();

    ImageIO.write(image, "JPEG",os);
    os.flush();
    os.close();
    os=null;
    response.flushBuffer();
    out.clear();
    out = pageContext.pushBody();
    }
    catch(IllegalStateException e)
    {
    System.out.println(e.getMessage());
    e.printStackTrace();
    }%>

    posted @ 2009-07-23 08:40 平濤 閱讀(472) | 評(píng)論 (0)編輯 收藏

    2009年7月22日 #

    這個(gè)錯(cuò)誤主要是struts-config.xml或web.xml上配置出錯(cuò)
    仔細(xì)對(duì)比后就可以解決
    struts-config.xml
    <controller
      processorClass="org.springframework.web.struts.DelegatingRequestProcessor">
     </controller>

      <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
        <set-property property="contextConfigLocation" value="/WEB-INF/classes/applicationContext.xml" />
      </plug-in>

    web.xml
    <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
      </context-param>
     
      <servlet>
       <servlet-name>context</servlet-name>
       <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
       <load-on-startup>1</load-on-startup>
      </servlet>
    主要是要保證contextConfigLocation名字沒(méi)有錯(cuò)誤即可。
    仔細(xì)對(duì)比 要一字不差
    posted @ 2009-07-22 23:15 平濤 閱讀(296) | 評(píng)論 (0)編輯 收藏

         摘要:   二、Struts2和Spring2.5的整合 (1)在web.xml中加入Struts2過(guò)濾器 <filter>   <filter-name>struts2</filter-name> ...  閱讀全文
    posted @ 2009-07-22 17:02 平濤 閱讀(1663) | 評(píng)論 (0)編輯 收藏

    2009年7月20日 #

         摘要:   一、Srping 與 Hibnernate 的整合 (4)開(kāi)發(fā)        這里采用自底向上的開(kāi)發(fā)模式。        (a)底層的開(kāi)發(fā)        打開(kāi)DB Explorer,連接上數(shù)據(jù)庫(kù),...  閱讀全文
    posted @ 2009-07-20 22:04 平濤 閱讀(1585) | 評(píng)論 (2)編輯 收藏

             使用的版本為:Struts 2.1.6 + Spring 2.5 + Hibernate 3.2

            開(kāi)發(fā)環(huán)境為:MyEclipse 7.1.1 + Jdk 1.6.0_13 + Tomcat 6.0.18 + MySQL 6.0.10 alpha

           所用表:test.employee

     

    id        int(11)       NO   PRI | NULL     auto_increment

    name     varchar(
    255) YES        NULL                   

    address   varchar(
    255)   YES      NULL    

    phone    varchar(
    255)   YES       NULL  

           這個(gè)實(shí)例主要是實(shí)現(xiàn)簡(jiǎn)單的CRUD方法。在搭建環(huán)境前,需要處理一個(gè)問(wèn)題:因?yàn)?/span>Spring2.5 AOP Liberaries里的asm2.2.3.jarHiberate中的生成代理用的asm.jar沖突,我們需要?jiǎng)h除asm2.2.3.jar,不然就會(huì)發(fā)生異常:java.lang.NoClassDefFoundError: org/objectweb/asm/CodeVisitor 。具體的刪除方法(避免在Tomcat中的lib下刪除了,然后又重新發(fā)布項(xiàng)目時(shí)此jar又重新發(fā)不到lib下):在MyEclipse中【WindowàPreferencesàMyEclipse Enterprise WorkbenchàProject CapabilitiesàSpring】在spring2.5 AOP Libraries中刪除asm2.2.3.jar

           在開(kāi)發(fā)S2SH架構(gòu)時(shí),先整合Spring + Hibernate ,然后再整合Struts + Spring 完成S2SH架構(gòu)的搭建。

    一、Srping Hibnernate 的整合

           1)添加Hibernate支持

           在添加Hibernate支持之前,我們先在【MyEclipse DataBase Explorer】中設(shè)置數(shù)據(jù)庫(kù)連接。所用的mysql/jdbc的jar包為mysql-connector-java-5.1.8-bin.jar。


        注意:
    MySQLURL為:jdbc:mysql://localhost:3306/test(我所根據(jù)學(xué)的視頻案例是連接oracle的,根據(jù)視頻中所學(xué)的時(shí)候,url沒(méi)有添加數(shù)據(jù)庫(kù),在測(cè)試過(guò)程當(dāng)中怎么樣也找到實(shí)體,原因就是因?yàn)樵?/span>url中沒(méi)有添加數(shù)據(jù)庫(kù)的選擇。)

           后面按照默認(rèn)設(shè)置一直到【finish】即可。

           a)在導(dǎo)航中找到【MyEclipse】,然后選擇【Add Hibernate Capbilities

    這里可以直接選擇jar包拷貝到lib下面,也可以先不拷貝,到時(shí)候MyEclipse會(huì)自動(dòng)拷貝到lib下。

    b)由于Hibernate要與Spring整合,所以在這一步無(wú)需再配置更詳細(xì)的hibernate.cfg.xml

           在這個(gè)按列中,我們使用JDBC Driver模式。

    c)不創(chuàng)建sessionFactory。然后【finish


    2)添加Spring支持

    a)在導(dǎo)航中找到【MyEclipse】,然后選擇【Add Spring Capbilities

    添加5個(gè)類庫(kù)。

    b)生成applicationContext.xml,建議將其放在WEB-INF下面。

    c)創(chuàng)建sessionFactory。然后【finish

    3)整合SpringHibernate

    打開(kāi)applicationContext,在當(dāng)中增加DataSourceSessionFactory

    <bean id="sessionFactory"

        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

           <property name="configLocation"

               value="classpath:hibernate.cfg.xml">

           </property>

    </bean>

    先將原先自動(dòng)生成的上述代碼刪除。

    然后再Outline的導(dǎo)航中選擇【New DataSource and SessionFactory

    后面要用到Mapping Resources,所以你可以在這里隨便填一個(gè)值進(jìn)去。

    最后添加部分屬性(添加了
    hibernate.show_sql)后形成代碼如下:

    <bean id="dataSource"

           class="org.apache.commons.dbcp.BasicDataSource">

           <property name="driverClassName"

               value="com.mysql.jdbc.Driver">

           </property>

           <property name="url" value="jdbc:mysql://localhost:3306/test"></property>

           <property name="username" value="root"></property>

           <property name="password" value="123"></property>

        </bean>

        <bean id="sessionFactory"

            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

           <property name="dataSource">

               <ref bean="dataSource" />

           </property>

           <property name="hibernateProperties">

               <props>

                  <prop key="hibernate.dialect">

                      org.hibernate.dialect.MySQLDialect

                  </prop>

                  <prop key="hibernate.show_sql">true</prop>

               </props>

           </property>

           <property name="mappingDirectoryLocations">

               <list>

                  <value>file:src</value>

               </list>

           </property>

        </bean>

    自此已經(jīng)完成了SpringHibernate的整合。

    posted @ 2009-07-20 11:17 平濤 閱讀(5622) | 評(píng)論 (1)編輯 收藏

    僅列出標(biāo)題  下一頁(yè)
    主站蜘蛛池模板: 中文字幕精品亚洲无线码二区| 亚洲网站在线播放| 亚洲av无码乱码国产精品| 亚洲熟妇av午夜无码不卡| 无码精品国产一区二区三区免费| h片在线免费观看| 国产亚洲情侣一区二区无| 亚洲AV综合永久无码精品天堂| 曰批全过程免费视频播放网站 | 女性自慰aⅴ片高清免费| 四虎影永久在线高清免费| 亚洲国产高清在线精品一区| 亚洲精品无码高潮喷水A片软| 国产AV无码专区亚洲AV琪琪| 99视频全部免费精品全部四虎 | 亚洲国产成人精品无码区二本| 色老头永久免费网站| 国产亚洲一区二区三区在线观看| 男性gay黄免费网站| 免费a级毛片高清视频不卡 | 永久免费AV无码网站国产| 精品国产sm捆绑最大网免费站| 亚洲欧洲日产国码无码久久99 | 久久精品无码专区免费| 免费a级毛片视频| 青青草原精品国产亚洲av| 免费无码H肉动漫在线观看麻豆| 狠狠亚洲狠狠欧洲2019| 麻豆一区二区三区蜜桃免费| 97在线视频免费| 亚洲V无码一区二区三区四区观看| 久久精品免费大片国产大片 | 久久精品国产免费一区| 国产中文在线亚洲精品官网| 黄色大片免费网站| 亚洲国产精品日韩| 亚洲国产精品人久久电影 | 午夜男人一级毛片免费| 亚洲综合色丁香婷婷六月图片| 伊人免费在线观看| 国产成人免费高清在线观看|