JAVAweb之SSH框架
SSH框架( struts+spring+hibernate)
開發(fā)環(huán)境 myeclipes2015 sqlserver2012 Java
簡(jiǎn)述
SSH是 struts+spring+hibernate的一個(gè)集成框架,是06年之前較為流行的一種Web應(yīng)用程序開源框架.。集成SSH框架的系統(tǒng)從職責(zé)上分為四層:表示層、業(yè)務(wù)邏輯層、數(shù)據(jù)持久層和域模塊層,以幫助開發(fā)人員在短期內(nèi)搭建結(jié)構(gòu)清晰、可復(fù)用性好、維護(hù)方便的Web應(yīng)用程序。其中使用Struts作為系統(tǒng)的整體基礎(chǔ)架構(gòu),負(fù)責(zé)MVC的分離,在Struts框架的模型部分,控制業(yè)務(wù)跳轉(zhuǎn),利用Hibernate框架對(duì)持久層提供支持,Spring做管理,管理struts和hibernate。
SSH框架優(yōu)點(diǎn)
優(yōu)秀的解耦性,很少有軟件產(chǎn)品的需求從一開始就完全是固定的??蛻魧?duì)軟件需求,是隨著軟件開發(fā)過(guò)程的深入,不斷明晰起來(lái)的。因此,常常遇到軟件開發(fā)到一定程度時(shí),由于客戶對(duì)軟件需求發(fā)生了變化,使得軟件的實(shí)現(xiàn)不得不隨之改變。ssh三層構(gòu)架,控制層依賴于業(yè)務(wù)邏輯層,但絕不與任何具體的業(yè)務(wù)邏輯組件耦合,只與接口耦合;同樣,業(yè)務(wù)邏輯層依賴于DAO層,也不會(huì)與任何具體的DAO組件耦合,而是面向接口編程。采用這種方式的軟件實(shí)現(xiàn),即使軟件的部分發(fā)生改變,其他部分也不會(huì)改變。
框架解析
Struts
(一般開發(fā)選用的是Struts2【Struts的升級(jí)版】})
Struts2是一個(gè)基于MVC設(shè)計(jì)模式的Web應(yīng)用框架,它本質(zhì)上相當(dāng)于一個(gè)servlet,在MVC設(shè)計(jì)模式中,Struts2作為控制器(Controller)來(lái)建立模型與視圖的數(shù)據(jù)交互。Struts 2是Struts的下一代產(chǎn)品,是在 struts 1和WebWork的技術(shù)基礎(chǔ)上進(jìn)行了合并的全新的Struts 2框架。其全新的Struts 2的體系結(jié)構(gòu)與Struts 1的體系結(jié)構(gòu)差別巨大。Struts 2以WebWork為核心,采用攔截器的機(jī)制來(lái)處理用戶的請(qǐng)求,這樣的設(shè)計(jì)也使得業(yè)務(wù)邏輯控制器能夠與ServletAPI完全脫離開,所以Struts 2可以理解為WebWork的更新產(chǎn)品。
spring
Spring就像是整個(gè)項(xiàng)目中裝配bean的大工廠,在配置文件中可以指定使用特定的參數(shù)去調(diào)用實(shí)體類的構(gòu)造方法來(lái)實(shí)例化對(duì)象。Spring,使用基本的實(shí)體JavaBean來(lái)完成以前只能用EJB完成的事情。而其核心則是控制反轉(zhuǎn)(IOC)和面向切面編程(AOP)。使用Spring,意味著一個(gè)對(duì)象的創(chuàng)建再也不是自己new出來(lái)的,而是全權(quán)交給了IOC容器去實(shí)例化。與此同時(shí),Spring通過(guò)采用依賴注入(DI)的方式,通過(guò)屬性的Setter和Getter方法來(lái)注入這個(gè)對(duì)象的屬性,這樣的好處就是不完全依賴于容器的API,且查詢依賴與代碼實(shí)現(xiàn)了解耦。而AOP,則是將應(yīng)用的業(yè)務(wù)邏輯和系統(tǒng)級(jí)服務(wù)(例如事務(wù))分離開來(lái),進(jìn)行內(nèi)聚性的開發(fā),應(yīng)用對(duì)象只負(fù)責(zé)完成業(yè)務(wù)邏輯而不關(guān)心日志或者事務(wù)的處理。
spring優(yōu)勢(shì)
spring提高了一種對(duì)象管理方法,有效的組織系統(tǒng)中間層對(duì)象。是框架的完美“粘合劑”。有利于面向接口編程習(xí)慣的養(yǎng)成,使代碼結(jié)構(gòu)清晰。
hibernate
Hibernate,是負(fù)責(zé)了跟數(shù)據(jù)庫(kù)的交接。通過(guò)持久化數(shù)據(jù)對(duì)象,進(jìn)行對(duì)象關(guān)系的映射,并以對(duì)象的角度來(lái)訪問(wèn)數(shù)據(jù)庫(kù)。通過(guò)封裝JDBC,使得開發(fā)人員可以以面向?qū)ο缶幊痰乃枷雭?lái)操控?cái)?shù)據(jù)庫(kù),從而擺脫了以往使用JDBC編程時(shí)的“死板”操作。通過(guò)hibernate.cfg.xml文件來(lái)取代以往的JDBC連接數(shù)據(jù)庫(kù)的一大串代碼,通過(guò)XXX(實(shí)體Bean的類名).hbm.xml文件來(lái)與數(shù)據(jù)庫(kù)的具體表進(jìn)行映射。并且Hibernate有自己的HQL語(yǔ)句,與數(shù)據(jù)庫(kù)的SQL語(yǔ)句相似,但不同的是HQL語(yǔ)句在面向?qū)ο缶幊痰慕嵌壬?#xff0c;通過(guò)Session的createQuery方法創(chuàng)建戶一個(gè)query對(duì)象,由這個(gè)對(duì)象來(lái)完成對(duì)數(shù)據(jù)庫(kù)的增刪改查等操作。通過(guò)Struts2中Action的返回值,來(lái)調(diào)用Dao層中的業(yè)務(wù)處理。
hibernate優(yōu)勢(shì)
hibernate是JDBC輕量級(jí)的封裝,占用內(nèi)存較少,性能比較高。與JDBC相比,如果開發(fā)JDBC的人員技術(shù)能力非常強(qiáng),hibernate執(zhí)行效率會(huì)比JDBC弱一些,但是大部分情況是程序員在使用JDBC時(shí)是不可能做到最高效率,hibernate可以幫大部分開發(fā)人員提高運(yùn)行效率??梢砸氲谌蕉?jí)緩存,提高系統(tǒng)查詢效率,減少系統(tǒng)里存在大量單例類(singleton),大量的單例類,會(huì)降低系統(tǒng)的可測(cè)試性和面向?qū)ο蟪潭取ibernate兼容JDBC。理論上可以應(yīng)用在任何使用JDBC的場(chǎng)景。
可以逆向工程,簡(jiǎn)化了手寫model實(shí)體類的繁瑣。
整體設(shè)計(jì)
| 業(yè)務(wù)邏輯層 | (Iplm,DAO,接口及接口實(shí)現(xiàn),action,Servlet包)業(yè)務(wù)規(guī)則的制定、業(yè)務(wù)流程的實(shí)現(xiàn)等與業(yè)務(wù)需求有關(guān)的系統(tǒng)設(shè)計(jì),對(duì)于數(shù)據(jù)訪問(wèn)層而言,它是調(diào)用者;對(duì)于表示層而言,它卻是被調(diào)用者。UserDAO.java/ UserDAOImpl.java,AddcardAction.java/ FileUploadServlet.java |
| 模塊層 | (hibernate逆向工程)實(shí)體層model包),以幫助開發(fā)人員在短期內(nèi)搭建結(jié)構(gòu)清晰、可復(fù)用性好、維護(hù)方便的Web應(yīng)用程序。TUser.java/TUser.hbm.xml |
| 數(shù)據(jù)持久層 | (SQL server,基類實(shí)現(xiàn),hql)主要是負(fù)責(zé)數(shù)據(jù)庫(kù)的訪問(wèn),可以訪問(wèn)數(shù)據(jù)庫(kù)系統(tǒng)、二進(jìn)制文件、文本文檔或是XML文檔。iHibBaseDAOImpl.java/ iHibBaseDAO.java |
DAO接口模式為了減少業(yè)務(wù)邏輯和數(shù)據(jù)訪問(wèn)邏輯之間的耦合,當(dāng)一個(gè)持久層框架被應(yīng)用時(shí),該模式將會(huì)減少業(yè)務(wù)對(duì)象和該框架之間的耦合,這樣我們可以不修改業(yè)務(wù)對(duì)象而選擇不同的持久層框架的實(shí)現(xiàn)。
業(yè)務(wù)邏輯層:包含了系統(tǒng)所需要的所有功能上的算法和計(jì)算過(guò)程,并與數(shù)據(jù)訪問(wèn)層和表現(xiàn)層交互。服務(wù)端返回?cái)?shù)據(jù)的處理以及相應(yīng)頁(yè)面的改變。
設(shè)計(jì)原則:
業(yè)務(wù)層接口的設(shè)計(jì)原則:一個(gè)實(shí)體類一個(gè)接口,一次提交一個(gè)業(yè)務(wù)方法。業(yè)務(wù)方法的參數(shù)來(lái)自表現(xiàn)層。
持久層接口的設(shè)計(jì)原則:一個(gè)實(shí)體類一個(gè)接口,一次數(shù)據(jù)庫(kù)操作一個(gè)持久方法。
實(shí)例手把手教學(xué)搭建
開發(fā)工具:myeclipes2015 sqlserver2012
新建一個(gè)SSHtest的web project項(xiàng)目
輸入項(xiàng)目名稱,根據(jù)需要選擇各項(xiàng)版本(一般默認(rèn)即可),點(diǎn)擊下一步
點(diǎn)擊下一步
勾選后點(diǎn)擊下一步
點(diǎn)擊Finish,項(xiàng)目就建好了。
搭建框架
●創(chuàng)建hibernate
為了更好的與spring匹配我們這里選擇3.3版本的hibernate,選好后點(diǎn)擊下一步
根據(jù)上圖操作就建立好了hibernate的session工廠。
接下來(lái)我們看一下建好的hibernate配置文件
在hibernate配置文件里配置與數(shù)據(jù)庫(kù)的連接,獲得數(shù)據(jù)持久化(相關(guān)配置會(huì)在后面步驟中介紹)
●創(chuàng)建spring
Spring整合Hibernate(一般先建hibernate再建spring,因?yàn)楹蠼╯pring的話,就會(huì)自動(dòng)把一些相關(guān)配置整合到spring里,減少了手動(dòng)操作的麻煩)
spring一般選4.1版本,切合hibernate3.3,(記得選擇版本的時(shí)候,兩個(gè)版本要相對(duì)應(yīng),否則會(huì)因?yàn)槿笔鄳?yīng)的架包而報(bào)錯(cuò))點(diǎn)擊下一步
你不用管,直接下一步
到此步,點(diǎn)擊Finish,現(xiàn)在spring就創(chuàng)建好了
接下來(lái)我們來(lái)看創(chuàng)建好的spring配置文件
●創(chuàng)建Struts2
選擇2.1版本,點(diǎn)擊下一步
到此步點(diǎn)擊Finish,Struts2就創(chuàng)建好。
接下來(lái)我們來(lái)看Struts2的配置文件
現(xiàn)在我們已經(jīng)完成了基本SSH框架的搭建。
我們的框架布局基本就搭建完成了,我們先來(lái)運(yùn)行測(cè)試一下(一般運(yùn)行沒(méi)錯(cuò),就說(shuō)明搭建沒(méi)問(wèn)題)
將項(xiàng)目部署到Tomcat上:
運(yùn)行
因?yàn)橐B接數(shù)據(jù)庫(kù),所以我們要新建一個(gè)數(shù)據(jù)庫(kù)
●以sqlserver2012為例,新建一個(gè)名為SSHtest的數(shù)據(jù)庫(kù)
創(chuàng)建數(shù)據(jù)庫(kù)
點(diǎn)擊確定,數(shù)據(jù)庫(kù)就創(chuàng)好了。
我們?cè)谶@了以用戶登錄為例,建一張用戶表T_User
填寫數(shù)據(jù)
3. 創(chuàng)建所需包
4 . 配置框架
●hibernate連接數(shù)據(jù)庫(kù),獲得持久化數(shù)據(jù)
新建數(shù)據(jù)池database
操作完以上點(diǎn)擊下一步
點(diǎn)擊Finish,數(shù)據(jù)庫(kù)連接池就做好了
hibernate配置
操作完以上記得ctrl+s保存,這樣hibernate就配置好了。
接下來(lái)我們看一下hibernate的配置文件
hibernate逆向工程(獲得model實(shí)體類)
點(diǎn)擊ok,
下一步
直接下一步
點(diǎn)擊后會(huì)出現(xiàn)如下
選擇yes
到此步逆向工程就完成了。
接下來(lái)可以寫一些類
business.basic包(放置基類及幫助類)
business.dao包(放置業(yè)務(wù)接口供給調(diào)用)
創(chuàng)建一個(gè)用戶業(yè)務(wù)接口
選擇interface,下一步
點(diǎn)擊finish,接口類就創(chuàng)建好了。
UserDAO代碼如下(一般書寫登錄及增刪查改接口)
business.impl包(放置接口實(shí)現(xiàn)類)
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-XTSG4bfP-1574340786841)(https://img-blog.c sdnimg.cn/20191121192641243.png)]
代碼如下
business.factory包(放置工廠類)
工廠里整合了接口和接口實(shí)現(xiàn)類,在action里直接調(diào)用工廠類,就不用再分開調(diào)用接口和接口實(shí)現(xiàn),不用再下實(shí)例化對(duì)象在調(diào)用。
代碼如下
動(dòng)態(tài)工廠
動(dòng)態(tài)工廠
package business.factory; import business.dao.UserDAO; import business.impl.UserDAOImpl; public class StaticDAOFactory {/*** (靜態(tài)方法)返回一個(gè)用于對(duì)用戶信息操作的UserDAO對(duì)象* @return UserDAO*/public static UserDAO getUserDAO(){return new UserDAOImpl();}}一般選用動(dòng)態(tài)。
spring配置
可創(chuàng)建bean來(lái)管理接口及接口實(shí)現(xiàn)(將接口及接口實(shí)現(xiàn)、工廠注冊(cè)給bean,配置好后交給spring統(tǒng)一管理)也可直接在session工廠利配置
平常的java開發(fā)中,程序員在某個(gè)類中需要依賴其它類的方法,則通常是new一個(gè)依賴類再調(diào)用類實(shí)例的方法,這種開發(fā)存在的問(wèn)題是new的類實(shí)例不好統(tǒng)一管理,spring提出了依賴注入的思想,即依賴類不由程序員實(shí)例化,而是通過(guò)spring容器幫我們new指定實(shí)例并且將實(shí)例注入到需要該對(duì)象的類中。依賴注入的另一種說(shuō)法是“控制反轉(zhuǎn)”,通俗的理解是:平常我們new一個(gè)實(shí)例,這個(gè)實(shí)例的控制權(quán)是我們程序員,而控制反轉(zhuǎn)是指new實(shí)例工作不由我們程序員來(lái)做而是交給spring容器來(lái)做。
創(chuàng)建一個(gè)新springbean來(lái)注冊(cè)管理,我們命名為bean1
選擇other
下一步
選擇sping鏈接(根據(jù)所需配置加載)
勾選如上復(fù)選框,點(diǎn)擊Finish,springbean就創(chuàng)建好了。
接下來(lái)配置bean
這里講一下靜態(tài)工廠的方法注入
靜態(tài)工廠顧名思義,就是通過(guò)調(diào)用靜態(tài)工廠的方法來(lái)獲取自己需要的對(duì)象,為了讓spring管理所有對(duì)象,我們不能直接通過(guò)"工程類.靜態(tài)方法()"來(lái)獲取對(duì)象,而是依然通過(guò)spring注入的形式獲取:
工程項(xiàng)目下的web.xml的配置
到此步springbean就配置成功了。
struts.xml配置
為了更好的進(jìn)行配置,我們選擇視圖界面配置
建好后的視圖界面
首先我們先創(chuàng)建如下幾個(gè)jsp和css文件
接下來(lái)添加action
配置失敗返回參數(shù)
如果跳轉(zhuǎn)到網(wǎng)頁(yè)可以使用dispatcher,頁(yè)面跟共用響應(yīng)對(duì)象
redirect簡(jiǎn)單的重定位,不共用響應(yīng)對(duì)象
redirectAction action跳轉(zhuǎn)action,不共用響應(yīng)對(duì)象
建立好的包視圖
看看他的配置文件
它的參數(shù)要在action里定義才會(huì)生效
接下來(lái)就可以書寫action了
打開新建好的LoginAction類
公共封裝方法命名為BaseAction如下
當(dāng)struts接受這個(gè)action請(qǐng)求時(shí),struts調(diào)用 username的get方法把前臺(tái)的值傳到action中的username,當(dāng)action處理完成,要返回到頁(yè)面時(shí)。在生成jsp的過(guò)程中,你可以在頁(yè)面中使用EL表達(dá)式,${username}進(jìn)行綁值,這時(shí)調(diào)用username的set方法。
在jsp頁(yè)面頂部導(dǎo)入el表達(dá)式標(biāo)簽連接
LoginAction類
success.jsp代碼
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"><title>SSH</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="SSH"></head><body> <h2>當(dāng)前的登錄用戶為:<span style="color:yellow; font:bold">${loginuser.username} </span></h2>添加user,如果姓名沒(méi)有沖突,那么就添加到數(shù)據(jù)庫(kù),如果姓名沖突了就不能添加,返回失敗頁(yè)面<form action="add.action" method="get">UserName:<input type="text" name="user.username"><br />UserPassword:<input type="password" name="user.userpassword"><br />UserMessage:<input type="text" name="user.usermessage"><br /><input type="submit" value="提交"> <input type="reset"value="重置"></form>根據(jù)姓名查詢,若不輸入,則查詢?nèi)?lt;form action="query.action" method="post">UserName: <input type="text" name="queryText" value="${searchText }" /><input type="submit" value="查詢" /></form><table width="70%" border="1px" align="center" cellpadding="0"cellspacing="0"><thead><tr bgcolor="#ff0"><th width="25%">編號(hào)</th><th width="25%">姓名</th><th width="25%">信息</th><th width="25%">操作</th></tr></thead><tbody><c:forEach var="user" items="${users }"><tr><td>${user.id}</td><td>${user.username}</td><td>${user.usermessage}</td><td><a href="edit.action?param=0&id=${user.id}">編輯</a> <ahref="delete.action?id=${user.id}">刪除</a></td></tr></c:forEach></tbody></table></body> </html>fail.jsp代碼
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%String path = request.getContextPath();String basePath = request.getScheme() + "://"+ request.getServerName() + ":" + request.getServerPort()+ path + "/"; %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"><title>fail</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="fail"></head><body><div style="color:red;">fail</div><br/><center><p><h2>${errorsText}</h2></p></center><div id = "foot"><a href="${backurl}">返回上一頁(yè)面</a></div><!-- <a href="query.action?queryText=">返回主頁(yè)</a> --> </body> </html>建立好如上,運(yùn)行測(cè)試
輸入為空測(cè)試
輸入賬號(hào)密碼測(cè)試
輸入后會(huì)報(bào)如上錯(cuò)誤
經(jīng)過(guò)一番上網(wǎng)查詢測(cè)試,發(fā)現(xiàn):
主要 是里面的Structs 1.3 (structs 2)和Hibernate 3.2(或更高版本)中的JAR包里antlr2.7.2 與 antlr2.7.6 沖突,只要?jiǎng)h除Structs 1.3中的低版本的antlr2.7.2就可以了。具體操作如下:在MyEclipse 下,windows–>preferences–>在文本框中搜索struts2–>選擇 antlr2.7.2–>remove
現(xiàn)在重啟Tomcat再次測(cè)試:
現(xiàn)在登陸成功了,并且獲取到了用戶名。
在測(cè)試查詢時(shí),利用<c:forEach items>查詢多條記錄可以正常使用,但存在的單條記錄會(huì)報(bào)錯(cuò)。如下
經(jīng)過(guò)小編多放查證,終于發(fā)現(xiàn):
在訪問(wèn)某個(gè)頁(yè)面出現(xiàn)了上標(biāo)題所示的異常。一開始我也不知道什么原因,因?yàn)楹笈_(tái)已經(jīng)返回了數(shù)據(jù),而且前端的el/jstl表達(dá)式都寫的沒(méi)毛病。
后來(lái)無(wú)意中想到,我這個(gè)數(shù)據(jù)是確定的只有一條,但是我還是用的<c:forEach>來(lái)寫。然后我把數(shù)據(jù)包裝了一下,雖然只有一條數(shù)據(jù),但是我返回的還是一個(gè)list集合就沒(méi)問(wèn)題啦(重新寫了一個(gè)接口)
改變后的action
測(cè)試通過(guò)
項(xiàng)目完整演示:
注意
本項(xiàng)目的SSH框架中spring是以單spring框架搭建(單純的整合hibernate數(shù)據(jù)庫(kù)連接,其間的接口及其注入配置貌似沒(méi)有什么作用,其實(shí)實(shí)配置不配置程序都能運(yùn)行。)而在實(shí)際項(xiàng)目開發(fā)中多是spring與其他技術(shù)架構(gòu)結(jié)合的,比如springMVC、springBoot等等。這些項(xiàng)目框架會(huì)在后續(xù)博文中給大家呈現(xiàn)。
項(xiàng)目中有什么錯(cuò)誤之處,希望有心之人在評(píng)論中指出或私發(fā)消息討論。
此項(xiàng)目用SSH框架搭建,實(shí)現(xiàn)了用戶的登錄、查詢、刪除、添加。
項(xiàng)目(源碼+數(shù)據(jù)庫(kù))我已上傳至gitee碼云上,有需要的可以進(jìn)行下載:
GITEE碼云地址:https://gitee.com/zhangyant/SSHtest
記得更改hibernate數(shù)據(jù)庫(kù)連接(導(dǎo)入sql文件夾中sql語(yǔ)句)。
另一種ssh架構(gòu)可參考:https://www.cnblogs.com/acm-bingzi/p/ssh.html
本人覺(jué)得此方法有點(diǎn)難以理解(–^^–)。
總結(jié)
以上是生活随笔為你收集整理的JAVAweb之SSH框架的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: node2vec 包安装
- 下一篇: EEGLAB在MATLAB中的下载、安装