javascript
整合Struts2、Spring、Hibernate构建J2EE应用
【論文摘要】
J2EE即是以Java 2平臺為基礎的體系結構,又是一組旨在簡化企業解決方案的開發、部署、運行、維護等相關復雜問題的技術規范與指南。Struts2、Spring、Hibernate是當今符合J2EE技術規范的三個流行的開源框架。本文通過對這三個框架的工作機制的分析引伸出它們在J2EE應用中的互補作用,進而講解它們在J2EE開發中的整合。最后通過一個簡單的實例演示Struts2+Spring+Hibernate的開發流程。
關鍵字: Struts2? Spring? Hibernate? J2EE??
【Abstract】
J2EE is the structure base on Java 2 platform, it also a set of technical specification and guidelines to simplify the complex issues of the enterprise solutions of development, deployment, operation and maintenance of enterprise solutions. Struts2, Spring and Hibernate are three prevailing open-source framework in line with J2EE technical specification. This paper analyzes the working mechanism of these three frameworks, amplifies the complementary effect in their application of J2EE, and then introduces their integration in the development of J2EE. Finally, it demonstrates the developing process of Struts2+Spring+Hibernate through a simple case.
一 Struts2簡介
(一) Struts2是什么,及在Java web開發中的作用
Struts2是一個基于J2EE平臺的開源的MVC框架。它著力于Control和View,提供完善的控制方案并定制了功能強大的標簽庫。從某種意義上講Struts2并不涉及Model,但它提供了訪問Model的入口(execute()方法相當于訪問Model的一個入口,業務邏輯層及其以下層次Struts2不涉及)。使用Struts2開發的系統具有以下多種優點:結構層次分明(MVC),可重用性高(框架正是把系統的共性部分抽取出來,提供給不同應用使用),程序健壯性(強大的驗證機制與類型轉換功能)、可伸縮性(動態加載插件、設計良好的抽象類、接口等)有保證,便于開發與設計分工(MVC)等。
(二) Struts2與Struts的關系及區別
Struts2不是Struts的簡單的版本升級,而是本質上的飛越。事實上Struts2主要是從WebWork基礎上發展起來,再吸收Struts的一些優點匯集而成的。(至于為什么叫Struts2而不叫WebWork2.x,很大程度是因為Struts在業內的知名度要比WebWork要高的原故。)
由于Struts2主要是繼承于WebWrok的,所以它與Struts1的區別其實是很大的,以下列舉其中幾個重要方面:
Action類:Struts1要求Action類必須繼承一個抽象基類(如Action、BasicAction)。Struts2也提供一個抽象基類ActionSupport實現常用的一些接口,Struts2的Action類盡管常常實現這個類,但這不是必須的,它不只可以繼承一個Action類,還可以不繼承Action類而實現其他接口,以便于定制一些特定的服務,增強了Action類的靈活性。
線程模式: Struts1的Action是單例模式,盡管這一定程度節約了資源的損耗,但同時要求開發者必須小心翼翼地把它設計成線程安全(需要是無狀態的,即不能有可寫屬性)的,從而限制了Action所能做的工作。Struts2的Action即可以是單例模式,也可以是原型模式的,即可為每一個請求產生一個實例,因此沒有線程安全問題。這也進一步體現了Struts2比Struts1要優雅得多。
對Servlet依賴: Struts1的Action依賴于Servlet API,當一個Action被調用時HttpServletRequest和HttpServletResponse需被傳遞給execute(或其它定制的)方法。Struts2的Action不依賴于容器,允許Action脫離容器單獨執行(從而提高了可測性)。在需要時Struts2的Action也可以訪問HttpServetRequest和HttpServletResponse。
輸入捕獲: Struts1的Action是單例模式(不應該出現可寫屬性),數據是先經過ActionForm封裝再交給Action的。我認為這是Struts1設計的最大缺陷之一,ActionForm與DAO層的Doamin對象形式差不多,執行的功能也相似,只是意圖不同,這種代碼的冗余會給開發、維護帶來一系列問題。而Struts2的Action則是原型模式,每個Action都可以有其特有的屬性,從而數據不需要經由ActionForm封裝便可直接獲取。很明顯Struts2對輸入的捕獲及處理過程更加易于理解、更加簡潔。
(三) strust2的工作流程
strust2的工作流程可歸納為以下幾個步驟
1.客戶端Http請求提交。
2.strust2的總控制器FilterDispatcher通過sturts.xml分析哪個Action進行處理。
3.指定的Action執行相關的類型轉換方法(可省)、setXxx()方法、validate()方法等。
4.執行execute()方法(如果有指定其它方法則調用其它方法)。
5.sturts.xml根據execute()方法(或其它方法)返回的結果字符串確定接下來的工作(通常是調用一個jsp頁面,也可以是另一個Action或其它方式)。
6.Http響應客戶端。
二 Spring簡介
(一) Spring是什么
Spring是一個輕量級的提供控制反轉(IoC)、面向切面(AOP)容器的開源框架。
2004年Spring創始人Rod Johnson發表的《Expert one-to-one J2EE Development without EJB》劍指EJB,對EJB的各種龐大又笨重的結構進行了分析和否定,隨后推出的Spring便是以簡潔實用的方式替換了EJB所能完成的大部分功能(以我對EJB的一點淺薄認識,必須承認就目前而言,特別是EJB3.0的推出,在很多方面Spring還是無法企及的)。它使用基本的JavaBean來完成以前只能由EJB完成的事情。當然Spring適合的范圍不僅限于服務器端的開發。從簡單性、可測試性和松耦合的角度而言,任何Java應用都可以從Spring中受益。
傳統J2EE應用由于分層多,而各層之間又沒有合理的銜接,至使開發效率低、系統也不易維護,應用服務器廠商對各種技術的支 持 并沒有真正統一,導致J2EE的應用沒有真正實現一次編譯及到處執行的承諾。Spring的推出簡化了J2EE應用開發的復雜性,它能獨立于各種應用服務器容器,致力于J2EE應用各層的解決方案,它貫穿于View、Business及DAO各層,是它們之間很好的黏合劑。Spring的作用正是能與已有的框架配合,把它們無縫地整合在一起,使整個J2EE應用開發更加順暢。
(二) Spring相關技術介紹
1.輕量級:
Spring的輕量級并不是體現在Spring的完整代碼只有那么一點點(不到3MB),而是指Spring所需的系統開銷是很小的(簡直不能與EJB相提并論)。另外,Spring應用中的對象并不依賴于Spring的特定類(對象無需顯示的聲明Spring的特定類),Spring是非侵入式的。
2.控制反轉:
控制反轉(IoC)技術的運用降低了各層的耦合度。這是Spring框架最核心的一個方面。IoC概括起來說就是:一個對象所依賴的其它對象會通過容器(被動的)傳遞(在Spring常稱為“注入”)進來,而不是該對象自己創建或者查找依賴對象。可以說企業級應用各層的無逢銜接正是通過IoC實現。更進一步說,Spring抽象了服務,借助于各種J2EE API抽象,開發者能夠一致地使用J2EE 技術,而不管具體的實現方式是怎樣的。下面代碼可以很好的說明這一點:
這是傳統的服務層的實現類:
public class UserServiceImpl implements UserService{
//由于依賴對象由當前對象管理,所以這里new 需指明具體實現類。
private UserDao userDao=new UserDaoImpl();
private void add(User user)
{
? userDao.add(user);
}
}
使用Spring框架后的情況:
public class PersonServiceBean implements PersonService {
//依賴注入,即通過構造器,讓容器把創建好的依賴對象注入進來
//此處不需要硬編碼說明具體實現類(只需在xml文件配置即可),這便是IoC的巨大優點!
private UserDao userDao;
public PersonServiceBean(UserDao userDao) {
? this.UserDao=userDao;
}
private void add(User user)
{
? userDao.add(user);
}
}
抽象了服務!僅此一點,足矣讓絕大多數開發者興奮不已!
3.面向切面:
Spring提供了面向切面(AOP)編程的支 持 ,允許開發者以聲名方式使用企業級服務,最典型的是聲明式事務管理。通過Spring提供的事務管理服務,開發者便不再需要手工管理事務,也無需處理復雜的事務傳播行為。
下面還是以例子說明AOP的作用:
這是DAO層的代碼:
public class UserDaoImpl implements UserDao
{
public void save(User user)
{
? Session s=HibernateUtil.getSession();
? Transaction tx=null;
? try {
?? tx=s.beginTransaction(); //開啟事務
?? s.save(user);
?? tx.commit();//提交事務
? }catch(Exception e){
?? if(tx!=null)
??? tx.rollback();//回滾事務
?? try {
??? throw e;
?? }catch (Exception e1) {
??? e1.printStackTrace();
?? }
? }finally{
?? if(s!=null)
??? s.close();//關閉session
? }
}
}
顯然這是不好的代碼。盡管事務管理屬于DAO層的代碼,但由于DAO各方法會以不同方式組合成同一個事務,從而事務不應該在DAO層管理,而應該交給更高一層級,于是應該去掉事務管理代碼,改為:
public class UserDaoImpl implements UserDao
{
public void save(User user)
{
? s=HibernateUtil.getSession();
? try {
?? s.save(user);
? }finally{
?? //同上,關閉session
? }
}
}
然后是服務層代碼:
public class UserManagerImpl implements UserManager {
private UserDao userDao;
public void saveUser(User user)
{
? Session s=HibernateUtil.getSession();
? Transaction tx=null;
? try {
?? tx=s.beginTransaction();
?? userDao.save(user);
?? //其它方法
?? sendMessage();
?? sendEmail();
?? tx.commit();
? }catch(Exception e){
?? //同上,回滾事務
? }finally{
?? //同上,關閉session
? }
}
}
這是在沒有Spring情況下習慣的做法,這似乎也是較為合理的做法,但事務的開啟與關閉是DAO層的代碼,怎么跑到服務層來了呢?顯然這樣做服務層一定程度耦合了DAO層,通過Spring可以得到很好的解決:
public class UserManagerImpl implements UserManager {
private UserDao userDao;
//聲明事務處理方式
@Transactional(propagation=Propagation.REQUIRED)
public void saveUser(User user)
{
? userDao.save(user);
? //其它方法
? sendMessage();
? sendEmail();
<, SPAN style="mso-spacerun: yes"> }
}
不但徹底解耦,還大大簡化了代碼,程序顯得優雅許多了。
4.容器:
Spring容器包含并管理應用對象的配置和生命周期,開發者可以通過XML配置每個bean如何被創建(默認是singleton,也可以是prototype),以及它們是如何相互關聯的。
如下applicationContext.xml配置:
class="org.apache.commons.dbcp.BasicDataSource">
class="org.Springframework.orm.Hibernate3.LocalSessionFactoryBean"?
destroy-method="close">
?
可以看得出Spring自底向上把各層銜接起來。特別是在多框架整合的情況(如上面配置,即是整合了Hibernate、Struts2的典型配置方式),Spring使各框架無逢地結合到了一起。
三 Hibernate簡介
(一) Hibernate是什么
Hibernate是一個開源的數據持久層框架,用于實現對象與關系之間的映射(即O/R Mapping)。它對JDBC進行了輕量級的對象封裝,使Java程序員可以使用面向對象編程思想來操作數據庫。它不但提供了從Java類到數據表的映射,還提供了數據查詢和恢復機制。相對于使用JDBC和SQL來操作數據庫,通過使用Hibernate,大量封裝持久化操作的業務邏輯不再需要編寫煩瑣的JDBC語句,極大簡化了編程實現。Hibernate是跨數據庫的,因此基于Hibernate編寫的代碼不會因為數據庫的更換而重寫。
(二) 領域模型
Hibernate中領域模型(Domain)對象通過xml文件映射了數據庫的一張表(或多張表),xml文件通常位于Domain對象同一個包,命名為ClassName.hbm.xml(ClassName為映射的類名),Domain對象通常只有一些屬性(對應表的字段)及相應的setter、getter方法,當然還得符合以下幾個條件才能成為Domain對象:
1。必須要有默認的構造方法。
2。有無意義的標識符id(主鍵)。
3。非final,這是使用懶加載所需的要求。(因為懶加載需要繼承該類,如果加了final,該類便不可繼承了。)
(三) 對象狀態
在Hibernate中,對象狀態也是比較重要的概念,分別有以下三種:
1.瞬時:數據庫沒有記錄與之對應。
2.持久:數據庫有記錄與之對應,當前與session有關聯,并且相關聯的session沒有關閉,事務沒有提交。持久對象狀態發生改變,在事務提交時會影響到數據庫。
3.脫管:即脫離管理。數據庫有記錄與之對應,當前沒有session與之關聯,脫管對象狀態發生改變,不會影響到數據庫。
(四) HQL(Hibernate Query Language)
是Hibernate提供的用于跨數據庫查詢的面向對象查詢語言,它是按對象名而不是按表名來查詢。同時支 持 多態查詢,即查詢父類,會同時查詢子類。比如from Object會查詢所有對象,即查詢所有表。
(五) 對象關系映射
Hibernate提供了一對一、多對一、一對多、多對多等對象關系映射。
但需要指出的是,由于實際系統運行時性能的需求,往往不做多對多關聯(它需要對多個表進行關聯查詢,效率很低),甚至一對多關聯也很少做。
(六) 懶加載
懶加載,即只有在要用到數據時才到數據庫里讀取。通過session.load()可以實現對象的懶加載,從而盡量減少數據庫訪問次數以緩解系統的壓力。需要注意的是,能夠懶加載的對象都是被改寫過的代 理 對象,當相關聯的session沒有關閉時,訪問這些懶加載對象(代 理 對象)的屬性(getId、getClass除外)Hibernate會初始化這些代 理 ,或用Hibernate.initialize(proxy)來初始化代 理 對象;當相關聯的session關閉后,再訪問懶加載對象將出現異常。
(七) 緩存
緩存又可分為一級緩存跟二級緩存。
一級緩存,是Session級共享。save、update、saveOrUpdate、load、get、list、iterate、lock這些方法都會將對象放入一級緩存中,由于一級緩存不能控制緩存的大小,不宜操作過大的數據,否則容易造成內存溢出,為此需用session.evict(Object)、session.clear()方法清除緩存中的內容。
二級緩存,是SessionFactory級共享。Hibernate并沒有實現二級緩存,而是將之交給第三方緩存組件(如:EhCache、OSCache等)實現。
四 整合Struts2、Spring、Hibe, rnate構建J2EE應用
(一) 什么是J2EE
J2EE即Java2平臺企業版(Java 2 Platform Enterprise Edition),是一套以Java 2平臺為基礎的技術架構。包含許多組件,目的在于簡化并規范應用系統的開發與部署,進而提高可移植性、安全性與再用價值。J2EE核心是一組技術規范與指南,它給開發人員提供了一個應用標準,定義了一個標準的應用體系結構,J2EE作為解決企業級應用的標準,將企業級應用劃分成不同層次,便于應用開發,管理和部署。J2EE應用服務器支 持 各種組件,如Servlet、JSP、EJB等,這些組件分別安裝和部署于各自的容器中,使用標準的J2EE service API連接,靈活地實現應用。
(二) J2EE多層應用分析與實現
經典的J2EE三層結構是指表示層(Presentation),業務邏輯層(Business logic)以及基礎架構層(Infrastructure)。在實際項目開發中,往往會對三層體系結構做一些擴展來滿足項目的需要。如今較流行的方式是將三層體系擴展為五層體系,即在表示層與業務邏輯層之間增加控制層(在某些情況下甚至還會在控制層與業務邏輯層再增加代 理 層),再把基礎架構層細分為數據訪問層、數據層。Struts2 + Spring + Hibernate可以實現J2EE的這種多層結構。其中Struts2用于表示層與控制層,而Spring工作的中心在業務層,同時又粘合控制層、業務層與數據訪問層,Hibernate則用于數據訪問與持久化工作。
(三) J2EE層次結構
1. 數據層
數據層是指提供所需數據的數據庫系統。數據庫里記錄了系統所需要的所有數據。由于數據庫系統本身的多樣性,J2EE提供了JDBC接口用于數據庫之上的組件能訪問各種數據庫系統。Hibernate則進一步封裝了JDBC對數據庫的操作。
2. 數據訪問層
包括數據查詢與持久化工作。本層將完成具體的數據處理工作,包括增、查、改、刪(CRUD)。
本層運用DAO設計模式,通過使用Hibernate的ORM技術很好的解決了“阻抗不匹配”(即對象操作與關系數據庫操作方式不同)的問題。DAO進一步封裝了JDBC對數據庫表的CRUD操作,實現了用一致的面向對象的方式操作不同數據庫,同時也降低了數據操作的難度。
3. 服務層
本層是整個系統架構的核心,需完成所有業務規則的制定、業務流程的實現等與業務需求有關的系統設計。Spring的引入很大程度的簡化這一層的復雜性。例如事務處理,開發者不再為事務邊界控制而為難。本層把一些算法、數據處理(通過調用DAO層)等與業務相關的處理封裝于一體,交由控制層調用。把服務層與控制層分離,使層次更加分明,分工更加細致,從而更方便團隊調配工作。
4. 控制層
本層接受客戶端的請求,轉交給服務層處理,最后將處理結果返回給客戶。通過引入Struts2框架,控制層會以Struts2為主導。(相對Struts1而言)Struts2作為一個Filter而不再只是Servlet,在請求到來時(在必要的情況下會)對信息進行驗證、處理(如類型轉換),只有驗證通過的請求才會轉交給業務層處理,最后將處理結果返回給客戶。盡管在未引入Struts2的情況下Servlet可以做相同的事,但相比之下Struts2使這些工作規范化、模式化,開發者只需在模式化的處理(Action)類填補一些代碼,甚至可以通過XML文件的配置來實現這些操作,大大簡化了代碼,提高了開發效率。
5. 視圖層
視圖層是呈現給客戶的界面,通常是JSP、HTML等頁面。在使用Struts2框架的應用中,會使用Struts2提供的功能豐富的標簽庫增強頁面動態內容的輸出能力。
(四) 為什么要整合Struts2、Spring、Hibernate
通過以上各層的分析,可以清楚的看到Struts2、Spring、Hibernate在整個J2EE應用中的作用以及它們相互間的協作關系。Hibernate負責底層數據庫操作,Spring協調整個應用各功能組件,并在業務層中解耦該層與數據訪問層,而Struts2則在控制層做主導,并對視圖層頁面輸出能力做了增強。三個框架功能互補,讓整個J2EE應用確實體現高效、易擴展、健壯。
五一個簡單的應用示例
(一) 項目介紹與準備工作
為進一步分析如何通過Struts2、Spring、Hibernate構建J2EE應用,并且能在盡可能小的篇幅說明開發的過程,下面將通過項目開發中常見的“管理員登錄”的例子演示它們的整合過程。與此登錄過程無關的數據、設計過程、代碼將不做說明。另外,以下所講的各層,并不是真實項目開發的“步驟”,事實上正是框架的引入最大限度的使各層解耦,從而允許各層并行的開發。以下是項目的整體架構圖(亦是工作流程圖):
(注:Spring的ContextLoaderListener及applicationContext.xml不屬于單獨的某一層,而是橫跨控制層、服務層、DAO層,管理各層組件。Hibernate的HibernateDaoSupport對JDBC進行了封裝。)
開發、測試環境:Eclipse6.5、jdk1.6、tomcat6.0、IE6
數據庫:mysql5.0
建立J2EE項目EShop2,并導入Spring、Hibernate、Struts2及整合所需相關jar包。將Spring、Struts2框架引進項目(Hibernate將由Spring引入)。(位于WebRoot\WEB-INF目錄下的)web.xml需做如下配置:
Struts2
org.apache.Struts2.dispatcher.FilterDispatcher
Struts2
/*
org.Springframework.web.context.ContextLoaderListener
(二) 數據庫設計
管理員表admin相關字段:
ID帳號? &, nbsp;?????????????????????????????? 密碼
id(int)??? LoginName(char(12))?????? loginPwd(char(12))
(三) Domain對象及O/R Mapping映射文件建立
Domain對象源文件Admin.java如下:
public class Admin {
private Integer id;
private String loginName;
private String loginPwd;
public Admin(){}
public Integer getId() {
? return id;
}
public void setId(Integer id) {
? this.id = id;
}
//其它getter、setter略
}
O/R Mapping映射文件Admin.hbm.xml主要內容:
?
??
?
?
??
?
?
??
?
Hibernate正是通過本文件建立了對象與數據庫表的映射關系,從而程序員可以通過操作對象的方式操作數據庫表。
(四) DAO層
面向接口編程,這是好的做法。如下是AdminDao接口:
public interface AdminDao {
public Admin findAdminByNP(String LoginName,String LoginPwd);
//還有其它方法如saveAdmin(),removeAdmin()等略。
}
接口實現類:
//本類繼承于HibernateDaoSupport,這是Hibernate提供的一個重要的類,通過它操作數據庫,使代碼如此簡潔,以至程序無需任何注釋了。
public class AdminDaoImpl extends HibernateDaoSupport implements AdminDao {
public Admin findAdminByNP(String loginName, String loginPwd) {
? String hql="from Admin where LoginName=? and LoginPwd=?";
? String []values={loginName, loginPwd};
? List list=(List)this.getHibernateTemplate().find(hql,values);
? if (list.size()>0)
? {
?? return list.get(0);
? }
? return null;
}
//其它實現方法略。
}
(五) 服務層
還是面向接口,AdminService接口代碼如下:
public interface AdminService {
public Admin adminLogin(String loginName,String loginPwd) throws Exception;
//其它業務方法略
}
接口實現AdminServiceImpl:
public class AdminServiceImpl implements AdminService {
private AdminDao adminDao; //服務層通過DAO層接口操作數據庫
public Admin adminLogin(String loginName, String loginPwd) throws Exception {
? Admin admin = adminDao.findAdminByNP(loginName, loginPwd);
? return admin;
}
}
盡管服務層是項目的核心,通常也是開發過程中最復雜的一個環節,但可以看到,有了DAO層,本例程序相當簡單。這似乎未見Spring的身影。好,我們擴展一下功能,設想登錄時需要更新管理員的登錄次數并記錄日志。日志對象會對應數據庫的另一個表。這樣登錄時將同時寫兩個表,出于數據一致性的考慮,這時就需要開啟事務,如何管理呢?看如下代碼:
//引入Spring事務注解及事務傳播屬性注解類
import org.Springframework.transaction.annotation.Transactional;
import org.Springframework.transaction.annotation.Propagation;
@Transactional?? //注解管理事務
public class AdminServiceImpl implements AdminService {
private AdminDao adminDao;
//指定本方法須在同一事務內處理
@Transactional(propagation=Propagation.REQUIRED)
public Admin adminLogin(String loginName, String loginPwd) throws Exception {
? Admin admin = adminDao.findAdminByNP(loginName, loginPwd);
? if (admin!=null)
? {
?????? //更新管理員登錄次數,代碼略
?????? //添加管理員登錄事件記錄,代碼略
? }
? return admin;
}
}
事務的創建、開啟、回滾、提交等操作交由Spring管理,程序不會因為事務的引入增加多少代碼(只是增加兩句注解語句而已),盡管可以通過xml配置的方式管理事務,但我認為這是最優雅的做法。
(六) 控制層
控制層將以Struts2為主導,首先是Struts2配置文件struts.xml,它應位于源文件夾src根目錄下(編譯后將位于classes根目錄下)。
核心代碼如下:
?
??
?? error.jsp
?
?
?
?? index.jsp
?? login.jsp
?
AdminAction.java涉及相關代碼:
import com.opensymphony.xwork2.ActionContext;
//通過繼承ActionSupport我們的Action類將獲得一些像自動成員賦值、校驗、類型轉換等功能。
public class AdminAction extends ActionSupport {
private Admin admin;
private AdminService adminService;
//相關getter、setter方法略
public String login() throws Exception {
? String result=this.ERROR;
? String loginName,loginPwd;
? /**
?? * 領域模型的賦值是通過繼承ActionSupport,由Struts2為我們做的。
?? * 盡管可以在此驗證this.getAdmin().getLoginName()、
?? * this.getAdmin().getLoginPwd()值的合法性(如是否非空、長度是否
?? * 適合等)但這不是規范的做法,這部分工作應該交由validate()方法處理
?? */?
? loginName=this.getAdmin().getLoginName();
? loginPwd=this.getAdmin().getLoginPwd();
? //調用服務層方法實現登錄驗證的操作,根據是否獲得Admin對象確定登錄成功與否
? Admin admin=this.getAdminService().adminLogin(loginName, loginPwd);
? if (admin!=null)
? {
?? Map session = ActionContext.getContext().getSession();
?? session.put("adminId",admin.getId()); //盡管可以把整個admin對象放入session,但這不是好的做法,畢竟除了id跟LoginName其它信息基本不使用。
?? session.put("adminLoginName",admin.getLoginName());
?? result=this.SUCCESS;
? }
? else
? {
?? Map request=(Map)ActionContext.getContext().get("request");
?? request.put("errorMessage", "用戶名或密碼輸入不正確!");
? }
? return result;
}
@Override
public void validate() {
? // 具體驗證實現略
}
}
前面除了在業務層擴展登錄方法,其它地方一直沒有出現Spring,必須承認 ContextLoaderListener是很容易讓人遺忘它的存在(除了在配置web.xml的時候),事實上站在開發者的角度看Spring很大程度是通過applicationContext.xml文件發揮作用的。盡管Spring不屬于控制層,但控制層是它為我們的項目服務的最后一層,是時候請出我們的功臣了。如下是applicationContext.xml配置:
class="org.apache.commons.dbcp.BasicDataSource">
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" destroy-method="close">
?
可以看出,整個開發中除了視圖層Spring未涉足,從數據層到控制層,Spring一直在發揮作用。它調配好各項準備工作,使各層有機的融合在一起。
(七) 視圖層
視圖層是客戶向服務器發起請求的窗口,表單頁面login.jsp主要代碼如下:
<%@ taglib uri="/Struts-tags" prefix="s" %>
<SPAN style=" Roman’?="" New="" ’Times="" Roman’;="" 宋體;="" 150%;="" 12pt;="">用戶名" required="true" />
<SPAN style=" Roman’?="" New="" ’Times="" Roman’;="" 宋體;="" 150%;="" 12pt;="">密碼" required="true"/>
<SPAN style=" Roman’?="" New="" ’Times="" Roman’;="" 宋體;="" 150%;="" 12pt;="">登錄">
<SPAN style=" Roman’?="" New="" ’Times="" Roman’;="" 宋體;="" 150%;="" 12pt;="">重置">
另外還有一個用于顯示錯誤報告的頁面error.jsp,內容略。
(八) 程序運行
輸入http://localhost:8080/EShop2/adminope/login.jsp進入登錄頁面:
輸入不完整信息(未輸入密碼),程序返回登錄頁并提示錯誤:
輸入驗證未通過的信息(用戶名或密碼錯誤),需說明的是,因為是以dispatcher方式跳轉,所以隱藏了error.jsp的真實地址(仍為表單目標地址adminLogin.action):
輸入正確信息,成功登錄后臺:
(九) 總結
至此“管理員登錄”功能已開發完畢。當然,本例所談的開發,僅指編碼,事實上它只是軟件開發的一個環節。關于可行性研究、需求分析、設計、測試以及運行、維護不是本文所討論的范疇。通過以上的分析與說明,相信讀者能看出整個流程的規范化。盡管看起來有些按部就班,但事實上這正是現代軟件業向大規模、群體、團隊開發的必由之路。J2EE的規范以及為我們提供的指南是每個軟件開發從業人員所必須深刻學習的。而Struts2、Spring、Hibernate框架的學習與整合三者構建J2EE應用,從小的方面看是幫助我們領會與實踐J2EE思想、提高軟件開發素質,從大的方面看是提高軟件開發效率(各種框架為我們做了很多工作)、使軟件易于維護(規范化的代碼),進而促進軟件業的發展。
參考書目:
1.《輕量級Java EE企業應用實戰-struts2+spring+hibernate整合開發》 李剛 電子工業出版社
2.《spring揭秘》 王福強 人民郵電出版社
3.《Struts 2深入詳解》孫鑫 電子工業出版社
4.《J2EE 企業級應用測試實踐》 白勝 清華大學出版社
?
http://www.striveday.com/newsshow/532.html
總結
以上是生活随笔為你收集整理的整合Struts2、Spring、Hibernate构建J2EE应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 4415y相当于i5多少
- 下一篇: 单节点配置SecondaryNameNo