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

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

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

    posts - 120,  comments - 19,  trackbacks - 0
     

    最近身體不太好,轉(zhuǎn)貼一則文章,提醒自己多多休息和鍛煉。

    ------------------------

     只要踏入在我們IT這個(gè)行業(yè), 過不了幾年身體就是亞健康狀態(tài),過渡的話就可能會(huì)“過勞死”,要想防止“過勞死”,就必須了解身體為我們發(fā)出的“過勞死”信號(hào)。

    ??? 研究者認(rèn)為:在這27項(xiàng)癥狀和因素中占有7項(xiàng)以上,即是有過度疲勞危險(xiǎn)者,占10項(xiàng)以上就可能在任何時(shí)候發(fā)生“過勞死”。同時(shí),在第1項(xiàng)到第9項(xiàng)中占兩項(xiàng)以上或者在第10項(xiàng)到18項(xiàng)中占3項(xiàng)以上者也要特別注意,這27項(xiàng)癥狀和因素分別是:

      1.經(jīng)常感到疲倦,忘性大;

      2.酒量突然下降,即使飲酒也不感到有滋味;

      3.突然覺得有衰老感;

      4.肩部和頸部發(fā)木發(fā)僵;

      5.因?yàn)槠诤涂鄲炇撸?

      6.有一點(diǎn)小事也煩躁和生氣;

      7.經(jīng)常頭痛和胸悶;

      8.發(fā)生高血壓、糖尿病,心電圖測(cè)試結(jié)果不正常;

      9.體重突然變化大,出現(xiàn)“將軍肚”;

      10.幾乎每天晚上聚餐飲酒;

      11.一天喝5杯以上咖啡;

      12.經(jīng)常不吃早飯或吃飯時(shí)間不固定;

      13.喜歡吃油炸食品;

      14.一天吸煙30支以上;

      15.晚上10時(shí)也不回家或者12時(shí)以后回家占一半以上;

      16.上下班單程占2小時(shí)以上;

      17.最近幾年運(yùn)動(dòng)也不流汗;

      18.自我感覺身體良好而不看??;

      19.一天工作10小時(shí)以上;

      20.星期天也上班;

      21.經(jīng)常出差,每周只在家住兩三天;

      22.夜班多,工作時(shí)間不規(guī)則;

      23.最近有工作調(diào)動(dòng)或工作變化;

      24.升職或者工作量增多;

      25.最近以來加班時(shí)間突然增加;

      26.人際關(guān)系突然變壞;

      27.最近工作失誤或者發(fā)生不和。

      針對(duì)如何擺脫過度疲勞,何永成博士開出如下處方:

      消除腦力疲勞法:適當(dāng)參加體育鍛煉和文娛活動(dòng),積極休息。如果是心理疲勞,千萬(wàn)不要濫用鎮(zhèn)靜劑、安眠藥等,應(yīng)找出引起感情憂郁的原因,并求得解脫。病理性疲勞,應(yīng)及時(shí)找醫(yī)生檢查和治療。

      飲食補(bǔ)充法:注意飲食營(yíng)養(yǎng)的搭配。多吃含蛋白質(zhì)、脂肪和豐富的B族維生素食物,如豆腐、牛奶、魚肉類,多吃水果、蔬菜,適量飲水。

      休息恢復(fù)法:每天都要留出一定的休息時(shí)間。聽音樂、繪畫、散步等有助解除生理疲勞。

      科學(xué)健身方法:一是有氧運(yùn)動(dòng),如跑步、打球、打拳、騎車、爬山等;二是腹式呼吸,全身放松后深呼吸,鼓足腹部,憋一會(huì)兒再慢慢呼出;三是做保健操;四是點(diǎn)穴按摩。

    ??? 哥們, 上面27條在你身上出現(xiàn)幾條癥狀了?? 怕怕吧??

      建議哥們們每天早上和傍晚各抽出一小時(shí)鍛煉身體,畢竟身體是革命的本錢!

    轉(zhuǎn)自: 電子商務(wù)論壇 http://bbs.eczn.com/

    posted @ 2006-02-21 08:59 阿成 閱讀(201) | 評(píng)論 (0)編輯 收藏

    Hibenate作為一種Java對(duì)象持久化技術(shù),在很多大型的多層體系構(gòu)架中得到應(yīng)用,比如在開發(fā)一套電子商務(wù)系統(tǒng)可以以J2EE作為體系構(gòu)架,Structs作為java Web應(yīng)用框架,以Hibenate實(shí)現(xiàn)對(duì)象持久化任務(wù),以EJB或者普通的javabean實(shí)現(xiàn)業(yè)務(wù)邏輯,其實(shí)現(xiàn)過程的復(fù)雜度可想而知,下面收集一些在Hibenate中多對(duì)多關(guān)系中應(yīng)用技巧給大家分享

    1.cascade="..."?

    cascade屬性并不是多對(duì)多關(guān)系一定要用的,有了它只是讓我們?cè)诓迦牖騽h除對(duì)像時(shí)更方便一些,只要在cascade的源頭上插入或是刪除,所有cascade的關(guān)系就會(huì)被自己動(dòng)的插入或是刪除。便是為了能正確的cascade,unsaved-value是個(gè)很重要的屬性。

    Hibernate通過這個(gè)屬性來判斷一個(gè)對(duì)象應(yīng)該save還是update,如果這齠韻蟮膇d是unsaved-value的話,那說明這個(gè)對(duì)象不是persistence object要save(insert);如果id是非unsaved-value的話,那說明這個(gè)對(duì)象是persistence object(數(shù)據(jù)庫(kù)中已存在),只要update就行了。saveOrUpdate方法用的也是這個(gè)機(jī)制。

    2.inverse="ture"?

    inverse屬性默認(rèn)是false的,就是說關(guān)系的兩端都來維護(hù)關(guān)系。這個(gè)意思就是說,如有一個(gè)Student, Teacher和TeacherStudent表,Student和Teacher是多對(duì)多對(duì)多關(guān)系,這個(gè)關(guān)系由TeacherStudent這個(gè)表來表現(xiàn)。那么什么時(shí)候插入或刪除TeacherStudent表中的記錄來維護(hù)關(guān)系呢?在用hibernate時(shí),我們不會(huì)顯示的對(duì)TeacherStudent表做操作。

    對(duì)TeacherStudent的操作是hibernate幫我們做的。hibernate就是看hbm文件中指定的是"誰(shuí)"維護(hù)關(guān)系,那個(gè)在插入或刪除"誰(shuí)"時(shí),就會(huì)處發(fā)對(duì)關(guān)系表的操作。前提是"誰(shuí)"這個(gè)對(duì)象已經(jīng)知道這個(gè)關(guān)系了,就是說關(guān)系另一頭的對(duì)象已經(jīng)set或是add到"誰(shuí)"這個(gè)對(duì)象里來了。前面說過inverse默認(rèn)是false,就是關(guān)系的兩端都維護(hù)關(guān)系,對(duì)其中任一個(gè)操作都會(huì)處發(fā)對(duì)表系表的操作。當(dāng)在關(guān)系的一頭,如Student中的bag或set中用了inverse="true"時(shí),那就代表關(guān)系是由另一關(guān)維護(hù)的(Teacher)。就是說當(dāng)這插入Student時(shí),不會(huì)操作TeacherStudent表,即使Student已經(jīng)知道了關(guān)系。只有當(dāng)Teacher插入或刪除時(shí)才會(huì)處發(fā)對(duì)關(guān)系表的操作。

    所以,當(dāng)關(guān)系的兩頭都用inverse="true"是不對(duì)的,就會(huì)導(dǎo)致任何操作都不處發(fā)對(duì)關(guān)系表的操作。當(dāng)兩端都是inverse="false"或是default值是,在代碼對(duì)關(guān)系顯示的維護(hù)也是不對(duì)的,會(huì)導(dǎo)致在關(guān)系表中插入兩次關(guān)系。在一對(duì)多關(guān)系中inverse就更有意義了。在多對(duì)多中,在哪端inverse="true"效果差不多(在效率上)。但是在一對(duì)多中,如果要一方維護(hù)關(guān)系,就會(huì)使在插入或是刪除"一"方時(shí)去update"多"方的每一個(gè)與這個(gè)"一"的對(duì)象有關(guān)系的對(duì)象。

    而如果讓"多"方面維護(hù)關(guān)系時(shí)就不會(huì)有update操作,因?yàn)殛P(guān)系就是在多方的對(duì)象中的,直指插入或是刪除多方對(duì)象就行了。當(dāng)然這時(shí)也要遍歷"多"方的每一個(gè)對(duì)象顯示的操作修關(guān)系的變化體現(xiàn)到DB中。不管怎樣說,還是讓"多"方維護(hù)關(guān)系更直觀一些。

    3.cascade和inverse有什么區(qū)別?

    可以這樣理解,cascade定義的是關(guān)系兩端對(duì)象到對(duì)象的級(jí)聯(lián)關(guān)系;而inverse定義的是關(guān)系和對(duì)象的級(jí)聯(lián)關(guān)系。

    4.net.sf.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): 2, of class: Xxxxx

    這個(gè)問題出現(xiàn)在要?jiǎng)h除關(guān)系的一頭時(shí)。如,要?jiǎng)h除一個(gè)已經(jīng)和Student有關(guān)系的Teacher。當(dāng)tx.commit();時(shí)才會(huì)拋出這個(gè)異常。這時(shí)一個(gè)在關(guān)系另一頭的Student對(duì)象中的Set或是List中把這個(gè)Teacher對(duì)象顯示的remove掉,再session.delete(這個(gè)teacher);。這是為了防止在Student端有cascade時(shí)把這個(gè)Teacher對(duì)象再存回DB。

    所以,這個(gè)異常的只有在Student的關(guān)系定義中有cascade="...",而且沒有像上面說的顯示的解除關(guān)系時(shí)才會(huì)出現(xiàn)。所以防止出現(xiàn)這個(gè)異常的方法就是:1,在Student端不用cascade;2,或是用cascade的話,就顯示的刪除對(duì)像中的關(guān)系。 3,在Teacher端要用cascade。

    5.net.sf.hibernate.HibernateException: identifier of an instance of my.MyObject altered from N to N

    這個(gè)異常其實(shí)不是多對(duì)多中常遇到的,但是這個(gè)異常的提示不make sense,所以提一下,是因?yàn)閕d的java對(duì)象中的type和hbm文件中定義的不一樣,如:java中用long,而hbm中用type="integer",并且generator用的是identity時(shí)就會(huì)出現(xiàn)。

    posted @ 2006-02-15 10:09 阿成 閱讀(274) | 評(píng)論 (0)編輯 收藏

    延遲初始化錯(cuò)誤是運(yùn)用Hibernate開發(fā)項(xiàng)目時(shí)最常見的錯(cuò)誤。如果對(duì)一個(gè)類或者集合配置了延遲檢索策略,那么必須當(dāng)代理類實(shí)例或代理集合處于持久化狀態(tài)(即處于Session范圍內(nèi))時(shí),才能初始化它。如果在游離狀態(tài)時(shí)才初始化它,就會(huì)產(chǎn)生延遲初始化錯(cuò)誤。

    下面把Customer.hbm.xml文件的<class>元素的lazy屬性設(shè)為true,表示使用延遲檢索策略:

    <class name="mypack.Customer" table="CUSTOMERS" lazy="true">

    當(dāng)執(zhí)行Session的load()方法時(shí),Hibernate不會(huì)立即執(zhí)行查詢CUSTOMERS表的select語(yǔ)句,僅僅返回Customer類的代理類的實(shí)例,這個(gè)代理類具由以下特征:

    (1) 由Hibernate在運(yùn)行時(shí)動(dòng)態(tài)生成,它擴(kuò)展了Customer類,因此它繼承了Customer類的所有屬性和方法,但它的實(shí)現(xiàn)對(duì)于應(yīng)用程序是透明的。
    (2) 當(dāng)Hibernate創(chuàng)建Customer代理類實(shí)例時(shí),僅僅初始化了它的OID屬性,其他屬性都為null,因此這個(gè)代理類實(shí)例占用的內(nèi)存很少。
    (3) 當(dāng)應(yīng)用程序第一次訪問Customer代理類實(shí)例時(shí)(例如調(diào)用customer.getXXX()或customer.setXXX()方法),Hibernate會(huì)初始化代理類實(shí)例,在初始化過程中執(zhí)行select語(yǔ)句,真正從數(shù)據(jù)庫(kù)中加載Customer對(duì)象的所有數(shù)據(jù)。但有個(gè)例外,那就是當(dāng)應(yīng)用程序訪問Customer代理類實(shí)例的getId()方法時(shí),Hibernate不會(huì)初始化代理類實(shí)例,因?yàn)樵趧?chuàng)建代理類實(shí)例時(shí)OID就存在了,不必到數(shù)據(jù)庫(kù)中去查詢。

    提示:Hibernate采用CGLIB工具來生成持久化類的代理類。CGLIB是一個(gè)功能強(qiáng)大的Java字節(jié)碼生成工具,它能夠在程序運(yùn)行時(shí)動(dòng)態(tài)生成擴(kuò)展Java類或者實(shí)現(xiàn)Java接口的代理類。關(guān)于CGLIB的更多知識(shí),請(qǐng)參考:http://cglib.sourceforge.net/。

    以下代碼先通過Session的load()方法加載Customer對(duì)象,然后訪問它的name屬性:

    tx = session.beginTransaction();
    Customer customer=(Customer)session.load(Customer.class,new Long(1));
    customer.getName();
    tx.commit();

    在運(yùn)行session.load()方法時(shí)Hibernate不執(zhí)行任何select語(yǔ)句,僅僅返回Customer類的代理類的實(shí)例,它的OID為1,這是由load()方法的第二個(gè)參數(shù)指定的。當(dāng)應(yīng)用程序調(diào)用customer.getName()方法時(shí),Hibernate會(huì)初始化Customer代理類實(shí)例,從數(shù)據(jù)庫(kù)中加載Customer對(duì)象的數(shù)據(jù),執(zhí)行以下select語(yǔ)句:

    select * from CUSTOMERS where ID=1;
    select * from ORDERS where CUSTOMER_ID=1;

    當(dāng)<class>元素的lazy屬性為true,會(huì)影響Session的load()方法的各種運(yùn)行時(shí)行為,下面舉例說明。

    1.如果加載的Customer對(duì)象在數(shù)據(jù)庫(kù)中不存在,Session的load()方法不會(huì)拋出異常,只有當(dāng)運(yùn)行customer.getName()方法時(shí)才會(huì)拋出以下異常:

    ERROR LazyInitializer:63 - Exception initializing proxy
    net.sf.hibernate.ObjectNotFoundException: No row with the given identifier exists: 1, of class:
    mypack.Customer

    2.如果在整個(gè)Session范圍內(nèi),應(yīng)用程序沒有訪問過Customer對(duì)象,那么Customer代理類的實(shí)例一直不會(huì)被初始化,Hibernate不會(huì)執(zhí)行任何select語(yǔ)句。以下代碼試圖在關(guān)閉Session后訪問Customer游離對(duì)象:

    tx = session.beginTransaction();
    Customer customer=(Customer)session.load(Customer.class,new Long(1));
    tx.commit();
    session.close();
    customer.getName();

    由于引用變量customer引用的Customer代理類的實(shí)例在Session范圍內(nèi)始終沒有被初始化,因此在執(zhí)行customer.getName()方法時(shí),Hibernate會(huì)拋出以下異常:

    ERROR LazyInitializer:63 - Exception initializing proxy
    net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed

    由此可見,Customer代理類的實(shí)例只有在當(dāng)前Session范圍內(nèi)才能被初始化。

    3.net.sf.hibernate.Hibernate類的initialize()靜態(tài)方法用于在Session范圍內(nèi)顯式初始化代理類實(shí)例,isInitialized()方法用于判斷代理類實(shí)例是否已經(jīng)被初始化。例如:

    tx = session.beginTransaction();
    Customer customer=(Customer)session.load(Customer.class,new Long(1));
    if(!Hibernate.isInitialized(customer))
    Hibernate.initialize(customer);
    tx.commit();
    session.close();
    customer.getName();

    以上代碼在Session范圍內(nèi)通過Hibernate類的initialize()方法顯式初始化了Customer代理類實(shí)例,因此當(dāng)Session關(guān)閉后,可以正常訪問Customer游離對(duì)象。

    4.當(dāng)應(yīng)用程序訪問代理類實(shí)例的getId()方法時(shí),不會(huì)觸發(fā)Hibernate初始化代理類實(shí)例的行為,例如:

    tx = session.beginTransaction();
    Customer customer=(Customer)session.load(Customer.class,new Long(1));
    customer.getId();
    tx.commit();
    session.close();
    customer.getName();

    當(dāng)應(yīng)用程序訪問customer.getId()方法時(shí),該方法直接返回Customer代理類實(shí)例的OID值,無(wú)需查詢數(shù)據(jù)庫(kù)。由于引用變量customer始終引用的是沒有被初始化的Customer代理類實(shí)例,因此當(dāng)Session關(guān)閉后再執(zhí)行customer.getName()方法,Hibernate會(huì)拋出以下異常:

    ERROR LazyInitializer:63 - Exception initializing proxy
    net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed

    posted @ 2006-02-13 17:24 阿成 閱讀(325) | 評(píng)論 (0)編輯 收藏

    使用FileUpload組件實(shí)現(xiàn)文件上傳
    文件上傳在web應(yīng)用中非常普遍,要在servlet/jsp環(huán)境中實(shí)現(xiàn)文件上傳功能非常容易,因?yàn)榫W(wǎng)上已經(jīng)有許多用java開發(fā)的組件用于文件上傳,本文以commons-fileupload組件為例,為servlet/jsp應(yīng)用添加文件上傳功能。

    common-fileupload組件是apache的一個(gè)開源項(xiàng)目之一,可以從http://jakarta.apache.org/commons/fileupload/下載。該組件簡(jiǎn)單易用,可實(shí)現(xiàn)一次上傳一個(gè)或多個(gè)文件,并可限制文件大小。

    下載后解壓zip包,將commons-fileupload-1.0.jar復(fù)制到tomcat的webapps\你的webapp\WEB-INF\lib\下,如果目錄不存在請(qǐng)自建目錄。

    新建一個(gè)servlet: Upload.java用于文件上傳:

    import java.io.*;
    import java.util.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import org.apache.commons.fileupload.*;

    public class Upload extends HttpServlet {

    ????private String uploadPath = "C:\\upload\\"; // 用于存放上傳文件的目錄
    ????private String tempPath = "C:\\upload\\tmp\\"; // 用于存放臨時(shí)文件的目錄

    ????public void doPost(HttpServletRequest request, HttpServletResponse response)
    ????????throws IOException, ServletException
    ????{
    ????}
    }

    當(dāng)servlet收到瀏覽器發(fā)出的Post請(qǐng)求后,在doPost()方法中實(shí)現(xiàn)文件上傳。以下是示例代碼:

    public void doPost(HttpServletRequest request, HttpServletResponse response)
    ????throws IOException, ServletException
    {
    ????try {
    ????????DiskFileUpload fu = new DiskFileUpload();
    ????????// 設(shè)置最大文件尺寸,這里是4MB
    ????????fu.setSizeMax(4194304);
    ????????// 設(shè)置緩沖區(qū)大小,這里是4kb
    ????????fu.setSizeThreshold(4096);
    ????????// 設(shè)置臨時(shí)目錄:
    ????????fu.setRepositoryPath(tempPath);

    ????????// 得到所有的文件:
    ????????List fileItems = fu.parseRequest(request);
    ????????Iterator i = fileItems.iterator();
    ????????// 依次處理每一個(gè)文件:
    ????????while(i.hasNext()) {
    ????????????FileItem fi = (FileItem)i.next();
    ????????????// 獲得文件名,這個(gè)文件名包括路徑:
    ????????????String fileName = fi.getName();
    ????????????if(fileName!=null) {
    ????????????????// 在這里可以記錄用戶和文件信息
    ????????????????// ...
    ????????????????// 寫入文件a.txt,你也可以從fileName中提取文件名:
    ????????????????fi.write(new File(uploadPath + "a.txt"));
    ????????????}
    ????????}
    ????????// 跳轉(zhuǎn)到上傳成功提示頁(yè)面
    ????}
    ????catch(Exception e) {
    ????????// 可以跳轉(zhuǎn)出錯(cuò)頁(yè)面
    ????}
    }

    如果要在配置文件中讀取指定的上傳文件夾,可以在init()方法中執(zhí)行:

    public void init() throws ServletException {
    ????uploadPath = ....
    ????tempPath = ....
    ????// 文件夾不存在就自動(dòng)創(chuàng)建:
    ????if(!new File(uploadPath).isDirectory())
    ????????new File(uploadPath).mkdirs();
    ????if(!new File(tempPath).isDirectory())
    ????????new File(tempPath).mkdirs();
    }

    編譯該servlet,注意要指定classpath,確保包含commons-upload-1.0.jar和tomcat\common\lib\servlet-api.jar。

    配置servlet,用記事本打開tomcat\webapps\你的webapp\WEB-INF\web.xml,沒有的話新建一個(gè)。典型配置如下:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!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>Upload</servlet-name>
    ????????<servlet-class>Upload</servlet-class>
    ????</servlet>

    ????<servlet-mapping>
    ????????<servlet-name>Upload</servlet-name>
    ????????<url-pattern>/fileupload</url-pattern>
    ????</servlet-mapping>
    </web-app>


    配置好servlet后,啟動(dòng)tomcat,寫一個(gè)簡(jiǎn)單的html測(cè)試:

    <form action="fileupload" method="post"
    enctype="multipart/form-data" name="form1">
    ??<input type="file" name="file">
    ??<input type="submit" name="Submit" value="upload">
    </form>

    注意action="fileupload"其中fileupload是配置servlet時(shí)指定的url-pattern。

    posted @ 2006-02-10 15:52 阿成 閱讀(351) | 評(píng)論 (0)編輯 收藏

    spring下載包中doc目錄下的MVC-step-by-step和sample目錄下的例子都是比較好的spring開發(fā)的例子.

     1、如何學(xué)習(xí)Spring?

      你可以通過下列途徑學(xué)習(xí)spring:

      (1) spring下載包中doc目錄下的MVC-step-by-step和sample目錄下的例子都是比較好的spring開發(fā)的例子。

      (2) AppFuse集成了目前最流行的幾個(gè)開源輕量級(jí)框架或者工具 Ant,XDoclet,Spring,Hibernate(iBATIS),JUnit,Cactus,StrutsTestCase,Canoo's WebTest,Struts Menu,Display Tag Library,OSCache,JSTL,Struts 。

      你可以通過AppFuse源代碼來學(xué)習(xí)spring。

    AppFuse網(wǎng)站:http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse

      (3)Spring 開發(fā)指南(夏昕)(http://www.xiaxin.net/Spring_Dev_Guide.rar)

      一本spring的入門書籍,里面介紹了反轉(zhuǎn)控制和依賴注射的概念,以及spring的bean管理,spring的MVC,spring和hibernte,iBatis的結(jié)合。

      (4) spring學(xué)習(xí)的中文論壇

      SpringFramework中文論壇(http://spring.jactiongroup.net)

      Java視線論壇(http://forum.javaeye.com)的spring欄目

      2、利用Spring框架編程,console打印出log4j:WARN Please initialize the log4j system properly?

      說明你的log4j.properties沒有配置。請(qǐng)把log4j.properties放到工程的classpath中,eclipse的classpath為bin目錄,由于編譯后src目錄下的文件會(huì)拷貝到bin目錄下,所以你可以把log4j.properties放到src目錄下。

      這里給出一個(gè)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=%d %5p (%F:%L) - %m%n

      3、出現(xiàn) java.lang.NoClassDefFoundError?

      一般情況下是由于你沒有把必要的jar包放到lib中。

      比如你要采用spring和hibernate(帶事務(wù)支持的話),你除了spring.jar外還需要hibernat.jar、aopalliance.jar、cglig.jar、jakarta-commons下的幾個(gè)jar包。

    http://www.springframework.org/download.html下載spring開發(fā)包,提供兩種zip包
    spring-framework-1.1.3-with-dependencies.zip和spring-framework-1.1.3.zip,我建議你下載spring-framework-1.1.3-with-dependencies.zip。這個(gè)zip解壓縮后比后者多一個(gè)lib目錄,其中有hibernate、j2ee、dom4j、aopalliance、jakarta-commons等常用包。

      4、java.io.FileNotFoundException: Could not open class path resource [....hbm.xml],提示找不到xml文件?

      原因一般有兩個(gè):

      (1)該xml文件沒有在classpath中。

      (2)applicationContext-hibernate.xml中的xml名字沒有帶包名。比如:


    <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
    <property name="dataSource"><ref bean="dataSource"/></property>
    <property name="mappingResources">
    ?。糽ist>
     ?。紇alue>User.hbm.xml</value>
      錯(cuò),改為:
     ?。紇alue>com/yz/spring/domain/User.hbm.xml</value>
     </list>
    </property>
    <property name="hibernateProperties">
    <props>
     <prop key="hibernate.dialect"> net.sf.hibernate.dialect.MySQLDialect </prop>
     <prop key="hibernate.show_sql">true</prop>
    </props>
    </property>
    </bean>

      5、org.springframework.beans.NotWritablePropertyException: Invalid property 'postDao' of bean class?

      出現(xiàn)異常的原因是在application-xxx.xml中property name的錯(cuò)誤。

     ?。紁roperty name="...."> 中name的名字是與bean的set方法相關(guān)的,而且要注意大小寫。

      比如


    public class PostManageImpl extends BaseManage implements PostManage {
     private PostDAO dao = null;
     public void setPostDAO(PostDAO postDAO){
      this.dao = postDAO;
     }
    }

      那么xml的定義應(yīng)該是:


    <bean id="postManage" parent="txProxyTemplate">
    <property name="target">
     <bean class="com.yz.spring.service.implement.PostManageImpl">
     ?。紁roperty name="postDAO"><ref bean="postDAO"/></property> 對(duì)
     ?。紁roperty name="dao"><ref bean="postDAO"/></property> 錯(cuò)
    ?。?bean>
    </property>
    </bean>

      6、Spring中如何實(shí)現(xiàn)事務(wù)管理?

      首先,如果使用mysql,確定mysql為InnoDB類型。

      事務(wù)管理的控制應(yīng)該放到商業(yè)邏輯層。你可以寫個(gè)處理商業(yè)邏輯的JavaBean,在該JavaBean中調(diào)用DAO,然后把該Bean的方法納入spring的事務(wù)管理。

      比如:xml文件定義如下:


    <bean id="txProxyTemplate" abstract="true"
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager"><ref bean="transactionManager"/></property>
    <property name="transactionAttributes">
    <props>
    <prop key="save*">PROPAGATION_REQUIRED</prop>
    <prop key="remove*">PROPAGATION_REQUIRED</prop>
    <prop key="*">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>

    <bean id="userManage" parent="txProxyTemplate">
    ?。紁roperty name="target">
     ?。糱ean class="com.yz.spring.service.implement.UserManageImpl">
       <property name="userDAO"><ref bean="userDAO"/></property>
     ?。?bean>
    ?。?property>
    </bean>

      com.yz.spring.service.implement.UserManageImpl就是我們的實(shí)現(xiàn)商業(yè)邏輯的JavaBean。我們通過parent元素聲明其事務(wù)支持。

      7、如何管理Spring框架下更多的JavaBean?

      JavaBean越多,spring配置文件就越大,這樣不易維護(hù)。為了使配置清晰,我們可以將JavaBean分類管理,放在不同的配置文件中。 應(yīng)用啟動(dòng)時(shí)將所有的xml同時(shí)加載。

      比如:

      DAO層的JavaBean放到applicationContext-hibernate.xml中,商業(yè)邏輯層的JavaBean放到applicationContext-service.xml中。然后啟動(dòng)類中調(diào)用以下代碼載入所有的ApplicationContext。


    String[] paths = {"com/yz/spring/dao/hibernate/applicationContext-hibernate.xml",
    "com/yz/spring/service/applicationContext-service.xml"};
    ctx = new ClassPathXmlApplicationContext(paths);

      8、web應(yīng)用中如何加載ApplicationContext?

      可以通過定義web.xml,由web容器自動(dòng)加載。


    <servlet>
    <servlet-name>context</servlet-name>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext-hibernate.xml</param-value>
    <param-value>/WEB-INF/applicationContext-service.xml</param-value>
    </context-param>

      9、在spring中如何配置的log4j?

      在web.xml中加入以下代碼即可。


    <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/log4j.properties</param-value>
    </context-param>

      10、Spring框架入門的編程問題解決了,我該如何更深地領(lǐng)會(huì)Spring框架呢?

      這兩本書你該去看看。這兩本書是由Spring的作者Rod Johnson編寫的。


    Expert One on one J2EE Design and Development
    Expert One on one J2EE Development Without EJB

      你也該看看martinfowler的Inversion of Control Containers and the Dependency Injection pattern。


    http://www.martinfowler.com/articles/injection.html
     
      再好好研讀一下spring的文檔。


    http://www.jactiongroup.net/reference/html/index.html(中文版,未全部翻譯)

      還有就是多實(shí)踐吧。
    posted @ 2006-02-10 10:46 阿成 閱讀(255) | 評(píng)論 (0)編輯 收藏
    、JDK,SDK,JRE,JVM

    我們可以通過helloworld來理解這幾個(gè)縮寫詞的具體含義:

    public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("helloworld");
    }
    }



    編譯之后, 我們得到了HelloWorld.class(圖中的"Your program's class files")
    在HelloWorld里面, 我們調(diào)用了 JAVA API中的 java.lang.System這個(gè)類的靜態(tài)成員對(duì)象 out, out 的靜態(tài)方法: public static void println(String string);

    然后我們讓虛擬機(jī)器來執(zhí)行這個(gè)HelloWorld。
    1. 虛擬機(jī)會(huì)在classpath中找到HelloWorld.class。
    2. 虛擬機(jī)中的解釋器(interpret)會(huì)把HelloWorld.class解釋成字節(jié)碼。
    3. 把解釋后的字節(jié)碼交由execution engin執(zhí)行。
    4. execution engin會(huì)調(diào)用native method(即平臺(tái)相關(guān)的字節(jié)碼)來在host system的stdout(顯示器)的指定部分打印出指定的字符串。
    5. 這樣, 我們就看到"helloworld"字樣了。

    有了這個(gè)流程后, 我們就好理解上面幾個(gè)術(shù)語(yǔ)了:
    a. JDK: java develop kit (JAVA API包)
    b. SDK: software develop kit, 以前JDK 叫做java software develop kit, 后來出了1.2版本后, 就改名叫jdk了, 省時(shí)省力, 節(jié)約成本。
    c. JRE. java runtime environment 我們的helloworld必須在JRE(JAVA運(yùn)行環(huán)境,JAVA運(yùn)行環(huán)境又叫JAVA平臺(tái))里面, 才能跑起來。 所以, 顯然地, JRE其實(shí)就是JDK + JVM

    d. JVM java virtual machine. 簡(jiǎn)單地講, 就是把class文件變成字節(jié)碼, 然后送到excution engin中執(zhí)行。 而為什么叫虛擬機(jī), 而不叫真實(shí)機(jī)呢? 因?yàn)镴VM本身是又不能運(yùn)算, 又不能讓顯示器顯示"helloworld"的, 它只能再調(diào)用host system的API, 比如在w32里面就會(huì)調(diào)c++的API, 來讓CPU幫他做做算術(shù)運(yùn)算, 來調(diào)用c++里面的API來控制顯示器顯示顯示字符串。 而這些API不是JDK里面有的,我們平時(shí)又看不見的,所以我們就叫它native api了(亦曰私房XX)。

    e. 解釋平臺(tái)無(wú)關(guān)。 有人會(huì)說, 在linux的里面調(diào)用native api與w32里面調(diào)用的api肯定不一樣吧? 那為什么說JAVA是平臺(tái)無(wú)關(guān)的呢?
    其 實(shí)是這樣的, 君不見java.sun.com里面又有jdk-for-w32又有jdk-for-linux下載嗎? 剛才不是說了嗎? native api, native api, 就是我們平時(shí)看不見的api嗎! 調(diào)用native這些煩瑣的活兒都讓jdk去做了。 所以我們調(diào)用的時(shí)候只用知道jdk(java api) 里面的java.io.*能提供磁盤訪問功能, java.awt.* 能畫個(gè)框框畫個(gè)圓圓就行了嗎。 至于JDK又是怎么調(diào)用的, 在LINXU上更圓呢? 還是在W32上更圓,(x) 這個(gè)就是JDK個(gè)人的事情了。(理論上講是一樣圓的, 當(dāng)然這又和顯示器是否純平相關(guān)了:D)

    同時(shí), 這里就引申出了另一個(gè)話題。 既如何編寫平臺(tái)無(wú)關(guān)的JAVA程序。 其中關(guān)鍵的一條, 就是調(diào)用且只調(diào)用jdk中的API, 而不要私自調(diào)用native api。 原因很簡(jiǎn)單啊, JDK-for-linux和JDK-for-w32表面都是一樣的, 所以我在w32里面調(diào)用JDK寫的java程序,在linux里面也會(huì)一樣的寫法啊, 所以就可以移植來移植去都沒問題。(b) 但是如果我在w32里面調(diào)用了 一個(gè)圖形顯示的native api, 當(dāng)我移植到linux去的時(shí)候, 誰(shuí)又能保證里面也有相同名稱, 相同參數(shù),相同返回值, 相同功能的native api供我調(diào)用呢!(?)

    -以上是個(gè)人理解, 如有錯(cuò)漏之處, 萬(wàn)望指出, 共同進(jìn)步!


    2.Re:[入門]什么叫JDK,SDK,JRE,JVM [Re: sojan] Copy to clipboard
    Posted by: reddream
    Posted on: 2003-11-27 13:02

    sojan wrote:
    ... 所以, 顯然地, JRE其實(shí)就是JDK + JVM...

    這句話不對(duì)。JRE顧名思義只是java class運(yùn)行時(shí)需要的環(huán)境,JDK不僅包含了JRE,還提供了開發(fā)調(diào)試java程序需要的工具

    3.Re:[入門]什么叫JDK,SDK,JRE,JVM [Re: sojan] Copy to clipboard
    Posted by: sojan
    Posted on: 2003-11-27 13:30

    我將JRE(Java運(yùn)行環(huán)境)理解為JAVA PLATFORM, 既JAVA平臺(tái)。

    reddream 的話也是對(duì)的, JRE同時(shí)也包括讓JAVA運(yùn)行起來的工具,比如: javac(編譯), java(運(yùn)行), javap(反編譯)這些。

    另一角度

    如果安裝了JDK,會(huì)發(fā)同你的電腦有兩套JRE,一套位于 jre 另外一套位于 C:\Program Files\Java\j2re1.4.1_01 目錄下,后面這套比前面那套少了Server端的Java虛擬機(jī),不過直接將前面那套的Server端Java虛擬機(jī)復(fù)制過來就行了。而且在安裝JDK可 以選擇是否安裝這個(gè)位于 C:\Program Files\Jav a 目錄下的JRE。如果你只安裝JRE,而不是JDK,那么只會(huì)在 C:\Program Files\Java 目錄下安裝唯一的一套JRE。?

    ??? JRE的地位就象一臺(tái)PC機(jī)一樣,我們寫好的Win32應(yīng)用程序需要操作系統(tǒng)幫我們運(yùn)行,同樣的,我們編寫的Java程序也必須要JRE才能運(yùn)行。所以當(dāng) 你裝完JDK后,如果分別在硬盤上的兩個(gè)不同地方安裝了兩套JRE,那么你可以想象你的電腦有兩臺(tái)虛擬的Java PC機(jī),都具有運(yùn)行Java程序的功能。所以我們可以說,只要你的電腦安裝了JRE,就可以正確運(yùn)行Jav a應(yīng)用程序。

    ???? ?1、為什么Sun要讓JDK安裝兩套相同的JRE?這是因?yàn)镴DK里面有很多用Java所編寫的開發(fā)工具(如javac.exe、jar.exe等),而且都放置在 lib\tools.jar 里。從下面例子可以看出,先將tools.jar改名為tools1.jar,然后運(yùn)行javac.exe,顯示如下結(jié)果: Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac /Main 這個(gè)意思是說,你輸入javac.exe與輸入 java -cp c:\jdk\lib\tools.jar com.sun.tools.javac.Main 是一樣的,會(huì)得到相同的結(jié)果。從這里我們可以證明javac.exe只是一個(gè)包裝器(Wrapper),而制作的目的是為了讓開發(fā)者免于輸入太長(zhǎng)的指命。 而且可以發(fā)現(xiàn)lib目錄下的程序都很小,不大于2 9K,從這里我們可以得出一個(gè)結(jié)論。就是JDK里的工具幾乎是用Java所編寫,所以也是Java應(yīng)用程序,因此要使用JDK所附的工具來開發(fā)Java程 序,也必須要自行附一套JRE才行,所以位于C:\Program Files\Java目錄下的那套JRE就是用來運(yùn)行一般Java程序用的。

    ???? 2、如果一臺(tái)電腦安裝兩套以上的JRE,誰(shuí)來決定呢?這個(gè)重大任務(wù)就落在java.exe身上。Java.exe的工作就是找到合適的JRE來運(yùn)行 Java程序。 Java.exe依照底下的順序來查找JRE:自己的目錄下有沒有JRE;父目錄有沒有JRE;查詢注冊(cè)表: [HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment] 所以java.exe的運(yùn)行結(jié)果與你的電腦里面哪個(gè)JRE被執(zhí)行有很大的關(guān)系。

    ??? 3、介紹JVM JRE目錄下的Bin目錄有兩個(gè)目錄:server與client。這就是真正的jvm.dll所在。 jvm.dll無(wú)法單獨(dú)工作,當(dāng)jvm.dll啟動(dòng)后,會(huì)使用explicit的方法(就是使用Win32 API之中的LoadLibrary()與GetProcAddress()來載入輔助用的動(dòng)態(tài)鏈接庫(kù)),而這些輔助用的動(dòng)態(tài)鏈接庫(kù)(.dll)都必須位 于jvm.dll所在目錄的父目錄之中。因此想使用哪個(gè)JVM,只需要設(shè)置PATH,指向JRE所在目錄底下的jvm.dll。



    對(duì)于這個(gè)系列里的問題,每個(gè)學(xué)Java的人都應(yīng)該搞懂。當(dāng)然,如果只是學(xué)Java玩玩就無(wú)所謂了。如果你認(rèn)為自己已經(jīng)超越初學(xué)者了,卻不很懂這些問題,請(qǐng)將你自己重歸初學(xué)者行列。內(nèi)容均來自于CSDN的經(jīng)典老貼。

    二、
    java環(huán)境變量有三個(gè)

    JAVA_HOME,CLASSPATH,PATH.

    只有這三個(gè)java環(huán)境變量。

    JAVA_HOME指向的是JDK的安裝路徑,如C:\j2sdk1.4.2_09,在這路徑下你應(yīng)該能夠找到bin、lib等目錄。當(dāng)然,你愿意放哪里,就放哪里。我的是放在c盤根目錄

    JAVA_HOME=C:\j2sdk1.4.2_09;

    PATH環(huán)境變量,目的是為了指向JDK的bin目錄,這里面放的是各種編譯執(zhí)行命令。

    我的設(shè)置是:

    PATH=C:\j2sdk1.4.2_09\bin;C:\j2sdk1.4.2_09\jre\bin;

    需要說明,系統(tǒng)中本身就有PATH環(huán)境變量,只要把C:\j2sdk1.4.2_09\bin;C:\j2sdk1.4.2_09\jre\bin;直接放到后面即可,中間有分號(hào)間隔。

    如果你的JAVA_HOME是別的目錄,就對(duì)照著該吧。

    CLASSPATH最重要。

    CLASSPATH=.;C:\j2sdk1.4.2_09\lib;C:\j2sdk1.4.2_09\lib\tools.jar;這時(shí)我的設(shè)置。這是類的路徑。前面加上點(diǎn)和分號(hào),意為首先在當(dāng)前目錄查找,以后你自己編寫類的時(shí)候自然明白這點(diǎn)。

    那么為什么要設(shè)置環(huán)境變量,以前編寫c語(yǔ)言的時(shí)候怎么不設(shè)置呢?

    由于WINDOWS默認(rèn)的搜索順序,先搜索當(dāng)前目錄的,再搜索系統(tǒng)目錄的,再搜索PATH環(huán)境變量設(shè)定的。你在編寫java程序時(shí),在一個(gè)指定目錄,這里沒有編譯執(zhí)行命令,而系統(tǒng)目錄里面,也沒有編譯執(zhí)行命令。所以放在環(huán)境變量里面, 從這里你應(yīng)該可以看出,環(huán)境變量是干什么用的了。簡(jiǎn)單說就是告訴操作系統(tǒng)到那里去找指定的文件。你要是把系統(tǒng)目錄給改了,看你用dos命令還好不好使。

    配置完后,在命令提示符下,鍵入java -version,如果出現(xiàn)java的一些信息,說明配置成功

    //問題一
    在命令行中輸入 javac HelloWorld.java 后出現(xiàn)如下錯(cuò)誤:
    ′javac′ 不是內(nèi)部或外部命令,也不是可運(yùn)行的程序或批處理文件。
    (javac: Command not found)

    這個(gè)錯(cuò)誤產(chǎn)生的原因是沒有設(shè)置好環(huán)境變量path。下面以windows xp為例子來講解如何設(shè)置環(huán)境變量path。右鍵單擊我的電腦->屬性->高級(jí)->環(huán)境變量,然后在系統(tǒng)變量中選擇添加,變量名為path,變量值為d:\j2se\bin(這里假設(shè)你的jdk的安裝d:\j2se,當(dāng)然如果你的jdk的安裝目錄是別的目錄的話,比如c:\jdk1.2,那么你的path應(yīng)該設(shè)置為c:\jdk1.2\bin。)。最后不要忘記了重新啟動(dòng),當(dāng)然你也可以再接著設(shè)置完另一個(gè)環(huán)境變量classpath后再重新啟動(dòng)。

    //問題二
    在命令行中輸入 java HelloWorld 后出現(xiàn)如下錯(cuò)(注意不是 java HelloWorld.class 。)

    Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld

    這個(gè)錯(cuò)誤產(chǎn)生的原因是沒有設(shè)置好環(huán)境變量classpath,這時(shí)只需要將classpath的值設(shè)置為
    .;d:\j2se\lib\dt.jar;d:\j2se\lib\tools.jar
    當(dāng)然,如果你的jdk的安裝目錄是在別的地方的話,比如c:\jdk1.2,那么你的classpath變量應(yīng)該設(shè)置為
    .;c:\jdk1.2\lib\dt.jar;c:\jdk1.2\lib\tools.jar
    最后重新啟動(dòng),然后再小心:)的去編譯你的HelloWorld.java程序


    三、基礎(chǔ)知識(shí)


    問題一:我聲明了什么!

    String s = "Hello world!";

    許多人都做過這樣的事情,但是,我們到底聲明了什么?回答通常是:一個(gè)String,內(nèi)容是“Hello world!”。這樣模糊的回答通常是概念不清的根源。如果要準(zhǔn)確的回答,一半的人大概會(huì)回答錯(cuò)誤。
    這個(gè)語(yǔ)句聲明的是一個(gè)指向?qū)ο蟮囊茫麨椤皊”,可以指向類型為String的任何對(duì)象,目前指向"Hello world!"這個(gè)String類型的對(duì)象。這就是真正發(fā)生的事情。我們并沒有聲明一個(gè)String對(duì)象,我們只是聲明了一個(gè)只能指向String對(duì)象的引用變量。所以,如果在剛才那句語(yǔ)句后面,如果再運(yùn)行一句:

    String string = s;

    我們是聲明了另外一個(gè)只能指向String對(duì)象的引用,名為string,并沒有第二個(gè)對(duì)象產(chǎn)生,string還是指向原來那個(gè)對(duì)象,也就是,和s指向同一個(gè)對(duì)象。

    問題二:"=="和equals方法究竟有什么區(qū)別?

    ==操作符專門用來比較變量的值是否相等。比較好理解的一點(diǎn)是:
    int a=10;
    int b=10;
    則a==b將是true。
    但不好理解的地方是:
    String a=new String("foo");
    String b=new String("foo");
    則a==b將返回false。

    根據(jù)前一帖說過,對(duì)象變量其實(shí)是一個(gè)引用,它們的值是指向?qū)ο笏诘膬?nèi)存地址,而不是對(duì)象本身。a和b都使用了new操作符,意味著將在內(nèi)存中產(chǎn)生兩個(gè)內(nèi)容為"foo"的字符串,既然是“兩個(gè)”,它們自然位于不同的內(nèi)存地址。a和b的值其實(shí)是兩個(gè)不同的內(nèi)存地址的值,所以使用"=="操作符,結(jié)果會(huì)是false。誠(chéng)然,a和b所指的對(duì)象,它們的內(nèi)容都是"foo",應(yīng)該是“相等”,但是==操作符并不涉及到對(duì)象內(nèi)容的比較。
    對(duì)象內(nèi)容的比較,正是equals方法做的事。

    看一下Object對(duì)象的equals方法是如何實(shí)現(xiàn)的:
    boolean equals(Object o){

    return this==o;

    }
    Object對(duì)象默認(rèn)使用了==操作符。所以如果你自創(chuàng)的類沒有覆蓋equals方法,那你的類使用equals和使用==會(huì)得到同樣的結(jié)果。同樣也可以看出,Object的equals方法沒有達(dá)到equals方法應(yīng)該達(dá)到的目標(biāo):比較兩個(gè)對(duì)象內(nèi)容是否相等。因?yàn)榇鸢笐?yīng)該由類的創(chuàng)建者決定,所以O(shè)bject把這個(gè)任務(wù)留給了類的創(chuàng)建者。

    看一下一個(gè)極端的類:
    Class Monster{
    private String content;
    ...
    boolean equals(Object another){ return true;}

    }
    我覆蓋了equals方法。這個(gè)實(shí)現(xiàn)會(huì)導(dǎo)致無(wú)論Monster實(shí)例內(nèi)容如何,它們之間的比較永遠(yuǎn)返回true。

    所以當(dāng)你是用equals方法判斷對(duì)象的內(nèi)容是否相等,請(qǐng)不要想當(dāng)然。因?yàn)榭赡苣阏J(rèn)為相等,而這個(gè)類的作者不這樣認(rèn)為,而類的equals方法的實(shí)現(xiàn)是由他掌握的。如果你需要使用equals方法,或者使用任何基于散列碼的集合(HashSet,HashMap,HashTable),請(qǐng)察看一下java doc以確認(rèn)這個(gè)類的equals邏輯是如何實(shí)現(xiàn)的。

    問題三:String到底變了沒有?

    沒有。因?yàn)镾tring被設(shè)計(jì)成不可變(immutable)類,所以它的所有對(duì)象都是不可變對(duì)象。請(qǐng)看下列代碼:

    String s = "Hello";
    s = s + " world!";

    s所指向的對(duì)象是否改變了呢?從本系列第一篇的結(jié)論很容易導(dǎo)出這個(gè)結(jié)論。我們來看看發(fā)生了什么事情。在這段代碼中,s原先指向一個(gè)String對(duì)象,內(nèi)容是"Hello",然后我們對(duì)s進(jìn)行了+操作,那么s所指向的那個(gè)對(duì)象是否發(fā)生了改變呢?答案是沒有。這時(shí),s不指向原來那個(gè)對(duì)象了,而指向了另一個(gè)String對(duì)象,內(nèi)容為"Hello world!",原來那個(gè)對(duì)象還存在于內(nèi)存之中,只是s這個(gè)引用變量不再指向它了。
    通過上面的說明,我們很容易導(dǎo)出另一個(gè)結(jié)論,如果經(jīng)常對(duì)字符串進(jìn)行各種各樣的修改,或者說,不可預(yù)見的修改,那么使用String來代表字符串的話會(huì)引起很大的內(nèi)存開銷。因?yàn)镾tring對(duì)象建立之后不能再改變,所以對(duì)于每一個(gè)不同的字符串,都需要一個(gè)String對(duì)象來表示。這時(shí),應(yīng)該考慮使用StringBuffer類,它允許修改,而不是每個(gè)不同的字符串都要生成一個(gè)新的對(duì)象。并且,這兩種類的對(duì)象轉(zhuǎn)換十分容易。
    同時(shí),我們還可以知道,如果要使用內(nèi)容相同的字符串,不必每次都new一個(gè)String。例如我們要在構(gòu)造器中對(duì)一個(gè)名叫s的String引用變量進(jìn)行初始化,把它設(shè)置為初始值,應(yīng)當(dāng)這樣做:
    public class Demo {
    private String s;
    ...
    public Demo {
    s = "Initial Value";
    }
    ...
    }
    而非
    s = new String("Initial Value");
    后者每次都會(huì)調(diào)用構(gòu)造器,生成新對(duì)象,性能低下且內(nèi)存開銷大,并且沒有意義,因?yàn)镾tring對(duì)象不可改變,所以對(duì)于內(nèi)容相同的字符串,只要一個(gè)String對(duì)象來表示就可以了。也就說,多次調(diào)用上面的構(gòu)造器創(chuàng)建多個(gè)對(duì)象,他們的String類型屬性s都指向同一個(gè)對(duì)象。
    上面的結(jié)論還基于這樣一個(gè)事實(shí):對(duì)于字符串常量,如果內(nèi)容相同,Java認(rèn)為它們代表同一個(gè)String對(duì)象。而用關(guān)鍵字new調(diào)用構(gòu)造器,總是會(huì)創(chuàng)建一個(gè)新的對(duì)象,無(wú)論內(nèi)容是否相同。
    至于為什么要把String類設(shè)計(jì)成不可變類,是它的用途決定的。其實(shí)不只String,很多Java標(biāo)準(zhǔn)類庫(kù)中的類都是不可變的。在開發(fā)一個(gè)系統(tǒng)的時(shí)候,我們有時(shí)候也需要設(shè)計(jì)不可變類,來傳遞一組相關(guān)的值,這也是面向?qū)ο笏枷氲捏w現(xiàn)。不可變類有一些優(yōu)點(diǎn),比如因?yàn)樗膶?duì)象是只讀的,所以多線程并發(fā)訪問也不會(huì)有任何問題。當(dāng)然也有一些缺點(diǎn),比如每個(gè)不同的狀態(tài)都要一個(gè)對(duì)象來代表,可能會(huì)造成性能上的問題。所以Java標(biāo)準(zhǔn)類庫(kù)還提供了一個(gè)可變版本,即StringBuffer。

    問題四:final關(guān)鍵字到底修飾了什么?

    final使得被修飾的變量"不變",但是由于對(duì)象型變量的本質(zhì)是“引用”,使得“不變”也有了兩種含義:引用本身的不變,和引用指向的對(duì)象不變。

    引用本身的不變:
    final StringBuffer a=new StringBuffer("immutable");
    final StringBuffer b=new StringBuffer("not immutable");
    a=b;//編譯期錯(cuò)誤

    引用指向的對(duì)象不變:
    final StringBuffer a=new StringBuffer("immutable");
    a.append(" broken!"); //編譯通過

    可見,final只對(duì)引用的“值”(也即它所指向的那個(gè)對(duì)象的內(nèi)存地址)有效,它迫使引用只能指向初始指向的那個(gè)對(duì)象,改變它的指向會(huì)導(dǎo)致編譯期錯(cuò)誤。至于它所指向的對(duì)象的變化,final是不負(fù)責(zé)的。這很類似==操作符:==操作符只負(fù)責(zé)引用的“值”相等,至于這個(gè)地址所指向的對(duì)象內(nèi)容是否相等,==操作符是不管的。

    理解final問題有很重要的含義。許多程序漏洞都基于此----final只能保證引用永遠(yuǎn)指向固定對(duì)象,不能保證那個(gè)對(duì)象的狀態(tài)不變。在多線程的操作中,一個(gè)對(duì)象會(huì)被多個(gè)線程共享或修改,一個(gè)線程對(duì)對(duì)象無(wú)意識(shí)的修改可能會(huì)導(dǎo)致另一個(gè)使用此對(duì)象的線程崩潰。一個(gè)錯(cuò)誤的解決方法就是在此對(duì)象新建的時(shí)候把它聲明為final,意圖使得它“永遠(yuǎn)不變”。其實(shí)那是徒勞的。

    問題五:到底要怎么樣初始化!

    本問題討論變量的初始化,所以先來看一下Java中有哪些種類的變量。
    1. 類的屬性,或者叫值域
    2. 方法里的局部變量
    3. 方法的參數(shù)

    對(duì)于第一種變量,Java虛擬機(jī)會(huì)自動(dòng)進(jìn)行初始化。如果給出了初始值,則初始化為該初始值。如果沒有給出,則把它初始化為該類型變量的默認(rèn)初始值。

    int類型變量默認(rèn)初始值為0
    float類型變量默認(rèn)初始值為0.0f
    double類型變量默認(rèn)初始值為0.0
    boolean類型變量默認(rèn)初始值為false
    char類型變量默認(rèn)初始值為0(ASCII碼)
    long類型變量默認(rèn)初始值為0
    所有對(duì)象引用類型變量默認(rèn)初始值為null,即不指向任何對(duì)象。注意數(shù)組本身也是對(duì)象,所以沒有初始化的數(shù)組引用在自動(dòng)初始化后其值也是null。

    對(duì)于兩種不同的類屬性,static屬性與instance屬性,初始化的時(shí)機(jī)是不同的。instance屬性在創(chuàng)建實(shí)例的時(shí)候初始化,static屬性在類加載,也就是第一次用到這個(gè)類的時(shí)候初始化,對(duì)于后來的實(shí)例的創(chuàng)建,不再次進(jìn)行初始化。這個(gè)問題會(huì)在以后的系列中進(jìn)行詳細(xì)討論。

    對(duì)于第二種變量,必須明確地進(jìn)行初始化。如果再?zèng)]有初始化之前就試圖使用它,編譯器會(huì)抗議。如果初始化的語(yǔ)句在try塊中或if塊中,也必須要讓它在第一次使用前一定能夠得到賦值。也就是說,把初始化語(yǔ)句放在只有if塊的條件判斷語(yǔ)句中編譯器也會(huì)抗議,因?yàn)閳?zhí)行的時(shí)候可能不符合if后面的判斷條件,如此一來初始化語(yǔ)句就不會(huì)被執(zhí)行了,這就違反了局部變量使用前必須初始化的規(guī)定。但如果在else塊中也有初始化語(yǔ)句,就可以通過編譯,因?yàn)闊o(wú)論如何,總有至少一條初始化語(yǔ)句會(huì)被執(zhí)行,不會(huì)發(fā)生使用前未被初始化的事情。對(duì)于try-catch也是一樣,如果只有在try塊里才有初始化語(yǔ)句,編譯部通過。如果在catch或finally里也有,則可以通過編譯??傊?,要保證局部變量在使用之前一定被初始化了。所以,一個(gè)好的做法是在聲明他們的時(shí)候就初始化他們,如果不知道要出事化成什么值好,就用上面的默認(rèn)值吧!

    其實(shí)第三種變量和第二種本質(zhì)上是一樣的,都是方法中的局部變量。只不過作為參數(shù),肯定是被初始化過的,傳入的值就是初始值,所以不需要初始化。

    問題六:instanceof是什么東東?

    instanceof是Java的一個(gè)二元操作符,和==,>,<是同一類東東。由于它是由字母組成的,所以也是Java的保留關(guān)鍵字。它的作用是測(cè)試它左邊的對(duì)象是否是它右邊的類的實(shí)例,返回boolean類型的數(shù)據(jù)。舉個(gè)例子:

    String s = "I AM an Object!";
    boolean isObject = s instanceof Object;

    我們聲明了一個(gè)String對(duì)象引用,指向一個(gè)String對(duì)象,然后用instancof來測(cè)試它所指向的對(duì)象是否是Object類的一個(gè)實(shí)例,顯然,這是真的,所以返回true,也就是isObject的值為True。
    instanceof有一些用處。比如我們寫了一個(gè)處理賬單的系統(tǒng),其中有這樣三個(gè)類:

    public class Bill {//省略細(xì)節(jié)}
    public class PhoneBill extends Bill {//省略細(xì)節(jié)}
    public class GasBill extends Bill {//省略細(xì)節(jié)}

    在處理程序里有一個(gè)方法,接受一個(gè)Bill類型的對(duì)象,計(jì)算金額。假設(shè)兩種賬單計(jì)算方法不同,而傳入的Bill對(duì)象可能是兩種中的任何一種,所以要用instanceof來判斷:

    public double calculate(Bill bill) {
    if (bill instanceof PhoneBill) {
    //計(jì)算電話賬單
    }
    if (bill instanceof GasBill) {
    //計(jì)算燃?xì)赓~單
    }
    ...
    }
    這樣就可以用一個(gè)方法處理兩種子類。

    然而,這種做法通常被認(rèn)為是沒有好好利用面向?qū)ο笾械亩鄳B(tài)性。其實(shí)上面的功能要求用方法重載完全可以實(shí)現(xiàn),這是面向?qū)ο笞兂蓱?yīng)有的做法,避免回到結(jié)構(gòu)化編程模式。只要提供兩個(gè)名字和返回值都相同,接受參數(shù)類型不同的方法就可以了:

    public double calculate(PhoneBill bill) {
    //計(jì)算電話賬單
    }

    public double calculate(GasBill bill) {
    //計(jì)算燃?xì)赓~單
    }

    所以,使用instanceof在絕大多數(shù)情況下并不是推薦的做法,應(yīng)當(dāng)好好利用多態(tài)。

    posted @ 2006-02-07 11:29 阿成 閱讀(272) | 評(píng)論 (0)編輯 收藏
    ?? ??過年8天假很快就過去了,新的一年即將開始。
    ??? ?希望今年能夠快速的提高編程技術(shù),打好基礎(chǔ)。盡快成長(zhǎng)起來。開工嘍!
    posted @ 2006-02-05 19:02 阿成 閱讀(225) | 評(píng)論 (0)編輯 收藏
    Java數(shù)據(jù)庫(kù)連接(JDBC)由一組用 Java 編程語(yǔ)言編寫的類和接口組成。JDBC 為工具/數(shù)據(jù)庫(kù)開發(fā)人員提供了一個(gè)標(biāo)準(zhǔn)的 API,使他們能夠用純Java API 來編寫數(shù)據(jù)庫(kù)應(yīng)用程序。然而各個(gè)開發(fā)商的接口并不完全相同,所以開發(fā)環(huán)境的變化會(huì)帶來一定的配置變化。本文主要集合了不同數(shù)據(jù)庫(kù)的連接方式。

      一、連接各種數(shù)據(jù)庫(kù)方式速查表

      下面羅列了各種數(shù)據(jù)庫(kù)使用JDBC連接的方式,可以作為一個(gè)手冊(cè)使用。

      1、Oracle8/8i/9i數(shù)據(jù)庫(kù)(thin模式)

    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
    String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl為數(shù)據(jù)庫(kù)的SID
    String user="test";
    String password="test";
    Connection conn= DriverManager.getConnection(url,user,password);

      2、DB2數(shù)據(jù)庫(kù)

    Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
    String url="jdbc:db2://localhost:5000/sample"; //sample為你的數(shù)據(jù)庫(kù)名
    String user="admin";
    String password="";
    Connection conn= DriverManager.getConnection(url,user,password);

      3、Sql Server7.0/2000數(shù)據(jù)庫(kù)

    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
    String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";
    //mydb為數(shù)據(jù)庫(kù)
    String user="sa";
    String password="";
    Connection conn= DriverManager.getConnection(url,user,password);

      4、Sybase數(shù)據(jù)庫(kù)

    Class.forName("com.sybase.jdbc.SybDriver").newInstance();
    String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB為你的數(shù)據(jù)庫(kù)名
    Properties sysProps = System.getProperties();
    SysProps.put("user","userid");
    SysProps.put("password","user_password");
    Connection conn= DriverManager.getConnection(url, SysProps);

      5、Informix數(shù)據(jù)庫(kù)

    Class.forName("com.informix.jdbc.IfxDriver").newInstance();
    String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
    user=testuser;password=testpassword"; //myDB為數(shù)據(jù)庫(kù)名
    Connection conn= DriverManager.getConnection(url);

      6、MySQL數(shù)據(jù)庫(kù)

    Class.forName("org.gjt.mm.mysql.Driver").newInstance();
    String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
    //myDB為數(shù)據(jù)庫(kù)名
    Connection conn= DriverManager.getConnection(url);

      7、PostgreSQL數(shù)據(jù)庫(kù)

    Class.forName("org.postgresql.Driver").newInstance();
    String url ="jdbc:postgresql://localhost/myDB" //myDB為數(shù)據(jù)庫(kù)名
    String user="myuser";
    String password="mypassword";
    Connection conn= DriverManager.getConnection(url,user,password);

      8、access數(shù)據(jù)庫(kù)直連用ODBC的

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
    String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
    Connection conn = DriverManager.getConnection(url,"","");
    Statement stmtNew=conn.createStatement() ;

      二、JDBC連接MySql方式

      下面是使用JDBC連接MySql的一個(gè)小的教程

      1、查找驅(qū)動(dòng)程序

      MySQL目前提供的java驅(qū)動(dòng)程序?yàn)镃onnection/J,可以從MySQL官方網(wǎng)站下載,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驅(qū)動(dòng)程序?yàn)榧僯ava驅(qū)動(dòng)程序,不需做其他配置。

      2、動(dòng)態(tài)指定classpath

      如果需要執(zhí)行時(shí)動(dòng)態(tài)指定classpath,就在執(zhí)行時(shí)采用-cp方式。否則將上面的.jar文件加入到classpath環(huán)境變量中。

      3、加載驅(qū)動(dòng)程序

    try{
     Class.forName(com.mysql.jdbc.Driver);
     System.out.println(Success loading Mysql Driver!);
    }catch(Exception e)
    {
     System.out.println(Error loading Mysql Driver!);
     e.printStackTrace();
    }

      4、設(shè)置連接的url

    jdbc:mysql://localhost/databasename[?pa=va][&pa=va]

      三、以下列出了在使用JDBC來連接Oracle數(shù)據(jù)庫(kù)時(shí)可以使用的一些技巧

      1、在客戶端軟件開發(fā)中使用Thin驅(qū)動(dòng)程序

      在開發(fā)Java軟件方面,Oracle的數(shù)據(jù)庫(kù)提供了四種類型的驅(qū)動(dòng)程序,二種用于應(yīng)用軟件、applets、servlets等客戶端軟件,另外二種用于數(shù)據(jù)庫(kù)中的Java存儲(chǔ)過程等服務(wù)器端軟件。在客戶機(jī)端軟件的開發(fā)中,我們可以選擇OCI驅(qū)動(dòng)程序或Thin驅(qū)動(dòng)程序。OCI驅(qū)動(dòng)程序利用Java本地化接口(JNI),通過Oracle客戶端軟件與數(shù)據(jù)庫(kù)進(jìn)行通訊。Thin驅(qū)動(dòng)程序是純Java驅(qū)動(dòng)程序,它直接與數(shù)據(jù)庫(kù)進(jìn)行通訊。為了獲得最高的性能,Oracle建議在客戶端軟件的開發(fā)中使用OCI驅(qū)動(dòng)程序,這似乎是正確的。但我建議使用Thin驅(qū)動(dòng)程序,因?yàn)橥ㄟ^多次測(cè)試發(fā)現(xiàn),在通常情況下,Thin驅(qū)動(dòng)程序的性能都超過了OCI驅(qū)動(dòng)程序。

      2、關(guān)閉自動(dòng)提交功能,提高系統(tǒng)性能

      在第一次建立與數(shù)據(jù)庫(kù)的連接時(shí),在缺省情況下,連接是在自動(dòng)提交模式下的。為了獲得更好的性能,可以通過調(diào)用帶布爾值false參數(shù)的Connection類的setAutoCommit()方法關(guān)閉自動(dòng)提交功能,如下所示:

      conn.setAutoCommit(false);

      值得注意的是,一旦關(guān)閉了自動(dòng)提交功能,我們就需要通過調(diào)用Connection類的commit()和rollback()方法來人工的方式對(duì)事務(wù)進(jìn)行管理。

      3、在動(dòng)態(tài)SQL或有時(shí)間限制的命令中使用Statement對(duì)象

      在執(zhí)行SQL命令時(shí),我們有二種選擇:可以使用PreparedStatement對(duì)象,也可以使用Statement對(duì)象。無(wú)論多少次地使用同一個(gè)SQL命令,PreparedStatement都只對(duì)它解析和編譯一次。當(dāng)使用Statement對(duì)象時(shí),每次執(zhí)行一個(gè)SQL命令時(shí),都會(huì)對(duì)它進(jìn)行解析和編譯。這可能會(huì)使你認(rèn)為,使用PreparedStatement對(duì)象比使用Statement對(duì)象的速度更快。然而,我進(jìn)行的測(cè)試表明,在客戶端軟件中,情況并非如此。因此,在有時(shí)間限制的SQL操作中,除非成批地處理SQL命令,我們應(yīng)當(dāng)考慮使用Statement對(duì)象。

      此外,使用Statement對(duì)象也使得編寫動(dòng)態(tài)SQL命令更加簡(jiǎn)單,因?yàn)槲覀兛梢詫⒆址B接在一起,建立一個(gè)有效的SQL命令。因此,我認(rèn)為,Statement對(duì)象可以使動(dòng)態(tài)SQL命令的創(chuàng)建和執(zhí)行變得更加簡(jiǎn)單。

      4、利用helper函數(shù)對(duì)動(dòng)態(tài)SQL命令進(jìn)行格式化

      在創(chuàng)建使用Statement對(duì)象執(zhí)行的動(dòng)態(tài)SQL命令時(shí),我們需要處理一些格式化方面的問題。例如,如果我們想創(chuàng)建一個(gè)將名字O'Reilly插入表中的SQL命令,則必須使用二個(gè)相連的“''”號(hào)替換O'Reilly中的“'”號(hào)。完成這些工作的最好的方法是創(chuàng)建一個(gè)完成替換操作的helper方法,然后在連接字符串心服用公式表達(dá)一個(gè)SQL命令時(shí),使用創(chuàng)建的helper方法。與此類似的是,我們可以讓helper方法接受一個(gè)Date型的值,然后讓它輸出基于Oracle的to_date()函數(shù)的字符串表達(dá)式。

      5、利用PreparedStatement對(duì)象提高數(shù)據(jù)庫(kù)的總體效率

      在使用PreparedStatement對(duì)象執(zhí)行SQL命令時(shí),命令被數(shù)據(jù)庫(kù)進(jìn)行解析和編譯,然后被放到命令緩沖區(qū)。然后,每當(dāng)執(zhí)行同一個(gè)PreparedStatement對(duì)象時(shí),它就會(huì)被再解析一次,但不會(huì)被再次編譯。在緩沖區(qū)中可以發(fā)現(xiàn)預(yù)編譯的命令,并且可以重新使用。在有大量用戶的企業(yè)級(jí)應(yīng)用軟件中,經(jīng)常會(huì)重復(fù)執(zhí)行相同的SQL命令,使用PreparedStatement對(duì)象帶來的編譯次數(shù)的減少能夠提高數(shù)據(jù)庫(kù)的總體性能。如果不是在客戶端創(chuàng)建、預(yù)備、執(zhí)行PreparedStatement任務(wù)需要的時(shí)間長(zhǎng)于Statement任務(wù),我會(huì)建議在除動(dòng)態(tài)SQL命令之外的所有情況下使用PreparedStatement對(duì)象。

      6、在成批處理重復(fù)的插入或更新操作中使用PreparedStatement對(duì)象

      如果成批地處理插入和更新操作,就能夠顯著地減少它們所需要的時(shí)間。Oracle提供的Statement和 CallableStatement并不真正地支持批處理,只有PreparedStatement對(duì)象才真正地支持批處理。我們可以使用addBatch()和executeBatch()方法選擇標(biāo)準(zhǔn)的JDBC批處理,或者通過利用PreparedStatement對(duì)象的setExecuteBatch()方法和標(biāo)準(zhǔn)的executeUpdate()方法選擇速度更快的Oracle專有的方法。要使用Oracle專有的批處理機(jī)制,可以以如下所示的方式調(diào)用setExecuteBatch():

    PreparedStatement pstmt3D null;
    try {
     ((OraclePreparedStatement)pstmt).setExecuteBatch(30);
     ...
     pstmt.executeUpdate();
    }

      調(diào)用setExecuteBatch()時(shí)指定的值是一個(gè)上限,當(dāng)達(dá)到該值時(shí),就會(huì)自動(dòng)地引發(fā)SQL命令執(zhí)行,標(biāo)準(zhǔn)的executeUpdate()方法就會(huì)被作為批處理送到數(shù)據(jù)庫(kù)中。我們可以通過調(diào)用PreparedStatement類的sendBatch()方法隨時(shí)傳輸批處理任務(wù)。

      7、使用Oracle locator方法插入、更新大對(duì)象(LOB)

      Oracle的PreparedStatement類不完全支持BLOB和CLOB等大對(duì)象的處理,尤其是Thin驅(qū)動(dòng)程序不支持利用PreparedStatement對(duì)象的setObject()和setBinaryStream()方法設(shè)置BLOB的值,也不支持利用setCharacterStream()方法設(shè)置CLOB的值。只有l(wèi)ocator本身中的方法才能夠從數(shù)據(jù)庫(kù)中獲取LOB類型的值。可以使用PreparedStatement對(duì)象插入或更新LOB,但需要使用locator才能獲取LOB的值。由于存在這二個(gè)問題,因此,我建議使用locator的方法來插入、更新或獲取LOB的值。

      8、使用SQL92語(yǔ)法調(diào)用存儲(chǔ)過程

      在調(diào)用存儲(chǔ)過程時(shí),我們可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并沒有什么實(shí)際的好處,而且會(huì)給以后維護(hù)你的應(yīng)用程序的開發(fā)人員帶來麻煩,因此,我建議在調(diào)用存儲(chǔ)過程時(shí)使用SQL92。

      9、使用Object SQL將對(duì)象模式轉(zhuǎn)移到數(shù)據(jù)庫(kù)中

      既然可以將Oracle的數(shù)據(jù)庫(kù)作為一種面向?qū)ο蟮臄?shù)據(jù)庫(kù)來使用,就可以考慮將應(yīng)用程序中的面向?qū)ο竽J睫D(zhuǎn)到數(shù)據(jù)庫(kù)中。目前的方法是創(chuàng)建Java bean作為偽裝的數(shù)據(jù)庫(kù)對(duì)象,將它們的屬性映射到關(guān)系表中,然后在這些bean中添加方法。盡管這樣作在Java中沒有什么問題,但由于操作都是在數(shù)據(jù)庫(kù)之外進(jìn)行的,因此其他訪問數(shù)據(jù)庫(kù)的應(yīng)用軟件無(wú)法利用對(duì)象模式。如果利用Oracle的面向?qū)ο蟮募夹g(shù),可以通過創(chuàng)建一個(gè)新的數(shù)據(jù)庫(kù)對(duì)象類型在數(shù)據(jù)庫(kù)中模仿其數(shù)據(jù)和操作,然后使用JPublisher等工具生成自己的Java bean類。如果使用這種方式,不但Java應(yīng)用程序可以使用應(yīng)用軟件的對(duì)象模式,其他需要共享你的應(yīng)用中的數(shù)據(jù)和操作的應(yīng)用軟件也可以使用應(yīng)用軟件中的對(duì)象模式。

      10、利用SQL完成數(shù)據(jù)庫(kù)內(nèi)的操作

      我要向大家介紹的最重要的經(jīng)驗(yàn)是充分利用SQL的面向集合的方法來解決數(shù)據(jù)庫(kù)處理需求,而不是使用Java等過程化的編程語(yǔ)言。

      如果編程人員要在一個(gè)表中查找許多行,結(jié)果中的每個(gè)行都會(huì)查找其他表中的數(shù)據(jù),最后,編程人員創(chuàng)建了獨(dú)立的UPDATE命令來成批地更新第一個(gè)表中的數(shù)據(jù)。與此類似的任務(wù)可以通過在set子句中使用多列子查詢而在一個(gè)UPDATE命令中完成。當(dāng)能夠在單一的SQL命令中完成任務(wù),何必要讓數(shù)據(jù)在網(wǎng)上流來流去的?我建議用戶認(rèn)真學(xué)習(xí)如何最大限度地發(fā)揮SQL的功能。
    posted @ 2006-01-26 11:32 阿成 閱讀(254) | 評(píng)論 (0)編輯 收藏
    在Servlet2.3規(guī)范中,Web應(yīng)用事件是新增加的部分。它讓你能最大程度地控制你的Web應(yīng)用。在本文中,我們將學(xué)習(xí)兩個(gè)很重要的應(yīng)用事件:

    應(yīng)用的啟動(dòng)和停止

    Session的創(chuàng)建和失效如它們的名字那樣,應(yīng)用啟動(dòng)事件發(fā)生在你的應(yīng)用第一次被servlet容器裝載和啟動(dòng)的時(shí)候;停止事件發(fā)生在Web應(yīng)用停止的時(shí)候。

    Session創(chuàng)建事件發(fā)生在每次一個(gè)新的session創(chuàng)建的時(shí)候,類似地Session失效事件發(fā)生在每次一個(gè)Session失效的時(shí)候。為了使用這些Web應(yīng)用事件為你做些有用的事情,我們必須創(chuàng)建和使用一些特殊的“監(jiān)聽”類。下面,我們將研究這些監(jiān)聽類到地是什么以及我們?nèi)绾稳ナ褂盟鼈儭?br />
    監(jiān)聽類:

    它們是實(shí)現(xiàn)了下邊兩個(gè)接口中任何一個(gè)接口的簡(jiǎn)單的java類:

    javax.servlet.ServletContextListener 
    javax.servlet.http.HttpSessionListener


    如果你想讓你的類監(jiān)聽?wèi)?yīng)用的啟動(dòng)和停止事件,你就得實(shí)現(xiàn)ServletContextListener接口;如果你想讓你的類去監(jiān)聽Session的創(chuàng)建和失效事件,那你就得實(shí)現(xiàn)HttpSessionListener接口。 讓我們看看在這些接口中你必須要實(shí)現(xiàn)的方法。

    1.ServletContextListener :

    接口包括如下兩個(gè)方法:

    public void contextInitialized
    (ServletContextEvent sce); 
    
    public void contextDestroyed
    (ServletContextEvent sce);


    如果你實(shí)現(xiàn)了一個(gè)接口,那你就必須實(shí)現(xiàn)它所有的方法。因此,如果你想利用應(yīng)用的啟動(dòng)和停止事件,你就需要?jiǎng)?chuàng)建一個(gè)Java類并實(shí)現(xiàn)ServletContextListener接口。下邊是這樣的一個(gè)類的例子:

    /*File : ApplicationWatch.java*/
    import javax.servlet.ServletContextListener;
    import javax.servlet.ServletContextEvent;
    public class ApplicationWatch implements 
    ServletContextListener 
    {
    public static long
    applicationInitialized = 0L;
    /* 應(yīng)用啟動(dòng)事件 */
    public void contextInitialized
    (ServletContextEvent ce)
    {
    applicationInitialized =
    System.currentTimeMillis();
    }
    /*應(yīng)用停止事件 */
    public void contextDestroyed
    (ServletContextEvent ce) {}
    }


    在上邊的代碼中,ApplicationWatch類實(shí)現(xiàn)了ServletContextListener接口。它實(shí)現(xiàn)了接口中的兩個(gè)方法,但只用了其中的一個(gè)方法,另一個(gè)方法中沒有寫任何代碼。這個(gè)類把應(yīng)用啟動(dòng)的時(shí)間記錄在一個(gè)可以從其它應(yīng)用類中存取應(yīng)用啟動(dòng)時(shí)間的public static變量中。

    我將很快解釋如何告訴服務(wù)器我們有這個(gè)監(jiān)聽類,但首先讓我們看看HttpSessionListener接口有什么不同的方法。

    2.HttpSessionListener :

    這個(gè)接口也只包含兩個(gè)方法,分別對(duì)應(yīng)于Session的創(chuàng)建和失效:

    public void sessionCreated
    (HttpSessionEvent se); 
    
    public void sessionDestroyed
    (HttpSessionEvent se);


    如上邊的ApplicationWatch例子那樣,我們也創(chuàng)建了一個(gè)實(shí)現(xiàn)HttpSessionListener接口的類。如下:

    /*File : SessionCounter.java*/
    import javax.servlet.http.HttpSessionListener;
    import javax.servlet.http.HttpSessionEvent;
    public class SessionCounter
    implements HttpSessionListener 
    {
    private static int activeSessions =0;
    /* Session創(chuàng)建事件 */
    public void sessionCreated
    (HttpSessionEvent se)
    {
           activeSessions++;
    }
    /* Session失效事件 */
    public void sessionDestroyed
    (HttpSessionEvent se)
    {
    if(activeSessions>0)activeSessions--;
    }
    
    public static int getActiveSessions()
    {
    return activeSessions;
    }
    }


    在上邊的代碼中,SessionCounter類實(shí)現(xiàn)了HttpSessionListener接口,其目的是計(jì)算活動(dòng)會(huì)話的數(shù)量。

    好了,我們已經(jīng)學(xué)習(xí)了什么是Web應(yīng)用事件,有什么接口可以用以及看到了一些實(shí)現(xiàn)這些接口的例子。讓我們看看如何告訴應(yīng)用服務(wù)器我們有這些監(jiān)聽類。

    Web.xml :

    我們通過把類路徑加入/WEB-INF/web.xml文件的標(biāo)簽中來告訴服務(wù)器我們的監(jiān)聽類。下邊是一個(gè)web.xml文件的例子:

    <!-- Web.xml -->
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-appPUBLIC "-//Sun Microsystems,
    Inc.//DTD Web Application 2.3
    //EN""http://java.sun.com
    /j2ee/dtds/web-app_2.3.dtd">
    <web-app>
    <!-- Listeners -->
    <listener>
    <listener-class>
    com.stardeveloper.web.listener.SessionCounter
    </listener-class>
    </listener>
    <listener>
    <listener-class>
    com.stardeveloper.web.listener.
    ApplicationWatch</listener-class>
    </listener>
    </web-app>


    如上所示,在web.xml文件中聲明監(jiān)聽類是非常簡(jiǎn)單的?,F(xiàn)在,每次的服務(wù)器的啟動(dòng)和停止,會(huì)話的創(chuàng)建和失效,配置好的監(jiān)聽類的相應(yīng)的方法就會(huì)被調(diào)用。
    posted @ 2006-01-25 10:11 阿成 閱讀(238) | 評(píng)論 (0)編輯 收藏
    ?????? 快過年了,這幾天才越來越感覺到,學(xué)生時(shí)代的生活一去不復(fù)返了。
    ??????以前的日子,無(wú)論高三還是大學(xué),這個(gè)時(shí)候早就在家待著了,或許在家看電視,或許賀同學(xué) 聚會(huì),
    或許在親戚家住著。。。。
    ??????可是現(xiàn)在,還在公司上班。晚上沒事,來公司上上網(wǎng),過年前的這幾天,學(xué)習(xí)好像也沒有多大的興趣了,不由自主的懷念起學(xué)生時(shí)代的生活。和舍友一起出去吃飯,上網(wǎng)吧聯(lián)網(wǎng)打游戲等等,心里有些失落
    。
    ??? 但上班了,也越來越體會(huì)到父母的辛苦。
    ??? 他們?cè)谝惶煲惶熳兝希晌以谝惶煲惶臁伴L(zhǎng)大”嗎?
    ??? 家里的擔(dān)子要接過來了,他們?cè)撔菹⑿菹⒘恕?
    posted @ 2006-01-24 21:27 阿成 閱讀(193) | 評(píng)論 (0)編輯 收藏
    僅列出標(biāo)題
    共10頁(yè): First 上一頁(yè) 2 3 4 5 6 7 8 9 10 下一頁(yè) 
    主站蜘蛛池模板: 亚洲欧美熟妇综合久久久久| 亚洲图片激情小说| 亚洲第一AAAAA片| 91嫩草亚洲精品| 亚洲AV无码XXX麻豆艾秋| 2022免费国产精品福利在线| 久久福利青草精品资源站免费| 在线观看免费av网站| 成年在线网站免费观看无广告| 国产免费拔擦拔擦8x| 亚洲色精品aⅴ一区区三区| 亚洲美女激情视频| 亚洲欧美精品午睡沙发| 精品熟女少妇aⅴ免费久久| 99精品国产成人a∨免费看| 精品国产免费观看| 亚洲精品无码AV人在线播放| 亚洲精品国产专区91在线| 久久精品国产亚洲av天美18| a级男女仿爱免费视频| 18勿入网站免费永久| 亚洲国产V高清在线观看| 亚洲视频.com| 爱爱帝国亚洲一区二区三区| a毛片免费全部播放完整成| 一二三四免费观看在线电影| 亚洲国产精品专区在线观看| 亚洲黄色免费观看| 三年片在线观看免费观看大全中国| 日韩免费高清大片在线| 国产真实伦在线视频免费观看| 亚洲AV无码一区二区三区DV| 亚洲欧洲专线一区| 免费在线看污视频| 日本特黄特色aa大片免费| 久久精品亚洲中文字幕无码麻豆| 国产精品亚洲精品日韩电影| 67pao强力打造高清免费| 亚洲精品成a人在线观看| 亚洲一级片在线观看| a级毛片免费播放|