Spring,hibernate,struts的面試筆試題(含答案)
Spring,hibernate,struts的面試筆試題(含答案)
【分享面試題二】Spring,hibernate,struts的面試筆試題(含答案)
Hibernate工作原理及為什么要用?
原理:
1.讀取并解析配置文件
2.讀取并解析映射信息,創建SessionFactory
3.打開Sesssion
4.創建事務Transation
5.持久化操作
6.提交事務
7.關閉Session
8.關閉SesstionFactory
為什么要用:
1. 對JDBC訪問數據庫的代碼做了封裝,大大簡化了數據訪問層繁瑣的重復性代碼。
2. Hibernate是一個基于JDBC的主流持久化框架,是一個優秀的ORM實現。他很大程度的簡化DAO層的編碼工作
3. hibernate使用Java反射機制,而不是字節碼增強程序來實現透明性。
4. hibernate的性能非常好,因為它是個輕量級框架。映射的靈活性很出色。它支持各種關系數據庫,從一對一到多對多的各種復雜關系。
2. Hibernate是如何延遲加載?
1. Hibernate2延遲加載實現:a)實體對象 b)集合(Collection)
2. Hibernate3 提供了屬性的延遲加載功能
當Hibernate在查詢數據的時候,數據并沒有存在與內存中,當程序真正對數據的操作時,對象才存在與內存中,就實現了延遲加載,他節省了服務器的內存開銷,從而提高了服務器的性能。
3.Hibernate中怎樣實現類之間的關系?(如:一對多、多對多的關系)
類與類之間的關系主要體現在表與表之間的關系進行操作,它們都市對對象進行操作,我們程序中把所有的表與類都映射在一起,它們通過配置文件中的many-to-one、one-to-many、many-to-many、
4. 說下Hibernate的緩存機制
1. 內部緩存存在Hibernate中又叫一級緩存,屬于應用事物級緩存
2. 二級緩存:
a) 應用及緩存
b) 分布式緩存
條件:數據不會被第三方修改、數據大小在可接受范圍、數據更新頻率低、同一數據被系統頻繁使用、非 關鍵數據
c) 第三方緩存的實現
5. Hibernate的查詢方式
Sql、Criteria,object comptosition
Hql:
1、 屬性查詢
2、 參數查詢、命名參數查詢
3、 關聯查詢
4、 分頁查詢
5、 統計函數
6. 如何優化Hibernate?
1.使用雙向一對多關聯,不使用單向一對多
2.靈活使用單向一對多關聯
3.不用一對一,用多對一取代
4.配置對象緩存,不使用集合緩存
5.一對多集合使用Bag,多對多集合使用Set
6. 繼承類使用顯式多態
7. 表字段要少,表關聯不要怕多,有二級緩存撐腰
7. Struts工作機制?為什么要使用Struts?
工作機制:
Struts的工作流程:
在web應用啟動時就會加載初始化ActionServlet,ActionServlet從
struts-config.xml文件中讀取配置信息,把它們存放到各種配置對象
當ActionServlet接收到一個客戶請求時,將執行如下流程.
-(1)檢索和用戶請求匹配的ActionMapping實例,如果不存在,就返回請求路徑無效信息;
-(2)如果ActionForm實例不存在,就創建一個ActionForm對象,把客戶提交的表單數據保存到ActionForm對象中;
-(3)根據配置信息決定是否需要表單驗證.如果需要驗證,就調用ActionForm的validate()方法;
-(4)如果ActionForm的validate()方法返回null或返回一個不包含ActionMessage的ActuibErrors對象, 就表示表單驗證成功;
-(5)ActionServlet根據ActionMapping所包含的映射信息決定將請求轉發給哪個Action,如果相應的 Action實例不存在,就先創建這個實例,然后調用Action的execute()方法;
-(6)Action的execute()方法返回一個ActionForward對象,ActionServlet在把客戶請求轉發給 ActionForward對象指向的JSP組件;
-(7)ActionForward對象指向JSP組件生成動態網頁,返回給客戶;
為什么要用:
JSP、Servlet、JavaBean技術的出現給我們構建強大的企業應用系統提供了可能。但用這些技術構建的系統非常的繁亂,所以在此之上,我們需要一個規則、一個把這些技術組織起來的規則,這就是框架,Struts便應運而生。
基于Struts開發的應用由3類組件構成:控制器組件、模型組件、視圖組件
8. Struts的validate框架是如何驗證的?
在struts配置文件中配置具體的錯誤提示,再在FormBean中的validate()方法具體調用。
9. 說下Struts的設計模式
MVC模式: web應用程序啟動時就會加載并初始化ActionServler。用戶提交表單時,一個配置好的ActionForm對象被創建,并被填入表單相應的數據,ActionServler根據Struts-config.xml文件配置好的設置決定是否需要表單驗證,如果需要就調用ActionForm的Validate()驗證后選擇將請求發送到哪個Action,如果Action不存在,ActionServlet會先創建這個對象,然后調用Action的execute()方法。Execute()從ActionForm對象中獲取數據,完成業務邏輯,返回一個ActionForward對象,ActionServlet再把客戶請求轉發給ActionForward對象指定的jsp組件,ActionForward對象指定的jsp生成動態的網頁,返回給客戶。
10. spring工作機制及為什么要用?
1.spring mvc請所有的請求都提交給DispatcherServlet,它會委托應用系統的其他模塊負責負責對請求進行真正的處理工作。
2.DispatcherServlet查詢一個或多個HandlerMapping,找到處理請求的Controller.
3.DispatcherServlet請請求提交到目標Controller
4.Controller進行業務邏輯處理后,會返回一個ModelAndView
5.Dispathcher查詢一個或多個ViewResolver視圖解析器,找到ModelAndView對象指定的視圖對象
6.視圖對象負責渲染返回給客戶端。
為什么用:
{AOP 讓開發人員可以創建非行為性的關注點,稱為橫切關注點,并將它們插入到應用程序代碼中。使用 AOP 后,公共服務 (比 如日志、持久性、事務等)就可以分解成方面并應用到域對象上,同時不會增加域對象的對象模型的復雜性。
IOC 允許創建一個可以構造對象的應用環境,然后向這些對象傳遞它們的協作對象。正如單詞 倒置 所表明的,IOC 就像反 過來的 JNDI。沒有使用一堆抽象工廠、服務定位器、單元素(singleton)和直接構造(straight construction),每一個對象都是用其協作對象構造的。因此是由容器管理協作對象(collaborator)。
Spring即使一個AOP框架,也是一IOC容器。 Spring 最好的地方是它有助于您替換對象。有了 Spring,只要用 JavaBean 屬性和配置文件加入依賴性(協作對象)。然后可以很容易地在需要時替換具有類似接口的協作對象。}
Spring 框架是一個分層架構,由 7 個定義良好的模塊組成。Spring 模塊構建在核心容器之上,核心容器定義了創建、配置和管理 bean 的方式,如圖 1 所示。
組成 Spring 框架的每個模塊(或組件)都可以單獨存在,或者與其他一個或多個模塊聯合實現。每個模塊的功能如下:
☆ 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要組件是 BeanFactory,它是工廠模式的實現。BeanFactory 使用控制反轉(IOC) 模式將應用程序的配置和依賴性規范與實際的應用程序代碼分開。
☆ Spring 上下文:Spring 上下文是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和調度功能。
☆ Spring AOP:通過配置管理特性,Spring AOP 模塊直接將面向方面的編程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何對象支持 AOP。Spring AOP 模塊為基于 Spring 的應用程序中的對象提供了事務管理服務。通過使用 Spring AOP,不用依賴 EJB 組件,就可以將聲明性事務管理集成到應用程序中。
☆ Spring DAO:JDBC DAO 抽象層提供了有意義的異常層次結構,可用該結構來管理異常處理和不同數據庫供應商拋出的錯誤消息。異常層次結構簡化了錯誤處理,并且極大地降低了需要編寫的異常代碼數量(例如打開和關閉連接)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結構。
☆ Spring ORM:Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的對象關系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有這些都遵從 Spring 的通用事務和 DAO 異常層次結構。
☆ Spring Web 模塊:Web 上下文模塊建立在應用程序上下文模塊之上,為基于 Web 的應用程序提供了上下文。所以,Spring 框架支持與 Jakarta Struts 的集成。Web 模塊還簡化了處理多部分請求以及將請求參數綁定到域對象的工作。
☆ Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程序的 MVC 實現。通過策略接口,MVC 框架變成為高度可配置的,MVC 容納了大量視圖技術,其中包括 JSP、Velocity、Tiles、iText 和 POI。
Spring 框架的功能可以用在任何 J2EE 服務器中,大多數功能也適用于不受管理的環境。Spring 的核心要點是:支持不綁定到特定 J2EE 服務的可重用業務和數據訪問對象。毫無疑問,這樣的對象可以在不同 J2EE 環境 (Web 或 EJB)、獨立應用程序、測試環境之間重用。
IOC 和 AOP
控制反轉模式(也稱作依賴性介入)的基本概念是:不創建對象,但是描述創建它們的方式。在代碼中不直接與對象和服務連接,但在配置文件中描述哪一個組件需要哪一項服務。容器(在 Spring 框架中是 IOC 容器) 負責將這些聯系在一起。
在典型的 IOC 場景中,容器創建了所有對象,并設置必要的屬性將它們連接在一起,決定什么時間調用方法。下表列出了 IOC 的一個實現模式。
Spring 框架的 IOC 容器采用類型 2 和類型3 實現。
面向方面的編程
面向方面的編程,即 AOP,是一種編程技術,它允許程序員對橫切關注點或橫切典型的職責分界線的行為(例如日志和事務管理)進行模塊化。AOP 的核心構造是方面,它將那些影響多個類的行為封裝到可重用的模塊中。
AOP 和 IOC 是補充性的技術,它們都運用模塊化方式解決企業應用程序開發中的復雜問題。在典型的面向對象開發方式中,可能要將日志記錄語句放在所有方法和 Java 類中才能實現日志功能。在 AOP 方式中,可以反過來將日志服務模塊化,并以聲明的方式將它們應用到需要日志的組件上。當然,優勢就是 Java 類不需要知道日志服務的存在,也不需要考慮相關的代碼。所以,用 Spring AOP 編寫的應用程序代碼是松散耦合的。
AOP 的功能完全集成到了 Spring 事務管理、日志和其他各種特性的上下文中。
IOC 容器
Spring 設計的核心是 org.springframework.beans 包,它的設計目標是與 JavaBean 組件一起使用。這個包通常不是由用戶直接使用,而是由服務器將其用作其他多數功能的底層中介。下一個最高級抽象是 BeanFactory 接口,它是工廠設計模式的實現,允許通過名稱創建和檢索對象。BeanFactory 也可以管理對象之間的關系。
BeanFactory 支持兩個對象模型。
□ 單態 模型提供了具有特定名稱的對象的共享實例,可以在查詢時對其進行檢索。Singleton 是默認的也是最常用的對象模型。對于無狀態服務對象很理想。
□ 原型 模型確保每次檢索都會創建單獨的對象。在每個用戶都需要自己的對象時,原型模型最適合。
bean 工廠的概念是 Spring 作為 IOC 容器的基礎。IOC 將處理事情的責任從應用程序代碼轉移到框架。正如我將在下一個示例中演示的那樣,Spring 框架使用 JavaBean 屬性和配置數據來指出必須設置的依賴關系。
BeanFactory 接口
因為 org.springframework.beans.factory.BeanFactory 是一個簡單接口,所以可以針對各種底層存儲方法實現。最常用的 BeanFactory 定義是 XmlBeanFactory,它根據 XML 文件中的定義裝入 bean,如清單 1 所示。
清單 1. XmlBeanFactory
BeanFactory factory = new XMLBeanFactory(new FileInputSteam("mybean.xml"));
在 XML 文件中定義的 Bean 是被消極加載的,這意味在需要 bean 之前,bean 本身不會被初始化。要從 BeanFactory 檢索 bean,只需調用 getBean() 方法,傳入將要檢索的 bean 的名稱即可,如清單 2 所示。
清單 2. getBean()
MyBean mybean = (MyBean) factory.getBean("mybean");
每個 bean 的定義都可以是 POJO (用類名和 JavaBean 初始化屬性定義) 或 FactoryBean。FactoryBean 接口為使用 Spring 框架構建的應用程序添加了一個間接的級別。
IOC 示例
理解控制反轉最簡單的方式就是看它的實際應用。在對由三部分組成的 Spring 系列 的第 1 部分進行總結時,我使用了一個示例,演示了如何通過 Spring IOC 容器注入應用程序的依賴關系(而不是將它們構建進來)。
我用開啟在線信用帳戶的用例作為起點。對于該實現,開啟信用帳戶要求用戶與以下服務進行交互:
☆ 信用級別評定服務,查詢用戶的信用歷史信息。
☆ 遠程信息鏈接服務,插入客戶信息,將客戶信息與信用卡和銀行信息連接起來,以進行自動借記(如果需要的話)。
☆ 電子郵件服務,向用戶發送有關信用卡狀態的電子郵件。
三個接口
對于這個示例,我假設服務已經存在,理想的情況是用松散耦合的方式把它們集成在一起。以下清單顯示了三個服務的應用程序接口。
清單 3. CreditRatingInterface
public interface CreditRatingInterface {
public boolean getUserCreditHistoryInformation(ICustomer iCustomer);
}
清單 3 所示的信用級別評定接口提供了信用歷史信息。它需要一個包含客戶信息的 Customer 對象。該接口的實現是由 CreditRating 類提供的。
清單 4. CreditLinkingInterface
public interface CreditLinkingInterface {
public String getUrl();
public void setUrl(String url);
public void linkCreditBankAccount() throws Exception ;
}
信用鏈接接口將信用歷史信息與銀行信息(如果需要的話)連接在一起,并插入用戶的信用卡信息。信用鏈接接口是一個遠程服務,它的查詢是通過 getUrl() 方法進行的。URL 由 Spring 框架的 bean 配置機制設置,我稍后會討論它。該接口的實現是由 CreditLinking 類提供的。
清單 5. EmailInterface
public interface EmailInterface {
public void sendEmail(ICustomer iCustomer);
public String getFromEmail();
public void setFromEmail(String fromEmail) ;
public String getPassword();
public void setPassword(String password) ;
public String getSmtpHost() ;
public void setSmtpHost(String smtpHost);
public String getUserId() ;
public void setUserId(String userId);
A不會涉及到2級緩存以及hql
1. Configuration
讀取hibernate.cfg.xml.并把.hbm.xml文件交給HbmBinder做第一次處理, HbmBinder根據.hbm.xml解析出PersistentClass, Collection,然后在創建SessionFactory的時候,會對Collection做第2次處理塞入關聯
2 PersistentClass
根據.hbm.xml產生的描述要持久化的類的信息的類.主要的實例變量包括List <Property> properties
Property對象里的有個Value屬性value,通過value來描述該property和
數據庫里的哪些列對應以及獲得該property對應的type
3 Value
主要分為
SimpleValue,Collection,Component,ToOne
SimpleValue主要包括Table和Columns屬性,用于描述簡單屬性或單主鍵
Collection主要屬性包括
collectionTable表示Collection里面element對象所對應的Table
key表示CollectionTable里的哪幾列和Collection owner所對應的表的主鍵做關聯
element,描述了主表(referencingTable),從表的EnityName,以及從表對應的PersistentClass
Component可以用來描述多主鍵,通過屬性properties來表示
ToOne包括被引用的屬性名,被引用的實體名,columns,(被引用的屬性名不能
和columns同時設置),用于OneToOne,ManyToOne
4 SessionFactory
在創建SessionFactory的時候,會根據Configuration里Classes和
Collections,創建EntityPersister和CollectionPersister.
SessionFactory會緩存這些persisters.
EnityPersistenter的key是EntityName,
CollectionPersister的key是entityName+propertyName
5 EntityPersister
分為
SingleTableEntityPersister(一個實體一個表/一個類繼承結構一個表)
通過一個字段做標識
JoinedSubclassEntityPersister(每個子類一個表)
UnionSubclassEntityPersister(每個具體類一個表)
6 CollectionPersister
封裝對一個Collection的crud操作.
不過做insert,update,delete,recreate的時候,會判Inverse是否為false.如果為false才會執行相應的操作,表示是由Collection維護關系.
如果Inverse==true,表示關聯關系是由多端來維護(即直接通過操作Collection里的element來維護,而不是通過操作Collection來維護)
則該CollectionPersister不會做任何操作
7 Type
主要包括對SqlTypes的封裝,以及CollectionType,EntityType
(ManyToOneType,OneToOneType),主要接口有nullSafeGet(
從ResultSet拼裝出對象),nullSafeSet(給PreparedStatement
setParameter).
可以通過Value.getType()獲得Type
對于EntityType,CollectionType,就是通過resolve方法從
ResultSet中拼裝出對象
EntityType的nullSafeSet,就是獲取One端對象的主鍵所對應
的Type進行nullSafeSet
CollectionType沒有實現nullSafeSet,通過保存時的
Cascade或者CollectionPersister,將Collection的
Element一個一個的set
也可以自定義Type,實現UserType接口
具體見
http://docs.huihoo.com/framework/hibernate/reference-v3_zh-cn/inheritance.html
封裝對一個entity的crud操作,在創建EntityPersister實例過程中,會產
生crud的sql,可以在以后的操作提高效率。不過如果是DynamicInsert, DynamicUpdate,則會根據對象修改的屬性動態的生成sql
DAS不支持類繼承的映射,因此只會用到SingleTableEntityPersister
8 StatefulPersistenceContext
StatefulPersistenceContext和SessionImpl是一一對應的,會緩存通過
SessionImpl操作過的對象,包括entity和collection.主要屬性有
EntitiesByKey key=EntityKey, value=entity.
(EntityKey=id+EntityPersister+EntityMode entityMode))
entityEntries key=entity, value=EntityEntry.
EntityEntry用于描述一個對象的持久化狀態,如DELETED,MANAGED等等
CollectionsByKey
key=CollectionKey, value=PersistentCollection
CollectionKey=CollectionPersister+key+EntityMode,這個
Key是通過Collection.value.getType.nullSafeGet()得到的
PersistentCollection是hibernate對于Collection的封裝,
主要用于實現延遲加載
collectionEntries key=PersistentCollection,value=CollectionEntry
StatefulPersistenceContext的主要用途可以實現對象之間的關聯關系
的設置,動態的更新,以及對緩存的數據無需顯示調用save,update,delete的
方法就可以實現這些操作,是因為在Transaction.commit()的時候會調用
session.flush(),會保證內存對象狀態和數據庫的一致性
9 Cascade,CascadeStyle,CascadingAction
在Cascade執行級聯操作的時候,會通過CascadeStyle.doCascade(
CascadingAction)來判斷是否可以執行cascade,并且當要保存的對象有外鍵
約束的關聯對象時候會通過ForeignKeyDirection來判斷是應該在保存該對象
之前要保存關聯對象還是在保存該對象之后再保存關聯對象
10 Loader,CriteriaQueryTranslator,Criteria,QueryParameters, CriteriaJoinWalker
用于Criteria api對實體的查詢
Criteria 是一個查詢entity的api。可以設置類似where條件的表達式,
Select字段,order等等
當使用Criteria查詢時,首先會創建CriteriaLoader,CriteriaLoader會
通過CriteriaQueryTranslator從Criteria中得到查詢參數
QueryParameters,通過CriteriaJoinWalker把Criteria變成sql,然后
執行查詢
11 ActionQueue
當調用session對實體進行insert,update,delete的時候,只是會創建相應
的action放入ActionQueue,然后在session.flush()的時候才會真正操作
數據庫
ActionQueue的執行順序:
executeActions( insertions );executeActions( updates );executeActions( collectionRemovals );executeActions( collectionUpdates );executeActions( collectionCreations );executeActions( deletions );
12 Tuplizer
用于根據entityname實例化出對象,以及set/get property
hibernate內置的有PojoEntityTuplizer,Dom4jEntityTuplizer
DAS是在hibernate基礎之上實現了DataObject的持久化,支持DataObject對象之間的關聯,延遲加載,級聯,控制反轉,不支持DataObject的繼承
1.新實現了一個SDOEntityTuplizer
支持創建DataObject,以及set/get DataObject的屬性
SDOEntityTuplizer實現抽象類中規定的如下方法
SDOEntityTuplizer類的buildInstantiator方法用來根據mapping信息來為相應的實體建立不同的構造器,我們用SDOEntityInstantiator來實現SDO的構造器:
2其中SDOComponentInstantiator是用來當實體有復合主鍵用于實例化表示主鍵的類
3PropertyAccessor是Hibernate中定義的一個接口,用來表達在訪問mapping的實體對象的屬性的時候使用的“屬性訪問器”。它有兩個相關的接口:Getter接口和Setter接口。
DASPropertyAccessor的內部結構如下圖所示:
其中getGetter方法和getSetter方法是PropertyAccessor接口定的規格。DASGetter實現Getter接口,DASSetter類實現Setter接口。
4 自定義type,支持blob,clob的存儲
BlobFileType:從一個文件路徑讀取文件存入數據庫blob字段.從數據庫讀取
blob字段,生成文件放在臨時目錄,返回路徑
BlobByteArrayType:把一個byte[]數組存入blob字段.從數據庫讀取blob
字段放入byte[]
ClobFileType:從一個文件路徑讀取文件存入數據庫clob字段.從數據庫讀取
clob字段,生成文件放在臨時目錄,返回路徑
ClobStringType:把一個String存入blob字段.從數據庫讀取blob
字段放入String
5對查詢實體的支持
增加一個查詢實體定義文件.dbquery. 因為查詢實體沒有唯一標識,所以默認的
id的是"$queryEntityId$".用戶也可以自己指定一個列做唯一標識.
在Loader.prepareQueryStatement()里增加轉換帶查詢實體的Sql.
SelectFragment.addColumn() 做了判斷,如果列名是"$queryEntityId$",查詢的column就替換成'queryEntityId'常量.
在Loader.getRow() 增加判斷如果key.getIdentifier()是
queryEntityId的話,則不做檢查,看內存是否存在.
AbstractEntityPersister.getDatabaseSnapshot()里修改生成的查詢
語句,如果有QueryEntity,則用定義的sql替換QueryEntity
為什么要用hibernate:把coder從繁重與重復的jdbc代碼中解放出來。
為什么要用spring:coder不用再理會bean的創建
為什么要用struts:它有良好的開發模式-MVC 業務,邏輯,數據統統分開,解耦較好(當然,即使你用了, 如果不小心,還是會寫出耦合很高的代碼)。
5. Hibernate的查詢方式
Sql、Criteria,object comptosition
Hql:
1、 屬性查詢
2、 參數查詢、命名參數查詢
3、 關聯查詢
4、 分頁查詢
5、 統計函數
這個 加一條 hibernate filter
如何建立你的架構,并且怎樣讓你的各個應用層保持一致。?如何整合框架以便讓每個層在以一種松散偶合的方式彼此作用而不用管低層的技術細節?這對我們來說真是一種挑戰。 這里討論一個整合框架的策略( 使用3 種受歡迎的開源框架) :表示層我們用Struts; 業務層我們用Spring;而持久層則用Hibernate。 你也可以用其他FrameWork替換只要能得到同樣的效果。
應用程序的分層
大部分的Web應用在職責上至少能被分成4層。 這四層是:presentation(描述),persistence(持久),business(業務)和domain model(域模塊)。每個層在處理程序上都應該有一項明確的責任, 而不應該在功能上與其它層混合,并且每個層要與其它層分開的,但要給他們之間放一個通信接口。我們就從介紹各個層開始,討論一下這些層應該提供什么,不應該提供什么。
表示層(The Presentation Layer)
一般來講,一個典型的Web應用的的末端應該是表示層。 很多Java發者也理解Struts所提供的。 象業務邏輯之類的被打包到org.apache.struts.Action., 因此,我們很贊成使用Struts這樣的框架。
下面是Struts所負責的:
* 管理用戶的請求,做出相應的響應。
* 提供一個Controller ,委派調用業務邏輯和其它上層處理。
* 處理異常,拋給Struts Action
* 為顯示提供一個模型
* UI驗證。
以下條款,不該在Struts顯示層的編碼中經常出現。 它們與顯示層無關的。
* 直接的與數據庫通信,例如JDBC調用。
* 與你應用程序相關聯的業務邏輯以及校驗。
* 事物管理。
在表示層引入這些代碼,則會帶來高偶合和麻煩的維護。
持久層(The Persistence Layer)
典型的Web應用的另一個末端是持久層。這里通常是程序最容易失控的地方。開發者總是低估構建他們自己的持久框架的挑戰性。系統內部的持續層不但需要大量調試時間,而且還經常缺少功能使之變得難以控制,這是持久層的通病。 還好有幾個ORM開源框架很好的解決了這類問題。尤其是Hibernate。 Hibernate為java提供了OR持久化機制和查詢服務, 它還給已經熟悉SQL和JDBC API 的Java開發者一個學習橋梁,他們學習起來很方便。 Hibernate的持久對象是基于POJO和Java collections。此外,使用Hibernate并不妨礙你正在使用的IDE。
請看下面的條目,你在持久層編碼中需要了解的。
* 查詢對象的相關信息的語句。 Hibernate通過一個OO查詢語言(HQL)或者正則表達的API來完成查詢。 HQL非常類似于SQL-- 只是把SQL里的table和columns用Object和它的fields代替。 你需要學習一些新的HQL語言; 不管怎樣,他們容易理解而文檔也做的很好。 HQL是一種對象查詢的自然語言,花很小的代價就能學習它。
* 如何存儲,更新,刪除數據庫記錄。
* 象Hibernate這類的高級ORM框架支持大部分主流數據庫,并且他們支持 Parent/child關系,事物處理,繼承和多態。
業務層(The Business Layer)
一個典型Web應用的中間部分是業務層或者服務層。從編碼的視角來看,這層是最容易被忽視的一層。 而我們卻往往在UI層或持久層周圍看到這些業務處理的代碼,這其實是不正確的,因為它導致了程序代碼的緊密偶合,這樣一來,隨著時間推移這些代碼很難維護。幸好,針對這一問題有好幾種Frameworks存在。 最受歡迎的兩個框架是Spring和PicoContainer。 這些為也被稱為microcontainers,他們能讓你很好的把對象搭配起來。 這兩個框架都著手于‘依賴注射’(dependency injection)(還有我們知道的‘控制反轉’Inversion of Control=IoC)這樣的簡單概念。 這篇文章將關注于Spring的注射(譯注:通過一個給定參數的Setter方法來構造Bean,有所不同于Factory), Spring還提供了Setter Injection(type2),Constructor Injection(type3)等方式供我們選擇。 Spring把程序中所涉及到包含業務邏輯和Dao的Objects——例如transaction management handler(事物管理控制)、Object Factoris(對象工廠)、service objects(服務組件)——都通過XML來配置聯系起來。
后面我們會舉個例子來揭示一下Spring 是怎樣運用這些概念。
業務層所負責的如下:
* 處理應用程序的 業務邏輯和業務校驗
* 管理事物
* 允許與其它層相互作用的接口
* 管理業務層級別的對象的依賴。
* 在顯示層和持久層之間增加了一個靈活的機制,使得他們不直接的聯系在一起。
* 通過揭示 從顯示層到業務層之間的Context來得到business services。
* 管理程序的執行(從業務層到持久層)。
域模塊層(The Domain Model Layer )
既然我們致力于的是一個不是很復雜的Web的應用, 我們需要一個對象集合,讓它在不同層之間移動的。 域模塊層由實際需求中的業務對象組成 比如, OrderLineItem , Product等等。 開發者在這層 不用管那些DTOs,僅關注domain object即可。 例如,Hibernate允許你將數據庫中的信息存放入對象(domain objects),這樣你可以在連接斷開的情況下把這些數據顯示到UI層。而那些對象也可以返回給持續層,從而在數據庫里更新。 而且,你不必把對象轉化成DTOs(這可能似的它在不同層之間的在傳輸過程中丟失),這個模型使得Java開發者能很自然運用OO,而不需要附加的編碼。
域對象層(Domain Object Layer)
這層是編碼的著手點,我們的編碼就從這層開始。 例子中Order 與OrderItem 是一個One—To—Many的關系。 下面就是Domain Object Layer的兩個對象:
· com.meagle.bo.Order.java: 包含了一個Order的概要信息
· com.meagle.bo.OrderLineItem.java: 包含了Order的詳細信息
好好考慮怎你的package命名,這反應出了你是怎樣分層的。例如 domain objects在程序中可能打包在com.meagle.bo內。更詳細一點將打包在com. meagle.bo的子目錄下面。business logic應該從com.meagle.serice開始打包,而DAO 對象應該位于com.meagle.service.dao.hibernate。反應Forms和Actions的 持久對象(presentation classes) 應該分別放在 com.meagle.action和com.meagle.forms包。 準確的給包命名使得你的classes很好分割并且易于維護,并且在你添加新的classes時,能使得程序結構上保持上下一致。
持久層的配置(Persistence Layer Configuration)
建立Hibernate的持久層需要好幾個步驟。 第一步讓我們把BO持久化。 既然Hibernate是通過POJO工作的, 因此Order和 OrderLineItem對象需要給所有的fileds 加上getter,setter方法。 Hibernate通過XML文件來映射(OR)對象,以下兩個xml文件分別映射了Order 和OrderItem對象。(這里有個叫XDoclet工具可以自動生成你的XML影射文件)
- Order.hbm.xml
- OrderLineItem.hbm.xml
你可以在WebContent/WEB-INF/classes/com/meagle/bo目錄下找到這些xml文件。Hibernate的 [urlhttp://www.hibernate.org/hib_docs/api/net/sf/hibernate/SessionFactory.html]SessionFactory [/url]是用來告訴程序 應該與哪個數據庫通信,該使用哪個連接池或使用了DataSource,應該加載哪些持久對象。而Session接口是用來完成Selecting,Saving,Delete和Updating這些操作。后面的我們將講述SessionFactory和Session是怎樣設置的。
業務層的配置(Business Layer Configuration)
既然我們已經有了domain objects,接下來我們就要business service objects了,用他們來執行程序的logic,調用持久層,得到UI層的requests,處理transactions,并且控制 exceptions。 為了將這些連接起來并且易于管理,我們將使用面向方面的 SpringFramework。 Spring 提供了 控制倒置(inversion of control 0==IoC)和注射依賴設置(setter dependency injection)這些方式(可供選擇),用XML文件將對象連接起來。 IoC是一個簡單概念(它允許一個對象在上層接受其他對象的創建),用IoC這種方式讓你的對象從創建中釋放了出來,降低了偶合度。
建立我們的業務服務對象(Building Our Business Service Objects)
Business Object中的Setter方法接受的是接口,這樣我們可以很松散的定義對象實現,然后注入。 在我們的案例中,我們將用一個business service object接收一個DAO,用它來控制domain objects的持久化。 由于在這個例子中使用了Hibernate,我們可以很方便的用其他持久框架實現同時通知Spring 有新的DAO可以使用了。
在面向接口的編程中,你會明白 “注射依賴”模式是怎樣松散耦合你的業務邏輯和持久機制的:)。
Spring 和Bean 的還有一點要注意的: bean可以以用兩種方式創造。 這些都在單例模式(Sington)和原型模式(propotype)中定義了。 默認的方式是singleton,這意味著共享的實例將被束縛。而原形模式是在Spring用到bean的時候允許新建實例的。當每個用戶需要得到他們自己Bean的Copy時,你應該僅使用prototype模式。(更多的請參考設計模式中的單例模式和原形模式)
提供一個服務定位器(Providing a Service Locator)
既然我們已經將我們的Serices和DAO搭配起來了。我們需要把我們的Service顯示到其他層。 這個通常是在Struts或者Swing這層里編碼。一個簡單方法就是用 服務定位器返回給Spring context 。當然,可以通過直接調用Spring中的Bean來做。
11. 常用的Struts標簽.迭代是用什么標簽
<logic:iterate>
12. Struts是否線程安全的,不是怎么處理使它安全.
不安全.
解決方法:
1. 采用單線程方式
在JSP文件中加上,使它以單線程方式執行,這時仍然只有一個實例,所有客戶端的請求以串行方式執行.這樣會降低系統的性能.
2. 對函數加synchronized進行線程同步,JSP仍然以多線程方式執行,但是也會降低系統性能.
3. 采用局部變量代替實例變量
13. Struts中文亂碼怎么處理
1、 所有HTML/JSP頁面全部采用UTF-8編碼
2、 客戶端瀏覽器完全支持UTF-8編碼
14. Hibernate最常遇到一種異常
是空指針(ObjectNotFoundExceptio).
15. Hibernate session 的 get()和load()有什么區別
1. 如果未能發現符合條件的記錄,get方法返回null,而load方法會拋出一個ObjectNotFoundException
2. Load方法可返回實體的代理類實例,而get方法永遠直接返回實體類.
3. load方法可以充分利用內部緩存和二級緩存中的現有數據,而get方法則僅僅在內部緩存中進行數據查找,如沒有發現對應數據,將越過二級緩存,直接調用SQL完成數據讀取。
16. Hibernate延長加載
1. 實體對象的延遲加載
在set中指定lazy=true
這樣只有實際加載與對象相關聯的集合對象的時候,再通過session從數據庫中加載實際的數據集
2. 屬性延遲加載
在property節點中聲明lazy=true,而且還需要借助Hibernate類增強器對POJO類的二進制Class文件進行強化處理.
17. Hibernate中事務怎么處理
Hibernate有三種事務
1. JDBC 2. JTA事務 3. CMT事務
在這三種事務中,JDBC事務是默認的。這就意味著如果未設置hibernate.properties文件中的hibernate.transaction_factory的鍵值,beginTransaction將返回一個JDBC事務。
雖然一個會話中可以包含多個事務,但并不需要人為地對這些事務進行分割,而是由會話中的一些方法對多個事務進行管理的。下面將詳細描述這些方法:
commit()方法是結束事務的兩個方法。在這方法在內部調用了會話對象的save()方法。當調用這個方法時,如果這個事務已經被初始化,那么這個事務將成功提交。
18. 說說Spring AOP和IOC
AOP是OOP的延續,是Aspect Oriented Programming的縮寫,意思是面向方面編程, AOP非常適合開發J2EE容器服務器.
IoC就是Inversion of Control,控制反轉。在Java開發中,IoC意味著將你設計好的類交給系統去控制,而不是在你的類內部控制。這稱為控制反轉.