webber

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            11 Posts :: 2 Stories :: 3 Comments :: 0 Trackbacks

          *****************web開發的問題匯總********************


          2.      Hibernate優化問題。如何優化數據庫訪問,使程序訪問數據庫更優化。

           初用HIBERNATE的人也許都遇到過性能問題,實現同一功能,用HIBERNATE與用JDBC性能相差十幾倍很正常,如果不及早調整,很可能影響整個項目的進度。

            大體上,對于HIBERNATE性能調優的主要考慮點如下:

            * 數據庫設計調整

            * HQL優化

            *  API的正確使用(如根據不同的業務類型選用不同的集合及查詢API)

            * 主配置參數(日志,查詢緩存,fetch_size, batch_size等)

          * 映射文件優化(ID生成策略,二級緩存,延遲加載,關聯優化)

            * 一級緩存的管理

            * 針對二級緩存,還有許多特有的策略

            * 事務控制策略。

            1、 數據庫設計

            a) 降低關聯的復雜性

            b) 盡量不使用聯合主鍵

            c) ID的生成機制,不同的數據庫所提供的機制并不完全一樣

            d) 適當的冗余數據,不過分追求高范式

            2、 HQL優化

            HQL如果拋開它同HIBERNATE本身一些緩存機制的關聯,HQL的優化技巧同普通的SQL優化技巧一樣,可以很容易在網上找到一些經驗之談。

            3、 主配置

            a) 查詢緩存,同下面講的緩存不太一樣,它是針對HQL語句的緩存,即完全一樣的語句再次執行時可以利用緩存數據。但是,查詢緩存在一個交易系統(數據變更頻繁,查詢條件相同的機率并不大)中可能會起反作用:它會白白耗費大量的系統資源但卻難以派上用場。

            b) fetch_size,同JDBC的相關參數作用類似,參數并不是越大越好,而應根據業務特征去設置

            c) batch_size同上。

            d) 生產系統中,切記要關掉SQL語句打印。

            4、 緩存

            a) 數據庫級緩存:這級緩存是最高效和安全的,但不同的數據庫可管理的層次并不一樣,比如,在ORACLE中,可以在建表時指定將整個表置于緩存當中。

            b) SESSION緩存:在一個HIBERNATE SESSION有效,這級緩存的可干預性不強,大多于HIBERNATE自動管理,但它提供清除緩存的方法,這在大批量增加/更新操作是有效的。比如,同時增加十萬條記錄,按常規方式進行,很可能會發現OutofMemeroy的異常,這時可能需要手動清除這一級緩存:Session.evict以及Session.clear

            c) 應用緩存:在一個SESSIONFACTORY中有效,因此也是優化的重中之重,因此,各類策略也考慮的較多,在將數據放入這一級緩存之前,需要考慮一些前提條件:

            i. 數據不會被第三方修改(比如,是否有另一個應用也在修改這些數據?)

            ii. 數據不會太大

            iii. 數據不會頻繁更新(否則使用CACHE可能適得其反)

            iv. 數據會被頻繁查詢

            v. 數據不是關鍵數據(如涉及錢,安全等方面的問題)。

            緩存有幾種形式,可以在映射文件中配置:read-only(只讀,適用于很少變更的靜態數據/歷史數據),nonstrict-read-write,read-write(比較普遍的形式,效率一般),transactional(JTA中,且支持的緩存產品較少)

            d) 分布式緩存:同c)的配置一樣,只是緩存產品的選用不同,在目前的HIBERNATE中可供選擇的不多,oscache, jboss cache,目前的大多數項目,對它們的用于集群的使用(特別是關鍵交易系統)都持保守態度。在集群環境中,只利用數據庫級的緩存是最安全的。

            5、 延遲加載

            a) 實體延遲加載:通過使用動態代理實現

            b) 集合延遲加載:通過實現自有的SET/LIST,HIBERNATE提供了這方面的支持

            c) 屬性延遲加載:

            6、 方法選用

            a) 完成同樣一件事,HIBERNATE提供了可供選擇的一些方式,但具體使用什么方式,可能用性能/代碼都會有影響。顯示,一次返回十萬條記錄(List/Set/Bag/Map等)進行處理,很可能導致內存不夠的問題,而如果用基于游標(ScrollableResults)或Iterator的結果集,則不存在這樣的問題。

            b) Session的load/get方法,前者會使用二級緩存,而后者則不使用。

            c) Query和list/iterator,如果去仔細研究一下它們,你可能會發現很多有意思的情況,二者主要區別(如果使用了Spring,在HibernateTemplate中對應find,iterator方法):

            i. list只能利用查詢緩存(但在交易系統中查詢緩存作用不大),無法利用二級緩存中的單個實體,但list查出的對象會寫入二級緩存,但它一般只生成較少的執行SQL語句,很多情況就是一條(無關聯)。

            ii. iterator則可以利用二級緩存,對于一條查詢語句,它會先從數據庫中找出所有符合條件的記錄的ID,再通過ID去緩存找,對于緩存中沒有的記錄,再構造語句從數據庫中查出,因此很容易知道,如果緩存中沒有任何符合條件的記錄,使用iterator會產生N+1條SQL語句(N為符合條件的記錄數)

            iii. 通過iterator,配合緩存管理API,在海量數據查詢中可以很好的解決內存問題,如:

            while(it.hasNext()){

            YouObject object = (YouObject)it.next();

            session.evict(youObject);

           sessionFactory.evice(YouObject.class, youObject.getId());

            }

            如果用list方法,很可能就出OutofMemory錯誤了。

            iv. 通過上面的說明,我想你應該知道如何去使用這兩個方法了。

            7、 集合的選用

            在HIBERNATE 3.1文檔的“19.5. Understanding Collection performance”中有詳細的說明。

            8、 事務控制

            事務方面對性能有影響的主要包括:事務方式的選用,事務隔離級別以及鎖的選用

            a) 事務方式選用:如果不涉及多個事務管理器事務的話,不需要使用JTA,只有JDBC的事務控制就可以。

            b) 事務隔離級別:參見標準的SQL事務隔離級別

            c) 鎖的選用:悲觀鎖(一般由具體的事務管理器實現),對于長事務效率低,但安全。樂觀鎖(一般在應用級別實現),如在HIBERNATE中可以定義VERSION字段,顯然,如果有多個應用操作數據,且這些應用不是用同一種樂觀鎖機制,則樂觀鎖會失效。因此,針對不同的數據應有不同的策略,同前面許多情況一樣,很多時候我們是在效率與安全/準確性上找一個平衡點,無論如何,優化都不是一個純技術的問題,你應該對你的應用和業務特征有足夠的了解。

            9、 批量操作

            即使是使用JDBC,在進行大批數據更新時,BATCH與不使用BATCH有效率上也有很大的差別。我們可以通過設置batch_size來讓其支持批量操作。

            舉個例子,要批量刪除某表中的對象,如“delete Account”,打出來的語句,會發現HIBERNATE找出了所有ACCOUNT的ID,再進行刪除,這主要是為了維護二級緩存,這樣效率肯定高不了,在后續的版本中增加了bulk delete/update,但這也無法解決緩存的維護問題。也就是說,由于有了二級緩存的維護問題,HIBERNATE的批量操作效率并不盡如人意!

          3.      網站是動態的,需要頻繁訪問數據庫,如何提高訪問速度,減少服務器壓力?

          提供JDBC數據庫鏈接池共享,大大降低數據庫壓力;

          智能動態HTML,大大減少網絡數據流量;

          海量數據優化,大大提高登錄和訪問速度;

          用戶界面和數據緩存,大大提高登錄速度;

          多層次體系結構,支持多個應用程序服務器并行,大大提高系統伸縮性,并發訪問用戶數目和數據安全性

          4.      搜索引擎優化,如何提高網站排名。優化有哪些具體技術措施?

             網站結構設計中面向搜索引擎的優化注意事項包括:

          1)鏈接引用的重要性

          a.以量取勝:不一定加入傳統門戶網站的分類目錄才是網站推廣,來自其他網站的任何反相鏈接都是有用的

          b. 以質取勝:被PageRank高的網站引用能更快地提高PageRank

          c. 了解搜索引擎的"價值觀":不要通過Link Farm提高自身的站點排名:Google會懲罰那些主動鏈接到Link Farm站點以提高自身排名站點,相應站點的頁面將不會被收入到索引中。但如果你的頁面被別的Link Farm鏈接了也不必擔心,因為這種被動的鏈接是不會被懲罰的。

          d. 不要吝嗇給其他網站的鏈接:如果一個網頁只有大量的進入鏈接,而缺乏導出鏈接,也會被搜索引擎認為是沒有價值的站點。

          2)如何突出關鍵詞:網頁標題、主題的設計

          a.Theme Engine正在逐步超過PR,成為結果排序中更主要的因素

          b.不要空著標題:空著<title></title>無異于浪費了最有價值的一塊陣地

          c. 標題長度和內容:不要過長,一般在40個字(80個字節)以內,并充分突出關鍵詞的比重

          d. 如果網頁很多的話,盡量使用不同的網頁標題,爭取讓自己網站的內容更多的進入搜索引擎索引范圍

          e. 除了<title></title>外,還可以用<h1></h1>標題行突出內容主題, 加強標題的效果

          3)頁面及站點結構設計注意事項

          a. 靜態鏈接: 大部分搜索引擎都認為靜態鏈接的網頁是優質網頁,Google在優先抓取索引的網頁中70%以上是不帶參數鏈接的靜態網頁。而且即使同樣的內容,靜態網頁也 會比動態網頁權重高

          b. 能夠進入Google索引的頁面數量越多越好

          c. 網站目錄結構要扁平,因為每深一級目錄,PAGERANK降低1-2個檔次。假設首頁是3,其子可能目錄就是1了,更深可能就無法列入評級范圍了。

          d. 表現和內容的分離:“綠色”網頁

          網頁中的javascript和css盡可能和網頁分離,一方面提高代碼重用度(也方便頁面緩存),另外一方面,由于有效內容占網頁長度的百分比高,也能提高相關關鍵詞在頁面中的比重也增加了。總之,應該鼓勵遵循w3c的規范,使用更規范的XHTML和XML作為顯示格式便于內容更長時間的保存。

          e. 讓所有的頁面都有能夠快速入口:站點地圖, 方便網頁爬蟲(spider)快速遍歷網站所有需要發布的內容。如果首頁就是用Flash或圖片進入的話,無異于將搜索引擎拒之門外,除了UI設計的用戶 友好外,spider friendly也是非常重要的

          f. 保持網站自身的健康:經常利用壞 鏈檢查工具檢查網站中是否有死鏈

          g. 保持網頁內容/鏈接的穩定性和持久性:在搜索引擎索引中網頁存在的歷史也是一個比較重要的因素,而且歷史比較久的網頁被鏈接的幾率越高。為了 保證自己網頁能夠被比較持久的被其他網站的頁面引用,如果自己網頁中有鏈接更新時,最好能保留舊的頁面并做好鏈接轉向,以保持內容的連續性。

          h. 文件類型因素:Google有對PDF, Word(Power Point, Excel), PS文檔的索引能力,由于這種文檔的內容比一般的HTML經過了更多的整理,學術價值一般比較高,所以這些類型的文檔天生就比一般的HTML類型的文檔 PageRank要高。因此,對于比較重要的文檔:技術白皮書,FAQ,安裝文檔等建議使用PDF PS等高級格式存取,這樣在搜索結果中也能獲得比較靠前的位zhi點訪問統計的重要性等;,的設計 

          4)以及站點訪問統計的重要性等

          5)Google的站點設計指南

          1.Make a site with a clear hierarchy and text links. Every page should be reachable from at least one static text link.  讓網站有著清晰的結構和文本鏈接,所有的頁面至少要有一個靜態文本鏈接入口

          批注:盡量不要用圖片和JAVASCRIPT

          2.Offer a site map to your users with links that point to the important parts of your site. If the site map is larger than 100 or so links, you may want to break the site map into separate pages.

          為用戶提供一個站點地圖:轉向網站的重要部分。如果站點地圖頁面超過100個鏈接,則需要將頁面分成多個頁面。

          批注:索引頁不要超過100個鏈接:SPIDER只考慮頁面中頭100個鏈接

          3.Create a useful, information-rich site and write pages that clearly and accurately describe your content.

          用一些有用的,信息量豐富的站點,清晰并正確的描述你的信息。

          4.Think about the words users would type to find your pages, and make sure that your site actually includes those words within it.

          想像用戶可能用來找到你的關鍵詞,并保證這些關鍵詞在網站中出現。

          批注:少用“最大”,“最好”之類的形容詞,用用戶最關心的詞,比如:下載,歌星名字,而不是一些抽象名詞。

          5.Try to use text instead of images to display important names, content, or links. The Google crawler doesn't recognize text contained in images.

          盡可能使用文本,而不是圖片顯示重要的名稱,內容和鏈接。GOOGLE的機器人不認識圖片中的文字。

          6.Make sure that your TITLE and ALT tags are descriptive and accurate.

          保證:頁面的TITLE和ALT標記正確的精確描述

          7.Check for broken links and correct HTML.

          檢查壞鏈并修正這些HTML錯誤。

          8.If you decide to use dynamic pages (i.e., the URL contains a '?' character), be aware that not every search engine spider crawls dynamic pages as well as static pages. It helps to keep the parameters short and the number of them small.

          如果你打算使用動態頁面:鏈接中包含"?",必須了解:并非所有的搜索引擎的機器人能想對待靜態頁面一樣對待動態頁面,保持動態頁面的參數盡可能的少也會 很有幫助。

          9.Keep the links on a given page to a reasonable number (fewer than 100).

          讓一個頁面中的鏈接少于100個。

          批注:用lynx -dump http://www.chedong.com/ 可以模擬從robot角度看到的頁面。其最后有鏈接統計

          5.      hibernate對動態查詢的理解,如何應用,并作應用示例。

          定義:

          ?靜態查詢:在編程時已經確定要查詢的字段,這時編寫的HQL或QBC稱為靜態查詢。

          ?動態查詢:在編程時無法確定要查詢的字段,這時編寫的HQL或QBC稱為動態查詢。比如組合查詢時,往往需要查詢的項很多,但不是每個項都必需。

          (HQL適用于靜態查詢,QBC適用于動態查詢)

          以下分別用HQL和QBC實現動態查詢:

          1)下面的程序通過對字符串的拼裝使用HQL語句實現動態查詢:

          Public List findStu(String name, int age){

          StringBuffer queryString= new StringBuffer();

          Boolean conditionFound= false;

          if(name!=null){

          queryString.append(“lower(s.name) like :name”);

          conditionFound= true;

          }if(age!= 0){

          if(conditionFound) queryString.append(“and”);

          queryString.append(“s.age= :age”);

          conditionFound=true;

          }

          String fromClause= conditionFound?”fromStudent s where” : ”fromStudent s”;

          queryString.insert(0,fromClause).append(“order by s.name”);

          Query query=getSession().createQuery(“queryString.toString()”);

          if(name!=null)query.setString(“name”,’%’+name.toLowerCase()+’%’);

          if(age!=0)query.setInteger(“age”,newInteger(age));

          return query.list();

          }

          上面的代碼雖然可以正常工作,但是把簡單的功能實現的相當復雜,維護起來不方便。我們來看一下使用QBC查詢。

          Public List findStu(String name, int age){

          Criteria crit= getSession().createCriteria(Student.class);

          if(name!=null){

          crit.add(Restrictions.like(“name”,name,MatchMode.ANYWHERE));

          }if(age!=0){

          crit.add(Restrictions.eq(“age”,newInteger(age)));

          }

          crit.addOrder(Order.asc(“name”));

          return crit.list();

          }

          6.      Hibernate問題

          ●     a different object with the same identifier value was already associated with the session是什么原因導致的?

          在hibernate中同一個session里面有了兩個相同標識但是是不同實體,當這時運行saveOrUpdate(object)操作的時候就會報這個錯誤。種錯誤經常出現在一對多映射和多對多映射

          在hibernate的開發中,HBM文件中會涉及到n2m的種種關系,但是,只有在出于必要性考慮的時候,才加上cascade="all" ,同時,需小心規避由此引起的程序Exception.

          考慮不周,會導致可能出現的最常見Exception是:

          net.sf.hibernate.NonUniqueObjectException

          a different object with the same identifier value was already associated with the session:......

          解決辦法是:

          1. 去掉引起Exception的associated Class對映HBM中的不必要cascade;

          2. 檢查Exception發生位置的session的使用情況;

          ●     Object references an unsaved transient instance-save the transient instance before flushing是什么原因導致的?

          某個對象的某個屬性是一個實體,在這個實體沒有保存之前就保存這個對象而造成了這個錯誤。

          以下舉個例子說明以下

          Session session = dao.getSession();

          Transaction tx = session.beginTransaction();

          Bo.setBman( form ,man,session);

          Bo.saveChangeTable( man,session); // 把man當作屬性賦給ChangeTable,并保存ChangeTable. 就是這出的錯,

          dao.save(man,session);  // 保存man

          tx.commit();

          ==================== 應該這樣寫:===============

          Session session = dao.getSession();

          Transaction tx = session.beginTransaction();

          Bo.setBman( form ,man,session);

          dao.save(man,session);  // 保存man

          Bo.saveChangeTable( man,session); // 把man當作屬性賦給ChangeTable,并保存ChangeTable

          tx.commit();

          這樣,問題就解決了。

           

          ●     如果修改一個列表中的一個數據,會發現這個數據不穩定,一會是修改后的,一會是修改前的,說出其原因

          因為hibernate利用了緩存技術,sql適時提交,當數據修改以后,數據并不一定及時提交到數據庫,而是放在hibernate的緩存中,當我們察看數據時,可能是提交完的,也可能是沒有提交的,所以就會出現數據的臟讀。

          如何避免使用緩存技術所帶來的臟數據問題呢?

          在設計、實現和測試時,應該清晰定義緩存數據的更新:

          i. 不考慮緩存數據的更新,重啟軟件系統是一種必要的方式;

          ii. 不考慮緩存數據的更新,緩存數據不可能成為臟數據(但在軟件系統中,往往“不可能”會在一次又一次的重構之后變為“可能”);

          iii. 考慮緩存數據的更新,當源數據變化時,實時更新緩存數據。

          ●     對于數據庫自增長來說,在映射文件中主鍵配置,用哪種配置方案最好,最不容易出現問題?

          Hibernate標識生成策略:

          標識符生成器 描述

          increment 適用于代理主鍵。由Hibernate自動以遞增方式生成。

          identity     適用于代理主鍵。由底層數據庫生成標識符。

          sequence  適用于代理主鍵。Hibernate根據底層數據庫的序列生成標識符,這要求底層數據庫支持序列。

          hilo       適用于代理主鍵。Hibernate分局high/low算法生成標識符。

          seqhilo     適用于代理主鍵。使用一個高/低位算法來高效的生成long,short或者int類型的標識符。

          native適用于代理主鍵。根據底層數據庫對自動生成標識符的方式,自動選擇identity、sequence或hilo。

          uuid.hex   適用于代理主鍵。Hibernate采用128位的UUID算法生成標識符。

          uuid.string       適用于代理主鍵。UUID被編碼成一個16字符長的字符串。

          assigned   適用于自然主鍵。由Java應用程序負責生成標識符。

          foreign     適用于代理主鍵。使用另外一個相關聯的對象的標識符。

          就這個問題我認為應該用increment、native都可以

          7.       概括你常用的框架的優缺點。

          1. Struts的優缺點:

          具體來講,Struts的優點有:

          1. 實現MVC模式,結構清晰,使開發者只關注業務邏輯的實現.

          2. 有豐富的tag可以用 ,Struts的標記庫(Taglib),如能靈活動用,則能大大提高開發效率。另外,就目前國內的JSP開發者而言,除了使用JSP自帶的常用標記外,很少開發自己的標記,或許Struts是一個很好的起點。

          3. 頁面導航.頁面導航將是今后的一個發展方向,事實上,這樣做,使系統的脈絡更加清晰。通過一個配置文件,即可把握整個系統各部分之間的聯系,這對于后期的維護有著莫大的好處。尤其是當另一批開發者接手這個項目時,這種優勢體現得更加明顯。

          4. 提供Exception處理機制 .

          5. 數據庫鏈接池管理

          6. 支持I18N

          缺點:

          一、 轉到展示層時,需要配置forward,每一次轉到展示層,相信大多數都是直接轉到jsp,而涉及到轉向,需要配置forward,如果有十個展示層的jsp,需要配置十次struts,而且還不包括有時候目錄、文件變更,需要重新修改forward,注意,每次修改配置之后,要求重新部署整個項目,而tomcate這樣的服務器,還必須重新啟動服務器,如果業務變更復雜頻繁的系統,這樣的操作簡單不可想象。現在就是這樣,幾十上百個人同時在線使用我們的系統,大家可以想象一下,我的煩惱有多大。

          二、 Struts 的Action必需是thread-safe方式,它僅僅允許一個實例去處理所有的請求。所以action用到的所有的資源都必需統一同步,這個就引起了線程安全的問題。

          三、 測試不方便. Struts的每個Action都同Web層耦合在一起,這樣它的測試依賴于Web容器,單元測試也很難實現。不過有一個Junit的擴展工具Struts TestCase可以實現它的單元測試。

          四、 類型的轉換. Struts的FormBean把所有的數據都作為String類型,它可以使用工具Commons-Beanutils進行類型轉化。但它的轉化都是在Class級別,而且轉化的類型是不可配置的。類型轉化時的錯誤信息返回給用戶也是非常困難的。

          五、 對Servlet的依賴性過強. Struts處理Action時必需要依賴ServletRequest 和ServletResponse,所有它擺脫不了Servlet容器。

          六、 前端表達式語言方面.Struts集成了JSTL,所以它主要使用JSTL的表達式語言來獲取數據。可是JSTL的表達式語言在Collection和索引屬性方面處理顯得很弱。

          七、 對Action執行的控制困難. Struts創建一個Action,如果想控制它的執行順序將會非常困難。甚至你要重新去寫Servlet來實現你的這個功能需求。

          八、 對Action 執行前和后的處理. Struts處理Action的時候是基于class的hierarchies,很難在action處理前和后進行操作。

          九、 對事件支持不夠. 在struts中,實際是一個表單Form對應一個Action類(或DispatchAction),換一句話說:在Struts中實際是一個表單只能對應一個事件,struts這種事件方式稱為application event,application event和component event相比是一種粗粒度的事件。

          Struts重要的表單對象ActionForm是一種對象,它代表了一種應用,這個對象中至少包含幾個字段,這些字段是Jsp頁面表單中的input字段,因為一個表單對應一個事件,所以,當我們需要將事件粒度細化到表單中這些字段時,也就是說,一個字段對應一個事件時,單純使用Struts就不太可能,當然通過結合JavaScript也是可以轉彎實現的。

           

                 2.Hibernate的優缺點:

          Hibernate是一個開放源代碼的對象關系映射框架,它對JDBC進行了非常輕量級的對象封裝,使得Java程序員可以隨心所欲的使用對象編程思維來操縱數據庫。

          Hibernate可以應用在任何使用JDBC的場合,既可以在Java的客戶端程序實用,也可以在Servlet/JSP的Web應用中使用,最具革命意義的是,Hibernate可以在應用EJB的J2EE架構中取代CMP,完成數據持久化的重任。

          大多數開發機構經常采取創建各自獨立的數據持久層。一旦底層的數據結構發生改變,那么修改應用的其余部分使之適應這種改變的代價將是十分巨大的。Hibernate適時的填補了這一空白,它為Java應用提供了一個易用的、高效率的對象關系映射框架。hibernate是個輕量級的持久性框架,功能卻非常豐富。

          優點:

          a. Hibernate 使用 Java 反射機制而不是字節碼增強程序來實現透明性。

          b. Hibernate 的性能非常好,因為它是個輕量級框架。映射的靈活性很出色。

          c. 它支持各種關系數據庫,從一對一到多對多的各種復雜關系。

          缺點:它限制您所使用的對象模型。(例如,一個持久性類不能映射到多個表)其獨有的界面和可憐的市場份額也讓人不安,盡管如此,Hibernate 還是以其強大的發展動力減輕了這些風險。其他的開源持久性框架也有一些,不過都沒有 Hibernate 這樣有市場沖擊力。

          3. Spring框架的優缺點

          它是一個開源的項目,而且目前非常活躍;它基于IoC(Inversion of Control,反向控制)和AOP的構架多層j2ee系統的框架,但它不強迫你必須在每一層中必須使用Spring,因為它模塊化的很好,允許你根據自己的需要選擇使用它的某一個模塊;它實現了很優雅的MVC,對不同的數據訪問技術提供了統一的接口,采用IoC使得可以很容易的實現bean的裝配,提供了簡潔的AOP并據此實現Transcation Managment,等等

          優點

             a. Spring能有效地組織你的中間層對象,不管你是否選擇使用了EJB。如果你僅僅使用了Struts或其他為J2EE的 API特制的framework,Spring致力于解決剩下的問題。

             b. Spring能消除在許多工程中常見的對Singleton的過多使用。根據我的經驗,這是一個很大的問題,它降低了系統的可測試性和面向對象的程度。

             c. 通過一種在不同應用程序和項目間一致的方法來處理配置文件,Spring能消除各種各樣自定義格式的屬性文件的需要。曾經對某個類要尋找的是哪個魔法般的屬性項或系統屬性感到不解,為此不得不去讀Javadoc甚至源編碼?有了Spring,你僅僅需要看看類的JavaBean屬性。Inversion of Control的使用(在下面討論)幫助完成了這種簡化。

            d.  通過把對接口編程而不是對類編程的代價幾乎減少到沒有,Spring能夠促進養成好的編程習慣。

            e. Spring被設計為讓使用它創建的應用盡可能少的依賴于他的APIs。在Spring應用中的大多數業務對象沒有依賴于Spring。

            f. 使用Spring構建的應用程序易于單元測試。

            g.  Spring能使EJB的使用成為一個實現選擇,而不是應用架構的必然選擇。你能選擇用POJOs或local EJBs來實現業務接口,卻不會影響調用代碼。

            h. Spring幫助你解決許多問題而無需使用EJB。Spring能提供一種EJB的替換物,它們適用于許多web應用。例如,Spring能使用AOP提供聲明性事務管理而不通過EJB容器,如果你僅僅需要與單個數據庫打交道,甚至不需要一個JTA實現。

            i.  Spring為數據存取提供了一個一致的框架,不論是使用的是JDBC還是O/R mapping產品

          Spring確實使你能通過最簡單可行的解決辦法來解決你的問題。而這是有有很大價值的。

          缺點:使用人數不多、jsp中要寫很多代碼、控制器過于靈活,缺少一個公用控制器

          8.       是否了解設計模式,將幾種常用的設計模式的思想、并舉例。

          創建模式:

          Factory、Prototype(原型)、Builder、Singleton

          結構模式:

          Facade(外觀)、Proxy(代理)、Adapter(適配器)、Composite(組合)、Decorator(油漆工)、Bridge、Flyweight(享元)

          行為模式:

          Template、Memento(備忘機制)、Observer、Chain of Responsibility(職責鏈)、Command、State、Strategy(策略)、Mediator(中介者)、Interdivter(解釋器)、Visitor

          9.       頁面重復刷新,如何解決?客戶的行為是無法控制的,那如何控制客戶的重復刷新導致的重復提交。

          Jsp防止頁面刷新表單自提交重復提交思路:

          1. 提交后禁用提交按鈕(大部分人都是這樣做的)

          2. 用javascript實現

          10.   如何精確記錄同時在線人數

             我們可以利用Servlet規范中定義的事件監聽器(Listener)來解決這個問題,實現更準確的在線人數統計功能。對每一個正在訪問的用戶,J2EE應用服務器會為其建立一個對應的HttpSession對象。當一個瀏覽器第一次訪問網站的時候,J2EE應用服務器會新建一個HttpSession對象,并觸發HttpSession創建事件,如果注冊了HttpSessionListener事件監聽器,則會調用HttpSessionListener事件監聽器的sessionCreated方法。相反,當這個瀏覽器訪問結束超時的時候,J2EE應用服務器會銷毀相應的HttpSession對象,觸發HttpSession銷毀事件,同時調用所注冊HttpSessionListener事件監聽器的sessionDestroyed方法。

            可見,對應于一個用戶訪問的開始和結束,相應的有sessionCreated方法和sessionDestroyed方法執行。這樣,我們只需要在HttpSessionListener實現類的sessionCreated方法中讓計數器加1,在sessionDestroyed方法中讓計數器減1,就輕松實現了網站在線人數的統計功能。

            下面就是利用HttpSessionListener實現在線人數統計的一個例子,這個例子已經在中創軟件的J2EE應用服務器InforWeb中測試通過。

            首先,編寫一個簡單的計數器,代碼如下:

          package gongfei.cmc.articles.onlinecounter;

          public class OnlineCounter {

              private static long online = 0;    

              public static long getOnline() {

                  return online;

              }    

              public static void raise(){

                  online++;

              } 

              public static void reduce(){

                  online--;

             }

          }

            然后,編寫HttpSessionListener實現類,在這個實現類的sessionCreated方法中調用OnlineCounter的raise方法,在sessionDestroyed方法中調用OnlineCounter的reduce方法,代碼如下:

          package gongfei.cmc.articles.onlinecounter;

          import javax.servlet.http.HttpSessionEvent;

          import javax.servlet.http.HttpSessionListener;

          public class OnlineCounterListener implements HttpSessionListener {

              public void sessionCreated(HttpSessionEvent hse) {

                  OnlineCounter.raise();

              }

              public void sessionDestroyed(HttpSessionEvent hse) {

                  OnlineCounter.reduce();

              }

          }

            再然后,把這個HttpSessionListener實現類注冊到網站應用中,也就是在網站應用的web.xml中加入如下內容:

          <web-app>

              ……

              <listener>

                  <listener-class>

                      gongfei.cmc.articles.example.OnlineCounterListener

                  </listener-class>

              </listener>

              ……

          </web-app>

          OK,在線人數統計功能已經實現,只要在JSP頁面中加入下面這樣的腳本就能顯示但前在線人數了:

          <%@ page language="java" pageEncoding="GB2312" %>

          <%@ page language="java" pageEncoding="GB2312" %>

          <%@ page import="gongfei.cmc.articles.onlinecounter.OnlineCounter" %>

          <html>

              <head><title>On Line Counert</title></head>

              <body bgcolor="#FFFFFF">

                  On line:<%=OnlineCounter.getOnline()%>

              </body>

          </html>

          11.   亂碼解決方案。是否遇到過?有哪些?講解具體遇到的情形,并說出你在具體的應用中的解決方案。

          1.JSP輸出中文的亂碼問題

          所謂在jsp輸出中文,即直接在jsp中輸出中文,或者給變量賦中文值再輸出等,這種情況下的亂碼問題往往是因為沒有給jsp頁面制定顯示中文字符的編碼方式,解決辦法如下:

          1)在jsp頁面頭部加上語句<%@ page contentType="text/html;charset=utf-8"%>(在Servlet中使用httpServletResponse.setContentType("text/html;charset=utf-8"),最好同時在jsp頁面的head部分加上<meta http-equiv="Content-Type" content="text/html;charset="utf-8">

          2)在每次要輸出中文的地方主動轉換編碼方式,比如要在頁面中輸入“中文”二字,就可以用以下的方法:

          <%

             String str="中文";

             byte[] tmpbyte=str.getBytes("ISO8859_1");

             str=new String(tmpbyte);

             out.println(str);

          %>

          對于以上這兩種方法,顯然第一種方法更通用一點,只需要在一個頁面中添加一次代碼即可;而對于第二種方法,在每個需要輸出中文的地方都需要轉碼,如果這樣的地方很多,這將是一個繁重的工作。

          2.獲取表單提交的數據時的中文亂碼問題

          在沒有加任何其他處理之前,用request.getParameter("paramName")獲取表單提交中的數據,且表單數據中含有中文時,返回的字符串會呈現亂碼。出現這種問題的原因是Tomcat的j2ee實現對表單提交,即以POST方式提交的參數采用默認的ISO-8859-1來處理。

          解決此問題的辦法有兩個:

          1)不修改其他配置,只是在將表單中的中文數據區出來后再轉換編碼,方法如語句 String str=request.getParameter("chStr");String str = new String(str.getBytes("ISO-8859-1"),"UTF-8");但這種方法只是從一個局部來考慮問題,如果這樣的情況很多,就要寫很多次,勢必加大工作量。

          2)讓對所有頁面的請求都通過一個Filter,將處理字符集設置為utf-8(根據自己需要也可以設置成其他的,如gb2312,gbk)。具體做法參考Tomcat的webapps/servlet-exemples目錄有一個完整的例子,也可以參考其中web.xml和SetCharacterEncodingFilter的配置.

          3.URL中的中文問題

          對于直接通過在url中傳遞中文參數,如http://localhost:8080/a.jsp?str="中文"這樣的get請求,在服務器端用request.getParameter("name")時返回的往往是亂碼。按照以上的做法設置Filter沒有用,用request.setCharacterEncoding("utf-8")的方式,仍然不管用。造成這種結果的原因是Tomcat中以get方式提交的請求對query-string處理時采用了和post方法不一樣的處理方式。

          解決這個問題的方法是是打開Tomcat安裝目錄下的/conf/server.xml文件,找到Connector塊,往其中添加URLEncoding="utf-8"/>

          4.數據庫訪問時的亂碼問題

          數據庫中所有表的編碼方式和jsp中的使用的編碼要保持一致,這樣做的目的可以減少不必要的編碼轉換問題.另外,在使用jdbc連接MySQL數據庫時,連接字符串寫成如下形式可以避免一些中文問題:

          jdbc://mysql://hostname:port/DBname?user=username&password=pwd&useUnicode=true&character Encoding=utf-8

          如果是以數據源的方式連接數據庫,配置文件中使用:

          <parameter>

             <name>url</name>

             <value>jdbc:mysql://hostname:port/DBname?&useUnicode=true&characterEncoding=utf-8

             </value>

          </parameter>

          但是如果使用一個已經存在的數據庫,數據庫的編碼方式為ISO-8859-1,而Web應用中使用的utf-8,且數據庫已經有很多重要的信息,因此不能通過更改數據庫的編碼方式來解決。這個時候,在往數據庫中寫數據時,一定要在jdbc連接字符串中加入“useUnicode=true&characterEncoding=ISO-8859-1”,這樣可以順利的王數據庫寫入正常的數據。但是,在將數據讀出數據庫時,亂碼又會出現,這個時候就應該在數據取出時對其轉碼,可以將轉碼功能寫為一個函數,具體實現如下:

          public String charConvert(String src){

          String result=null;

          if(src!=null){

            try{

             result=new String(src.getBytes("ISO-8859-1"),"UTF-8");

            }catch(Exception e){

             result=null;

            }

          }

          return result;

          }

          于是,在數據庫讀出數據過后調用charConvert(rs.getString("colName"));這樣就可以正常的顯示數據庫中的中文數據了。

          posted on 2010-01-13 15:26 webber 閱讀(365) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 正蓝旗| 衡东县| 青州市| 望奎县| 济宁市| 昌黎县| 潜江市| 千阳县| 连江县| 峡江县| 汤阴县| 汉阴县| 辽源市| 濮阳市| 宁乡县| 田阳县| 工布江达县| 南靖县| 尚志市| 乌拉特前旗| 常宁市| 平陆县| 河间市| 于田县| 涟源市| 固镇县| 沙河市| 红原县| 庆安县| 剑阁县| 凉城县| 玉屏| 井冈山市| 哈巴河县| 郸城县| 宝鸡市| 安宁市| 望都县| 桦川县| 绥化市| 东宁县|