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

          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. 得到某個類的靜態(tài)屬性

          ?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) :這里和上面有些不同,因為該屬性是靜態(tài)的,所以直接從類的Class里取。


          3. 執(zhí)行某對象的方法

          ?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行:配置參數(shù)的Class數(shù)組,作為尋找Method的條件。

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

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


          4. 執(zhí)行某個類的靜態(tài)方法

          ?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的一個參數(shù)是null,因為這是靜態(tài)方法,不需要借助實例運行。



          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?}


          這里說的方法是執(zhí)行帶參數(shù)的構(gòu)造函數(shù)來新建實例的方法。如果不需要參數(shù),可以直接使用newoneClass.newInstance()來實現(xiàn)。

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

          第5~第9行:得到參數(shù)的Class數(shù)組。

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

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


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

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



          7. 得到數(shù)組中的某個元素
          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;
          ????}

          ????
          /**
          ?????*?得到某類的靜態(tài)公共屬性
          ?????*
          ?????*?
          @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;
          ????}


          ????
          /**
          ?????*?執(zhí)行某對象方法
          ?????*
          ?????*?
          @param?owner
          ?????*????????????對象
          ?????*?
          @param?methodName
          ?????*????????????方法名
          ?????*?
          @param?args
          ?????*????????????參數(shù)
          ?????*?
          @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);
          ????}


          ??????
          /**
          ?????*?執(zhí)行某類的靜態(tài)方法
          ?????*
          ?????*?
          @param?className
          ?????*????????????類名
          ?????*?
          @param?methodName
          ?????*????????????方法名
          ?????*?
          @param?args
          ?????*????????????參數(shù)數(shù)組
          ?????*?
          @return?執(zhí)行方法返回的結(jié)果
          ?????*?
          @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
          ?????*????????????構(gòu)造函數(shù)的參數(shù)
          ?????*?
          @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);
          ????}
          ????
          ????
          /**
          ?????*?得到數(shù)組中的某個元素
          ?????*?
          @param?array?數(shù)組
          ?????*?
          @param?index?索引
          ?????*?
          @return?返回指定數(shù)組對象中索引組件的值
          ?????
          */
          ????
          public?Object?getByArray(Object?array,?int?index)?{
          ????????
          return?Array.get(array,index);
          ????}
          }
          ?
          posted @ 2007-01-12 10:03 保爾任 閱讀(525) | 評論 (2)編輯 收藏

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

          [C/C++/VC]

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

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

          URI(Uniform Resoure Identifier:統(tǒng)一資源標(biāo)識符),URL(Uniform Resoure Location:統(tǒng)一資源定位器),URN(Uniform Resource Name統(tǒng)一資源

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

          URI、URL和URN是識別、定位和命名互聯(lián)網(wǎng)上的資源的標(biāo)準(zhǔn)途徑; URL,URN是URI的子集.

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

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

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

          源不在存在或不再使用。

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

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

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

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

          的名字空間的標(biāo)識符--一組相關(guān)的名稱)開頭,語法如下:

          [scheme:] scheme-specific-part

          URI以scheme和冒號開頭。Scheme用大寫/小寫字母開頭,后面為空或者跟著更多的大寫/小寫字母、數(shù)字、加號、減號和點號。冒號把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看作是以某種方

          式引用某種資源,而這種方式對標(biāo)識符出現(xiàn)的環(huán)境沒有依賴。   

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

          開始的URI。

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

          文件系統(tǒng)作類比,相對的URI類似于從當(dāng)前目錄開始的文件路徑。

          URI:

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

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

          URL:

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

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


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


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

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

          統(tǒng)一資源引用符"等。

          ?

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

            1、中文問題的來源

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

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

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

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

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

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

            2、JAVA編碼轉(zhuǎn)換的詳細過程

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

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

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

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

          ??? 第一步,我們在中文win2k中用編輯軟件如記事本編寫一個Java源程序文件(包括以上五類JAVA 程序),程序文件在保存時默認采用了操作系統(tǒng)默認支持GBK編碼格式(操作系統(tǒng)默認支持的格式為file.encoding格式)形成了一個.java文件,也即,java程序在被編譯前,我們的JAVA源程序文件是采用操作系統(tǒng)默認支持的file.encoding編碼格式保存的,java源程序中含有中文信息字符和英文程序代碼;要查看系統(tǒng)的file.encoding參數(shù),可以用以下代碼:
            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參數(shù)指定我們的 JAVA源程序的編碼格式,則javac.exe首先獲得我們操作系統(tǒng)默認采用的編碼格式,也即在編譯java程序時,若我們不指定源程序文件的編碼格式,JDK首先獲得操作系統(tǒng)的file.encoding參數(shù)(它保存的就是操作系統(tǒng)默認的編碼格式,如WIN2k,它的值為GBK),然后JDK就把我們的java源程序從file.encoding編碼格式轉(zhuǎn)化為JAVA內(nèi)部默認的 UNICODE格式放入內(nèi)存中。然后,javac把轉(zhuǎn)換后的unicode格式的文件進行編譯成.class類文件,此時.class文件是 UNICODE編碼的,它暫放在內(nèi)存中,緊接著,JDK將此以UNICODE編碼的編譯后的class文件保存到我們的操作系統(tǒng)中形成我們見到的. class文件。對我們來說,我們最終獲得的.class文件是內(nèi)容以UNICODE編碼格式保存的類文件,它內(nèi)部包含我們源程序中的中文字符串,只不過此時它己經(jīng)由file.encoding格式轉(zhuǎn)化為UNICODE格式了。

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

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

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

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

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

          圖1

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

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

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

          圖2


          ??? C、JSP代碼和Servlet類

          ??? 經(jīng)過第二步后,JSP文件也被轉(zhuǎn)化為Servlets類文件,只不過它不像標(biāo)準(zhǔn)的Servlets一校存在于classes目錄中,它存在于WEB容器的臨時目錄中,故這一步中我們也把它做為Servlets來看。

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

          圖3

          D、Java程序和數(shù)據(jù)庫之間

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

          圖4


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

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

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


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

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

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

          ??? 1、 針對直接在console上運行的類
          ??? 對于這種情況,我們建議在程序編寫時,如果需要從用戶端接收用戶的可能含有中文的輸入或含有中文的輸出,程序中應(yīng)該采用字符流來處理輸入和輸出,具體來說,應(yīng)用以下面向字符型節(jié)點流類型:
          ??? 對文件:FileReader,F(xiàn)ileWrieter
          ??????? 其字節(jié)型節(jié)點流類型為:FileInputStream,F(xiàn)ileOutputStream
          ??? 對內(nèi)存(數(shù)組):CharArrayReader,CharArrayWriter
          ??????? 其字節(jié)型節(jié)點流類型為:ByteArrayInputStream,ByteArrayOutputStream
          ??? 對內(nèi)存(字符串):StringReader,StringWriter
          ??? 對管道:PipedReader,PipedWriter
          ??????? 其字節(jié)型節(jié)點流類型為:PipedInputStream,PipedOutputStream
          ??? 同時,應(yīng)該用以下面向字符型處理流來處理輸入和輸出:
          ??? BufferedWriter,BufferedReader
          ??????? 其字節(jié)型的處理流為:BufferedInputeStream,BufferedOutputStream
          ??? InputStreamReader,OutputStreamWriter
          ??? 其字節(jié)型的處理流為:DataInputStream,DataOutputStream
          ??? 其中InputStreamReader和InputStreamWriter用于將字節(jié)流按照指定的字符編碼集轉(zhuǎn)換到字符流,如:
          ??? 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中文測試,這是內(nèi)部硬編碼的串"+"\ntest english character";
          ??? String strin= "";
          ??? BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in,"gb2312")); //設(shè)置輸入接口按中文編碼
          ??? BufferedWriter stdout = new BufferedWriter(new OutputStreamWriter(System.out,"gb2312")); //設(shè)置輸出接口按中文編碼
          ??? stdout.write("請輸入:");
          ??? stdout.flush();
          ??? strin = stdin.readLine();
          ??? stdout.write("這是從用戶輸入的串:"+strin);
          ??? stdout.write(str);
          ??? stdout.flush();
          ??? }}
          ??? 同時,在編譯程序時,我們用以下方式來進行:
          ??? javac -encoding gb2312 Read.java
          ??? 其運行結(jié)果如圖5所示:

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

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


          ??? 3、 針對Servlet類

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

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

          ??? //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"); //設(shè)置輸入編碼格式
          ??? response.setContentType("text/html;charset=GB2312"); //設(shè)置輸出編碼格式
          ??? 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"); //設(shè)置輸入編碼格式
          ??? response.setContentType("text/html;charset=GB2312"); //設(shè)置輸出編碼格式
          ??? 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>
          ??? 其運行結(jié)果如圖6所示:

          ??? 圖6
          ??? 4、 JAVA程序和數(shù)據(jù)庫之間

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

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

          ??? 5、 針對JSP代碼

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

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

          ??? <%@page contentType="text/html; charset=gb2312"%>
          ??? 2、為了讓JSP能正確獲得傳入的參數(shù),我們在JSP源文件頭加入下面一句:
          ??? <%request.setCharacterEncoding("GB2312");%>
          ??? 3、為了讓JSP編譯器能正確地解碼我們的含有中文字符的JSP文件,我們需要在JSP源文件中指定我們的JSP源文件的編碼格式,具體來說,我們在JSP源文件頭上加入下面的一句即可:
          ??? <%@page pageEncoding="GB2312"%>或<%@page pageEncoding="GBK"%>
          ??? 這是JSP規(guī)范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是此程序運行的結(jié)果示意圖:

          ??? 圖7

          ??? 5、總結(jié)

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

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

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

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

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

          目錄:
          一、術(shù)語session
          二、HTTP協(xié)議與狀態(tài)保持
          三、理解cookie機制
          四、理解session機制
          五、理解javax.servlet.http.HttpSession
          六、HttpSession常見問題
          七、跨應(yīng)用程序的session共享
          八、總結(jié)
          參考文檔

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

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

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

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

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

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

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

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

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

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

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

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

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

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

          下面就是一個goolge設(shè)置cookie的響應(yīng)頭的例子
          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的資源時自動向外發(fā)送cookie


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


          IE也可以設(shè)置在接受cookie前詢問


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

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

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

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

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

          另一種技術(shù)叫做表單隱藏字段。就是服務(wù)器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把session id傳遞回服務(wù)器。比如下面的表單
          <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>
          這種技術(shù)現(xiàn)在已較少應(yīng)用,筆者接觸過的很古老的iPlanet6(SunONE應(yīng)用服務(wù)器的前身)就使用了這種技術(shù)。
          實際上這種技術(shù)可以簡單的用對action應(yīng)用URL重寫來代替。

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

          恰恰是由于關(guān)閉瀏覽器不會導(dǎo)致session被刪除,迫使服務(wù)器為seesion設(shè)置了一個失效時間,當(dāng)距離客戶端上一次使用session的時間超過這個失效時間時,服務(wù)器就可以認為客戶端已經(jīng)停止了活動,才會把session刪除以節(jié)省存儲空間。

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

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

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

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

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

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

          關(guān)于session的設(shè)置參考[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869

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


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

          由于session會消耗內(nèi)存資源,因此,如果不打算使用session,應(yīng)該在所有的JSP中關(guān)閉它。

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

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

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

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

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

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

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

          9、為什么在Weblogic Server中改變session的值后要重新調(diào)用一次session.setValue
          做這個動作主要是為了在集群環(huán)境中提示W(wǎng)eblogic Server session中的值發(fā)生了改變,需要向其他服務(wù)器進程復(fù)制新的session值。

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

          七、跨應(yīng)用程序的session共享

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

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

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

          根據(jù)這個特性,我們可以推測Tomcat中session的內(nèi)存結(jié)構(gòu)大致如下。

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

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

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


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

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

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

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

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

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

          值得注意的是這種用法不可移植,因為根據(jù)ServletContext的JavaDoc,應(yīng)用服務(wù)器可以處于安全的原因?qū)τ赾ontext.getContext("/appA");返回空值,以上做法在Weblogic Server 8.1中通過。

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

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

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

          參考文檔:
          [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 保爾任 閱讀(313) | 評論 (0)編輯 收藏

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

          ThreadLocal是什么

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

          ThreadLocal的設(shè)計

          首先看看ThreadLocal的接口:

          Object get() ;

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

          void set(Object value);

          // 設(shè)置當(dāng)前線程的線程局部變量副本的值

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

          protected Object initialValue() { return null; }

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


          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;
          }
          }

          ?


          當(dāng)然,這并不是一個工業(yè)強度的實現(xiàn),但JDK中的ThreadLocal的實現(xiàn)總體思路也類似于此。

          ThreadLocal的使用

          如果希望線程局部變量初始化其它值,那么需要自己實現(xiàn)ThreadLocal的子類并重寫該方法,通常使用一個內(nèi)部匿名類對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的,所以在需要獲取當(dāng)前線程的序號時,簡單地調(diào)用:

          int serial = SerialNum.get();

          即可。

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

          ThreadLocal與其它同步機制的比較

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

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

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

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

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

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

          第三,
          pageEncoding="UTF-8"表示此文件的編碼方式,必須與此文件存儲方式一致(所以eclipse會首選根據(jù)它來存文件),tomcat根據(jù)這個來讀此.jsp文件并編譯為servlet(至于編譯成的.java和.class文件應(yīng)該為tomcat服務(wù)器默認編碼)。
          contentType="text/html;charset=UTF-8"表示當(dāng)服務(wù)器給瀏覽器傳頁面文件時編碼方式為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字符集,當(dāng)瀏覽器打開此頁面后,查看原碼就會發(fā)現(xiàn)源碼為GBK字符集。

          第四,
          request.setCharacterEncoding("UTF-8")是把提交內(nèi)容的字符集設(shè)為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");來轉(zhuǎn)換成你想要的UTF-8編碼方式。但如果每處都加詞句太麻煩,故分post和get兩種方式區(qū)分提交(tomcat5以后分開處理,之前處理方式一樣,即都可以用 request.setCharacterEncoding("UTF-8")方法處理,不過tomcat5以后get提交方法用此語句無效)。
          1,post提交的數(shù)據(jù):
          程序加上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>

          因為規(guī)范要求瀏覽器提交數(shù)據(jù)都要用utf8編碼,所以這里設(shè)置編碼方式為UTF8.

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

          2,get提交的數(shù)據(jù):
          兩種情況:
          a,如果從地址欄直接輸入漢字,則一般編碼為"GBK",需要用
          new String(request.getParameter("something").getBytes("ISO-8859-1"),"GBK")
          取出
          b,如果是頁面超連接連接中帶的漢字,則編碼根據(jù)頁面編碼的不同而不同,如果頁面的
          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取出正確內(nèi)容.
          如果content="text/html; charset=GBK",需用
          new String(request.getParameter("something").getBytes("ISO-8859-1"),"GBK")
          取出,其他情況類似.

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

          第六,連接數(shù)據(jù)庫
          ?

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

          2、mysql里數(shù)據(jù)庫和表也都設(shè)為utf8_unicode_ci

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

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

          Java基礎(chǔ)方面:

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

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

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

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

          5、繼承時候類的執(zhí)行順序問題,一般都是選擇題,問你將會打印出什么?
          答:
          父類:
          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();
          ?}
          }
          輸出結(jié)果:
          C:\>java test.ChildClass
          FatherClass Create
          FatherClass Create
          ChildClass Create

          6、內(nèi)部類的實現(xiàn)方式?
          答:
          示例代碼如下:
          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();
          ?}
          }
          輸出結(jié)果:
          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();
          ?? }
          說明如下:
          一.靜態(tài)內(nèi)部類可以有靜態(tài)成員,而非靜態(tài)內(nèi)部類則不能有靜態(tài)成員。 故 A、B 錯
          二.靜態(tài)內(nèi)部類的非靜態(tài)成員可以訪問外部類的靜態(tài)變量,而不可訪問外部類的非靜態(tài)變量;return d1 出錯。

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

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

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

          9、介紹JAVA中的Collection FrameWork(包括如何寫自己的數(shù)據(jù)結(jié)構(gòu))?
          答:
          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中)可以有自己的部分實現(xiàn),而接口則完全是一個標(biāo)識(同時有多重繼承的功能)。

          13、Java 的通信編程,編程題(或問答),用JAVA SOCKET編程,讀服務(wù)器幾個字符,再寫入本地顯示?
          答:
          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實現(xiàn)一種排序,JAVA類實現(xiàn)序列化的方法(二種)? 如在COLLECTION框架中,實現(xiàn)比較要實現(xiàn)什么樣的接口?
          答:
          用插入法進行排序代碼如下
          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類實現(xiàn)序例化的方法是實現(xiàn)java.io.Serializable接口
          Collection框架中實現(xiàn)比較要實現(xiàn)Comparable 接口和 Comparator 接口

          15、編程:編寫一個截取字符串的函數(shù),輸入為一個字符串和字節(jié)數(shù),輸出為按字節(jié)截取的字符串。 但是要保證漢字不被截半個,如“我ABC”4,應(yīng)該截為“我AB”,輸入“我ABC漢DEF”,6,應(yīng)該輸出為“我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的區(qū)別。
          答:
          STRING的長度是不可變的,STRINGBUFFER的長度是可變的。如果你對字符串中的內(nèi)容經(jīng)常進行操作,特別是內(nèi)容要修改時,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法

          Jsp方面

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

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

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

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

          Servlet方面

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

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

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

          4、Servlet的基本架構(gòu)
          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的程序,并實現(xiàn)數(shù)據(jù)查詢.
          答:
          程序如下:
          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的作用?為什么要用?
          答:
          調(diào)用該訪問返回一個以字符串指定類名的類的對象。

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

          4、在ORACLE大數(shù)據(jù)量下的分頁解決方法。一般用截取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++;}
          %>
          //輸出內(nè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有哪些解析技術(shù)?區(qū)別是什么?
          答:
          有DOM,SAX,STAX等
          DOM: 處理大型文件時其性能下降的非常厲害。這個問題是由DOM的樹結(jié)構(gòu)所造成的,這種結(jié)構(gòu)占用的內(nèi)存較多,而且DOM必須在解析文件之前把整個文檔裝入內(nèi)存, 適合對 XML的隨機訪問SAX:不現(xiàn)于DOM,SAX是事件驅(qū)動型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個文件。當(dāng)遇到像文件開頭,文檔結(jié)束,或者標(biāo)簽開頭與標(biāo)簽結(jié)束時,它會觸發(fā)一個事件,用戶通過在其回調(diào)事件中寫入處理代碼來處理XML文件,適合對XML的順序訪問
          STAX:Streaming API for XML (StAX)

          2、你在項目中用到了xml技術(shù)的哪些方面?如何實現(xiàn)的?
          答:
          用到了數(shù)據(jù)存貯,信息配置兩方面。在做數(shù)據(jù)交換平臺時,將不能數(shù)據(jù)源的數(shù)據(jù)組裝成XML文件,然后將XML文件壓縮打包加密后通過網(wǎng)絡(luò)傳送給接收者,接收解密與解壓縮后再同XML文件中還原相關(guān)信息進行處理。在做軟件配置時,利用XML可以很方便的進行,軟件的各種配置參數(shù)都存貯在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>信息學(xué)院</college>??
          ? <telephone>6258113</telephone>
          ? <notes>男,1955年生,博士,95年調(diào)入海南大學(xué)</notes>
          ?</person>
          ?事件回調(diào)類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內(nèi)容顯示源碼,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>學(xué)院</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有哪些內(nèi)容?分別用在什么場合? EJB2.0和EJB1.1的區(qū)別?
          答:
          規(guī)范內(nèi)容包括Bean提供者,應(yīng)用程序裝配者,EJB容器,EJB配置工具,EJB服務(wù)提供者,系統(tǒng)管理員。這里面,EJB容器是EJB之所以能夠運行的核心。 EJB容器管理著EJB的創(chuàng)建,撤消,激活,去活,與數(shù)據(jù)庫的連接等等重要的核心工作。JSP,Servlet,EJB,JNDI,JDBC, JMS.....

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

          3、EJB的基本架構(gòu)
          答:
          一個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的各個部分都有那些技術(shù)來實現(xiàn)?如何實現(xiàn)?
          答:
          MVC 是Model-View- Controller的簡寫。"Model" 代表的是應(yīng)用的業(yè)務(wù)邏輯(通過JavaBean,EJB組件實現(xiàn)), "View" 是應(yīng)用的表示面(由JSP頁面產(chǎn)生),"Controller" 是提供應(yīng)用的處理過程控制(一般是一個Servlet),通過這種設(shè)計模型把應(yīng)用邏輯,處理過程和顯示邏輯分成不同的組件實現(xiàn)。這些組件可以進行交互和重用。

          2、應(yīng)用服務(wù)器與WEB SERVER的區(qū)別?
          希望大家補上,謝謝


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

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


          5、BS與CS的聯(lián)系與區(qū)別。
          希望大家補上,謝謝

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

          設(shè)計模式方面

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


          2、UML方面
          答:
          標(biāo)準(zhǔn)建模語言UML。用例圖,靜態(tài)圖(包括類圖、對象圖和包圖),行為圖,交互圖(順序圖,合作圖),實現(xiàn)圖,

          JavaScript方面

          1、如何校驗數(shù)字型?
          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 標(biāo)準(zhǔn)是公共對象請求代理結(jié)構(gòu)(Common Object Request Broker Architecture),由對象管理組織 (Object Management Group,縮寫為 OMG)標(biāo)準(zhǔn)化。它的組成是接口定義語言(IDL), 語言綁定(binding:也譯為聯(lián)編)和允許應(yīng)用程序間互操作的協(xié)議。其目的為:
          用不同的程序設(shè)計語言書寫
          在不同的進程中運行
          為不同的操作系統(tǒng)開發(fā)


          LINUX方面

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

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

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

          常用鏈接

          留言簿(4)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 宁乡县| 恭城| 饶河县| 山阴县| 化州市| 康保县| 镶黄旗| 苗栗县| 鄱阳县| 黄梅县| 同江市| 海兴县| 澄迈县| 紫金县| 阿拉善左旗| 徐汇区| 广河县| 政和县| 雷山县| 乌审旗| 巴南区| 库尔勒市| 荥经县| 桓仁| 舒兰市| 茶陵县| 荔浦县| 甘肃省| 陕西省| 巴彦县| 涿鹿县| 四子王旗| 枣强县| 泾源县| 城口县| 屯昌县| 临安市| 清原| 安阳市| 尤溪县| 陇川县|