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

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

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

    posts - 73,  comments - 55,  trackbacks - 0
    URL(Uniform Resoure Locator,統一資源定位器)是Internet中對資源進行統一定位和管理的標志。
    一個完整的URL包括如下內容:
    1.???????? 應用協議名稱,包括http,ftp,file等標志
    2.???????? 資源定位,是由(.)分割等網絡路徑
    3.???????? 端口號,按照規定,http應用端口是80,telnet協議應用端口是23。
    4.???????? 服務器中的文件路徑
    5.???????? 文件中的編碼位置
    一個完整的URL如下:
    http://SomeUser:mypassword@www.some_server.com:8080/path/file.html
    ?URL無法顯示某些特殊符號,這個時候就要使用編碼了。編碼的格式為:一個百分號,后面跟對應字符的ASCII(16進制)碼值。例如 空格的編碼值是"%20"。(ASCII參考)
    有些字符在URL中具有特殊含義,基本編碼規則如下:
    特殊含義??????????????????????????????????????????????????????????? 十六進制值
    1.+ 表示空格(在 URL 中不能使用空格)????????? %20
    2./ 分隔目錄和子目錄????????????????????????????????????????????? %2F
    3.? 分隔實際的 URL 和參數?????????????????????????????????? %3F
    4.% 指定特殊字符??????????????????????????????????????????????????? %25
    5.# 表示書簽???????????????????????????????????????????????????????????? %23
    6.& URL 中指定的參數間的分隔符??????????????????????? %26
    java中URL 的編碼和解碼函數
    java.net.URLEncoder.encode(String s)和java.net.URLDecoder.decode(String s);
    在javascript 中URL 的編碼和解碼函數
    escape(String s)和unescape(String s) ;
    posted @ 2007-01-12 21:14 保爾任 閱讀(10323) | 評論 (0)編輯 收藏
    (轉自:http://blog.csdn.net/nomads/archive/2006/09/05/1178867.aspx)
    Java提供了一套機制來動態執行方法和構造方法,以及數組操作等,這套機制就叫——反射。反射機制是如今很多流行框架的實現基礎,其中包括Spring、Hibernate等。原理性的問題不是本文的重點,接下來讓我們在實例中學習這套精彩的機制。

    1. 得到某個對象的屬性

    1?public?Object?getProperty(Object?owner,?String?fieldName)?throws?Exception?{
    2?????Class?ownerClass?=?owner.getClass();
    3?
    4?????Field?field?=?ownerClass.getField(fieldName);
    5?
    6?????Object?property?=?field.get(owner);
    7?
    8?????return?property;
    9?}

    Class ownerClass = owner.getClass():得到該對象的Class。

    Field field = ownerClass.getField(fieldName):通過Class得到類聲明的屬性。

    Object property = field.get(owner):通過對象得到該屬性的實例,如果這個屬性是非公有的,這里會報IllegalAccessException。



    2. 得到某個類的靜態屬性

    ?1?public?Object?getStaticProperty(String?className,?String?fieldName)
    ?2?????????????throws?Exception?{
    ?3?????Class?ownerClass?=?Class.forName(className);
    ?4?
    ?5?????Field?field?=?ownerClass.getField(fieldName);
    ?6?
    ?7?????Object?property?=?field.get(ownerClass);
    ?8?
    ?9?????return?property;
    10?}


    Class ownerClass = Class.forName(className) :首先得到這個類的Class。

    Field field = ownerClass.getField(fieldName):和上面一樣,通過Class得到類聲明的屬性。

    Object property = field.get(ownerClass) :這里和上面有些不同,因為該屬性是靜態的,所以直接從類的Class里取。


    3. 執行某對象的方法

    ?1?public?Object?invokeMethod(Object?owner,?String?methodName,?Object[]?args)?throws?Exception?{
    ?2?
    ?3?????Class?ownerClass?=?owner.getClass();
    ?4?
    ?5?????Class[]?argsClass?=?new?Class[args.length];
    ?6?
    ?7?????for?(int?i?=?0,?j?=?args.length;?i?<?j;?i++)?{
    ?8?????????argsClass[i]?=?args[i].getClass();
    ?9?????}
    10?
    11?????Method?method?=?ownerClass.getMethod(methodName,?argsClass);
    12?
    13?????return?method.invoke(owner,?args);
    14?}

    Class owner_class = owner.getClass() :首先還是必須得到這個對象的Class。

    5~9行:配置參數的Class數組,作為尋找Method的條件。

    Method method = ownerClass.getMethod(methodName, argsClass):通過Method名和參數的Class數組得到要執行的Method。

    method.invoke(owner, args):執行該Method,invoke方法的參數是執行這個方法的對象,和參數數組。返回值是Object,也既是該方法的返回值。


    4. 執行某個類的靜態方法

    ?1?public?Object?invokeStaticMethod(String?className,?String?methodName,
    ?2?????????????Object[]?args)?throws?Exception?{
    ?3?????Class?ownerClass?=?Class.forName(className);
    ?4?
    ?5?????Class[]?argsClass?=?new?Class[args.length];
    ?6?
    ?7?????for?(int?i?=?0,?j?=?args.length;?i?<?j;?i++)?{
    ?8?????????argsClass[i]?=?args[i].getClass();
    ?9?????}
    10?
    11?????Method?method?=?ownerClass.getMethod(methodName,?argsClass);
    12?
    13?????return?method.invoke(null,?args);
    14?}


    基本的原理和實例3相同,不同點是最后一行,invoke的一個參數是null,因為這是靜態方法,不需要借助實例運行。



    5. 新建實例
    ?1?
    ?2?public?Object?newInstance(String?className,?Object[]?args)?throws?Exception?{
    ?3?????Class?newoneClass?=?Class.forName(className);
    ?4?
    ?5?????Class[]?argsClass?=?new?Class[args.length];
    ?6?
    ?7?????for?(int?i?=?0,?j?=?args.length;?i?<?j;?i++)?{
    ?8?????????argsClass[i]?=?args[i].getClass();
    ?9?????}
    10?
    11?????Constructor?cons?=?newoneClass.getConstructor(argsClass);
    12?
    13?????return?cons.newInstance(args);
    14?
    15?}


    這里說的方法是執行帶參數的構造函數來新建實例的方法。如果不需要參數,可以直接使用newoneClass.newInstance()來實現。

    Class newoneClass = Class.forName(className):第一步,得到要構造的實例的Class。

    第5~第9行:得到參數的Class數組。

    Constructor cons = newoneClass.getConstructor(argsClass):得到構造子。

    cons.newInstance(args):新建實例。


    6. 判斷是否為某個類的實例

    1?public?boolean?isInstance(Object?obj,?Class?cls)?{
    2?????return?cls.isInstance(obj);
    3?}



    7. 得到數組中的某個元素
    1?public?Object?getByArray(Object?array,?int?index)?{
    2?????return?Array.get(array,index);
    3?}



    附完整源碼:

    import?java.lang.reflect.Array;
    import?java.lang.reflect.Constructor;
    import?java.lang.reflect.Field;
    import?java.lang.reflect.Method;


    /**
    ?*?Java?Reflection?Cookbook
    ?*
    ?*?
    @author?Michael?Lee
    ?*?
    @since?2006-8-23
    ?*?
    @version?0.1a
    ?
    */

    public?class?Reflection?{
    ????
    /**
    ?????*?得到某個對象的公共屬性
    ?????*
    ?????*?
    @param?owner,?fieldName
    ?????*?
    @return?該屬性對象
    ?????*?
    @throws?Exception
    ?????*
    ?????
    */
    ????
    public?Object?getProperty(Object?owner,?String?fieldName)?throws?Exception?{
    ????????Class?ownerClass?
    =?owner.getClass();

    ????????Field?field?
    =?ownerClass.getField(fieldName);

    ????????Object?property?
    =?field.get(owner);

    ????????
    return?property;
    ????}

    ????
    /**
    ?????*?得到某類的靜態公共屬性
    ?????*
    ?????*?
    @param?className???類名
    ?????*?
    @param?fieldName???屬性名
    ?????*?
    @return?該屬性對象
    ?????*?
    @throws?Exception
    ?????
    */
    ????
    public?Object?getStaticProperty(String?className,?String?fieldName)
    ????????????
    throws?Exception?{
    ????????Class?ownerClass?
    =?Class.forName(className);

    ????????Field?field?
    =?ownerClass.getField(fieldName);

    ????????Object?property?
    =?field.get(ownerClass);

    ????????
    return?property;
    ????}


    ????
    /**
    ?????*?執行某對象方法
    ?????*
    ?????*?
    @param?owner
    ?????*????????????對象
    ?????*?
    @param?methodName
    ?????*????????????方法名
    ?????*?
    @param?args
    ?????*????????????參數
    ?????*?
    @return?方法返回值
    ?????*?
    @throws?Exception
    ?????
    */
    ????
    public?Object?invokeMethod(Object?owner,?String?methodName,?Object[]?args)
    ????????????
    throws?Exception?{

    ????????Class?ownerClass?
    =?owner.getClass();

    ????????Class[]?argsClass?
    =?new?Class[args.length];

    ????????
    for?(int?i?=?0,?j?=?args.length;?i?<?j;?i++)?{
    ????????????argsClass[i]?
    =?args[i].getClass();
    ????????}

    ????????Method?method?
    =?ownerClass.getMethod(methodName,?argsClass);

    ????????
    return?method.invoke(owner,?args);
    ????}


    ??????
    /**
    ?????*?執行某類的靜態方法
    ?????*
    ?????*?
    @param?className
    ?????*????????????類名
    ?????*?
    @param?methodName
    ?????*????????????方法名
    ?????*?
    @param?args
    ?????*????????????參數數組
    ?????*?
    @return?執行方法返回的結果
    ?????*?
    @throws?Exception
    ?????
    */
    ????
    public?Object?invokeStaticMethod(String?className,?String?methodName,
    ????????????Object[]?args)?
    throws?Exception?{
    ????????Class?ownerClass?
    =?Class.forName(className);

    ????????Class[]?argsClass?
    =?new?Class[args.length];

    ????????
    for?(int?i?=?0,?j?=?args.length;?i?<?j;?i++)?{
    ????????????argsClass[i]?
    =?args[i].getClass();
    ????????}

    ????????Method?method?
    =?ownerClass.getMethod(methodName,?argsClass);

    ????????
    return?method.invoke(null,?args);
    ????}



    ????
    /**
    ?????*?新建實例
    ?????*
    ?????*?
    @param?className
    ?????*????????????類名
    ?????*?
    @param?args
    ?????*????????????構造函數的參數
    ?????*?
    @return?新建的實例
    ?????*?
    @throws?Exception
    ?????
    */
    ????
    public?Object?newInstance(String?className,?Object[]?args)?throws?Exception?{
    ????????Class?newoneClass?
    =?Class.forName(className);

    ????????Class[]?argsClass?
    =?new?Class[args.length];

    ????????
    for?(int?i?=?0,?j?=?args.length;?i?<?j;?i++)?{
    ????????????argsClass[i]?
    =?args[i].getClass();
    ????????}

    ????????Constructor?cons?
    =?newoneClass.getConstructor(argsClass);

    ????????
    return?cons.newInstance(args);

    ????}


    ????
    ????
    /**
    ?????*?是不是某個類的實例
    ?????*?
    @param?obj?實例
    ?????*?
    @param?cls?類
    ?????*?
    @return?如果?obj?是此類的實例,則返回?true
    ?????
    */
    ????
    public?boolean?isInstance(Object?obj,?Class?cls)?{
    ????????
    return?cls.isInstance(obj);
    ????}
    ????
    ????
    /**
    ?????*?得到數組中的某個元素
    ?????*?
    @param?array?數組
    ?????*?
    @param?index?索引
    ?????*?
    @return?返回指定數組對象中索引組件的值
    ?????
    */
    ????
    public?Object?getByArray(Object?array,?int?index)?{
    ????????
    return?Array.get(array,index);
    ????}
    }
    ?
    posted @ 2007-01-12 10:03 保爾任 閱讀(524) | 評論 (2)編輯 收藏

    面試經驗 綜合/算法 C/C++/VC MS-SQL Server Java .NET技術 Oracle 其他
    [微軟系列] [INTEL] [網易] [中興] [華為] [Google12] [DELL] [朗訊] [神州數碼] [方正] [SUN]
    ?
    [面試經驗]
    高薪是怎么跳出來的?(轉載) (wjf4856)
    最近幾天招聘程序員的感想,另外附一份面試題,大家批批(jyk)
    機會是給有準備的人的,我今天去上海微創面試的體會(sanjie88)
    面試經歷分享:北京文思創新(ghz)
    面試的苦惱(palts520)
    面試阿里巴巴(boona)
    我的面試經歷,一個字難?。。。。。。。。?!(zxs3543)
    如何面試軟件工程師?(zenhan)
    在網上看了不少公司面試筆試的文章,郁悶了(BLGT)
    前天面試失敗,特來此作檢討.從今以后開始要好好學習.(utmost100)
    要到珠海優特公司面試,請教該做些什么準備?(Builder_Soft)
    美工面試一般都會問什么問題(qs_25)
    請問面試VB程序員要注意些什么?(chinayokel)
    沒有面試經驗,請大家指導一下(chinayokel)
    Asp.net面試一般問什么(zhukuanliang)
    急請大家幫忙一會要去面試,聽說是上機。一般都出什么題呀(tt5201)
    緊急求助:面試時,企業考察編程能力一般會出怎樣的題目,特別是VC++!(ab2)
    問個問題(視頻聊天)和寫寫4次面試的煩惱(jianjian8410)
    [新手求助]電話面試都要準備那些方面?(OpenHero)
    為什么每次面試之后都沒有結果啊(fangza)
    在華為地下室餐廳面試的來聊聊(xubai)
    過些天去面試, 軟件測試方面, 請各位大蝦請提些建議,非常感謝(Ripple_wang)
    江湖救急!馬上要去面試一個跟物流有關的技術職位,有做物流開發經驗的嗎?(givemecool)
    上周五去長沙大唐先一科技面試,十分郁悶,散分散心!(lingfeng0626)
    關于面試(mystones)
    做嵌入式開發,一般都面試哪方面的知識?(werqqq)
    這次面試太丟臉了,郁悶啊!(feng13555)
    繼續那個:從東軟面試回來郁悶中(轉)(mysticality)
    NEC公司明天面試,向去過或在這個公司的兄弟請教,頂者勿入(ATaoo)
    面試5個月后收到華為錄取通知,faint(gomydream)
    在面試的時候,自我介紹應該說些什么?(luobo525)
    ?
    [綜合/算法]
    101道經典面試題 - 01? 23456789 (china_cooooooooooder)
    一個年薪10萬美金的面試題(ayungood)
    面試考題,愁?。。。?/a>(mysticality)
    [調查]去西安交大的一個軟件公司面試,面試官問了一個問題,看有多少人能回答來,順便散分(bgqy2000)
    Google面試的20題,知道的麻煩給點提示 .(hansin)
    據說是微軟面試題,有答案了,但不知道為什么會是這樣!(DaChu)
    月薪3萬的一道面試題(看看你的IQ )(cgtsea)
    SZSM面試題:寫一個可以返回任意兩個string串的最大公串的函數,語言不限(redbirdli)
    分享一下:今天我們公司招聘產品設計師的面試題目……(KiteGirl)
    面試時一道超難的算法問題?。。?/a>(justrun2005)
    一道真正難倒億人的智力題,這是微軟的面試題(66766960)
    據說是一道微軟月薪5w職位的面試題(cjjfam)
    DELL的英文面試題(硬件部分和操作系統),兄弟們直接寫下答案,切磋以下!(zh050317)
    從網上搜集到的網易筆試題,大家一起討論一下.
    ?

    [C/C++/VC]

    再帖 幾道面試題(據說是INTEL公司的)(zdl1016)
    [轉帖]大家來試試GOOGLE面試題!!(laiwusheng)
    據說是朗訓面試題(flyiner)
    我的中興面試題,求達人給個答案啊(flyabcd)
    求面試題~南京聯創的(110120119)
    求教一面試題:編寫一個函數比較兩個整數大小,但不能使用任何比較操作符(neoadane)
    C語言面試題大匯總,個人覺得還是比較全地!!!(free131)
    前天的一道面試題,前輩幫看看!(67676373)
    微軟經典面試題(bastenf)
    問個面試題(zjbirdman)
    面試問題之反轉字符串中單詞的順序(ugg)
    求助:關于局部變量的一道面試題(neoadane)
    昨天朋友面試碰到的一面試題,請教大家(petertangpei)
    一個面試題(xiaojun19830916)
    兩道有趣的面試題目.(yangnix)
    各位大俠請幫小弟作道面試題,先謝了!(open_ocean)
    面試問題,求助,送分(OneAudollar)
    1道面試題 大家幫忙看看(gggaaakkk)
    面試題1(yangxudongseu)
    ?面試題目,求助!(OneAudollar)
    又有一個面試題,大家看看(yifongzhou)
    面試題,有點難,歡迎高手指點(xnkjdx1998)
    大家看看面試題!(yanjun885)
    求解幾個面試題,今天面的,郁悶死我了(paskaa)
    昨天的面試題,分享一下(jianyachu)
    一道面試糾錯題,大家看看吧(nysst_hxl)
    一個關于指針的面試題,會者請進。(fansgq)
    軟件外企C++面試題,大家試試看?(OneAudollar)
    兩道C面試題,不小心你未必能做對哦(ilelf)
    [高手進]一個面試題,希望高手幫我解答,圖形方面!(yangc_83)
    [要求置頂]開源軟件的面試題——各位大哥們給點思路(dream2013)
    面試時被人問到兩個問題(yjukh)
    求助:面試一些題目,高手們過來幫忙解答一下~(yjukh)
    今天的面試題(自學C果然夠嗆,望大家多多提示)(ppsdog1956)
    ?
    [MS-SQL Server]
    sql server 面試時 的考題!!(整理)(2344095)
    神州數碼11道面試題求解(jinder22)
    3棵面試題,大家來看看...................(hanchi8008)
    關于事務的問題(面試題)(zyq_10_25)
    sql server 面試時 的考題!!(2344095)
    昨天看了一個朋友的面試題,大家也來看看(THE_ROCK)
    這SQL語句我真的不會寫?面試題目(hzchl219)
    棘手的(SQL)面試題(songyutou)
    面試題!(zyq_10_25)
    我在面試時遇到的sql語句,請高人指點,跪求?。。。?/a>(polo_van)
    面試問題,請幫忙解答??!(songcan)
    這個sql語句該怎么寫?(面試題)(csdn02)
    這邊還有40分.求面試題:關于存儲過程和觸發器的,并附答案呀!!!!!!!!!!!!!!(fairan)
    面試問題 大表、小表 ,內聯查詢,大表放在前面還是后面查詢速度更快(jietuan)
    ?
    [Oracle]
    DBA常見面試題征集答案,并希望達人補充,希望此貼讓所有想做DBA的人有點方向。(pegtop)
    面試題(zyq_10_25)
    我今天面試的SQL題目,歡迎剛畢業的同學來試一試!!!(kong361)
    ?
    [Java]
    共享一些面試題(wts173)
    方正的面試題目(jmh0525)
    一個很妖的問題(sun公司的面試題)(CCJHJ)
    高分求救!面試的時候,考官這樣問我,我要怎么回答!! 謝謝??!定給高分!
    外企的一道面試題.還請高手多多指點指點(急)!謝了!!(ayorange)
    Java面試題(x_hong)
    一公司面試題,做一翻譯字典,要把不同的字典放在不同的服務器,高手幫忙啊(totti1110)
    請教一道面試題?(javaf1)
    本人自己遇到的面試題(急!急!急?。?/a>(caiheng520)
    一道面試題:這么確定a是不是B類的一個實例。謝謝(luofengjava)
    一個Hibernate 的面試題, 現場分析問題(this_is_alan)
    面試題!在線等!(mousefog)
    面試題目!誰能告訴我答案啊!(yinlei920)
    面試題(Hmilyl)
    感興趣的話來看一下這道面試題(chenfive)
    高分求教!!!一道面試題(url鏈接傳中文參數值亂碼問題)(tooker)
    面試題60分!請大家幫忙(zyq_10_25)
    面試題求答案(zhyhongyuan)
    共享J2ME面試題目,歡迎大家積極參與(Mailbomb)
    今天的面試題(Hmilyl)
    一道java面試題(今天剛面試回來)(cuiter)
    面試關于JSP+oracl的問題求救(coolcat_1981)
    ?
    [.NET技術] ?
    在網上看到的面試題大全,有興趣的朋友可以來試試看(greatbag)
    dotNet高級軟件工程師面試題(flyinsky333)
    .net面試題集(liuxingjin)
    閑來無事,做了一道面試題:100位數字相乘(czhenq)
    **大型軟件公司.net面試題!一定的看!(aspjsp)
    我們公司面試基本完成,現公開部分面試題,感興趣的來看看,同時也是給出標準答案供面試者參考。(Ivony)
    昨天面試微軟,只有這一題不會做。(amingo)
    一道真正難倒億人的智力題,這是微軟的面試題(66766960)
    【MS的一道面試題】Session問題(cxyppppp)
    我們公司的一道面試題(jobenc)
    有點麻煩的面試題,請給個核心算法(iacpdj)
    一道.net面試題???(never_give_up520)
    一道面試題,大家解答!(tigerlgf)
    今天面試的兩個問題,沒能回答好,郁悶!(zhanghaif)
    面試題大家都來看看 在線等急~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(willyer)
    一道面試題,怎么也沒看懂,大家幫忙看看(iacpdj)
    同學去面試的兩個面試題!(longshaoye)
    面試題(karso)
    不知道是垃圾面試題還是好的面試題?大家看看吧!(rex1984)
    面試遇到這種題,暈了!求各位施予援手!(songcan)
    一道面試題,沒做出來!(cloud_1981)
    面試題目:如何在客戶端新建一個項目到服務器端(evila_love)
    一道外企機試面試--------高手請進(getbyling)
    ?
    [其他]
    網絡安全方面的面試題(vagrantisme)
    軟件測試/質量評估(QA)面試的題目,大家幫忙想想(qiuzhizhe)
    [匯編]來者有分,面試題,貼出來一起討論,超難?。。。?!(crtd024)
    出了套面試題,大家看看,這讓沒經驗值的人做合不合適(wojiudaofen)
    急問一道關于測試的面試題(xjh_Love_paopao)
    一道關于路由器的面試題,高手請進!!(Gamehal)
    [Linux/Unix社區]今天面試的時候的問題沒有能夠回答出來的題,郁悶!各位幫忙看看
    [Linux/Unix社區]請教面試題一則(ty263)
    [Windows]昨天面試,考官問我平時用戶端的數據怎么做備份的,大家來談談!(ballatong)
    [Windows]求面試題(qiuyinggxnn)
    [ASP]下午去面試遇上了一個很有挑戰的問題,有沒高手路過?(me121121)
    [VB]VB面試過后不過,問問大家這幾題該怎么回答(xiebird)
    ?
    [微軟系列]
    [轉貼]微軟面試題系列(1) 2 3 4 5(fire_dragon)
    一道真正難倒億人的智力題,這是微軟的面試題(66766960)
    據說是一道微軟月薪5w職位的面試題(cjjfam)
    據說是微軟面試題,有答案了,但不知道為什么會是這樣!(DaChu)
    微軟經典面試題(bastenf)
    昨天面試微軟,只有這一題不會做。(amingo)
    一道真正難倒億人的智力題,這是微軟的面試題(66766960)
    【MS的一道面試題】Session問題(cxyppppp)

    posted @ 2006-12-31 16:09 保爾任 閱讀(5680) | 評論 (0)編輯 收藏

    URI(Uniform Resoure Identifier:統一資源標識符),URL(Uniform Resoure Location:統一資源定位器),URN(Uniform Resource Name統一資源

    名),URC(Uniform Resource Citation統一資源引用符)

    URI、URL和URN是識別、定位和命名互聯網上的資源的標準途徑; URL,URN是URI的子集.

    ???? URI不能定位或讀取/寫入資源。這是統一的資源定位器(URL)的任務。URL是一種URI,但是它的大綱組件是已知的網絡協議(簡稱協議

    ),并且它把URI組件與某種協議處理程序(一種資源定位器和根據協議建立的約束規則與資源通訊的讀/寫機制)。

      URI一般不能為資源提供持久不便的名稱。這是統一的資源命名(URN)的任務。URN也是一種URI,但是全球唯一的、持久不便的,即使資

    源不在存在或不再使用。

    ????? web上地址的基本形式是URI,它代表統一資源標識符。有兩種形式:
    ????? URL:目前URI的最普遍形式就是無處不在的URL或統一資源定位器。
    ????? URN:URL的一種更新形式,統一資源名稱(URN, Uniform Resource Name)不依賴于位置,并且有可能減少失效連接的個數。但是其流行

    還需假以時日,因為它需要更精密軟件的支持。

    體系中的URI、URL和URN是彼此關聯的。URI的范疇位于體系的頂層,URL和URN的范疇位于體系的底層。這種排列顯示URL和URN都是URI的子范疇

    , URI表示的是統一的資源標識,它是以某種統一的(標準化的)方式標識資源的簡單字符串。典型情況下,這種字符串以scheme(命名URI

    的名字空間的標識符--一組相關的名稱)開頭,語法如下:

    [scheme:] scheme-specific-part

    URI以scheme和冒號開頭。Scheme用大寫/小寫字母開頭,后面為空或者跟著更多的大寫/小寫字母、數字、加號、減號和點號。冒號把scheme與

    scheme-specific-part分開了,并且scheme-specific-part的語法和語義(意思)由URI的名字空間決定。  

    其中一個例子是http://www.cnn.com,其中http是scheme,//www.cnn.com是 scheme-specific-part,并且它的scheme與scheme-specific-

    part被冒號分開了。

    我們可以把URI按照絕對的或相對的分類。絕對的URI指以scheme(后面跟著冒號)開頭的URI。前面提到的http://www.cnn.com就是絕對的URI

    的一個例子,其它的例子還有mailto:jeff@javajeff.comnews:comp.lang.java.help和xyz://whatever。你可以把絕對的URI看作是以某種方

    式引用某種資源,而這種方式對標識符出現的環境沒有依賴。   

    如果使用文件系統作類比,絕對的URI類似于從根目錄開始的某個文件的路徑。與絕對的URI不同的,相對的URI不是以scheme(后面跟著冒號)

    開始的URI。

    它的一個例子是articles/articles.html。你可以把相對的URI看作是以某種方式引用某種資源,而這種方式依賴于標識符出現的環境。如果用

    文件系統作類比,相對的URI類似于從當前目錄開始的文件路徑。

    URI:

    Web上可用的每種資源 - HTML文檔、圖像、視頻片段、程序等 - 由一個通過通用資源標志符(Universal Resource Identifier, 簡稱"URI")

    進行定位。
    URI一般由三部分組成:
    1. 訪問資源的命名機制。
    2. 存放資源的主機名。
    3. 資源自身的名稱,由路徑表示。
    注:大多數人可能熟悉"URL",而不是URI。URL是URI命名機制的一個子集。

    URL:

    URL是Uniform Resource Location的縮寫,譯為"統一資源定位符"。通俗地說,URL是Internet上用來描述信息資源的字符串,主要用在各種

    WWW客戶程序和服務器程序上,特別是著名的Mosaic。采用URL可以用一種統一的格式來描述各種信息資源,包括文件、服務器的地址和目錄等

    。
    URL的格式
    URL的格式由下列三部分組成:
    第一部分是協議(或稱為服務方式);
    第二部分是存有該資源的主機IP地址(有時也包括端口號);
    第三部分是主機資源的具體地址。,如目錄和文件名等。
    第一部分和第二部分之間用"://"符號隔開,第二部分和第三部分用"/"符號隔開。第一部分和第二部分是不可缺少的,第三部分有時可以省略

    。
    URL的缺點:
    當信息資源的存放地點發生變化時,必須對URL作相應的改變。因此人們正在研究新的信息資源表示方法,例如:URI(Universal Resource

    Identifier)即"通用資源標識"(參見RFC 1630)、URN(Uniform Resource Name)即"統一資源名"和URC(Uniform Resource Citation)即"

    統一資源引用符"等。

    ?

    posted @ 2006-12-31 15:27 保爾任 閱讀(1126) | 評論 (0)編輯 收藏
    ?
    ?? Abstract:本文深入分析了Java程序設計中Java編譯器對java源文件和JVM對class類文件的編碼/解碼過程,通過此過程的解析透視出了Java編程中中文問題產生的根本原因,最后給出了建議的最優化的解決Java中文問題的方法。?

      1、中文問題的來源

    ??? 計算機最初的操作系統支持的編碼是單字節的字符編碼,于是,在計算機中一切處理程序最初都是以單字節編碼的英文為準進行處理。隨著計算機的發展,為了適應世界其它民族的語言(當然包括我們的漢字),人們提出了UNICODE編碼,它采用雙字節編碼,兼容英文字符和其它民族的雙字節字符編碼,所以,目前,大多數國際***的軟件內部均采用UNICODE編碼,在軟件運行時,它獲得本地支持系統(多數時間是操作系統)默認支持的編碼格式,然后再將軟件內部的 UNICODE轉化為本地系統默認支持的格式顯示出來。Java的JDK和JVM即是如此,我這里說的JDK是指國際版的JDK,我們大多數程序員使用的是國際化的JDK版本,以下所有的JDK均指國際化的JDK版本。我們的漢字是雙字節編碼語言,為了能讓計算機處理中文,我們自己制定的gb2312、 GBK、GBK2K等標準以適應計算機處理的需求。所以,大部分的操作系統為了適應我們處理中文的需求,均定制有中文操作系統,它們采用的是GBK, GB2312編碼格式以正確顯示我們的漢字。如:中文Win2K默認采用的是GBK編碼顯示,在中文WIN2k中保存文件時默認采用的保存文件的編碼格式也是GBK的,即,所有在中文WIN2K中保存的文件它的內部編碼默認均采用GBK編碼,注意:GBK是在GB2312基礎上擴充來的。

    ??? 由于Java語言內部采用UNICODE編碼,所以在JAVA程序運行時,就存在著一個從UNICODE編碼和對應的操作系統及瀏覽器支持的編碼格式轉換輸入、輸出的問題,這個轉換過程有著一系列的步驟,如果其中任何一步出錯,則顯示出來的漢字就會出是亂碼,這就是我們常見的JAVA中文問題。

    ??? 同時,Java是一個跨平臺的編程語言,也即我們編寫的程序不僅能在中文windows上運行,也能在中文Linux等系統上運行,同時也要求能在英文等系統上運行(我們經常看到有人把在中文win2k上編寫的JAVA程序,移植到英文Linux上運行)。這種移植操作也會帶來中文問題。

    ??? 還有,有人使用英文的操作系統和英文的IE等瀏覽器,來運行帶中文字符的程序和瀏覽中文網頁,它們本身就不支持中文,也會帶來中文問題。

    ??? 幾乎所有的瀏覽器默認在傳遞參數時都是以UTF-8編碼格式來傳遞,而不是按中文編碼傳遞,所以,傳遞中文參數時也會有問題,從而帶來亂碼現象。

    ??? 總之,以上幾個方面是JAVA中的中文問題的主要來源,我們把以上原因造成的程序不能正確運行而產生的問題稱作:JAVA中文問題。

      2、JAVA編碼轉換的詳細過程

    ??? 我們常見的JAVA程序包括以下類別:
    ???? *直接在console上運行的類(包括可視化界面的類)
    ???? *JSP代碼類(注:JSP是Servlets類的變型)
    ???? *Servelets類
    ???? *EJB類
    ???? *其它不可以直接運行的支持類

    ??? 這些類文件中,都有可能含有中文字符串,并且我們常用前三類JAVA程序和用戶直接交互,用于輸出和輸入字符,如:我們在JSP和Servlet中得到客戶端送來的字符,這些字符也包括中文字符。無論這些JAVA類的作用如何,這些JAVA程序的生命周期都是這樣的:

    ??? *編程人員在一定的操作系統上選擇一個合適的編輯軟件來實現源程序代碼并以.java擴展名保存在操作系統中,例如我們在中文win2k中用記事本編輯一個java源程序;
    ???? *編程人員用JDK中的javac.exe來編譯這些源代碼,形成.class類(JSP文件是由容器調用JDK來編譯的);
    ???? *直接運行這些類或將這些類布署到WEB容器中去運行,并輸出結果。
    ??? 那么,在這些過程中,JDK和JVM是如何將這些文件如何編碼和解碼并運行的呢?

    這里,我們以中文win2k操作系統為例說明JAVA類是如何來編碼和被解碼的。

    ??? 第一步,我們在中文win2k中用編輯軟件如記事本編寫一個Java源程序文件(包括以上五類JAVA 程序),程序文件在保存時默認采用了操作系統默認支持GBK編碼格式(操作系統默認支持的格式為file.encoding格式)形成了一個.java文件,也即,java程序在被編譯前,我們的JAVA源程序文件是采用操作系統默認支持的file.encoding編碼格式保存的,java源程序中含有中文信息字符和英文程序代碼;要查看系統的file.encoding參數,可以用以下代碼:
      public class ShowSystemDefaultEncoding {
      public static void main(String[] args) {
      String encoding = System.getProperty("file.encoding");
      System.out.println(encoding);
      }}

    ??? 第二步,我們用JDK的javac.exe文件編譯我們的Java源程序,由于JDK是國際版的,在編譯的時候,如果我們沒有用-encoding參數指定我們的 JAVA源程序的編碼格式,則javac.exe首先獲得我們操作系統默認采用的編碼格式,也即在編譯java程序時,若我們不指定源程序文件的編碼格式,JDK首先獲得操作系統的file.encoding參數(它保存的就是操作系統默認的編碼格式,如WIN2k,它的值為GBK),然后JDK就把我們的java源程序從file.encoding編碼格式轉化為JAVA內部默認的 UNICODE格式放入內存中。然后,javac把轉換后的unicode格式的文件進行編譯成.class類文件,此時.class文件是 UNICODE編碼的,它暫放在內存中,緊接著,JDK將此以UNICODE編碼的編譯后的class文件保存到我們的操作系統中形成我們見到的. class文件。對我們來說,我們最終獲得的.class文件是內容以UNICODE編碼格式保存的類文件,它內部包含我們源程序中的中文字符串,只不過此時它己經由file.encoding格式轉化為UNICODE格式了。

    ??? 這一步中,對于JSP源程序文件是不同的,對于JSP,這個過程是這樣的:即WEB容器調用JSP編譯器,JSP編譯器先查看JSP文件中是否設置有文件編碼格式,如果JSP文件中沒有設置JSP文件的編碼格式,則JSP編譯器調用JDK先把JSP文件用JVM默認的字符編碼格式(也即WEB容器所在的操作系統的默認的file.encoding)轉化為臨時的Servlet類,然后再把它編譯成UNICODE格式的class類,并保存在臨時文件夾中。如:在中文win2k上,WEB容器就把JSP文件從GBK編碼格式轉化為UNICODE格式,然后編譯成臨時保存的Servlet類,以響應用戶的請求。

    ??? 第三步,運行第二步編譯出來的類,分為三種情況:

    ??? A、 直接在console上運行的類
    ??? B、 EJB類和不可以直接運行的支持類(如JavaBean類)
    ??? C、 JSP代碼和Servlet類
    ??? D、 JAVA程序和數據庫之間
    ??? 下面我們分這四種情況來看。
    ??? A、直接在console上運行的類

    ??? 這種情況,運行該類首先需要JVM支持,即操作系統中必須安裝有JRE。運行過程是這樣的:首先java啟動JVM,此時JVM讀出操作系統中保存的 class文件并把內容讀入內存中,此時內存中為UNICODE格式的class類,然后JVM運行它,如果此時此類需要接收用戶輸入,則類會默認用 file.encoding編碼格式對用戶輸入的串進行編碼并轉化為unicode保存入內存(用戶可以設置輸入流的編碼格式)。程序運行后,產生的字符串(UNICODE編碼的)再回交給JVM,最后JRE把此字符串再轉化為file.encoding格式(用戶可以設置輸出流的編碼格式)傳遞給操作系統顯示接口并輸出到界面上。

    ??? 對于這種直接在console上運行的類,它的轉化過程可用圖1更加明確的表示出來:

    圖1

    以上每一步的轉化都需要正確的編碼格式轉化,才能最終不出現亂碼現象。

    ??? B、EJB類和不可以直接運行的支持類(如JavaBean類)

    ??? 由于EJB類和不可以直接運行的支持類,它們一般不與用戶直接交互輸入和輸出,它們常常與其它的類進行交互輸入和輸出,所以它們在第二步被編譯后,就形成了內容是UNICODE編碼的類保存在操作系統中了,以后只要它與其它的類之間的交互在參數傳遞過程中沒有丟失,則它就會正確的運行。
    這種EJB類和不可以直接運行的支持類, 它的轉化過程可用圖2更加明確的表示出來:

    圖2


    ??? C、JSP代碼和Servlet類

    ??? 經過第二步后,JSP文件也被轉化為Servlets類文件,只不過它不像標準的Servlets一校存在于classes目錄中,它存在于WEB容器的臨時目錄中,故這一步中我們也把它做為Servlets來看。

    ??? 對于Servlets,客戶端請求它時,WEB容器調用它的JVM來運行Servlet,首先,JVM把Servlet的class類從系統中讀出并裝入內存中,內存中是以UNICODE編碼的Servlet類的代碼,然后JVM在內存中運行該Servlet類,如果Servlet在運行的過程中,需要接受從客戶端傳來的字符如:表單輸入的值和URL中傳入的值,此時如果程序中沒有設定接受參數時采用的編碼格式,則WEB容器會默認采用ISO-8859- 1編碼格式來接受傳入的值并在JVM中轉化為UNICODE格式的保存在WEB容器的內存中。Servlet運行后生成輸出,輸出的字符串是 UNICODE格式的,緊接著,容器將Servlet運行產生的UNICODE格式的串(如html語法,用戶輸出的串等)直接發送到客戶端瀏覽器上并輸出給用戶,如果此時指定了發送時輸出的編碼格式,則按指定的編碼格式輸出到瀏覽器上,如果沒有指定,則默認按ISO-8859-1編碼發送到客戶的瀏覽器上。這種JSP代碼和Servlet類,它的轉化過程可用圖3更加明確地表示出來:

    圖3

    D、Java程序和數據庫之間

    ??? 對于幾乎所有數據庫的JDBC驅動程序,默認的在JAVA程序和數據庫之間傳遞數據都是以ISO-8859-1為默認編碼格式的,所以,我們的程序在向數據庫內存儲包含中文的數據時,JDBC首先是把程序內部的UNICODE編碼格式的數據轉化為ISO-8859-1的格式,然后傳遞到數據庫中,在數據庫保存數據時,它默認即以ISO-8859-1保存,所以,這是為什么我們常常在數據庫中讀出的中文數據是亂碼。
    ??? 對于JAVA程序和數據庫之間的數據傳遞,我們可以用圖4清晰地表示出來

    圖4


    ??? 3、分析常見的JAVA中文問題幾個必須清楚的原則

    ??? 首先,經過上面的詳細分析,我們可以清晰地看到,任何JAVA程序的生命期中,其編碼轉換的關鍵過程是在于:最初編譯成class文件的轉碼和最終向用戶輸出的轉碼過程。
    ??? 其次,我們必須了解JAVA在編譯時支持的、常用的編碼格式有以下幾種:
    ??? *ISO-8859-1,8-bit, 同8859_1,ISO-8859-1,ISO_8859_1等編碼
    ??? *Cp1252,美國英語編碼,同ANSI標準編碼
    ??? *UTF-8,同unicode編碼
    ??? *GB2312,同gb2312-80,gb2312-1980等編碼
    ??? *GBK , 同MS936,它是gb2312的擴充
    ??? 及其它的編碼,如韓文、日文、繁體中文等。同時,我們要注意這些編碼間的兼容關體系如下:
    ??? unicode和UTF-8編碼是一一對應的關系。GB2312可以認為是GBK的子集,即GBK編碼是在gb2312上擴展來的。同時,GBK編碼包含了20902個漢字,編碼范圍為:0x8140-0xfefe,所有的字符可以一一對應到UNICODE2.0中來。

    ??? 再次,對于放在操作系統中的.java源程序文件,在編譯時,我們可以指定它內容的編碼格式,具體來說用-encoding來指定。注意:如果源程序中含有中文字符,而你用-encoding指定為其它的編碼字符,顯然是要出錯的。用-encoding指定源文件的編碼方式為GBK或gb2312,無論我們在什么系統上編譯含有中文字符的JAVA源程序都不會有問題,它都會正確地將中文轉化為UNICODE存儲在class文件中。
    ????
    ??? 然后,我們必須清楚,幾乎所有的WEB容器在其內部默認的字符編碼格式都是以ISO-8859-1為默認值的,同時,幾乎所有的瀏覽器在傳遞參數時都是默認以UTF-8的方式來傳遞參數的。所以,雖然我們的Java源文件在出入口的地方指定了正確的編碼方式,但其在容器內部運行時還是以ISO-8859- 1來處理的。


    ?4、中文問題的分類及其建議最優解決辦法

    ??? 了解以上JAVA處理文件的原理之后,我們就可以提出了一套建議最優的解決漢字問題的辦法。
    ??? 我們的目標是:我們在中文系統中編輯的含有中文字符串或進行中文處理的JAVA源程序經編譯后可以移值到任何其它的操作系統中正確運行,或拿到其它操作系統中編譯后能正確運行,能正確地傳遞中文和英文參數,能正確地和數據庫交流中英文字符串。
    ??? 我們的具體思路是:在JAVA程序轉碼的入口和出口及JAVA程序同用戶有輸入輸出轉換的地方限制編碼方法使之正確即可。

    ??? 具體解決辦法如下:

    ??? 1、 針對直接在console上運行的類
    ??? 對于這種情況,我們建議在程序編寫時,如果需要從用戶端接收用戶的可能含有中文的輸入或含有中文的輸出,程序中應該采用字符流來處理輸入和輸出,具體來說,應用以下面向字符型節點流類型:
    ??? 對文件:FileReader,FileWrieter
    ??????? 其字節型節點流類型為:FileInputStream,FileOutputStream
    ??? 對內存(數組):CharArrayReader,CharArrayWriter
    ??????? 其字節型節點流類型為:ByteArrayInputStream,ByteArrayOutputStream
    ??? 對內存(字符串):StringReader,StringWriter
    ??? 對管道:PipedReader,PipedWriter
    ??????? 其字節型節點流類型為:PipedInputStream,PipedOutputStream
    ??? 同時,應該用以下面向字符型處理流來處理輸入和輸出:
    ??? BufferedWriter,BufferedReader
    ??????? 其字節型的處理流為:BufferedInputeStream,BufferedOutputStream
    ??? InputStreamReader,OutputStreamWriter
    ??? 其字節型的處理流為:DataInputStream,DataOutputStream
    ??? 其中InputStreamReader和InputStreamWriter用于將字節流按照指定的字符編碼集轉換到字符流,如:
    ??? InputStreamReader in = new InputStreamReader(System.in,"GB2312");
    ??? OutputStreamWriter out = new OutputStreamWriter (System.out,"GB2312");
    ??? 例如:采用如下的示例JAVA編碼就達到了要求:

    ??? //Read.java
    ??? import java.io.*;
    ??? public class Read {
    ??? public static void main(String[] args) throws IOException {
    ??? String str = "\n中文測試,這是內部硬編碼的串"+"\ntest english character";
    ??? String strin= "";
    ??? BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in,"gb2312")); //設置輸入接口按中文編碼
    ??? BufferedWriter stdout = new BufferedWriter(new OutputStreamWriter(System.out,"gb2312")); //設置輸出接口按中文編碼
    ??? stdout.write("請輸入:");
    ??? stdout.flush();
    ??? strin = stdin.readLine();
    ??? stdout.write("這是從用戶輸入的串:"+strin);
    ??? stdout.write(str);
    ??? stdout.flush();
    ??? }}
    ??? 同時,在編譯程序時,我們用以下方式來進行:
    ??? javac -encoding gb2312 Read.java
    ??? 其運行結果如圖5所示:

    ??? 圖5
    2、 針對EJB類和不可以直接運行的支持類(如JavaBean類)

    ??? 由于這種類它們本身被其它的類調用,不直接與用戶交互,故對這種類來說,我們的建議的處理方式是內部程序中應該采用字符流來處理程序內部的中文字符串(具體如上面一節中一樣),同時,在編譯類時用-encoding gb2312參數指示源文件是中文格式編碼的即可。


    ??? 3、 針對Servlet類

    ??? 針對Servlet,我們建議用以下方法:(我建議將.java文件設置為UTF8編碼的。當然如果是用Eclipse的話,只要設置下就是了。對于數據庫,我以為編碼最好設置為UTF8,便于國際化?。盡可能的使用UTF8碼,? 千里草)

    ??? 在編譯Servlet類的源程序時,用-encoding指定編碼為GBK或GB2312,且在向用戶輸出時的編碼部分用response對象的 setContentType("text/html;charset=GBK");或gb2312來設置輸出編碼格式,同樣在接收用戶輸入時,我們用 request.setCharacterEncoding("GB2312");這樣無論我們的servlet類移植到什么操作系統中,只有客戶端的瀏覽器支持中文顯示,就可以正確顯示。如下是一個正確的示例:

    ??? //HelloWorld.java
    ??? package hello;
    ??? import java.io.*;
    ??? import javax.servlet.*;
    ??? import javax.servlet.http.*;
    ??? public class HelloWorld extends HttpServlet
    ??? {
    ??? public void init() throws ServletException { }
    ??? public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    ??? {
    ??? request.setCharacterEncoding("GB2312"); //設置輸入編碼格式
    ??? response.setContentType("text/html;charset=GB2312"); //設置輸出編碼格式
    ??? PrintWriter out = response.getWriter(); //建議使用PrintWriter輸出
    ??? out.println("<hr>");
    ??? out.println("Hello World! This is created by Servlet!測試中文!");
    ??? out.println("<hr>");
    ??? }
    ??? public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    ??? {
    ??? request.setCharacterEncoding("GB2312"); //設置輸入編碼格式
    ??? response.setContentType("text/html;charset=GB2312"); //設置輸出編碼格式
    ??? String name = request.getParameter("name");
    ??? String id = request.getParameter("id");
    ??? if(name==null) name="";
    ??? if(id==null) id="";
    ??? PrintWriter out = response.getWriter(); //建議使用PrintWriter輸出
    ??? out.println("<hr>");
    ??? out.println("你傳入的中文字串是:" + name);
    ??? out.println("<hr>你輸入的id是:" + id);
    ??? out.println("<hr>");
    ??? }
    ??? public void destroy() { }
    ??? }
    ??????? 請用javac -encoding gb2312 HelloWorld.java來編譯此程序。
    ??????? 測試此Servlet的程序如下所示:
    ??? <%@page contentType="text/html; charset=gb2312"%>
    ??? <%request.setCharacterEncoding("GB2312");%>
    ??? <html><head><title></title>
    ??? <Script language="JavaScript">
    ??? function Submit() {
    ??? //通過URL傳遞中文字符串值給Servlet
    ??? document.base.action = "./HelloWorld?name=中文";
    ??? document.base.method = "POST";
    ??? document.base.submit();
    ??? }
    ??? </Script>
    ??? </head>

    <body bgcolor="#FFFFFF" text="#000000" topmargin="5">
    ??? <form name="base" method = "POST" target="_self">
    ??? <input name="id" type="text" value="" size="30">
    ??? <a href = "JavaScript:Submit()">傳給Servlet</a>
    ??? </form></body></html>
    ??? 其運行結果如圖6所示:

    ??? 圖6
    ??? 4、 JAVA程序和數據庫之間

    ??? 為避免JAVA程序和數據庫之間數據傳遞出現亂碼現象,我們建議采用以下最優方法來處理:
    ??? 1、 對于JAVA程序的處理方法按我們指定的方法處理。
    ??? 2、 把數據庫默認支持的編碼格式改為GBK或GB2312的。

    ??? 如:在mysql中,我們可以在配置文件my.ini中加入以下語句實現:
    ??? 在[mysqld]區增加:
    ??? default-character-set=gbk
    ??? 并增加:
    ??? [client]
    ??? default-character-set=gbk
    ??? 在SQL Server2K中,我們可以將數據庫默認的語言設置為Simplified Chinese來達到目的。

    ??? 5、 針對JSP代碼

    ??? 由于JSP是在運行時,由WEB容器進行動態編譯的,如果我們沒有指定JSP源文件的編碼格式,則JSP編譯器會獲得服務器操作系統的 file.encoding值來對JSP文件編譯的,它在移植時最容易出問題,如在中文win2k中可以很好運行的jsp文件拿到英文linux中就不行,盡管客戶端都是一樣的,那是因為容器在編譯JSP文件時獲取的操作系統的編碼不同造成的(在中文wink中的file.encoding和在英文 Linux中file.encoding是不同的,且英文Linux的file.encoding對中文不支持,所以編譯出來的JSP類就會有問題)。網絡上討論的大多數是此類問題,多是因為JSP文件移植平臺時不能正確顯示的問題,對于這類問題,我們了解了JAVA中程序編碼轉換的原理,解決起來就容易多了。我們建議的解決辦法如下:

    ??? 1、我們要保證JSP向客戶端輸出時是采用中文編碼方式輸出的,即無論如何我們首先在我們的JSP源代編中加入以下一行:

    ??? <%@page contentType="text/html; charset=gb2312"%>
    ??? 2、為了讓JSP能正確獲得傳入的參數,我們在JSP源文件頭加入下面一句:
    ??? <%request.setCharacterEncoding("GB2312");%>
    ??? 3、為了讓JSP編譯器能正確地解碼我們的含有中文字符的JSP文件,我們需要在JSP源文件中指定我們的JSP源文件的編碼格式,具體來說,我們在JSP源文件頭上加入下面的一句即可:
    ??? <%@page pageEncoding="GB2312"%>或<%@page pageEncoding="GBK"%>
    ??? 這是JSP規范2.0新增加的指令。
    ??? 我們建議使用此方法來解JSP文件中的中文問題,下面的代碼是一個正確做法的JSP文件的測試程序:

    //testchinese.jsp
    ??? <%@page pageEncoding="GB2312"%>
    ??? <%@page contentType="text/html; charset=gb2312"%>
    ??? <%request.setCharacterEncoding("GB2312");%>
    ??? <%
    ??? String action = request.getParameter("ACTION");
    ??? String name = "";
    ??? String str = "";
    ??? if(action!=null && action.equals("SENT"))
    ??? {
    ??? name = request.getParameter("name");
    ??? str = request.getParameter("str");
    ??? }
    ??? %>
    ??? <html>
    ??? <head>
    ??? <title></title>
    ??? <Script language="JavaScript">
    ??? function Submit()
    ??? {
    ??? document.base.action = "?ACTION=SENT&str=傳入的中文";
    ??? document.base.method = "POST";
    ??? document.base.submit();
    ??? }
    ??? </Script>
    ??? </head>
    ??? <body bgcolor="#FFFFFF" text="#000000" topmargin="5">
    ??? <form name="base" method = "POST" target="_self">
    ??? <input type="text" name="name" value="" size="30">
    ??? <a href = "JavaScript:Submit()">提交</a>
    ??? </form>
    ??? <%
    ??? if(action!=null && action.equals("SENT"))
    ??? {
    ??? out.println("<br>你輸入的字符為:"+name);
    ??? out.println("<br>你通過URL傳入的字符為:"+str);
    ??? }
    ??? %>
    ??? </body>
    ??? </html>
    ??? 如圖7是此程序運行的結果示意圖:

    ??? 圖7

    ??? 5、總結

    ??? 在上面的詳細分析中,我們清晰地給出了JAVA在處理源程序過程中的詳細轉換過程,為我們正確解決JAVA編程中的中文問題提供了基礎。同時,我們給出了認為是最優的解決JAVA中文問題的辦法。

    我的補充(需要特別注意): 在表單(form )提交時,如果提交的方法為get,那么request.setCharacterEncoding() 是不起作用的。此時在服務器端得到的字符編碼仍然是ISO8859-1,而不是你設置的編碼。所以一般我們在提交數據時,盡量使用post方法,此時 request.setCharacterEncoding()方法起效。

    ?如果非要使用get方法傳form則要轉換一下才行:?
    ? ----- ?
    ? <%@ ? page ? contentType="text/html;charset=gb2312"%> ?
    ? <%! ?
    ? ? ? ? ? public ? String ? getStr(String ? str){ ?
    ? try{ ?
    ? String ? temp_p=str; ?
    ? byte[] ? temp_t=temp_p.getBytes("ISO8859-1"); ?
    ? String ? temp=new ? String(temp_t); ?
    ? return ? temp; ?
    ? } ?
    ? catch(Exception ? e){ ?
    ? } ?
    ? return ? "null"; ?
    ? ? } ?
    ? ? %> ?
    ? 然后把String ? userId=request.getParameter("userId");改成 ?
    ? String ? userId=getStr(request.getParameter("userId"));??
    --------------------------------------------
    我來說一下tomcat如何實現JSP的你就明白了。
    預備知識:
     1.字節和unicode
      Java內核是unicode的,就連class文件也是,但是很多媒體,包括文件/流的保存方式
      是使用字節流的。 因此Java要對這些字節流經行轉化。char是unicode的,而byte是字節.
      Java中byte/char互轉的函數在sun.io的包中間有。其中ByteToCharConverter類是中調度,
      可以用來告訴你,你用的Convertor。其中兩個很常用的靜態函數是
       public static ByteToCharConverter getDefault() ;
       public static ByteToCharConverter getConverter(String encoding);
      如果你不指定converter,則系統會自動使用當前的Encoding,GB平臺上用GBK,EN平臺上用
      8859_1
      
      我們來就一個簡單的例子:
         "你"的gb碼是:0xC4E3 ,unicode是0x4F60
         你用:
         --encoding="gb2312";
         --byte b[]={(byte)'\u00c4',(byte)'\u00E3'};
         --convertor=ByteToCharConverter.getConverter(encoding);
         --char [] c=converter.convertAll(b);
         --for(int i=0;i<c.length;c++)
         --{
         -- System.out.println(Integer.toHexString(c[i]));
         --}
         --打印出來是0x4F60
         --但是如果使用8859_1的編碼,打印出來是
         --0x00C4,0x00E3
         ----例1
         反過來:
        ? --encoding="gb2312";
        ? --char c[]={'\u4F60'};
         --convertor=ByteToCharConverter.getConverter(encoding);
         --byte [] b=converter.convertAll(c);
         --for(int i=0;i<b.length;c++)
         --{
         -- System.out.println(Integer.toHexString(b[i]));
         --}
          --打印出來是:0xC4,0xE3
          ----例2
          --如果用8859_1就是0x3F,?號,表示無法轉化      --
          很多中文問題就是從這兩個最簡單的類派生出來的。而卻有很多類  
      不直接支持把Encoding輸入,這給我們帶來諸多不便。很多程序難得用encoding
      了,直接用default的encoding,這就給我們移植帶來了很多困難
      --
      2.UTF-8
      --UTF-8是和Unicode一一對應的,其實現很簡單
      --
      -- 7位的Unicode: 0 _ _ _ _ _ _ _
      --11位的Unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _
      --16位的Unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _
      --21位的Unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _
      --大多數情況是只使用到16位以下的Unicode:
      --"你"的gb碼是:0xC4E3 ,unicode是0x4F60
      --我們還是用上面的例子
      --  --例1:0xC4E3的二進制:
      --  --    1 1 0 0 0 1 0 0 1 1 1 0 0 0 1 1
      --  --    由于只有兩位我們按照兩位的編碼來排,但是我們發現這行不通,
      --  --    因為第7位不是0因此,返回"?"
      --  --   
      --  --例2:0x4F60的二進制:
      --  --    0 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0
      --  --    我們用UTF-8補齊,變成:
      --  --    11100100 10111101 10100000
      --  --    E4--BD-- A0
      --  --    于是返回0xE4,0xBD,0xA0
      --  --
      3.String和byte[]
      --String其實核心是char[],然而要把byte轉化成String,必須經過編碼。
      --String.length()其實就是char數組的長度,如果使用不同的編碼,很可
      --能會錯分,造成散字和亂碼。
      --例:
      ----byte [] b={(byte)'\u00c4',(byte)'\u00e3'};
      ----String str=new String(b,encoding);  ----
      ----如果encoding=8859_1,會有兩個字,但是encoding=gb2312只有一個字  ----
      --這個問題在處理分頁是經常發生
      4.Reader,Writer/InputStream,OutputStream
      --Reader和Writer核心是char,InputStream和OutputStream核心是byte。
      --但是Reader和Writer的主要目的是要把Char讀/寫InputStream/OutputStream
    --一個reader的例子:
    --文件test.txt只有一個"你"字,0xC4,0xE3--
    --String encoding=;
    --InputStreamReader reader=new InputStreamReader(
    ----new FileInputStream("text.txt"),encoding);
    --char []c=new char[10];
    --int length=reader.read(c);
    --for(int i=0;i<c.length;i++)
    ----System.out.println(c[i]);
      --如果encoding是gb2312,則只有一個字符,如果encoding=8859_1,則有兩個字符
      --------
    --
    --
      
       ----
     2.我們要對Java的編譯器有所了解:
     --javac -encoding
      我們常常沒有用到ENCODING這個參數。其實Encoding這個參數對于跨平臺的操作是很重要的。
      如果沒有指定Encoding,則按照系統的默認Encoding,gb平臺上是gb2312,英文平臺上是ISO8859_1?!?
     --Java的編譯器實際上是調用sun.tools.javac.Main的類,對文件進行編譯,這個類 --
     有compile函數中間有一個encoding的變量,-encoding的參數其實直接傳給encoding變量。
     編譯器就是根據這個變量來讀取java文件的,然后把用UTF-8形式編譯成class文件。
     一個例子:
     --public void test()
     --{
     ----String str="你";
     ----FileWriter write=new FileWriter("test.txt");
     ----write.write(str);
     ----write.close();
     --}
     ----例3
    --如果用gb2312編譯,你會找到E4 BD A0的字段
    --
    --如果用8859_1編譯,
    --00C4 00E3的二進制:
    --00000000 11000100 00000000 11100011--
    --因為每個字符都大于7位,因此用11位編碼:
    --11000001 10000100 11000011 10100011
    --C1-- 84-- C3--  A3
    --你會找到C1 84 C3 A3 --
        
      但是我們往往忽略掉這個參數,因此這樣往往會有跨平臺的問題:
      --  例3在中文平臺上編譯,生成ZhClass
      --  例3在英文平臺上編譯,輸出EnClass
      --1.  ZhClass在中文平臺上執行OK,但是在英文平臺上不行
      --2.  EnClass在英文平臺上執行OK,但是在中文平臺上不行
      原因:
     --1.在中文平臺上編譯后,其實str在運行態的char[]是0x4F60, ----
     --在中文平臺上運行,FileWriter的缺省編碼是gb2312,因此
     --CharToByteConverter會自動用調用gb2312的converter,把str轉化
     --成byte輸入到FileOutputStream中,于是0xC4,0xE3放進了文件。
     --但是如果是在英文平臺下,CharToByteConverter的缺省值是8859_1,
     --FileWriter會自動調用8859_1去轉化str,但是他無法解釋,因此他會
     --輸出"?" ----
     --2. 在英文平臺上編譯后,其實str在運行態的char[]是0x00C4 0x00E3, ----
     --在中文平臺上運行,中文無法識別,因此會出現??
     --  在英文平臺上,0x00C4-->0xC4,0x00E3->0xE3,因此0xC4,0xE3被放進了
     --文件
    ----
    1.對于JSP正文的解釋:
    --Tomcat首先看一下你的葉面中有沒有"<%@page include的符號。有,則在相同
    --地方設定response.setContentType(..);按照encoding的來讀,沒有他按照8859_1
    --讀取文件,然后用UTF-8寫成.java文件,然后用sun.tools.Main去讀取這個文件,
    --(當然它使用UTF-8去讀),然后編譯成class文件
    --setContentType改變的是out的屬性,out變量缺省的encoding是8859_1
    2.對Parameter的解釋
    --很不幸Parameter只有ISO8859_1的解釋,這個質料可以在servlet的實現代碼中找到。
    3.對include的解釋
    格式的,但是很不幸,由于那個寫"org.apache.jasper.compiler.Parser"的人
    在數組JspUtil.ValidAttribute[]忘記加了一個參數:encoding,因此導致不支
    持這種方式。你完全可以編譯源代碼,加上對encoding的支持
    總結:
    如果你在NT底下,最簡單的方法就是欺騙java,不加任何Encoding變量:
    <html>
    你好<%=request.getParameter("value")%>
    </html>
    http://localhost/test/test.jsp?value=你
    結果:你好你
    但這種方法局限性較大,比如對上傳的文章分段,這樣的做法是死定的,最好的
    解決方案是用這種方案:
    <%@ page contentType="text/html;charset=gb2312" %>
    <html>
    你好<%=new String(request.getParameter("value").getBytes("8859_1"),"gb2312")%>
    </html>

    <select name="account.accountId" >
    ? ??<OPTION value="<%=account.getAccountId()%>">我的日志</OPTION>
    ? ??<OPTION value="">所有日志</OPTION>
    ? ??<OPTION <%=s%> value="<%=a.getAccountId()%>"><%=a.getAccountName()%></OPTION>
    ? ?</select>
    posted @ 2006-12-31 10:13 保爾任 閱讀(322) | 評論 (0)編輯 收藏
    ?
      J2EE學習者越來越多,J2EE本身技術不斷在發展,涌現出各種概念,本文章試圖從一種容易理解的角度對這些概念向初學者進行解釋,以便掌握學習J2EE學習方向。
      首先我們需要知道Java和J2EE是兩個不同概念,Java不只是指一種語言,已經代表與微軟不同的另外一個巨大陣營,所以Java有時是指一種軟件系統的流派,當然目前主要是.NET和Java兩大主流體系。
      J2EE可以說指Java在數據庫信息系統上實現,數據庫信息系統從早期的dBase、到Delphi/VB等C/S結構,發展到B/S(Browser瀏覽器/Server服務器)結構,而J2EE主要是指B/S結構的實現。
      J2EE又是一種框架和標準,框架類似API、庫的概念,但是要超出它們。如果需要詳細了解框架,可先從設計模式開始學習。
      J2EE是一個虛的大的概念,J2EE標準主要有三種子技術標準:WEB技術、EJB技術和JMS,談到J2EE應該說最終要落實到這三個子概念上。
      這三種技術的每個技術在應用時都涉及兩個部分:容器部分和應用部分,Web容器也是指Jsp/Servlet容器,你如果要開發一個Web應用,無論是編譯或運行,都必須要有Jsp/Servlet庫或API支持(除了JDK/J2SE以外)。
      Web技術中除了Jsp/Servlet技術外,還需要JavaBeans或Java Class實現一些功能或者包裝攜帶數據,所以Web技術最初裸體簡稱為Jsp/Servlet+JavaBeans系統。
      談到JavaBeans技術,就涉及到組件構件技術(component),這是Java的核心基礎部分,很多軟件設計概念(設計模式)都是通過JavaBeans實現的。
      JavaBeans不屬于J2EE概念范疇中,如果一個JavaBeans對象被Web技術(也就是Jsp/Servlet)調用,那么JavaBeans就運行在J2EE的Web容器中;如果它被EJB調用,它就運行在EJB容器中。
      EJB(企業JavaBeans)是普通JavaBeans的一種提升和規范,因為企業信息系統開發中需要一個可伸縮的性能和事務、安全機制,這樣能保證企業系統平滑發展,而不是發展到一種規模重新更換一套軟件系統。
      至此,JavaBeans組件發展到EJB后,并不是說以前的那種JavaBeans形式就消失了,這就自然形成了兩種JavaBeans技術:EJB 和POJO,POJO完全不同于EJB概念,指的是普通JavaBeans,而且這個JavaBeans不依附某種框架,或者干脆可以說:這個 JavaBeans是你為這個應用程序單獨開發創建的。
      J2EE應用系統開發工具有很多:如JBuilder、 Eclipse等,這些IDE首先是Java開發工具,也就是說,它們首要基本功能是可以開發出JavaBeans或Java class,但是如果要開發出J2EE系統,就要落實到要么是Web技術或EJB技術,那么就有可能要一些專門模塊功能(如eclipse需要 lomboz插件),最重要的是,因為J2EE系統區分為容器和應用兩個部分,所以,在任何開發工具中開發J2EE都需要指定J2EE容器。
      J2EE容器分為WEB容器和EJB容器,Tomcat/Resin是Web容器;JBoss是EJB容器+Web容器等,其中Web容器直接使用 Tomcat實現的。所以你開發的Web應用程序可以在上面兩種容器運行,而你開發的Web+EJB應用則只可以在JBoss服務器上運行,商業產品 Websphere/Weblogic等和JBoss屬于同一種性質。
      J2EE容器也稱為J2EE服務器,大部分時它們概念是一致的。
      如果你的J2EE應用系統的數據庫連接是通過JNDI獲得,也就是說是從容器中獲得,那么你的J2EE應用系統基本與數據庫無關,如果你在你的J2EE 應用系統耦合了數據庫JDBC驅動的配置,那么你的J2EE應用系統就有數據庫概念色彩,作為一個成熟需要推廣的J2EE應用系統,不推薦和具體數據庫耦合,當然這其中如何保證J2EE應用系統運行性能又是體現你的設計水平了。
      衡量J2EE應用系統設計開發水平高低的標準就是:解耦性;你的應用系統各個功能是否能夠徹底脫離?是否不相互依賴,也只有這樣,才能體現可維護性、可拓展性的軟件設計目標。
      為了達到這個目的,誕生各種框架概念,J2EE框架標準將一個系統劃分為WEB和EJB主要部分,當然我們有時不是以這個具體技術區分,而是從設計上抽象為表現層、服務層和持久層,這三個層次從一個高度將J2EE分離開來,實現解耦目的。
      因此,我們實際編程中,也要將自己的功能向這三個層次上靠,做到大方向清楚,涇渭分明,但是沒有技術上約束限制要做到這點是很不容易的,因此我們還是必須借助J2EE具體技術來實現,這時,你可以使用EJB規范實現服務層和持久層,Web技術實現表現層;
      EJB為什么能將服務層從Jsp/Servlet手中分離出來,因為它對JavaBeans編碼有強制的約束,現在有一種對JavaBeans弱約束,使用Ioc模式實現的(當然EJB 3.0也采取這種方式),在Ioc模式誕生前,一般都是通過工廠模式來對JavaBeans約束,形成一個服務層,這也是是Jive這樣開源論壇設計原理之一。
      由此,將服務層從表現層中分離出來目前有兩種可選架構選擇:管理普通JavaBeans(POJO)框架(如 Spring、JdonFramework)以及管理EJB的EJB框架,因為EJB不只是框架,還是標準,而標準可以擴展發展,所以,這兩種區別將來是可能模糊,被納入同一個標準了。 但是,個人認為:標準制定是為某個目的服務的,總要犧牲一些換取另外一些,所以,這兩種架構會長時間并存。
      這兩種架構分歧也曾經誕生一個新名詞:完全POJO的系統也稱為輕量級系統(lightweight),其實這個名詞本身就沒有一個嚴格定義,更多是一個吸引人的招牌,輕量是指容易學習容易使用嗎?按照這個定義,其實輕量Spring等系統并不容易學習;而且EJB 3.0(依然叫EJB)以后的系統是否可稱為輕量級了呢?
      前面談了服務層框架,使用服務層框架可以將 JavaBeans從Jsp/Servlet中分離出來,而使用表現層框架則可以將Jsp中剩余的JavaBeans完全分離,這部分JavaBeans 主要負責顯示相關,一般是通過標簽庫(taglib)實現,不同框架有不同自己的標簽庫,Struts是應用比較廣泛的一種表現層框架。
      這樣,表現層和服務層的分離是通過兩種框架達到目的,剩余的就是持久層框架了,通過持久層的框架將數據庫存儲從服務層中分離出來是其目的,持久層框架有兩種方向:直接自己編寫JDBC等SQL語句(如iBatis);使用O/R Mapping技術實現的Hibernate和JDO技術;當然還有EJB中的實體Bean技術。
      持久層框架目前呈現百花齊放,各有優缺點的現狀,所以正如表現層框架一樣,目前沒有一個框架被指定為標準框架,當然,表現層框架現在又出來了一個JSF,它代表的頁面組件概念是一個新的發展方向,但是復雜的實現讓人有些忘而卻步。
      在所有這些J2EE技術中,雖然SUN公司發揮了很大的作用,不過總體來說:網絡上有這樣一個評價:SUN的理論天下無敵;SUN的產品用起來撞墻;對于初學者,特別是那些試圖通過或已經通過SUN認證的初學者,趕快擺脫SUN的陰影,立即開溜,使用開源領域的產品來實現自己的應用系統。
      最后,你的J2EE應用系統如果采取上面提到的表現層、服務層和持久層的框架實現,基本你也可以在無需深刻掌握設計模式的情況下開發出一個高質量的應用系統了。
      還要注意的是: 開發出一個高質量的J2EE系統還需要正確的業務需求理解,那么域建模提供了一種比較切實可行的正確理解業務需求的方法,相關詳細知識可從UML角度結合理解。
      當然,如果你想設計自己的行業框架,那么第一步從設計模式開始吧,因為設計模式提供你一個實現JavaBeans或類之間解耦參考實現方法,當你學會了系統基本單元JavaBean或類之間解耦時,那么系統模塊之間的解耦你就可能掌握,進而你就可以實現行業框架的提煉了,這又是另外一個發展方向了。
      以上理念可以總結為一句話:Java學習開發三件寶: Domain Model(域建模)、Patterns(模式)和Framework(框架)。集三寶理念于一身,小中型J2EE項目快速開發工具:Jdon Framework
    ----------------------------------------------------------------------------------------------------
    JoannaYe ask:
    你好 Banq先生 關注你的文章很長一段時間了, 對你在Java領域的技術水平,以及在很多問題上的看法, 也非常佩服. 國內目前達到你的水平的人真是很少(當然高人也許都隱居起來了). 但是, 有幾個問題想與你討論:
    首先,軟件是一個絕對的應用技術,任何技術離開了具體的應用, 坦率地說是毫無價值的.我看,Jdon也有在這方面的嘗試,如網站,網上商店生成系統等.但這與真正的企業應用還有非常大的距離. 我不了解,你在這一領域里為什么沒有涉足,是因為你認為很困難,基本上是以我們國內目前的技術水平無法到達呢, 還是因為你不屑于這方面的深入, 認為你所追求的是純粹超然的技術概念呢.
    我的其他問題有賴于了解你關于這個問題的回答,讓我們繼續關注和討論.
    banq answer:
    ?
    >但這與真正的企業應用還有非常大的距離. 我不了解,你在這一領域里為什么沒有涉足,是因為你認為很困難,基本上是以我們國內目前的技術
    多謝探討,這個問題很復雜,大概有下列幾點:
    1. 現在軟件技術不再象以前的技術,以前的技術可以說只有做個這個行業大型軟件系統的經驗的人才可以說對這些軟件技術有掌握,而現在的技術則不必了,J2EE 講究架構,J2EE它是一套應用軟件的規范,也就是說,J2EE是很多做過大型軟件的人進行匯總后的經驗精華,一個大型系統需要哪些技術部分、什么時候適合什么技術,在J2EE標準中基本都有涉及,例如EJB技術、JMS等。
    這樣,如果你能完全掌握和駕馭這些J2EE架構技術,你有時確實不必一定要做個大型軟件經驗才型,這稱為站在巨人的肩膀上。
    但是反過來,如果你沒有豐富的軟件系統實戰經驗,你去理解EJB/JMS等就很困難,所以這兩個技術對初學者比較難的原因之一。
    2. UML結合J2EE這樣OO一套實施過程從方法論以及模式角度固化了軟件數據庫系統的分析設計開發,這也是因為有MDA(將這些過程用軟件自動生成代碼)誕生的原因。雖然這些簡化了我們開發系統的過程,但是這只是解決了應用系統的一部分問題,工作流等尚未成熟,使用這樣方式開發系統,依據我的經驗,最后會將煩瑣和細致的工作壓在Jsp頁面上,目前開發一個系統,結合標簽庫和用戶界面需求這個工作反而花費我更多時間,希望JSF在這方面能有效率提升,等這些技術細節都能解決,基本J2EE非常成熟了。
    3.目前我通過咨詢角色和一些軟件公司一起承接一些企業應用項目,例如去年承接一個大型外資人事系統,他們要求管理GE 等幾家外資企業的人事福利(這些企業外包人事給他們),如果專為一家公司開發人事很簡單,但是要求這個人事適合多家,那么重用性要求很高,設計抽象面很高,他們在新加坡有類似系統,但技術很老,我聽過新加坡的系統,他們也有一些經驗總結,大部分和我的J2EE設計相吻合,我和新加坡的人交流過想法,他們很驚奇,不太相信,加上費用問題,只進行了初步架構設計就擱淺了。
    4.不要小看網站系統,以前網站系統都是用PHP Perl做,功能很弱,無法和企業系統相比,但是隨著Inernet普及,更多人要求聯網,例如如果一家公司的ERP通過互聯網實現,那么老總出差就很方便,但是現在為一家公司開發一個基于internet的ERP很貴,比傳統的貴,這不合理,這也是SOA提出的目的之一,以后ERP實現網上租用,就象你申請一個Blog或論壇或Email,你可以為你的企業申請一個ERP系統,這樣只要企業付租費就可以了,這可理想目前已經接近,前段時間美國一家提供這種服務的企業來上海做宣傳,他們的業績增長速度極其快 500%.
    通過網站提供ERP等企業服務對于軟件設計的重用性要求很高,就一套郵箱系統可以服務很多用戶一樣,你必須設計出一套重要性、靈活性很高的ERP系統適合不同的用戶,可見網站軟件的水平是極其高的。前面我做的網站自動生成系統到現在我都認為完成不夠好,現在很多網站都提供這種服務,這象Blog,但是Blog等只限制你網站模板,而不是自由定制頁面,所以 Blog這些都是小孩玩家家,根本無發走向商業,著名的那個方興東鼓吹Blog,其實沒有技術革新,靠你媒體吹呼就是革命了。
    ?
    JoannaYe ask:
    謝謝 Banq 先生在6月23日非常認真的回復(抱歉由于忙,沒能馬上回復). 總結起來, 如果我的理解不錯的話, 你的結論是 1)你認為網站系統并不可小覷(同意,一個高訪問量,同時能夠實現網上交易的網站的確如此).2)EJB/JMS技術對于初學者來說是不容易,但是對你來說,你是可以Handdle的. 3)你也有承接企業系統的實際經驗,象你說的那個HR系統. 但不知您以咨詢身份參加的這個HR系統到底都解決的是實際管理中的什么樣的問題?在性能方面都達到了什么樣的水平? 具體來說,采用了哪些技術(諸如您帖中提到的一些技術)應對了實際中具體的什么樣的問題. 此外以你在這個HR系統的經驗來看, 是一個多少人的Team,采取什么樣的開發方式和開發進度(人員和時間的分配比例)開發的.你認為在這樣的一個項目的開發過程中最關鍵的是什么?最影響 Prductivity的又是什么?
    對這樣一些問題看上去似乎很空泛,但是實際上能夠真正反映出我一開始提出的 issue,"軟件是一個絕對的應用技術,任何技術離開了具體的應用, 坦率地說是毫無價值的".舉個例子來說,書本上,名家們會告訴你, Value List Handler 這個設計模式是解決這樣的問題:"You have a remote client that wants to iterate over a large results list." 一般來說,如果是一個大量地查找某一些"topic/dimension"下的數據,這樣的問題,我們也毫無疑問地確定要用到這個模式.但是,如果對一條具體的數據,如某一個銷售員,要和他的客戶討論(在線談判)他們之間的一個具體合同,這時候會不會也需要用到這個模式.如果要用這個模式,到底是用 Stateful Session Bean 還是用 Stateless Session Bean 實現呢,他們各自在實現方法上對性能的影響是什么, 當你決定采用了某種實現方法,你到底是怎樣Tradeoff的呢; 最后對這個設計模式來說,在最終的設計方案中如何把它抽象到對一個通用的,普遍的業務問題,而不是僅僅對"某一個銷售員,要和他的客戶討論他們之間的一個具體合同"這樣的一個特例問題,作出一個通用的解決方案,適應任意規模,任意業務的企業,真正達到軟件工程的目標:高度的Reusing 和 Scalablity. 實際的企業應用系統就是充滿著類似這樣的問題,很有挑戰.但有些技術人員就僅僅滿足于自己可以用某項技術做出一些小的Demo了,就不愿意,或根本不屑于深入下去面對一個實際的應用問題.
    因此, 我相信您應該能夠非常理解,我為什么感興趣了解您對我上面提出問題答案.
    您的很多看法都很不錯, 我非常同意, 希望我們能在今后進一步深入地探討. 謝謝!
    banq answer:
    >你認為在這樣的一個項目的開發過程中最關鍵的是什么?最影響 Prductivity的又是什么?
    當這樣的項目使用框架組件組合后,由于系統重要重用的功能已經封裝在框架軟件中,所以,只要能夠組裝出應用系統,一般第一次測試就會立即通過,我已經不止一次體會這種快感,我現在基本告別以前那種花費大量時間在Java調試上時代,我相信很多初學者還在這個泥潭里掙扎,這就成為影響一個產品的主要原因,現在使用jdon框架開發,幾乎消滅這個因素。
    那么,現在最影響 Prductivity的是什么?就是技術外的因素:項目管理。
    關于你提的性能方面設計達到什么水平等,這些我已經整合進入Jdon框架,使用Jdon框架開發,幾乎無需考慮性能設計,一開始就具有優越的性能,這些都是有測試數據,Java產品的好處就是一切可以自己動手,不必聽從第三方評價,因為那些都有失公正,服務器配置上Jprofile/Optimizeit,客戶端配置Jmeter,啟動幾個線程一跑,Jdon框架和應用程序的性能真相就出來了,所以,在Java領域,開源和商業產品是在同一起跑線,面對不同的用戶:前者是更有頭腦,自己動手;后者是對自己缺乏自信的人;服務是兩者的重點。
    >在最終的設計方案中如何把它抽象到對一個通用的,普遍的業務問題,而不>是僅僅對"某一個銷售員,要和他的客戶討論他們之間的一個具體合同"這>樣的一個特例問題
    其實你說的行業框架提煉的問題,這和業務相關,Jdon框架等都是基礎框架,沒有這些組件框架的優雅解決方式,就沒有行業框架的好的開始,我想你不希望在行業框架提煉之后,發現無法加入一些縱向功能,就象數據庫設計好之后,幾年以后卻成為你發展的障礙。
    行業框架需要資深的行業背景,這也不是一般人做的,但是工作流/Portal等都是行業框架的提煉,這些也是我們以后發展的方向。
    就我個人來說,我愿意解決重要問題,然后我告訴更多人解決方向,如果他們相信,大家一起努力來解決所有問題,而不是靠我一個人解決所有問題。
    JoannaYe ask:
    謝謝Banq先生的回復, 你的很多觀點都很好,我非常同意.象你所說最影響Prductivity的是技術外的因素:項目管理. 但我不知你能不能有一些具體的看法.因為任何行業,最終的問題, 競爭力的問題都是如何通過管理來提高Prductivity. 不知你對軟件這一行業有沒有特別的見解.
    開源項目的確有它的優勢,特別是作這些開源項目的人,往往是一些技術的精英.但是, 我還是以為應該以成熟的Commercial產品作為自己開發的基礎,即所謂"巨人的肩膀". 這是因為, 成功的Commercial產品往往更注重最終用戶, 這是這些產品能夠給它的公司帶來巨大的商業利潤的源泉.純技術的專家往往會忽視這一點.
    要成就一件事(一個大型企業管理應用的項目), 是需要很多人踏踏實實,堅持不懈(這也非常重要)的努力.這和去上上課,或者在場外指導一下,有很大的區別.
    我希望通過你這個論壇, 結識一些志同道合的朋友, 能夠作成這樣一件事.再次謝謝你的回復, 我因為很多時候很忙,有一些Deadline非常緊的事情,有時沒能馬上給您回復, 請你見諒.
    banq answer:
    非常感謝JoannaYe 討論,從言論中感覺你是一個職業的項目經理。非常專業。
    項目經理和設計師良好溝通和理解交流,是一個項目成功的關鍵。
    關于開源和Commercial區別,我個人覺得它們之間真的沒有嚴格的區別,只不過是兩種思路的表現:開源通過免費產品賣服務;Commercial是既想賣產品又賣服務,不能因為它的產品賣錢,就是技術好,一般是市場品牌好。
    就拿EJB實現來說,在所有J2EE服務器中只有開源JBoss 4.0使用AOP實現,堅持AOP的一些純設計派認為EJB過時了,那么Weblogic /Websphere等這些以支持EJB自詡的服務器產品反而不如開源產品呢。這些人認為:EJB
    但是正如你說:為什么客戶還是購買Websphere等服務器,因為它們注重最終用戶。
    我認為一直試圖在這兩者之間尋找平衡是挑戰的事情。
    -------------------------------------------------------------------------------------------------------------------
    ?
    shuiwx ask:
    ?
    banq老師好,最近大致抽象總結出了一個比較淺顯的規律,既是您平均一兩個月能夠發一篇比較的適合初學者的帖子,但每一篇都可以對偶的有關知識的梳理和導向能夠起到很重要的作用,不敢說終生受用但也似乎會持久難忘了,在此還是要道一聲感謝。
    既然題目是初學者...高質量的J2EE系統,那么就題目本身這個用例來說,參與者該是“novice”了,領域模型應該是"高質量的"+"J2EE系統 ",那么能否請您再深一步的舉個樣例來說明何為"high quality j2ee system"呢?估計您不會選petshop,但有可能會將jive和jdon算進來,但偶真正想看到的是一個就您個人來講曾經有過 consultant經驗的項目作為例子來簡要闡述下高質量+j2ee系統的概貌,或者象您前面某篇論oo和數據庫的矛盾的文章一樣,能否前瞻性的給出一個在您心目中最理想的高質量j2ee系統的輪廓呢?比如jsf(new version>1.1)+ejb3.0+j2ee設計模式?偶覺得struts+spring+hibernate并不敢稱為高質量的或是 j2ee系統,所以總覺得從現在開始既該有意識的用一下jsf+ejb3來設計了,但由于不知道有沒有人在這方面開始吃螃蟹了,所以只好去隨大流的關心些什么ajax,xp之類的流行名詞了。但從內心來講,無論是javascript還是組件式編程,無論是spring+hibernate還是ejb3, 無論是xp還是fdd,無非是想盡量按照客戶的要求迅速提交一個界面新穎,結構穩定的一個能夠跨平臺的良好的系統吧。假如能預知何為一個好的系統的話,似乎事情會變的簡單些,也就不必為那些喋喋不休的爭論著技術名詞的人們所困擾了。
    但由于目前偶的能力所限和所處的時期的特殊性,似乎想馬上就拿jsf+ejb3來首選做企業級開發還有點不現實,那么作為一個apprentice來說,能夠做的似乎只有學習模式了,偶不知道關于模式該學到多深才合適,只相信盡量選擇從建模的時候就配合著設計模式來考慮可能會有助于系統的穩定和重用,談到這里有引申出關于題目的另外一個話題,就是 “初學者”,偶覺得如果想作為計算機編程人員的話,面對著不停的新技術名詞和版本更迭,似乎偶總要做一名初學著來的說,于是最近有意識的在看一些數據結構方面的課程,希望能夠從一些理論基礎中來尋找那些所謂的新技術背后所蘊涵的知識,但還是那句話,由于能力有限,所得甚淺,所以希望您如果能站在一個咨詢家的角度來看,能否指點一下,就您認為的如果想設計一個好的軟件系統來說,或許不僅限于j2ee,該多看看哪些computer science中的理論知識呢?偶不知道這個問題提的對不對,但總覺得設計模式對于系統的意義,是類似于數據結構和算法之相對于程序的意義的,所以假如您在類似的方面能有些心得的話,希望能夠得到一點指點。
    (偶的廢話似乎不少,希望banq老師能忍受)
    ?
    banq answer:
    很抱歉現在才回復你的問題:
    >如果想設計一個好的軟件系統來說,或許不僅限于j2ee,該多看看哪些>computer science中的理論知識
    設計一個好的軟件系統我文章里其實寫了,掌握分層解耦宗旨,學習使用一些現成的框架就可以了,如果你不原意囫圇吞棗,那么研究一下這些框架設計原理和模式,這些會花費你很長探索,數據結構、編譯原理這些已經成為底層機制,就象匯編是底層一樣,現在的大學計算機教學完全是錯誤的,學習的都是正確的廢話。所以沒有必要在那些大學課程上浪費時間。
    增強項目經驗,研讀源碼,自己動手編寫項目是提升水平的唯一道路。
    以上只是我個人意見。
    posted @ 2006-12-31 10:11 保爾任 閱讀(435) | 評論 (0)編輯 收藏
    ?

    作者:郎云鵬(dev2dev ID: hippiewolf)

    摘要:雖然session機制在web應用程序中被采用已經很長時間了,但是仍然有很多人不清楚session機制的本質,以至不能正確的應用這一技術。本文將詳細討論session的工作機制并且對在Java web application中應用session機制時常見的問題作出解答。

    目錄:
    一、術語session
    二、HTTP協議與狀態保持
    三、理解cookie機制
    四、理解session機制
    五、理解javax.servlet.http.HttpSession
    六、HttpSession常見問題
    七、跨應用程序的session共享
    八、總結
    參考文檔

    一、術語session
    在我的經驗里,session這個詞被濫用的程度大概僅次于transaction,更加有趣的是transaction與session在某些語境下的含義是相同的。

    session,中文經常翻譯為會話,其本來的含義是指有始有終的一系列動作/消息,比如打電話時從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個 session。有時候我們可以看到這樣的話“在一個瀏覽器會話期間,...”,這里的會話一詞用的就是其本義,是指從一個瀏覽器窗口打開到關閉這個期間 ①。最混亂的是“用戶(客戶端)在一次會話期間”這樣一句話,它可能指用戶的一系列動作(一般情況下是同某個具體目的相關的一系列動作,比如從登錄到選購商品到結賬登出這樣一個網上購物的過程,有時候也被稱為一個transaction),然而有時候也可能僅僅是指一次連接,也有可能是指含義①,其中的差別只能靠上下文來推斷②。

    然而當session一詞與網絡協議相關聯時,它又往往隱含了“面向連接”和/或“保持狀態”這樣兩個含義,“面向連接”指的是在通信雙方在通信之前要先建立一個通信的渠道,比如打電話,直到對方接了電話通信才能開始,與此相對的是寫信,在你把信發出去的時候你并不能確認對方的地址是否正確,通信渠道不一定能建立,但對發信人來說,通信已經開始了?!氨3譅顟B”則是指通信的一方能夠把一系列的消息關聯起來,使得消息之間可以互相依賴,比如一個服務員能夠認出再次光臨的老顧客并且記得上次這個顧客還欠店里一塊錢。這一類的例子有“一個TCP session”或者“一個POP3 session”③。

    而到了web服務器蓬勃發展的時代,session在web開發語境下的語義又有了新的擴展,它的含義是指一類用來在客戶端與服務器之間保持狀態的解決方案 ④。有時候session也用來指這種解決方案的存儲結構,如“把xxx保存在session里”⑤。由于各種用于web開發的語言在一定程度上都提供了對這種解決方案的支持,所以在某種特定語言的語境下,session也被用來指代該語言的解決方案,比如經常把Java里提供的 javax.servlet.http.HttpSession簡稱為session⑥。

    鑒于這種混亂已不可改變,本文中session一詞的運用也會根據上下文有不同的含義,請大家注意分辨。
    在本文中,使用中文“瀏覽器會話期間”來表達含義①,使用“session機制”來表達含義④,使用“session”表達含義⑤,使用具體的“HttpSession”來表達含義⑥

    二、HTTP協議與狀態保持
    HTTP協議本身是無狀態的,這與HTTP協議本來的目的是相符的,客戶端只需要簡單的向服務器請求下載某些文件,無論是客戶端還是服務器都沒有必要紀錄彼此過去的行為,每一次請求之間都是獨立的,好比一個顧客和一個自動售貨機或者一個普通的(非會員制)大賣場之間的關系一樣。

    然而聰明(或者貪心?)的人們很快發現如果能夠提供一些按需生成的動態信息會使web變得更加有用,就像給有線電視加上點播功能一樣。這種需求一方面迫使 HTML逐步添加了表單、腳本、DOM等客戶端行為,另一方面在服務器端則出現了CGI規范以響應客戶端的動態請求,作為傳輸載體的HTTP協議也添加了文件上載、cookie這些特性。其中cookie的作用就是為了解決HTTP協議無狀態的缺陷所作出的努力。至于后來出現的session機制則是又一種在客戶端與服務器之間保持狀態的解決方案。

    讓我們用幾個例子來描述一下cookie和session機制之間的區別與聯系。筆者曾經常去的一家咖啡店有喝5杯咖啡免費贈一杯咖啡的優惠,然而一次性消費5杯咖啡的機會微乎其微,這時就需要某種方式來紀錄某位顧客的消費數量。想象一下其實也無外乎下面的幾種方案:
    1、該店的店員很厲害,能記住每位顧客的消費數量,只要顧客一走進咖啡店,店員就知道該怎么對待了。這種做法就是協議本身支持狀態。
    2、發給顧客一張卡片,上面記錄著消費的數量,一般還有個有效期限。每次消費時,如果顧客出示這張卡片,則此次消費就會與以前或以后的消費相聯系起來。這種做法就是在客戶端保持狀態。
    3、發給顧客一張會員卡,除了卡號之外什么信息也不紀錄,每次消費時,如果顧客出示該卡片,則店員在店里的紀錄本上找到這個卡號對應的紀錄添加一些消費信息。這種做法就是在服務器端保持狀態。

    由于HTTP協議是無狀態的,而出于種種考慮也不希望使之成為有狀態的,因此,后面兩種方案就成為現實的選擇。具體來說cookie機制采用的是在客戶端保持狀態的方案,而session機制采用的是在服務器端保持狀態的方案。同時我們也看到,由于采用服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要借助于cookie機制來達到保存標識的目的,但實際上它還有其他選擇。

    三、理解cookie機制
    cookie機制的基本原理就如上面的例子一樣簡單,但是還有幾個問題需要解決:“會員卡”如何分發;“會員卡”的內容;以及客戶如何使用“會員卡”。

    正統的cookie分發是通過擴展HTTP協議來實現的,服務器通過在HTTP的響應頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie。然而純粹的客戶端腳本如Javascript或者VBscript也可以生成cookie。

    而cookie 的使用是由瀏覽器按照一定的原則在后臺自動發送給服務器的。瀏覽器檢查所有存儲的cookie,如果某個cookie所聲明的作用范圍大于等于將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上發送給服務器。意思是麥當勞的會員卡只能在麥當勞的店里出示,如果某家分店還發行了自己的會員卡,那么進這家店的時候除了要出示麥當勞的會員卡,還要出示這家店的會員卡。

    cookie的內容主要包括:名字,值,過期時間,路徑和域。
    其中域可以指定某一個域比如.google.com,相當于總店招牌,比如寶潔公司,也可以指定一個域下的具體某臺機器比如www.google.com或者froogle.google.com,可以用飄柔來做比。
    路徑就是跟在域名后面的URL路徑,比如/或者/foo等等,可以用某飄柔專柜做比。
    路徑與域合在一起就構成了cookie的作用范圍。
    如果不設置過期時間,則表示這個cookie的生命期為瀏覽器會話期間,只要關閉瀏覽器窗口,cookie就消失了。這種生命期為瀏覽器會話期的 cookie被稱為會話cookie。會話cookie一般不存儲在硬盤上而是保存在內存里,當然這種行為并不是規范規定的。如果設置了過期時間,瀏覽器就會把cookie保存到硬盤上,關閉后再次打開瀏覽器,這些cookie仍然有效直到超過設定的過期時間。

    存儲在硬盤上的cookie可以在不同的瀏覽器進程間共享,比如兩個IE窗口。而對于保存在內存里的cookie,不同的瀏覽器有不同的處理方式。對于 IE,在一個打開的窗口上按Ctrl-N(或者從文件菜單)打開的窗口可以與原窗口共享,而使用其他方式新開的IE進程則不能共享已經打開的窗口的內存 cookie;對于Mozilla Firefox0.8,所有的進程和標簽頁都可以共享同樣的cookie。一般來說是用javascript的window.open打開的窗口會與原窗口共享內存cookie。瀏覽器對于會話cookie的這種只認cookie不認人的處理方式經常給采用session機制的web應用程序開發者造成很大的困擾。

    下面就是一個goolge設置cookie的響應頭的例子
    HTTP/1.1 302 Found
    Location: http://www.google.com/intl/zh-CN/
    Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
    Content-Type: text/html


    這是使用HTTPLook這個HTTP Sniffer軟件來俘獲的HTTP通訊紀錄的一部分


    瀏覽器在再次訪問goolge的資源時自動向外發送cookie


    使用Firefox可以很容易的觀察現有的cookie的值
    使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理。


    IE也可以設置在接受cookie前詢問


    這是一個詢問接受cookie的對話框。

    四、理解session機制
    session機制是一種服務器端的機制,服務器使用一種類似于散列表的結構(也可能就是使用散列表)來保存信息。

    當程序需要為某個客戶端的請求創建一個session的時候,服務器首先檢查這個客戶端的請求里是否已包含了一個session標識 - 稱為session id,如果已包含一個session id則說明以前已經為此客戶端創建過session,服務器就按照session id把這個session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id,則為此客戶端創建一個session并且生成一個與此session相關聯的session id,session id的值應該是一個既不會重復,又不容易被找到規律以仿造的字符串,這個session id將被在本次響應中返回給客戶端保存。

    保存這個session id的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動的按照規則把這個標識發揮給服務器。一般這個cookie的名字都是類似于 SEEESIONID,而。比如weblogic對于web應用程序生成的cookie,JSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是 JSESSIONID。

    由于 cookie可以被人為的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞回服務器。經常被使用的一種技術叫做URL重寫,就是把session id直接附加在URL路徑的后面,附加方式也有兩種,一種是作為URL路徑的附加信息,表現形式為http://...../xxx; jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
    另一種是作為查詢字符串附加在URL后面,表現形式為http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
    這兩種方式對于用戶來說是沒有區別的,只是服務器在解析的時候處理的方式不同,采用第一種方式也有利于把session id的信息和正常程序參數區分開來。
    為了在整個交互過程中始終保持狀態,就必須在每個客戶端可能請求的路徑后面都包含這個session id。

    另一種技術叫做表單隱藏字段。就是服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把session id傳遞回服務器。比如下面的表單
    <form name="testform" action="/xxx">
    <input type="text">
    </form>
    在被傳遞給客戶端之前將被改寫成
    <form name="testform" action="/xxx">
    <input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
    <input type="text">
    </form>
    這種技術現在已較少應用,筆者接觸過的很古老的iPlanet6(SunONE應用服務器的前身)就使用了這種技術。
    實際上這種技術可以簡單的用對action應用URL重寫來代替。

    在談論session機制的時候,常常聽到這樣一種誤解“只要關閉瀏覽器,session就消失了”。其實可以想象一下會員卡的例子,除非顧客主動對店家提出銷卡,否則店家絕對不會輕易刪除顧客的資料。對session來說也是一樣的,除非程序通知服務器刪除一個session,否則服務器會一直保留,程序一般都是在用戶做log off的時候發個指令去刪除session。然而瀏覽器從來不會主動在關閉之前通知服務器它將要關閉,因此服務器根本不會有機會知道瀏覽器已經關閉,之所以會有這種錯覺,是大部分session機制都使用會話cookie來保存session id,而關閉瀏覽器后這個session id就消失了,再次連接服務器時也就無法找到原來的session。如果服務器設置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發出的 HTTP請求頭,把原來的session id發送給服務器,則再次打開瀏覽器仍然能夠找到原來的session。

    恰恰是由于關閉瀏覽器不會導致session被刪除,迫使服務器為seesion設置了一個失效時間,當距離客戶端上一次使用session的時間超過這個失效時間時,服務器就可以認為客戶端已經停止了活動,才會把session刪除以節省存儲空間。

    五、理解javax.servlet.http.HttpSession
    HttpSession是Java平臺對session機制的實現規范,因為它僅僅是個接口,具體到每個web應用服務器的提供商,除了對規范支持之外,仍然會有一些規范里沒有規定的細微差異。這里我們以BEA的Weblogic Server8.1作為例子來演示。

    首先,Weblogic Server提供了一系列的參數來控制它的HttpSession的實現,包括使用cookie的開關選項,使用URL重寫的開關選項,session持久化的設置,session失效時間的設置,以及針對cookie的各種設置,比如設置cookie的名字、路徑、域,cookie的生存時間等。

    一般情況下,session都是存儲在內存里,當服務器進程被停止或者重啟的時候,內存里的session也會被清空,如果設置了session的持久化特性,服務器就會把session保存到硬盤上,當服務器進程重新啟動或這些信息將能夠被再次使用,Weblogic Server支持的持久性方式包括文件、數據庫、客戶端cookie保存和復制。

    復制嚴格說來不算持久化保存,因為session實際上還是保存在內存里,不過同樣的信息被復制到各個cluster內的服務器進程中,這樣即使某個服務器進程停止工作也仍然可以從其他進程中取得session。

    cookie生存時間的設置則會影響瀏覽器生成的cookie是否是一個會話cookie。默認是使用會話cookie。有興趣的可以用它來試驗我們在第四節里提到的那個誤解。

    cookie的路徑對于web應用程序來說是一個非常重要的選項,Weblogic Server對這個選項的默認處理方式使得它與其他服務器有明顯的區別。后面我們會專題討論。

    關于session的設置參考[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869

    六、HttpSession常見問題
    (在本小節中session的含義為⑤和⑥的混合)


    1、session在何時被創建
    一個常見的誤解是以為session在有客戶端訪問時就被創建,然而事實是直到某server端程序調用 HttpServletRequest.getSession(true)這樣的語句時才被創建,注意如果JSP沒有顯示的使用 <%@page session="false"%> 關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的session對象的來歷。

    由于session會消耗內存資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。

    2、session何時被刪除
    綜合前面的討論,session在下列情況下被刪除a.程序調用HttpSession.invalidate();或b.距離上一次收到客戶端發送的session id時間間隔超過了session的超時設置;或c.服務器進程被停止(非持久session)

    3、如何做到在瀏覽器關閉時刪除session
    嚴格的講,做不到這一點。可以做一點努力的辦法是在所有的客戶端頁面里使用javascript代碼window.oncolose來監視瀏覽器的關閉動作,然后向服務器發送一個請求來刪除session。但是對于瀏覽器崩潰或者強行殺死進程這些非常規手段仍然無能為力。

    4、有個HttpSessionListener是怎么回事
    你可以創建這樣的listener去監控session的創建和銷毀事件,使得在發生這樣的事件時你可以做一些相應的工作。注意是session的創建和銷毀動作觸發listener,而不是相反。類似的與HttpSession有關的listener還有 HttpSessionBindingListener,HttpSessionActivationListener和 HttpSessionAttributeListener。

    5、存放在session中的對象必須是可序列化的嗎
    不是必需的。要求對象可序列化只是為了session能夠在集群中被復制或者能夠持久保存或者在必要時server能夠暫時把session交換出內存。在 Weblogic Server的session中放置一個不可序列化的對象在控制臺上會收到一個警告。我所用過的某個iPlanet版本如果session中有不可序列化的對象,在session銷毀時會有一個Exception,很奇怪。

    6、如何才能正確的應付客戶端禁止cookie的可能性
    對所有的URL使用URL重寫,包括超鏈接,form的action,和重定向的URL,具體做法參見[6]
    http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

    7、開兩個瀏覽器窗口訪問應用程序會使用同一個session還是不同的session
    參見第三小節對cookie的討論,對session來說是只認id不認人,因此不同的瀏覽器,不同的窗口打開方式以及不同的cookie存儲方式都會對這個問題的答案有影響。

    8、如何防止用戶打開兩個瀏覽器窗口操作導致的session混亂
    這個問題與防止表單多次提交是類似的,可以通過設置客戶端的令牌來解決。就是在服務器每次生成一個不同的id返回給客戶端,同時保存在session里,客戶端提交表單時必須把這個id也返回服務器,程序首先比較返回的id與保存在session里的值是否一致,如果不一致則說明本次操作已經被提交過了。可以參看《J2EE核心模式》關于表示層模式的部分。需要注意的是對于使用javascript window.open打開的窗口,一般不設置這個id,或者使用單獨的id,以防主窗口無法操作,建議不要再window.open打開的窗口里做修改操作,這樣就可以不用設置。

    9、為什么在Weblogic Server中改變session的值后要重新調用一次session.setValue
    做這個動作主要是為了在集群環境中提示Weblogic Server session中的值發生了改變,需要向其他服務器進程復制新的session值。

    10、為什么session不見了
    排除session正常失效的因素之外,服務器本身的可能性應該是微乎其微的,雖然筆者在iPlanet6SP1加若干補丁的Solaris版本上倒也遇到過;瀏覽器插件的可能性次之,筆者也遇到過3721插件造成的問題;理論上防火墻或者代理服務器在cookie處理上也有可能會出現問題。
    出現這一問題的大部分原因都是程序的錯誤,最常見的就是在一個應用程序中去訪問另外一個應用程序。我們在下一節討論這個問題。

    七、跨應用程序的session共享

    常常有這樣的情況,一個大項目被分割成若干小項目開發,為了能夠互不干擾,要求每個小項目作為一個單獨的web應用程序開發,可是到了最后突然發現某幾個小項目之間需要共享一些信息,或者想使用session來實現SSO(single sign on),在session中保存login的用戶信息,最自然的要求是應用程序間能夠訪問彼此的session。

    然而按照Servlet規范,session的作用范圍應該僅僅限于當前應用程序下,不同的應用程序之間是不能夠互相訪問對方的session的。各個應用服務器從實際效果上都遵守了這一規范,但是實現的細節卻可能各有不同,因此解決跨應用程序session共享的方法也各不相同。

    首先來看一下Tomcat是如何實現web應用程序之間session的隔離的,從Tomcat設置的cookie路徑來看,它對不同的應用程序設置的 cookie路徑是不同的,這樣不同的應用程序所用的session id是不同的,因此即使在同一個瀏覽器窗口里訪問不同的應用程序,發送給服務器的session id也可以是不同的。

    根據這個特性,我們可以推測Tomcat中session的內存結構大致如下。

    筆者以前用過的iPlanet也采用的是同樣的方式,估計SunONE與iPlanet之間不會有太大的差別。對于這種方式的服務器,解決的思路很簡單,實際實行起來也不難。要么讓所有的應用程序共享一個session id,要么讓應用程序能夠獲得其他應用程序的session id。

    iPlanet中有一種很簡單的方法來實現共享一個session id,那就是把各個應用程序的cookie路徑都設為/(實際上應該是/NASApp,對于應用程序來講它的作用相當于根)。
    <session-info>
    <path>/NASApp</path>
    </session-info>

    需要注意的是,操作共享的session應該遵循一些編程約定,比如在session attribute名字的前面加上應用程序的前綴,使得setAttribute("name", "neo")變成setAttribute("app1.name", "neo"),以防止命名空間沖突,導致互相覆蓋。


    在Tomcat 中則沒有這么方便的選擇。在Tomcat版本3上,我們還可以有一些手段來共享session。對于版本4以上的Tomcat,目前筆者尚未發現簡單的辦法。只能借助于第三方的力量,比如使用文件、數據庫、JMS或者客戶端cookie,URL參數或者隱藏字段等手段。

    我們再看一下Weblogic Server是如何處理session的。

    從截屏畫面上可以看到Weblogic Server對所有的應用程序設置的cookie的路徑都是/,這是不是意味著在Weblogic Server中默認的就可以共享session了呢?然而一個小實驗即可證明即使不同的應用程序使用的是同一個session,各個應用程序仍然只能訪問自己所設置的那些屬性。這說明Weblogic Server中的session的內存結構可能如下

    對于這樣一種結構,在session機制本身上來解決session共享的問題應該是不可能的了。除了借助于第三方的力量,比如使用文件、數據庫、JMS或者客戶端cookie,URL參數或者隱藏字段等手段,還有一種較為方便的做法,就是把一個應用程序的session放到ServletContext 中,這樣另外一個應用程序就可以從ServletContext中取得前一個應用程序的引用。示例代碼如下,

    應用程序A
    context.setAttribute("appA", session);

    應用程序B
    contextA = context.getContext("/appA");
    HttpSession sessionA = (HttpSession)contextA.getAttribute("appA");

    值得注意的是這種用法不可移植,因為根據ServletContext的JavaDoc,應用服務器可以處于安全的原因對于context.getContext("/appA");返回空值,以上做法在Weblogic Server 8.1中通過。

    那么Weblogic Server為什么要把所有的應用程序的cookie路徑都設為/呢?原來是為了SSO,凡是共享這個session的應用程序都可以共享認證的信息。一個簡單的實驗就可以證明這一點,修改首先登錄的那個應用程序的描述符weblogic.xml,把cookie路徑修改為/appA訪問另外一個應用程序會重新要求登錄,即使是反過來,先訪問cookie路徑為/的應用程序,再訪問修改過路徑的這個,雖然不再提示登錄,但是登錄的用戶信息也會丟失。注意做這個實驗時認證方式應該使用FORM,因為瀏覽器和web服務器對basic認證方式有其他的處理方式,第二次請求的認證不是通過session來實現的。具體請參看[7] secion 14.8 Authorization,你可以修改所附的示例程序來做這些試驗。

    八、總結
    session機制本身并不復雜,然而其實現和配置上的靈活性卻使得具體情況復雜多變。這也要求我們不能把僅僅某一次的經驗或者某一個瀏覽器,服務器的經驗當作普遍適用的經驗,而是始終需要具體情況具體分析。

    關于作者:
    郎云鵬(dev2dev ID: hippiewolf),軟件工程師,從事J2EE開發
    電子郵件:langyunpeng@yahoo.com.cn
    地址:大連軟件園路31號科技大廈A座大連博涵咨詢服務有限公司

    參考文檔:
    [1] Preliminary Specification http://wp.netscape.com/newsref/std/cookie_spec.html
    [2] RFC2109 http://www.rfc-editor.org/rfc/rfc2109.txt
    [3] RFC2965 http://www.rfc-editor.org/rfc/rfc2965.txt
    [4] The Unofficial Cookie FAQ http://www.cookiecentral.com/faq/
    [5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869
    [6] http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
    [7] RFC2616 http://www.rfc-editor.org/rfc/rfc2616.txt

    代碼下載sampleApp.zip

    posted @ 2006-12-31 10:10 保爾任 閱讀(311) | 評論 (0)編輯 收藏

    早在Java 1.2推出之時,Java平臺中就引入了一個新的支持:java.lang.ThreadLocal,給我們在編寫多線程程序時提供了一種新的選擇。使用這個工具類可以很簡潔地編寫出優美的多線程程序,雖然ThreadLocal非常有用,但是似乎現在了解它、使用它的朋友還不多。

    ThreadLocal是什么

    ThreadLocal并非是一個線程的本地實現版本,它并不是一個Thread,而是thread local variable(線程局部變量)。也許把它命名為ThreadLocalVar更加合適。線程局部變量(ThreadLocal)其實的功用非常簡單,就是為每一個使用該變量的線程都提供一個變量值的副本,是每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本沖突。從線程的角度看,就好像每一個線程都完全擁有該變量。線程局部變量并不是Java的新發明,在其它的一些語言編譯器實現(如IBM XL FORTRAN)中,它在語言的層次提供了直接的支持。因為Java中沒有提供在語言層次的直接支持,而是提供了一個ThreadLocal的類來提供支持,所以,在Java中編寫線程局部變量的代碼相對比較笨拙,這也許是線程局部變量沒有在Java中得到很好的普及的一個原因吧。

    ThreadLocal的設計

    首先看看ThreadLocal的接口:

    Object get() ;

    // 返回當前線程的線程局部變量副本 protected Object initialValue(); // 返回該線程局部變量的當前線程的初始值

    void set(Object value);

    // 設置當前線程的線程局部變量副本的值

    ThreadLocal有3個方法,其中值得注意的是initialValue(),該方法是一個protected的方法,顯然是為了子類重寫而特意實現的。該方法返回當前線程在該線程局部變量的初始值,這個方法是一個延遲調用方法,在一個線程第1次調用get()或者set(Object)時才執行,并且僅執行1次。ThreadLocal中的確實實現直接返回一個null:

    protected Object initialValue() { return null; }

    ThreadLocal是如何做到為每一個線程維護變量的副本的呢?其實實現的思路很簡單,在ThreadLocal類中有一個Map,用于存儲每一個線程的變量的副本。比如下面的示例實現:


    public class ThreadLocal
    {
    private Map values = Collections.synchronizedMap(new HashMap());
    public Object get()
    {
    Thread curThread = Thread.currentThread();
    Object o = values.get(curThread);
    if (o == null && !values.containsKey(curThread))
    {
    o = initialValue();
    values.put(curThread, o);
    }
    return o;
    }

    public void set(Object newValue)
    {
    values.put(Thread.currentThread(), newValue);
    }

    public Object initialValue()
    {
    return null;
    }
    }

    ?


    當然,這并不是一個工業強度的實現,但JDK中的ThreadLocal的實現總體思路也類似于此。

    ThreadLocal的使用

    如果希望線程局部變量初始化其它值,那么需要自己實現ThreadLocal的子類并重寫該方法,通常使用一個內部匿名類對ThreadLocal進行子類化,比如下面的例子,SerialNum類為每一個類分配一個序號


    public class SerialNum
    {
    // The next serial number to be assigned

    private static int nextSerialNum = 0;

    private static ThreadLocal serialNum = new ThreadLocal()
    {
    protected synchronized Object initialValue()
    {
    return new Integer(nextSerialNum++);
    }
    };


    public static int get()
    {
    return ((Integer) (serialNum.get())).intValue();
    }

    }

    ?


    SerialNum類的使用將非常地簡單,因為get()方法是static的,所以在需要獲取當前線程的序號時,簡單地調用:

    int serial = SerialNum.get();

    即可。

    在線程是活動的并且ThreadLocal對象是可訪問的時,該線程就持有一個到該線程局部變量副本的隱含引用,當該線程運行結束后,該線程擁有的所以線程局部變量的副本都將失效,并等待垃圾收集器收集。

    ThreadLocal與其它同步機制的比較

    ThreadLocal和其它同步機制相比有什么優勢呢?ThreadLocal和其它所有的同步機制都是為了解決多線程中的對同一變量的訪問沖突,在普通的同步機制中,是通過對象加鎖來實現多個線程對同一變量的安全訪問的。這時該變量是多個線程共享的,使用這種同步機制需要很細致地分析在什么時候對變量進行讀寫,什么時候需要鎖定某個對象,什么時候釋放該對象的鎖等等很多。所有這些都是因為多個線程共享了資源造成的。ThreadLocal就從另一個角度來解決多線程的并發訪問,ThreadLocal會為每一個線程維護一個和該線程綁定的變量的副本,從而隔離了多個線程的數據,每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量

    posted @ 2006-12-27 21:37 保爾任 閱讀(338) | 評論 (0)編輯 收藏
    ?

    第一,文件的的編碼方式其實就包括兩方面:存和取,存文件必須以一種編碼存;讀文件也必須以一種編碼讀。如果存取按照相同的編碼方式,則不會有問題,關鍵就是很多時候存取的方式不一致,產生亂碼。,如不特別設置取系統默認的編碼,中文windows為GBK編碼。

    從.java->.class過程是,先編寫.java文件并按莫種編碼方式保存,然后用javac方法編譯此文件,注意如.java沒按系統默認編碼保存則要帶encoding參數指明實際編碼,否則出錯,生成的.class文件存為系統默認編碼。

    從.jsp->.java->.class,先存為某種編碼的.jsp文件,然后tomcat根據pageEncoding讀取并轉化為servlet存為系統默認編碼,然后同上面.java->.class過程。

    第二,IDE的encoding為對系統下文件打開的解碼方式或保存的編碼方式。特例:如果.jsp文件有<%@ page language="java" pageEncoding="UTF-8"%>,則eclipse會自動存為UTF-8方式,不管eclipse的encoding是什么,這也是 eclipse的聰明之處。

    第三,
    pageEncoding="UTF-8"表示此文件的編碼方式,必須與此文件存儲方式一致(所以eclipse會首選根據它來存文件),tomcat根據這個來讀此.jsp文件并編譯為servlet(至于編譯成的.java和.class文件應該為tomcat服務器默認編碼)。
    contentType="text/html;charset=UTF-8"表示當服務器給瀏覽器傳頁面文件時編碼方式為UTF-8,形式為HTML。例如:
    <%@ page language="java" pageEncoding="UTF-8"%>
    <%@ page contentType="text/html;charset=GBK"%>
    <html>
    ?<head>
    ??<title>test</title>
    ?</head>
    ?<body>
    ??我是個好人
    ?</body>
    </html>

    表示本jsp文件存為UTF-8字符集,當瀏覽器打開此頁面后,查看原碼就會發現源碼為GBK字符集。

    第四,
    request.setCharacterEncoding("UTF-8")是把提交內容的字符集設為UTF-8
    response.setCharacterEncoding("UTF-8")可以把頁面中的<%@ page contentType="text/html;charset=iso8859-1"%>換為charset=UTF-8,是給告訴瀏覽器我這個文件的編碼方式。

    第五,表單提交:無論何種表單提交都可以在后臺的java文件中通過String des = new String(s.getBytes("iso8859-1"),"UTF-8");來轉換成你想要的UTF-8編碼方式。但如果每處都加詞句太麻煩,故分post和get兩種方式區分提交(tomcat5以后分開處理,之前處理方式一樣,即都可以用 request.setCharacterEncoding("UTF-8")方法處理,不過tomcat5以后get提交方法用此語句無效)。
    1,post提交的數據:
    程序加上org.springframework.web.filter.CharacterEncodingFilter過濾器.
    <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF8</param-value>
    </init-param>
    <init-param>
    <param-name>forceEncoding</param-name>
    <param-value>true</param-value>
    </init-param>
    </filter>

    <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>*.jsp</url-pattern>
    </filter-mapping>

    因為規范要求瀏覽器提交數據都要用utf8編碼,所以這里設置編碼方式為UTF8.

    特別注意:
    a,這個過濾器只是簡單的調用:request.setCharacterEncoding(this.encoding);
    在這個語句之前不能調用任何的request.getParameter()方法,否則會設置tomcat的缺省字符集為"ISO-8859-1",并且使 setCharacterEncoding的調用失效.所以在這個過濾器之前的過濾器中不能有對getParameter這類方法的調用,比較安全的做法就是把這個過濾器盡量靠前放.
    b,在server.xml中不能加上<Valve className="org.apache.catalina.valves.RequestDumperValve"/>
    這個value也設置tomcat的缺省字符集為"ISO-8859-1",使setCharacterEncoding的調用失效.可能其他的value也有這個問題,我沒有測試過.
    如果要觀察http請求參數,可以考慮用過濾器或者其他工具,例如ethereal(http://www.ethereal.com/)

    2,get提交的數據:
    兩種情況:
    a,如果從地址欄直接輸入漢字,則一般編碼為"GBK",需要用
    new String(request.getParameter("something").getBytes("ISO-8859-1"),"GBK")
    取出
    b,如果是頁面超連接連接中帶的漢字,則編碼根據頁面編碼的不同而不同,如果頁面的
    content="text/html; charset=utf-8",則在tomcat/conf/server.xml中的配置文件中:
    <!-- Define a non-SSL Coyote HTTP/1.1 Connector on port 8080 -->
    <Connector port="8080"
    maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
    enableLookups="false" redirectPort="8443" acceptCount="100"
    debug="0" connectionTimeout="20000" useBodyEncodingForURI="true"
    disableUploadTimeout="true" />

    加上:useBodyEncodingForURI="true"即可正常使用getParameter取出正確內容.
    如果content="text/html; charset=GBK",需用
    new String(request.getParameter("something").getBytes("ISO-8859-1"),"GBK")
    取出,其他情況類似.

    總結:
    1,所有頁面使用utf8編碼,
    2,服務器加上過濾器,
    3,server.xml中不要使用
    <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
    4,server.xml文件加上useBodyEncodingForURI="true"
    這樣應該可以搞定大多數前臺的中文問題.至于地址欄輸入中文,不支持也罷,一般的程序很少要求
    從這里輸入.

    第六,連接數據庫
    ?

    1、mysql配置文件:
    修改mysql在windows\my.ini里default-character-set=utf-8

    2、mysql里數據庫和表也都設為utf8_unicode_ci

    3、數據庫連結:jdbc:mysql://localhost/mydb?useUnicode=true&characterEncoding=utf-8
    注意,關鍵就在于此:此句中間是'&'不是'&amp;'這是因為數據庫連結時,在.jsp和.java文件中應該用&號,而XML文件中需要用&amp

    posted @ 2006-12-26 10:52 保爾任 閱讀(338) | 評論 (0)編輯 收藏
    ??

    Java基礎方面:

    1、作用域public,private,protected,以及不寫時的區別
    答:區別如下:
    作用域?????????? 當前類?????? 同一package? 子孫類?????? 其他package
    public??????????? √????????????? √????????????????? √???????????? √
    protected??????? √????????????? √????????????????? √???????????? ×
    friendly????????? √????????????? √?????????????????? ×??????????? ×
    private?????????? √????????????? ×?????????????????? ×??????????? ×
    不寫時默認為friendly

    2、ArrayList和Vector的區別,HashMap和Hashtable的區別
    答:
    就ArrayList與Vector主要從二方面來說.
    一.同步性:Vector是線程安全的,也就是說是同步的,而ArrayList是線程序不安全的,不是同步的
    二.數據增長:當需要增長時,Vector默認增長為原來一培,而ArrayList卻是原來的一半
    就HashMap與HashTable主要從三方面來說。
    一.歷史原因:Hashtable是基于陳舊的Dictionary類的,HashMap是Java 1.2引進的Map接口的一個實現
    二.同步性:Hashtable是線程安全的,也就是說是同步的,而HashMap是線程序不安全的,不是同步的
    三.值:只有HashMap可以讓你將空值作為一個表的條目的key或value

    3、char型變量中能不能存貯一個中文漢字?為什么?
    答:
    是能夠定義成為一個中文的,因為java中以unicode編碼,一個char占16個字節,所以放一個中文是沒問題的

    4、多線程有幾種實現方法,都是什么?同步有幾種實現方法,都是什么?
    答:
    多線程有兩種實現方法,分別是繼承Thread類與實現Runnable接口
    同步的實現方面有兩種,分別是synchronized,wait與notify

    5、繼承時候類的執行順序問題,一般都是選擇題,問你將會打印出什么?
    答:
    父類:
    package test;
    public class? FatherClass
    {
    ??? public FatherClass()
    ?{
    ??System.out.println("FatherClass Create");
    ?}
    }
    子類:
    package test;
    import test.FatherClass;
    public class? ChildClass extends FatherClass
    {
    ?public ChildClass()
    ?{
    ??System.out.println("ChildClass Create");
    ?}
    ?public static void main(String[] args)
    ?{
    ??FatherClass fc = new FatherClass();
    ??ChildClass cc = new ChildClass();
    ?}
    }
    輸出結果:
    C:\>java test.ChildClass
    FatherClass Create
    FatherClass Create
    ChildClass Create

    6、內部類的實現方式?
    答:
    示例代碼如下:
    package test;
    public class? OuterClass
    {
    ?private class InterClass
    ?{
    ??public InterClass()
    ??{
    ???System.out.println("InterClass Create");
    ??}
    ?}
    ?public OuterClass()
    ?{
    ??InterClass ic = new InterClass();
    ??System.out.println("OuterClass Create");
    ?}
    ?public static void main(String[] args)
    ?{
    ??OuterClass oc = new OuterClass();
    ?}
    }
    輸出結果:
    C:\>java test/OuterClass
    InterClass Create
    OuterClass Create
    再一個例題:
    public class OuterClass {
    ? private double d1 = 1.0;
    ??? //insert code here
    }
    You need to insert an inner class declaration at line 3. Which two inner class declarations are

    valid?(Choose two.)
    A. class InnerOne{
    ???? public static double methoda() {return d1;}
    ?? }
    B. public class InnerOne{
    ???? static double methoda() {return d1;}
    ?? }
    C. private class InnerOne{
    ???? double methoda() {return d1;}
    ?? }
    D. static class InnerOne{
    ???? protected double methoda() {return d1;}
    ?? }
    E. abstract class InnerOne{
    ???? public abstract double methoda();
    ?? }
    說明如下:
    一.靜態內部類可以有靜態成員,而非靜態內部類則不能有靜態成員。 故 A、B 錯
    二.靜態內部類的非靜態成員可以訪問外部類的靜態變量,而不可訪問外部類的非靜態變量;return d1 出錯。

    故 D 錯
    三.非靜態內部類的非靜態成員可以訪問外部類的非靜態變量。 故 C 正確
    四.答案為C、E

    7、垃圾回收機制,如何優化程序?
    希望大家補上,謝謝

    8、float型float f=3.4是否正確?
    答:
    不正確。精度不準確,應該用強制類型轉換,如下所示:float f=(float)3.4

    9、介紹JAVA中的Collection FrameWork(包括如何寫自己的數據結構)?
    答:
    Collection FrameWork如下:
    Collection
    ├List
    │├LinkedList
    │├ArrayList
    │└Vector
    │ └Stack
    └Set
    Map
    ├Hashtable
    ├HashMap
    └WeakHashMap
    Collection是最基本的集合接口,一個Collection代表一組Object,即Collection的元素(Elements)
    Map提供key到value的映射

    10、Java中異常處理機制,事件機制?

    11、JAVA中的多形與繼承?
    希望大家補上,謝謝

    12、抽象類與接口?
    答:
    抽象類與接口都用于抽象,但是抽象類(JAVA中)可以有自己的部分實現,而接口則完全是一個標識(同時有多重繼承的功能)。

    13、Java 的通信編程,編程題(或問答),用JAVA SOCKET編程,讀服務器幾個字符,再寫入本地顯示?
    答:
    Server端程序:
    package test;
    import java.net.*;
    import java.io.*;

    public class Server
    {
    ?private ServerSocket ss;
    ?private Socket socket;
    ?private BufferedReader in;
    ?private PrintWriter out;
    ?public Server()
    ?{
    ??try
    ??{
    ???ss=new ServerSocket(10000);
    ???while(true)
    ???{
    ????socket = ss.accept();
    ????String RemoteIP = socket.getInetAddress().getHostAddress();
    ????String RemotePort = ":"+socket.getLocalPort();
    ????System.out.println("A client come in!IP:"+RemoteIP+RemotePort);
    ????in = new BufferedReader(new

    InputStreamReader(socket.getInputStream()));
    ????String line = in.readLine();
    ????System.out.println("Cleint send is :" + line);
    ????out = new PrintWriter(socket.getOutputStream(),true);
    ????out.println("Your Message Received!");
    ????out.close();
    ????in.close();
    ????socket.close();
    ???}
    ??}catch (IOException e)
    ??{
    ???out.println("wrong");
    ??}
    ?}
    ?public static void main(String[] args)
    ?{
    ??new Server();
    ?}
    };
    Client端程序:
    package test;
    import java.io.*;
    import java.net.*;

    public class Client
    {
    ?Socket socket;
    ?BufferedReader in;
    ?PrintWriter out;
    ?public Client()
    ?{
    ??try
    ??{
    ???System.out.println("Try to Connect to 127.0.0.1:10000");
    ???socket = new Socket("127.0.0.1",10000);
    ???System.out.println("The Server Connected!");
    ???System.out.println("Please enter some Character:");
    ???BufferedReader line = new BufferedReader(new

    InputStreamReader(System.in));
    ???out = new PrintWriter(socket.getOutputStream(),true);
    ???out.println(line.readLine());
    ???in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    ???System.out.println(in.readLine());
    ???out.close();
    ???in.close();
    ???socket.close();
    ??}catch(IOException e)
    ??{
    ???out.println("Wrong");
    ??}
    ?}
    ?public static void main(String[] args)
    ?{
    ??new Client();
    ?}
    };

    14、用JAVA實現一種排序,JAVA類實現序列化的方法(二種)? 如在COLLECTION框架中,實現比較要實現什么樣的接口?
    答:
    用插入法進行排序代碼如下
    package test;
    import java.util.*;
    class? InsertSort
    {
    ?ArrayList al;
    ?public InsertSort(int num,int mod)
    ?{
    ??al = new ArrayList(num);
    ??Random rand = new Random();
    ??System.out.println("The ArrayList Sort Before:");
    ??for (int i=0;i<num ;i++ )
    ??{
    ???al.add(new Integer(Math.abs(rand.nextInt()) % mod + 1));
    ???System.out.println("al["+i+"]="+al.get(i));
    ??}
    ?}
    ?public void SortIt()
    ?{
    ??Integer tempInt;
    ??int MaxSize=1;
    ??for(int i=1;i<al.size();i++)
    ??{
    ?????? tempInt = (Integer)al.remove(i);
    ????if(tempInt.intValue()>=((Integer)al.get(MaxSize-1)).intValue())
    ????{
    ?????al.add(MaxSize,tempInt);
    ?????MaxSize++;
    ?????System.out.println(al.toString());
    ????} else {
    ?????for (int j=0;j<MaxSize ;j++ )
    ?????{
    ??????if

    (((Integer)al.get(j)).intValue()>=tempInt.intValue())
    ??????{
    ???????al.add(j,tempInt);
    ???????MaxSize++;
    ???????System.out.println(al.toString());
    ???????break;
    ??????}
    ?????}
    ????}
    ??}
    ??System.out.println("The ArrayList Sort After:");
    ??for(int i=0;i<al.size();i++)
    ??{
    ???System.out.println("al["+i+"]="+al.get(i));
    ??}
    ?}
    ?public static void main(String[] args)
    ?{
    ??InsertSort is = new InsertSort(10,100);
    ??is.SortIt();
    ?}
    }
    JAVA類實現序例化的方法是實現java.io.Serializable接口
    Collection框架中實現比較要實現Comparable 接口和 Comparator 接口

    15、編程:編寫一個截取字符串的函數,輸入為一個字符串和字節數,輸出為按字節截取的字符串。 但是要保證漢字不被截半個,如“我ABC”4,應該截為“我AB”,輸入“我ABC漢DEF”,6,應該輸出為“我ABC”而不是“我ABC+漢的半個”。
    答:
    代碼如下:
    package test;

    class? SplitString
    {
    ?String SplitStr;
    ?int SplitByte;
    ?public SplitString(String str,int bytes)
    ?{
    ??SplitStr=str;
    ??SplitByte=bytes;
    ??System.out.println("The String is:'"+SplitStr+"';SplitBytes="+SplitByte);
    ?}
    ?public void SplitIt()
    ?{
    ??int loopCount;
    ??

    loopCount=(SplitStr.length()%SplitByte==0)?(SplitStr.length()/SplitByte):(SplitStr.length()/Split

    Byte+1);
    ??System.out.println("Will Split into "+loopCount);
    ??for (int i=1;i<=loopCount ;i++ )
    ??{
    ???if (i==loopCount){
    ????

    System.out.println(SplitStr.substring((i-1)*SplitByte,SplitStr.length()));
    ???} else {
    ????

    System.out.println(SplitStr.substring((i-1)*SplitByte,(i*SplitByte)));
    ???}
    ??}
    ?}
    ?public static void main(String[] args)
    ?{
    ??SplitString ss = new SplitString("test中dd文dsaf中男大3443n中國43中國人

    0ewldfls=103",4);
    ??ss.SplitIt();
    ?}
    }

    16、JAVA多線程編程。 用JAVA寫一個多線程程序,如寫四個線程,二個加1,二個對一個變量減一,輸出。
    希望大家補上,謝謝

    17、STRING與STRINGBUFFER的區別。
    答:
    STRING的長度是不可變的,STRINGBUFFER的長度是可變的。如果你對字符串中的內容經常進行操作,特別是內容要修改時,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法

    Jsp方面

    1、jsp有哪些內置對象?作用分別是什么?
    答:
    JSP共有以下9種基本內置組件(可與ASP的6種內部組件相對應):
     request 用戶端請求,此請求會包含來自GET/POST請求的參數
    ?? response 網頁傳回用戶端的回應
    ?? pageContext 網頁的屬性是在這里管理
    ?? session 與請求有關的會話期
    ?? application servlet 正在執行的內容
    ?? out 用來傳送回應的輸出
    ?? config servlet的構架部件
    ?? page JSP網頁本身
    ?? exception 針對錯誤網頁,未捕捉的例外

    2、jsp有哪些動作?作用分別是什么?
    答:
    JSP共有以下6種基本動作
    ?? jsp:include:在頁面被請求的時候引入一個文件。
    ?? jsp:useBean:尋找或者實例化一個JavaBean。
    ?? jsp:setProperty:設置JavaBean的屬性。
    ?? jsp:getProperty:輸出某個JavaBean的屬性。
    ?? jsp:forward:把請求轉到一個新的頁面。
    ?? jsp:plugin:根據瀏覽器類型為Java插件生成OBJECT或EMBED標記

    3、JSP中動態INCLUDE與靜態INCLUDE的區別?
    答:
    動態INCLUDE用jsp:include動作實現
    ?? <jsp:include page="included.jsp" flush="true" />它總是會檢查所含文件中的變化,適合用于包含動態頁面,并且可以帶參數
    ?? 靜態INCLUDE用include偽碼實現,定不會檢查所含文件的變化,適用于包含靜態頁面
    ?? <%@ include file="included.htm" %>

    4、兩種跳轉方式分別是什么?有什么區別?
    答:
    有兩種,分別為:
    ? <jsp:include page="included.jsp" flush="true">
    ? <jsp:forward page= "nextpage.jsp"/>
    ? 前者頁面不會轉向include所指的頁面,只是顯示該頁的結果,主頁面還是原來的頁面。執行完后還會回來,相當于函數調用。并且可以帶參數.后者完全轉向新頁面,不會再回來。相當于go to 語句。

    Servlet方面

    1、說一說Servlet的生命周期?
    答:
    servlet有良好的生存期的定義,包括加載和實例化、初始化、處理請求以及服務結束。這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達。

    2、Servlet版本間(忘了問的是哪兩個版本了)的不同?
    希望大家補上,謝謝

    3、JAVA SERVLET API中forward() 與redirect()的區別?
    答:
    前者僅是容器中控制權的轉向,在客戶端瀏覽器地址欄中不會顯示出轉向后的地址;后者則是完全的跳轉,瀏覽器將會得到跳轉的地址,并重新發送請求鏈接。這樣,從瀏覽器的地址欄中可以看到跳轉后的鏈接地址。所以,前者更加高效,在前者可以滿足需要時,盡量使用forward()方法,并且,這樣也有助于隱藏實際的鏈接。在有些情況下,比如,需要跳轉到一個其它服務器上的資源,則必須使用sendRedirect()方法。

    4、Servlet的基本架構
    public class ServletName extends HttpServlet {
    ? public void doPost(HttpServletRequest request, HttpServletResponse response) throws
    ????? ServletException, IOException? {
    ????? }
    ? public void doGet(HttpServletRequest request, HttpServletResponse response) throws
    ????? ServletException, IOException? {
    ????? }
    }

    Jdbc、Jdo方面

    1、可能會讓你寫一段Jdbc連Oracle的程序,并實現數據查詢.
    答:
    程序如下:
    package hello.ant;
    import java.sql.*;
    public class? jdbc
    {
    ?String dbUrl="jdbc:oracle:thin:@127.0.0.1:1521:orcl";
    ?String theUser="admin";
    ?String thePw="manager";
    ?Connection c=null;
    ?Statement conn;
    ?ResultSet rs=null;
    ?public jdbc()
    ?{
    ??try{
    ??? Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
    ????????? c = DriverManager.getConnection(dbUrl,theUser,thePw);
    ??? conn=c.createStatement();
    ??}catch(Exception e){
    ???e.printStackTrace();
    ??}
    ?}
    ?public boolean executeUpdate(String sql)
    ?{
    ???try
    ???{
    ?????conn.executeUpdate(sql);
    ?????return true;
    ???}
    ???catch (SQLException e)
    ???{
    ?????e.printStackTrace();
    ?????return false;
    ???}
    ?}
    ?public ResultSet executeQuery(String sql)
    ?{
    ???rs=null;
    ???try
    ???{
    ?????rs=conn.executeQuery(sql);
    ???}
    ???catch (SQLException e)
    ???{
    ?????e.printStackTrace();
    ???}
    ???return rs;
    ?}
    ?public void close()
    ?{
    ???try
    ???{
    ?????conn.close();
    ?????c.close();
    ???}
    ???catch (Exception e)
    ???{
    ?????e.printStackTrace();
    ???}
    ?}
    ?public static void main(String[] args)
    ?{
    ??ResultSet rs;
    ??jdbc conn = new jdbc();
    ??rs=conn.executeQuery("select * from test");
    ??try{
    ??while (rs.next())
    ??{
    ???System.out.println(rs.getString("id"));
    ???System.out.println(rs.getString("name"));
    ??}
    ??}catch(Exception e)
    ??{
    ???e.printStackTrace();
    ??}
    ?}
    }

    2、Class.forName的作用?為什么要用?
    答:
    調用該訪問返回一個以字符串指定類名的類的對象。

    3、Jdo是什么?
    答:
    JDO 是Java對象持久化的新的規范,為java data object的簡稱,也是一個用于存取某種數據倉庫中的對象的標準化API。JDO提供了透明的對象存儲,因此對開發人員來說,存儲數據對象完全不需要額外的代碼(如JDBC API的使用)。這些繁瑣的例行工作已經轉移到JDO產品提供商身上,使開發人員解脫出來,從而集中時間和精力在業務邏輯上。另外,JDO很靈活,因為它可以在任何數據底層上運行。JDBC只是面向關系數據庫(RDBMS)JDO更通用,提供到任何數據底層的存儲功能,比如關系數據庫、文件、XML以及對象數據庫(ODBMS)等等,使得應用可移植性更強。

    4、在ORACLE大數據量下的分頁解決方法。一般用截取ID方法,還有是三層嵌套方法。
    答:
    一種分頁方法
    <%
    ? int i=1;
    ? int numPages=14;
    ? String pages = request.getParameter("page") ;
    ? int currentPage = 1;
    ? currentPage=(pages==null)?(1):{Integer.parseInt(pages)}
    ? sql = "select count(*) from tables";
    ? ResultSet rs = DBLink.executeQuery(sql) ;
    ? while(rs.next()) i = rs.getInt(1) ;
    ? int intPageCount=1;
    ? intPageCount=(i%numPages==0)?(i/numPages):(i/numPages+1);
    ? int nextPage ;
    ? int upPage;
    ? nextPage = currentPage+1;
    ? if (nextPage>=intPageCount) nextPage=intPageCount;
    ? upPage = currentPage-1;
    ? if (upPage<=1) upPage=1;
    ? rs.close();
    ? sql="select * from tables";
    ? rs=DBLink.executeQuery(sql);
    ? i=0;
    ? while((i<numPages*(currentPage-1))&&rs.next()){i++;}
    %>
    //輸出內容
    //輸出翻頁連接
    合計:<%=currentPage%>/<%=intPageCount%><a href="List.jsp?page=1">第一頁</a><a

    href="List.jsp?page=<%=upPage%>">上一頁</a>
    <%
    ? for(int j=1;j<=intPageCount;j++){
    ? if(currentPage!=j){
    %>
    ? <a href="list.jsp?page=<%=j%>">[<%=j%>]</a>
    <%
    ? }else{
    ? out.println(j);
    ? }
    ? }
    %>
    <a href="List.jsp?page=<%=nextPage%>">下一頁</a><a href="List.jsp?page=<%=intPageCount%>">最后頁

    </a>


    Xml方面

    1、xml有哪些解析技術?區別是什么?
    答:
    有DOM,SAX,STAX等
    DOM: 處理大型文件時其性能下降的非常厲害。這個問題是由DOM的樹結構所造成的,這種結構占用的內存較多,而且DOM必須在解析文件之前把整個文檔裝入內存, 適合對 XML的隨機訪問SAX:不現于DOM,SAX是事件驅動型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個文件。當遇到像文件開頭,文檔結束,或者標簽開頭與標簽結束時,它會觸發一個事件,用戶通過在其回調事件中寫入處理代碼來處理XML文件,適合對XML的順序訪問
    STAX:Streaming API for XML (StAX)

    2、你在項目中用到了xml技術的哪些方面?如何實現的?
    答:
    用到了數據存貯,信息配置兩方面。在做數據交換平臺時,將不能數據源的數據組裝成XML文件,然后將XML文件壓縮打包加密后通過網絡傳送給接收者,接收解密與解壓縮后再同XML文件中還原相關信息進行處理。在做軟件配置時,利用XML可以很方便的進行,軟件的各種配置參數都存貯在XML文件中。

    3、用jdom解析xml文件時如何解決中文問題?如何解析?
    答:
    看如下代碼,用編碼方式加以解決
    package test;
    import java.io.*;
    public class DOMTest
    {
    ?private String inFile = "c:\\people.xml";
    ?private String outFile = "c:\\people.xml";?
    ?public static void main(String args[])
    ?{
    ??? ?new DOMTest();
    ??? }
    ?public DOMTest()
    ?{
    ??try
    ???? {?
    ???? ?javax.xml.parsers.DocumentBuilder builder =
    ???? ??

    javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();
    ???? ?org.w3c.dom.Document doc = builder.newDocument();
    ???? ?org.w3c.dom.Element root = doc.createElement("老師");
    ???? ?org.w3c.dom.Element wang = doc.createElement("王");
    ???org.w3c.dom.Element liu = doc.createElement("劉");
    ???? ?wang.appendChild(doc.createTextNode("我是王老師"));
    ???? ?root.appendChild(wang);
    ???? ?doc.appendChild(root);
    ???? ?javax.xml.transform.Transformer transformer =
    ???? ??javax.xml.transform.TransformerFactory.newInstance().newTransformer();
    ???? ?transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "gb2312");
    ???? ?transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");??

    ? ?
    ???? ?transformer.transform(new javax.xml.transform.dom.DOMSource(doc),
    ???? ???????new

    javax.xml.transform.stream.StreamResult(outFile));
    ???? }
    ???? catch (Exception e)
    ???? {
    ???? ?System.out.println (e.getMessage());
    ???? }
    ??? }
    }

    4、編程用JAVA解析XML的方式.
    答:
    用SAX方式解析XML,XML文件如下:
    <?xml version="1.0" encoding="gb2312"?>
    <person>
    ? <name>王小明</name>
    ? <college>信息學院</college>??
    ? <telephone>6258113</telephone>
    ? <notes>男,1955年生,博士,95年調入海南大學</notes>
    ?</person>
    ?事件回調類SAXHandler.java
    ?import java.io.*;
    import java.util.Hashtable;
    import org.xml.sax.*;
    public class SAXHandler extends HandlerBase
    ? {
    ? private Hashtable table = new Hashtable();
    ? private String currentElement = null;
    ? private String currentValue = null;
    ? public void setTable(Hashtable table)
    ??? {
    ??? this.table = table;
    ??? }
    ? public Hashtable getTable()
    ??? {
    ??? return table;
    ??? }
    ? public void startElement(String tag, AttributeList attrs)
    ? throws SAXException
    ??? {
    ??? currentElement = tag;
    ??? }
    ? public void characters(char[] ch, int start, int length)
    ? throws SAXException
    ??? {
    ??? currentValue = new String(ch, start, length);
    ??? }
    ? public void endElement(String name) throws SAXException
    ??? {
    ??? if (currentElement.equals(name))
    ????? table.put(currentElement, currentValue);
    ??? }
    ? }
    JSP內容顯示源碼,SaxXml.jsp:
    <HTML>
    <HEAD>
    <TITLE>剖析XML文件people.xml</TITLE>
    </HEAD>
    <BODY>
    <%@ page errorPage="ErrPage.jsp"
    contentType="text/html;charset=GB2312" %>
    <%@ page import="java.io.*" %>
    <%@ page import="java.util.Hashtable" %>
    <%@ page import="org.w3c.dom.*" %>
    <%@ page import="org.xml.sax.*" %>
    <%@ page import="javax.xml.parsers.SAXParserFactory" %>
    <%@ page import="javax.xml.parsers.SAXParser" %>
    <%@ page import="SAXHandler" %>
    <%
    File file = new File("c:\\people.xml");
    FileReader reader = new FileReader(file);
    Parser parser;
    SAXParserFactory spf = SAXParserFactory.newInstance();
    SAXParser sp = spf.newSAXParser();
    SAXHandler handler = new SAXHandler();
    sp.parse(new InputSource(reader), handler);
    Hashtable hashTable = handler.getTable();
    out.println("<TABLE BORDER=2><CAPTION>教師信息表</CAPTION>");
    out.println("<TR><TD>姓名</TD>" + "<TD>" +
    ? (String)hashTable.get(new String("name")) + "</TD></TR>");
    out.println("<TR><TD>學院</TD>" + "<TD>" +
    ? (String)hashTable.get(new String("college"))+"</TD></TR>");
    out.println("<TR><TD>電話</TD>" + "<TD>" +
    ? (String)hashTable.get(new String("telephone")) + "</TD></TR>");
    out.println("<TR><TD>備注</TD>" + "<TD>" +
    ? (String)hashTable.get(new String("notes")) + "</TD></TR>");
    out.println("</TABLE>");
    %>
    </BODY>
    </HTML>

    EJB方面

    1、EJB2.0有哪些內容?分別用在什么場合? EJB2.0和EJB1.1的區別?
    答:
    規范內容包括Bean提供者,應用程序裝配者,EJB容器,EJB配置工具,EJB服務提供者,系統管理員。這里面,EJB容器是EJB之所以能夠運行的核心。 EJB容器管理著EJB的創建,撤消,激活,去活,與數據庫的連接等等重要的核心工作。JSP,Servlet,EJB,JNDI,JDBC, JMS.....

    2、EJB與JAVA BEAN的區別?
    答:
    Java Bean 是可復用的組件,對Java Bean并沒有嚴格的規范,理論上講,任何一個Java類都可以是一個Bean。但通常情況下,由于Java Bean是被容器所創建(如Tomcat)的,所以Java Bean應具有一個無參的構造器,另外,通常Java Bean還要實現Serializable接口用于實現Bean的持久性。Java Bean實際上相當于微軟COM模型中的本地進程內COM組件,它是不能被跨進程訪問的。Enterprise Java Bean 相當于DCOM,即分布式組件。它是基于Java的遠程方法調用(RMI)技術的,所以EJB可以被遠程訪問(跨進程、跨計算機)。但EJB必須被布署在諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問真正的EJB組件,而是通過其容器訪問。EJB容器是EJB組件的代理, EJB組件由容器所創建和管理。客戶通過容器來訪問真正的EJB組件。

    3、EJB的基本架構
    答:
    一個EJB包括三個部分:
    ? Remote Interface 接口的代碼
    ? package Beans;
    ? import javax.ejb.EJBObject;
    ? import java.rmi.RemoteException;
    ? public interface Add extends EJBObject
    ? {
    ?? //some method declare
    ? }
    ? Home Interface 接口的代碼
    ? package Beans;
    ? import java.rmi.RemoteException;
    ? import jaax.ejb.CreateException;
    ? import javax.ejb.EJBHome;
    ? public interface AddHome extends EJBHome
    ? {
    ??? //some method declare
    ? }
    ? EJB類的代碼
    ? package Beans;
    ? import java.rmi.RemoteException;
    ? import javax.ejb.SessionBean;
    ? import javx.ejb.SessionContext;
    ? public class AddBean Implements SessionBean
    ? {
    ??? //some method declare
    ? }?

    J2EE,MVC方面

    1、MVC的各個部分都有那些技術來實現?如何實現?
    答:
    MVC 是Model-View- Controller的簡寫。"Model" 代表的是應用的業務邏輯(通過JavaBean,EJB組件實現), "View" 是應用的表示面(由JSP頁面產生),"Controller" 是提供應用的處理過程控制(一般是一個Servlet),通過這種設計模型把應用邏輯,處理過程和顯示邏輯分成不同的組件實現。這些組件可以進行交互和重用。

    2、應用服務器與WEB SERVER的區別?
    希望大家補上,謝謝


    3、J2EE是什么?
    答:
    Je22 是Sun公司提出的多層(multi-diered),分布式(distributed),基于組件(component-base)的企業級應用模型 (enterpriese application model).在這樣的一個應用系統中,可按照功能劃分為不同的組件,這些組件又可在不同計算機上,并且處于相應的層次(tier)中。所屬層次包括客戶層(clietn tier)組件,web層和組件,Business層和組件,企業信息系統(EIS)層。

    4、WEB SERVICE名詞解釋。JSWDL開發包的介紹。JAXP、JAXM的解釋。SOAP、UDDI,WSDL解釋。
    答:
    Web Service描述語言WSDL
    SOAP即簡單對象訪問協議(Simple Object Access Protocol),它是用于交換XML編碼信息的輕量級協議。
    UDDI 的目的是為電子商務建立標準;UDDI是一套基于Web的、分布式的、為Web Service提供的、信息注冊中心的實現標準規范,同時也包含一組使企業能將自身提供的Web Service注冊,以使別的企業能夠發現的訪問協議的實現標準。


    5、BS與CS的聯系與區別。
    希望大家補上,謝謝

    6、STRUTS的應用(如STRUTS架構)
    答:
    Struts 是采用Java Servlet/JavaServer Pages技術,開發Web應用程序的開放源碼的framework。采用Struts能開發出基于MVC(Model-View- Controller)設計模式的應用構架。 Struts有如下的主要功能:
    一.包含一個controller servlet,能將用戶的請求發送到相應的Action對象。
    二.JSP自由tag庫,并且在controller servlet中提供關聯支持,幫助開發員創建交互式表單應用。
    三.提供了一系列實用對象:XML處理、通過Java reflection APIs自動處理JavaBeans屬性、國際化的提示和消息。

    設計模式方面

    1、開發中都用到了那些設計模式?用在什么場合?
    答:
    每個模式都描述了一個在我們的環境中不斷出現的問題,然后描述了該問題的解決方案的核心。通過這種方式,你可以無數次地使用那些已有的解決方案,無需在重復相同的工作。主要用到了MVC的設計模式。用來開發JSP/Servlet或者J2EE的相關應用。簡單工廠模式等。


    2、UML方面
    答:
    標準建模語言UML。用例圖,靜態圖(包括類圖、對象圖和包圖),行為圖,交互圖(順序圖,合作圖),實現圖,

    JavaScript方面

    1、如何校驗數字型?
    var re=/^\d{1,8}$|\.\d{1,2}$/;
    var str=document.form1.all(i).value;
    var r=str.match(re);
    if (r==null)
    {
    ?? sign=-4;
    ?? break;
    }
    else{
    ?? document.form1.all(i).value=parseFloat(str);
    }


    CORBA方面

    1、CORBA是什么?用途是什么?
    答:
    CORBA 標準是公共對象請求代理結構(Common Object Request Broker Architecture),由對象管理組織 (Object Management Group,縮寫為 OMG)標準化。它的組成是接口定義語言(IDL), 語言綁定(binding:也譯為聯編)和允許應用程序間互操作的協議。其目的為:
    用不同的程序設計語言書寫
    在不同的進程中運行
    為不同的操作系統開發


    LINUX方面

    1、LINUX下線程,GDI類的解釋。
    答:
    LINUX實現的就是基于核心輕量級進程的"一對一"線程模型,一個線程實體對應一個核心輕量級進程,而線程之間的管理在核外函數庫中實現。
    GDI類為圖像設備編程接口類庫。

    posted @ 2006-12-26 10:51 保爾任 閱讀(243) | 評論 (0)編輯 收藏
    僅列出標題
    共8頁: 上一頁 1 2 3 4 5 6 7 8 下一頁 

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(4)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 美女黄频a美女大全免费皮| 亚洲级αV无码毛片久久精品| 永久黄色免费网站| 人妖系列免费网站观看| 亚洲AV永久无码精品网站在线观看| 亚洲人成影院77777| 亚洲AV日韩AV天堂一区二区三区| 久久久久亚洲?V成人无码| 无码专区一va亚洲v专区在线| 免费大片在线观看网站| 日本特黄特色免费大片| 最好免费观看韩国+日本 | 日本一区二区三区在线视频观看免费| 国产99久久亚洲综合精品| 国产大片免费天天看| 一级成人毛片免费观看| 免费毛片在线看不用播放器 | 国产高清不卡免费在线| 在线看片免费人成视久网| 麻豆国产精品免费视频| 免费观看理论片毛片| 亚洲av无码一区二区三区乱子伦| 亚洲一区二区三区日本久久九| 亚洲福利视频网址| 亚洲国产精品一区二区三区在线观看 | 高清在线亚洲精品国产二区| 亚洲精品91在线| 中国一级特黄高清免费的大片中国一级黄色片| 精品在线免费观看| 8x8x华人永久免费视频| 亚洲美女在线国产| 久久精品国产亚洲AV无码偷窥| 一级女性全黄久久生活片免费| 思思99re66在线精品免费观看| 亚洲成a人一区二区三区| 亚洲不卡中文字幕无码| 亚洲人成电影亚洲人成9999网| 亚洲国产成人99精品激情在线| 男女作爱免费网站| 女人被男人桶得好爽免费视频| 亚洲视频在线观看网址|