Java 5.0php
Struts 2.0.9html
Spring 2.0.6java
Hibernate 3.2.4node
做者: Liu Liu 轉載請註明出處mysql
基本概念和典型實用例子。web
1、基本概念spring
Struts:做爲基於 MVC 模式的 Web 應用最經典框架,兩個項目Struts 和webwork已經集成,成爲如今的Struts2。目前的最新版本是2.0.9(2007-7)。sql
Spring: 是一個輕型的容器,利用它可使用一個外部 XML 配置文件方便地將對象鏈接在一塊兒。每一個對象均可以經過顯示一個 JavaBean 屬性收到一個到依賴對象的引用,留給您的簡單任務就只是在一個 XML 配置文件中把它們鏈接好。數據庫
Hibernate 是一個純 Java 的對象關係映射和持久性框架,它容許您用 XML 配置文件把普通Java 對象映射到關係數據庫表。使用 Hibernate 可以節約大量項目開發時間,由於整個 JDBC 層都由這個框架管理。這意味着您的應用程序的數據訪問層位於 Hibernate 之上,徹底是從底層數據模型中抽象出來的。apache
三種技術到目前已經比較成熟,並且他們都是免費的!讓咱們對三者集成進行一個初覽(簡單而不專業):
咱們用Struts實現從Web(網頁,MVC中的View)到後臺系統的映射(WebàAction),而後由Spring管理這些Action,把它們做爲Bean和其餘對象一塊兒處理。這些Bean之間處理業務邏輯、數據、系統狀態等,且它們被Spring統一管理,爲了區分,就算大概包括MVC的MC部分吧。而後須要持久化的數據由Spring和Hibernate之間的接口交由Hibernate處理(這個屬於持久層)。
必須基礎:只要Java基礎,一點HTML知識、XML基礎就能夠了。本文的目的就是從零開始創建第一個Struts+Spring+Hibernate應用。即便它是最簡單的,咱們也但願初學者可以從中理解一些思想,其中也包括系統架構的設計思想。
2、環境搭建
咱們堅持免費纔是硬道理,開源纔是好事情,因此咱們所有使用開源免費的工具和軟件。若是使用MyEclipse,其中的工具將有助於簡化下面演示的工程開發,但本文不用。
所需軟件包以下表:
序號 |
包 |
下載地址和文件(包)名 |
說明 |
|
1 |
JDK5.0 |
JDK5.0 |
||
2 |
Eclipse WTP |
Eclipse IDE for Java EE Developers 下載All in One,這樣不用本身下載其餘插件 |
包含網站開發的Eclipse,v3.3,下載All in One |
|
3 |
HibernateSynchronizer-3.1.9 |
https://sourceforge.net/project/showfiles.php?group_id=99370 |
幫助開發Hibernate應用的Eclipse插件 |
|
4 |
Hibernate3 |
http://sourceforge.net/project/showfiles.php?group_id=40712 à hibernate3所指示的包 |
Hibernate支持包 |
|
5 |
Spring |
http://sourceforge.net/project/showfiles.php?group_id=73357
|
spring-framework-2.0.6-with-dependencies.zip |
|
6 |
SpringIDE(可選) |
http://springide.org/updatesite/ 包名如 |
||
7 |
Struts |
http://struts.apache.org/download.cgi
|
爲了較全的例子和文檔,建議下載 |
|
8 |
Tomcat |
建議下載v5.5以上版本,應用服務器(支持JSP等)Apache項目之一 |
||
9 |
MySQL |
|
Hibernate演示須要 |
|
1、下載了eclipse之後安裝。在所安裝的目錄下有兩個子目錄plugins和features,這是兩個放eclipse插件的目錄,便可以經過拷貝須要的文件到這些目錄裏面,從而給eclipse添加新的功能。
2、將第3、6的包解壓,將其中的plugins目錄直接複製到eclipse安裝目錄下,選擇「所有」替換。
3、運行eclipse,選擇一個空目錄做爲工做區(WorkSpace),啓動之後能夠看到Welcome.html的歡迎界面。如今創建新工程FileàNewàProject,在打開的New Project窗口中選擇WebàDynamic Web Project。輸入Project name,在Target Runtime一項選擇新建(New),選擇你所安裝的Apache Tomcat,在彈出窗口輸入相關信息(Tomcat安裝目錄等)。
新建工程流程以下圖。
工程結構以下:
其中咱們要寫的Java代碼在Java Resource: src(之後直接稱src)下,網站根目錄內容在WebContent下,類所在根目錄是WEB-INF/classes,Eclipse會自動將build/classes裏面已經編譯的類同步過去。
向WEB-INF下的lib目錄添加以下所列的jar包。
(1)這些包在下載解壓後Spring,Struts,Hibernate的lib目錄或者dist/module目錄下面(若是不在,能夠到網上google一把。列表中mysql-*.jar包是MySQL數據庫的JDBC Driver)。也能夠把全部lib和dist下的jar包拷貝過來(能夠在系統複製這些jar包,而後到Eclipse裏面選中WEB-INF裏面的lib包,而後粘帖就能夠了)。但要注意全拷貝可能會存在衝突,如struts*plugin.jar等包不能引入,不然不能運行。
(2)這些Jar包是:
antlr-2.7.2.jar
cglib-nodep-2.1_3.jar
commons-beanutils-1.6.jar
commons-chain-1.1.jar
commons-collections-2.1.1.jar
commons-dbcp.jar
commons-digester.jar
commons-logging-1.0.4.jar
commons-logging-api-1.1.jar
commons-pool.jar
commons-validator-1.3.0.jar
dom4j-1.6.1.jar
el-api.jar
el-ri.jar
freemarker-2.3.8.jar
hibernate3.jar
jsf-api.jar
jta.jar
mysql-connector-java-3.0.14-production-bin.jar
ognl-2.6.11.jar
oro-2.0.8.jar
spring-hibernate3.jar
spring.jar
struts-config.xml
struts-core-1.3.5.jar
struts2-codebehind-plugin-2.0.9.jar
struts2-config-browser-plugin-2.0.9.jar
struts2-core-2.0.9.jar
struts2-jasperreports-plugin-2.0.9.jar
struts2-jfreechart-plugin-2.0.9.jar
struts2-jsf-plugin-2.0.9.jar
struts2-pell-multipart-plugin-2.0.9.jar
struts2-plexus-plugin-2.0.9.jar
struts2-sitegraph-plugin-2.0.9.jar
struts2-sitemesh-plugin-2.0.9.jar
struts2-spring-plugin-2.0.9.jar
struts2-struts1-plugin-2.0.9.jar
struts2-tiles-plugin-2.0.9.jar
tiles-api-2.0.4.jar
tiles-core-2.0.4.jar
tiles-jsp-2.0.4.jar
xwork-2.0.4.jar
3、開始工做
在WebContent下創建index.jsp,創建方式如圖。
index.jsp的內容如表,咱們暫時不分析。
<%@ page contentType="text/html; charset=UTF-8" %> <html> <head> <title>Example by Doer Liu@UTStarcom sz </title></head> <body> This is my JSP page. <br> <form name="userInfoForm" action="login.do" method="post"> 用戶名: <input name="username" type="text" /> 密碼: <input name="password" type="password"> <input name="sub" type="submit" value="增長" /> <input name="res" type="reset" value="重置" /> </form> </body> </html> |
此時就能夠運行該工程,忙了這麼久,看看效果吧。
運行方式:右鍵點擊index.jsp,選擇Run/Debug AsàRun on Server,在彈出窗口中默認咱們使用的Tomcat Server,點擊finish完成。能夠看到eclipse中內嵌的瀏覽器顯示咱們的網頁。其中表單的輸入在咱們的工程中將獲得輸入數據(用戶名和密碼),這些數據會傳給咱們將要創建的Action處理。
如今來看看如何創建咱們的Action。在src下新建一個package(包)名爲action用於保存響應Web請求的Action類。在action包下新建Action類LoginAction(action.LoginAction)以下,注意類的繼承關係。
package action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.validator.DynaValidatorForm; import org.springframework.web.struts.ActionSupport;
//咱們繼承spring提供的Action衍生類org.springframework.web.struts.ActionSupport public class LoginAction extends ActionSupport{
public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { return mapping.findForward("success");
} } |
可是如今index.jsp的內容怎麼和LoginAction的數據匹配呢,咱們看到LoginAction的execute方法有一個屬性ActionForm,因而咱們創建一個類forms.UserInfoForm以下,繼承ActionForm。
package forms; import org.apache.struts.action.ActionForm; public class UserInfoForm extends ActionForm { private String username; private String password;
public String getUsername() { return username; } public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
|
有了兩個頭,又有了保持內容的類,如今看看咱們如何用struts把他們聯繫起來吧。
如今須要在WEB-INF下創建文件struts-config.xml。其中form-beans定義了表單是如何映射的,這裏用咱們剛剛定義的forms.UserInfoForm。
<?xml version=」1.0」 encoding="ISO-8859-1"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config> <form-beans> <form-bean name="userInfoForm" type="forms.UserInfoForm"/> </form-beans>
<action-mappings> <action attribute="userInfoForm" path="/login"input="/index.jsp"type="org.springframework.web.struts.DelegatingActionProxy" name="userInfoForm" scope="session" validate="false"> <forward name="success" path="/success.html"/> </action> </action-mappings> </struts-config> |
在<action-mappings>中定義了咱們的Action。它的屬性attribute指出Action的內容輸入是咱們自定義的ActionForm,path給Action賦予一個路徑,input指明只接受index.jsp的輸入,<forward標籤訂義了當Action返回"success"的時候,將定向到/success.html這個網頁。 最重要的是type,它定義了這個處理這個請求的Action類,原本應該是咱們自定義的LoginAction,但咱們卻用了spring的一個Action,爲何?由於咱們要用Spring管理咱們自定義的Action。看,struts和Spring在這裏就開始鏈接起來了。
但還有兩個問題,Struts和Spring又是如何知道對方的存在,如何溝通呢?Spring如何知道把控制權交給咱們自定義的LoginAction呢?
咱們先來解決第一個問題,web.xml是Tomcat這些應用服務器管理的,所以咱們在這裏將struts和Spring配置聯繫起來。這是整個web.xml。請看註釋。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" id="WebApp" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name> Struts2+Spring2+Hibernate3 simple example by Doer Liu@UTstarcom</display-name> <!-- filter就理解爲一些對網頁請求的過濾吧 --> <!-- encodingFilter是爲了處理國際化,交由Spring處理,設置爲UTF-8 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <!-- struts 是struts的filter,這個定義就將能夠將請求交給struts過濾一番了 --> <filter> <filter-name>struts</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter>
<!-- 那麼哪些請求交給struts過濾呢,這裏包括 /struts2spring2hib3bydoer下和根目錄/下的全部請求--> <filter-mapping> <filter-name>struts</filter-name> <url-pattern>/struts2spring2hib3bydoer/*</url-pattern> <url-pattern>/*</url-pattern> </filter-mapping>
<!-- 定義一個監聽器,處理整個WebContext,簡單的理解爲整個網站的上下文環境監聽器吧這個屬於Spring--> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
<!-- servlet定義一個servlet爲struts的ActionServlet --> <servlet> <servlet-name>doertest</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
<!-- servlet-mapping將servlet和請求對應起來,這裏是全部*.do的請求交由上面定義的doertest處理 --> <servlet-mapping> <servlet-name>doertest</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
<!-- 定義默認返回頁,如輸入http://127.0.0.1/那麼根目錄下的index.html或者其餘文件就被請求 --> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
|
經過web.xml二者聯繫上了。如今它們各自還須要一些配置。
Struts在咱們的例子裏比較簡單,在build/class下面(最終會被eclipse同步到網站的WEB-INF/classes下面)創建struts.xml:
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts> <include file="struts-default.xml" /> </struts> |
Spring的默認配置文件是WEB-INF/applicationContext.xml,目前其內容很簡單,咱們只是把struts的Bean放進來,以下:
映射的規則:bean的name屬性必須等於struts-config.xml裏面定義的action的path屬性,class就是這個bean的類action.LoginAction。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">
<beans> <!-- Action Bean , 對應的部分 struts-config.xml form-bean and action-mappings --> <bean name="/login" class="action.LoginAction " singleton="false">
</property> </bean>
</beans> |
如今在WebContent下面創建success時重定向的目標success.html,方法和index.jsp相似,但選擇THML類型,隨便輸入內容以便測試。這時候struts和Spring就簡單的鏈接起來了。先停掉剛纔運行起來的Tomcat,從新啓動,運行index.jsp,點擊網頁中的按鈕<添加>,看看有什麼效果。
如今,然咱們簡略描述一下數據和請求的流程。
點擊<添加>,index.jsp的這個表單發送的請求是login.do(<form name="userInfoForm" action="login.do" method="post">),請求被傳給後臺,生成了doertest(處理*.do的請求)集合的一個servlet,而後傳到path爲/login的action,被Spring的org.springframework.web.struts.DelegatingActionProxy處理,該類找到name是/login的Bean,轉交處理權,等待結果。這個Bean就是咱們的action.LoginAction。咱們的execute中返回一個forward是"success"對應的網頁,就是success.html。因此……,你已經看到了,struts和spring已經聯繫起來了。OK!
下面咱們須要把hibernate整合進來了,原本考慮到例子的簡單性,打算用更簡單的類,但既然用三者整合,就是要有良好的設計。咱們須要如下幾個層次的設計:表現層,業務層,持久層。表現層就是網頁;表現層和業務層之間的接口就是網頁和action的接口,由struts處理了;業務層包括業務邏輯和事務管理等,由Spring管理,咱們只是創建具體處理對象;業務層和持久層之間由數據訪問對象DAO處理,持久層交給hibernate處理。貫穿這些層的是領域對象(domain object),即表示現實世界的對象(base object),如訂單對象,人物信息對象等等。如今看看咱們須要的剩餘設計結構。
業務層:放進包service
數據訪問對象: 放進包dao
持久層:hibernate
領域對象:放進包bo
既然領域對象是最基本的對象,咱們就得首先創建,本例中,能夠藉助HibernateSynchronizer生成:
首先在mysql中建立表
CREATE TABLE `userinfo` (
`id` int(11) primary key auto_increment,
`username` varchar(20) default NULL,
`Password` varchar(20) default NULL
)
在Eclipse中,創建hibernate的map文件:右鍵點擊WEB-INF(或其餘目錄均可,後面會提到如何使用該文件),選擇newàother,在彈出窗口中選擇Hibernate Mapping File。在彈出窗口輸入url,用戶名和密碼後點擊Refresh,能夠看到你選擇的數據庫的表,選中userinfo表。輸入包bo,用來保存從數據庫提取的領域對象。在Properties中將Id generator改成native。
HibernateSynchronizer將在WEB-INF下生成Uerinfo.hbm.xml文件。
右鍵點擊該文件,選擇Hibernate SynchronizeràSynchronize Files。將自動生成bo.base.BaseUserinfo和bo.Userinfo類。這兩個就是領域對象。工具正好啊!
如今bo包裏面的對象自動生成了。
下面創建dao包中對象dao.UserinfoDAO:
package dao; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import bo.Userinfo; //從HibernateDaoSupport繼承,從而可使用getHibernateTemplate().save保存數據。 public class UserinfoDAO extends HibernateDaoSupport {
public void save(Userinfo userinfo) { System.out.println("saved!"); getHibernateTemplate().save(userinfo); }
}
|
再創建service包中的業務對象,service.UserinfoService:
package service; import dao.UserinfoDAO; import bo.Userinfo; package service; public class LoginService { private UserinfoDAO userinfoDAO;
public UserinfoDAO getUserinfoDAO() { System.out.println("shit"); return userinfoDAO; }
public void setUserinfoDAO(UserinfoDAO userinfoDAO) { System.out.println("LoginService:setAdminDAO"); this.userinfoDAO = userinfoDAO; }
public void saveinfo(Userinfo userinfo) { //進行相關業務處理,好比validate之類的。 userinfoDAO.save(userinfo); } } |
好了,全部咱們應該創建的對象都生成了,如今把hibernate整合進來再進行一些後續處理。
首先,在applicationContext.xml文件中加入必需的Bean定義,成爲以下內容,注意其中註釋。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">
<beans> <!-- Action Bean , 對應的部分 struts-config.xml form-bean and action-mappings --> <bean name="/login" class="action.LoginAction" singleton="false"> <!-- property是該bean的屬性,以下面的property,在類LoginAction 中必有字段定義LoginService loginService;和getLoginService()以及setLoginService方法--> <property name="loginService"> <ref bean="loginService" /> </property>
</bean>
<!-- 定義DBCP的數據庫鏈接屬性,該數據源會被hibernate使用,DBCP是鏈接池開源包,其中的url,username,password須要替換成你的數據庫訪問屬性 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost/mysql</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>doerliu</value> </property> </bean>
<!-- 配置sessionFactory, 爲Hibernate配置屬性 --> <bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref local="dataSource" /> </property> <property name="mappingResources"> <list> <!—Hibernate的map 文件在這裏配置了,注意文件的相對位置。 --> <value>../Userinfo.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean>
<!-- 業務層的事務管理由該bean管理--> <bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> </bean>
<!-- 事務處理環境(代理)配置,爲業務處理LoginService定義一個事務處理*****--> <bean id="userDAOProxy"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <property name="target"> <ref local="loginService" /> </property> <property name="transactionAttributes"> <props> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="is*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
<!-- 業務處理Bean定義 --> <bean id="loginService" class="service.LoginService"> <property name="userinfoDAO"> <ref bean="userinfoDAO" /> </property> </bean>
<!-- 數據訪問對象的Bean --> <bean id="userinfoDAO" class="dao.UserinfoDAO"> <property name="sessionFactory"><ref local="sessionFactory"/></property> </bean>
</beans> |
最後,LoginAction能夠處理請求並和業務層進行交流了。所以須要增長實質性內容:
package action;
/* @sample for training. * @author doer.liu@utstarcom * @date 2007-7-30 */ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.springframework.web.struts.ActionSupport;
import bo.Userinfo;
import forms.UserInfoForm;
import service.LoginService;
//咱們繼承spring提供的Action衍生類org.springframework.web.struts.ActionSupport public class LoginAction extends ActionSupport {
LoginService loginService;
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { UserInfoForm userInfoForm = (UserInfoForm) form; String username = userInfoForm.getUsername(); String password = userInfoForm.getPassword(); Userinfo userinfo = new Userinfo(); userinfo.setUsername(username); userinfo.setPassword(password); loginService.saveinfo(userinfo);// 保存前臺的數據,插入數據庫
return mapping.findForward("success"); //返回頁。
}
public LoginService getLoginService() { return loginService; }
public void setLoginService(LoginService loginService) { System.out.println("setLoginService=" + loginService); this.loginService = loginService; } } |
Ok!整個流程到此就走通了。運行看看吧。還有什麼說的呢,動手開始吧,在此基礎上不斷修改測試,再參考相關文檔,一切都將愈來愈簡單!——有問題,看日誌!
附件是導出的WAR文件,其中lib已被清空,只要加入文中列出的lib文件便可運行(能夠將WAR導入eclipse,或者將war文件放到Tomcat的webaspps下)http://dl2.csdn.net/down4/20070806/06111224839.war
固然這個例子爲了清晰起見,在各類模式,java編程習慣上是不合適的,好比應該面向接口編程,而不是通通拿類,拿對象來處理。應該定義如ILoginService, ILoginDAO等接口,使得系統更靈活,更易移植。固然爲了說明,咱們這樣作是能夠原諒的,但工做中切記不要只圖簡單!不然還不如不用這種高級優秀的構架,由於你一用就把它破壞殆盡了。