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

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

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

    posts - 495,  comments - 11,  trackbacks - 0

    4.9 Struts與Hibernate的整合策略

    前面介紹了Hibernate的一些相關知識點,距離Hibernate進入實際開發還有一段路要走。Hibernate作為持久層解決方案,必須與其他表現層技術組合在一起才可形成一個J2EE開發框架。經常看到網上一些朋友給出的Hibernate入門示例,居然在JSP頁面中訪問Hibernate Configuratioin對象。甚至看到某些所謂的精通J2EE書籍,也居然在JSP頁面中訪問Hibernate的Configuration對象——這種現狀非常讓人擔憂,Hibernate并不是萬金油,并不是說項目中使用Hibernate就怎么了不起了,而是通過使用Hibernate,可以讓J2EE應用架構更科學,可以讓開發者以更好的面向對象的方式進行項目開發。

    反過來說,即使不使用Hibernate,而使用普通的JDBC持久化解決方案,也不應該在JSP(表現層)訪問到JDBC API(持久層API)。下面介紹如何讓Hibernate和Struts進行整合,整合Spring部分將在后面章節介紹。

    4.9.1 工廠模式介紹

    工廠模式是指當應用程序中A組件需要B組件協助時,并不是直接創建B組件的實例,而是通過B組件的工廠——該工廠可以生成某一個類型組件的實例。在這種模式下,A組件無須與B組件以硬編碼方式耦合在一起,而只需要與B組件的工廠耦合。

    對于A組件而言,它只關心工廠生產的實例是否滿足某種規范,即實現了某個接口(滿足接口規范,即可供自己正常調用)。這種模式提供了對象之間清晰的角色劃分,降低了程序的耦合。

    接口產生的全部實例通常實現相同接口,接口里定義全部實例共同擁有的方法,這些方法在不同的實現類中實現方式不同。程序調用者無須關心方法的具體實現,從而降低了系統異構的代價。

    下面是工廠模式的示例代碼:

    //Person接口定義

    public interface Person

    {??

    ??? /**

    ??? * @param name 對name打招呼

    ??? * @return 打招呼的字符串

    ??? */

    ??? public String sayHello(String name);

    ??? /**

    ??? * @param name 對name告別

    ??? * @return 告別的字符串

    ??? */

    ??? public String sayGoodBye(String name);

    }

    該接口定義Person的規范,該接口必須擁有兩個方法:能打招呼、能告別。規范要求實現該接口的類必須具有這兩個方法:

    //American類實現Person接口

    public class American implements Person

    {

    ??? /**

    ??? * @param name 對name打招呼

    ??? * @return 打招呼的字符串

    ??? */

    ??? public String sayHello(String name)

    ??? {

    ??????? return name + ",Hello";

    ??? }

    ??? /**

    ??? * @param name 對name告別

    ??? * @return 告別的字符串

    ??? */

    ??? public String sayGoodBye(String name)

    ??? {

    ??????? return name + ",Good Bye";

    ??? }

    }

    下面是實現Person接口的另一個實現類Chinese

    public class Chinese implements Person

    {

    ??? /**

    ??? * @param name 對name打招呼

    ??? * @return 打招呼的字符串

    ??? */

    ??? public String sayHello(String name)

    ??? {

    ??????? return name + ",您好";

    ??? }

    ??? /**

    ??? * @param name 對name告別

    ??? * @return 告別的字符串

    ??? */

    ??? public String sayGoodBye(String name)

    ??? {

    ??????? return name + ",下次再見";

    ??? }

    }

    然后看Person工廠的代碼:

    public class PersonFactory

    {

    ??? /**

    ??? * 獲得Person實例的工廠方法

    ??? * @ param ethnic 調用該實例工廠方法傳入的參數

    ??? * @ return返回Person實例

    ??? */

    ??? public Person getPerson(String ethnic)

    ??? {

    ??????? //根據參數返回Person接口的實例

    ??????? if (ethnic.equalsIgnoreCase("chin"))

    ??????? {

    ??????????? return new Chinese();

    ??????? }

    ??????? else

    ??????? {

    ??????????? return new American();

    ??????? }

    ??? }

    }

    最簡單的工廠模式的框架基本如上所示。

    主程序部分僅僅需要與工廠耦合,而無須與具體的實現類耦合在一起。下面是主程序部分:

    public class FactroyTest

    {

    ??? public static void main(String[] args)

    ??? {

    ??????? //創建PersonFactory的實例,獲得工廠實例

    ??????? PersonFactory pf = new PersonFactory();

    ??????? //定義接口Person的實例,面向接口編程

    ??????? Person p = null;

    ??????? //使用工廠獲得Person的實例

    ??????? p = pf.getPerson("chin");

    ??????? //下面調用Person接口的方法

    ??????? System.out.println(p.sayHello("wawa"));

    ??????? System.out.println(p.sayGoodBye("wawa"));

    ??????? //使用工廠獲得Person的另一個實例

    ??????? p = pf.getPerson("ame");

    ??????? //再次調用Person接口的方法

    ??????? System.out.println(p.sayHello("wawa"));

    ??????? System.out.println(p.sayGoodBye("wawa"));

    ??? }

    }

    主程序從Person接口的具體類中解耦出來,而且程序調用者無須關心Person的實例化過程,角色劃分清晰。主程序僅僅與工廠服務定位結合在一起,獲得工廠的引用,程序將可獲得所有工廠產生的實例。具體類的變化,重要接口不發生任何改變,調用者程序代碼部分幾乎無須發生任何改動。

    4.9.2 使用DAO模式

    第1章介紹了J2EE應用的架構,最上面的表現層,表現層與MVC框架的控制器交互,控制器負責調用業務邏輯組件的業務邏輯方法來處理用戶請求,而業務邏輯組件則依賴于DAO組件提供的數據庫原子操作,這種模式也被稱為DAO模式。

    由上面關于J2EE應用架構的介紹可見,控制器總是依賴于業務邏輯組件,而業務邏輯組件總是依賴于DAO組件。也就是說,控制器需要調用業務邏輯組件的方法,而業務邏輯組件需要調用DAO組件的方法。

    DAO模式的分層非常清晰,持久層訪問被封裝在DAO層下,而決不會擴散到業務邏輯層,更不會在JSP頁面(表現層)中進行持久層訪問。

    注意:即使在早期的Model 1(使用JSP + JavaBean創建應用的模式,沒有使用MVC設計模式)模式下,持久層訪問也被封裝在JavaBean中完成,而不是直接在JSP頁面中進行數據庫訪問。對于直接在JSP中訪問持久層API的做法,可以說根本不了解J2EE開發。

    那么控制器采用怎樣的方式訪問業務邏輯組件呢?應該采用工廠模式,讓控制器與業務邏輯組件的實現類分離,僅與業務邏輯工廠耦合;同樣,業務邏輯組件也應該采用工廠模式訪問DAO模式,而不是直接與DAO實現類耦合。

    后面的案例部分會介紹更實際的整合策略,此處僅僅介紹DAO模式下兩個工廠模式策略。

    4.9.3 DAO組件的工廠模式

    在J2EE應用開發中,可擴展性是一個隨時需要關注的問題。而DAO組件是經常需要增加的項目組件,如果每次需要增加一個DAO組件都需要修改代碼是相當讓人沮喪的事情。為了避免這種情況,采用XML配置文件來管理所有的DAO組件,這種DAO組件配置文件的代碼如下:

    <?xml version="1.0" encoding="GBK"?>

    <daoContext>

    ??? <!-- 配置應用需要的sonDao組件 -->

    ??? <dao id="sonDao" class="org.yeeku.dao.impl.SonDaoImpl"/>

    ??? <!-- 配置應用需要的personDao組件 -->

    ??? <dao id="personDao" class="org.yeeku.dao.impl.PersonDaoImpl"/>

    </daoContext>

    查看上面的配置文件可以看出,應用中有配置了兩個DAO組件,因為每個DAO組件在J2EE應用中僅需要一個實例就足夠了,因此DAO工廠類提供了一個緩存池來緩存每個DAO實例,并負責在應用啟動時創建所有的DAO。

    下面是DAO工廠類的代碼:

    public class DaoFactory

    {

    ??? //用于緩存DAO實例的Map對象

    ??? private Map<String, Dao> daoMap = new HashMap<String , Dao>();

    ??? //將DAO工廠寫成單態模式

    ??? private static DaoFactory df;

    ??? //DAO工廠的構造器

    ??? private DaoFactory()throws Exception

    ??? {

    ??????? //使用SAXReader來負責解析daoContext.xml配置文檔

    ??? ??? Document doc = new SAXReader().read(new File(ConstantsUtil.realPath

    ??????? + "\\daoContext.xml"));

    ??????? //獲取文檔的根文檔

    ??? ??? Element root = doc.getRootElement();

    ??????? //獲取daoContext根元素的所有子元素

    ??? ??? List el = root.elements();

    ??? ??? for (Iterator it = el.iterator();it.hasNext() ; )

    ??? ??? {

    ??????????? //每個子元素對應一個DAO組件

    ??????? ??? Element em = (Element)it.next();

    ??????? ??? String id = em.attributeValue("id");

    ??? ??????? //獲取實現類

    ??????? ??? String impl = em.attributeValue("class");

    ??????????? //通過反射,根據類名創建DAO組件的實例

    ??????? ??? Class implClazz = Class.forName(impl);

    ??????? ??? Dao d = (Dao)implClazz.newInstance();

    ??????????? //將創建的DAO組件放入緩存池中

    ??????? ??? daoMap.put(id, d);

    ??? ??? }

    ??? }

    ??? //單態模式必須提供一個入口方法來創建DAO工廠的方法

    ??? public static DaoFactory instance()throws Exception

    ??? {

    ??????? //如果DAO工廠還未創建

    ??? ??? if (df == null)

    ??? ??? {

    ??????? ??? df = new DaoFactory();

    ??? ??? }

    ??? ??? return df;

    ??? }

    ??? //下面的方法用于根據DAO組件ID獲取DAO組件

    ??? public Dao getDao(String id)

    ??? {

    ??? ??? return daoMap.get(id);

    ??? }

    }

    通過上面的工廠類代碼可以看出,DAO工廠負責初始化所有的DAO組件。系統每增加一個DAO組件,無須再修改任何代碼,僅僅需要在daoContext.xml配置文件中增加配置即可。

    注意:這種整合策略非常優秀。可擴展性很好,如果應用需要增加一個DAO組件,只需要修改配置文件,并提供相應的DAO組件實現即可。而且,如果有一天需要重構DAO組件,只須提供修改過的DAO組件實現類,而業務邏輯組件無須任何改變。

    業務邏輯組件代碼無須與DAO實現類耦合,業務邏輯組件的代碼面向DAO組件的接口編程,將業務邏輯組件和DAO組件的耦合降低到接口層次。

    4.9.4 業務邏輯組件的工廠模式

    與此類似的是,業務邏輯組件完全可以采用這種編程模式,業務邏輯組件的配置文件代碼如下:

    <?xml version="1.0" encoding="GBK"?>

    <appContext>

    ??? <!-- 配置應用需要的業務邏輯組件,每個業務邏輯組件對應一個app元素 -->

    ??? <app id="wawa" class="org.yeeku.service.impl.WawaServiceImpl"/>

    </appContext>

    業務邏輯組件工廠同樣可根據該配置文件來初始化所有業務邏輯組件,并將業務邏輯組件放入緩存池中,讓控制器與業務邏輯組件的耦合降低到接口層次。業務邏輯組件的工廠類代碼如下:

    public class AppFactory

    {

    ??? private Map<String , Object> appMap = new HashMap<String , Object>();

    ??? //業務邏輯組件工廠采用單態模式

    ??? private static AppFactory df;

    ??? //業務邏輯組件工廠的私有構造器

    ??? private AppFactory()throws Exception

    ??? {

    ??????? //使用SAXReader來負責解析appContext.xml配置文檔

    ??????? Document doc = new SAXReader().read(new File(ConstantsUtil.realPath

    ??????? + "\\appContext.xml"));

    ??????? //獲取文檔的根文檔

    ??????? Element root = doc.getRootElement();

    ??????? //獲取appContext根元素的所有子元素

    ??????? List el = root.elements();

    ??????? for (Iterator it = el.iterator();it.hasNext() ; )

    ??????? {

    ??????????? //每個app元素對應一個業務邏輯組件

    ??????????? Element em = (Element)it.next();

    ??????????? String id = em.attributeValue("id");

    ??????????? //根據配置文件指定的業務邏輯組件實現類來創建業務邏輯組件實例

    ??????????? String impl = em.attributeValue("class");

    ??????????? Class implClazz = Class.forName(impl);

    ??????????? Object d = implClazz.newInstance();

    ??????????? //將業務邏輯組件放入緩存池中

    ??????????? appMap.put(id , d);

    ??????? }

    ??? }

    ??? //單態模式必須提供入口方法,用于創建業務邏輯組件工廠

    ??? public static AppFactory instance()throws Exception

    ??? {

    ??????? //如果業務邏輯組件工廠為空

    ??????? if (df == null)

    ??????? {

    ??????????? df = new AppFactory();

    ??????? }

    ??????? return df;

    ??? }

    ??? //根據業務邏輯組件的id屬性獲取業務邏輯組件

    ??? public Object getApp(String id)

    ??? {

    ??????? //直接從緩存池中取出業務邏輯組件,并返回

    ??????? return appMap.get(id);

    ??? }

    }

    從某種程度上來講,這種方式與后來Spring的控制反轉(Inversion of Control,IoC)容器有異曲同工之妙,但Spring的IoC容器則提供了更多的功能。

    上面的兩個類中都用到了一個ConstantsUtil,它僅用于保存一個全局變量,有一個public static的realPath屬性,該屬性用于保存應用在服務器中的路徑。

    posted on 2009-07-19 10:08 jadmin 閱讀(67) 評論(0)  編輯  收藏

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


    網站導航:
     
    主站蜘蛛池模板: 亚洲中文无码卡通动漫野外| 亚洲国产成人精品青青草原| 深夜免费在线视频| 国产伦一区二区三区免费| 色综合久久精品亚洲国产| 午夜免费福利网站| 久久精品免费一区二区三区| 免费H网站在线观看的| 亚洲女人初试黑人巨高清| 免费电影在线观看网站| 亚洲人成欧美中文字幕| 无码专区一va亚洲v专区在线| 高清免费久久午夜精品| 国产亚洲成av人片在线观看| 午夜爽爽爽男女免费观看影院| 亚洲日本在线免费观看| 好吊妞788免费视频播放| 污网站在线观看免费| 亚洲Av无码专区国产乱码DVD| 精品一区二区三区无码免费视频| 亚洲午夜成激人情在线影院| 处破痛哭A√18成年片免费| 免费国产黄网站在线看| 久久亚洲国产精品五月天| 色噜噜狠狠色综合免费视频 | 在线观看免费播放av片| 亚洲韩国在线一卡二卡| 免费看片A级毛片免费看| 国产va免费精品| 亚洲毛片免费观看| 免费毛片a线观看| 激情亚洲一区国产精品| AV在线播放日韩亚洲欧| 亚洲毛片在线免费观看| 美女被羞羞网站免费下载| 99久久亚洲精品无码毛片| 国产jizzjizz视频免费看| 久久免费的精品国产V∧| 日本亚洲高清乱码中文在线观看| 久久精品国产亚洲av四虎| 国产精品视频免费一区二区三区 |