版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
我們所學(xué)習(xí)的技術(shù)框架有很多,例如struts1、struts2、JSF、Spring、SpringMVC、Hibernate、ibatis····在上篇博客我說了我們可能在開發(fā)的路途上會要學(xué)習(xí)這些框架,我也給出了我對框架學(xué)習(xí)的幾點:
我們首先要看一下這個框架屬于開發(fā)結(jié)構(gòu)中的那一層。因為我們的開發(fā)都是要用分層的思想來做的,所以我們第一個就要看看我們開發(fā)分層中,各個層次之間有哪些框架。
我們從圖上看到了那些框架屬于哪一層的(這里還有很多框架沒有涉及到)。之后我們來看一些常用的框架(這個常用相對于個人而言,我這里所說的常用針對我自己來說,如果這里我沒有介紹全的話,大家可以到相關(guān)的框架官網(wǎng)去查閱一下資料自主學(xué)習(xí))。
下面我就簡單的介紹一些我經(jīng)常使用的框架的結(jié)構(gòu)和一些分析:
Struts框架(分為struts1和struts2):
一、Struts框架結(jié)構(gòu)圖:
優(yōu)點:
1.Struts框架是一個基于mvc的框架,所以它繼承了所有mvc的優(yōu)點,例如:復(fù)用性好,團(tuán)隊開發(fā)分工明確,結(jié)構(gòu)層次分明等
2.給程序開發(fā)者在servlet層上節(jié)約了大量的開發(fā)時間,應(yīng)用程序開發(fā)者不再去觸及大量的servlet的編寫,僅僅變換為配置文件。
二、Struts1框架
1.框架的結(jié)構(gòu)圖:
2.Struts1框架有五個常用對象:actionservlet、actionmapping、actionform、action、actionforward
a)Actionservlet是核心控制,URL地址映射、ActionForm的匹配、Action的執(zhí)行都需要這個類來進(jìn)行導(dǎo)航
b)Actionmapping:它們可將請求URI映射到Action類,并且將Action類與ActionFormbean相關(guān)聯(lián)
c)Actionform:收集表單數(shù)據(jù)
d)Action:完成所需的業(yè)務(wù)邏輯,確定要跳轉(zhuǎn)的頁面
e)Actionforward:用來封裝轉(zhuǎn)發(fā)路徑的
3.Struts1框架的執(zhí)行流程:
1)檢索和用戶匹配的ActionMapping實例,如果不存在,就返回請求路徑無效的錯誤信息
2)如果ActionForm實例不存在,就創(chuàng)建一個ActionForm的對象,把客戶提交的表單數(shù)據(jù)封裝到ActionForm對象中。
3)根據(jù)配置信息決定是否要進(jìn)行表單驗證,如果需要,就調(diào)用ActionForm的validate()方法
4)如果validate()方法放回null,或者并不包含ActionMessage的ActionError對象,就表示驗證成功
5)ActionServlet根據(jù)ActionMapping所包含的映射信息決定將請求轉(zhuǎn)發(fā)給那個action,如果相應(yīng)的action實例不存在,就先創(chuàng)建這個action對象,然后再調(diào)用這個action的excute()方法
6)action的execute()方法返回一個ActionForword對象,ActionServlet會把客戶請求轉(zhuǎn)發(fā)給ActionForword對象所指向的JSP組件
7)ActionForword對象指向JSP組件生成動態(tài)網(wǎng)頁返回給客戶
4.優(yōu)點:和struts框架的優(yōu)點相同
5.缺點:
1)表現(xiàn)層技術(shù)單一:僅能用jsp
2)與servletAPI耦合性高,難于測試(httpservletrequest、httpservletresponse)
3)嚴(yán)重依賴于ServletAPI(繼承action,繼承actionform),與struts1框架耦合性太高
這篇博客就寫到這里,如果再寫篇幅可能會過長,對讀者的閱讀造成負(fù)面影響,所以我會在下面的博客中陸續(xù)介紹我經(jīng)常使用的框架,當(dāng)然我也會在這些同層之間的框架的分析中加入各個框架的區(qū)別,當(dāng)然在適當(dāng)?shù)牡胤綍嬕恍﹫D片來表示他們之間的知識關(guān)聯(lián)性,希望讀者能夠我一些建議和意見。
在上篇博客中,我簡單的介紹了我們分層開發(fā)中每一層中擁有的框架,而且介紹了我常用的框架struts1的結(jié)構(gòu)和原理分析,那么今天我繼續(xù)介紹我熟悉的框架struts2的框架的結(jié)構(gòu)和原理分析。
在說struts2框架之前,我要先介紹另外一個框架webwork框架,這個框架也是一個mvc的框架,這個框架的設(shè)計思路是采用攔截鏈將用戶的請求的數(shù)據(jù)轉(zhuǎn)發(fā)到Action中,并負(fù)責(zé)將Action的處理結(jié)果轉(zhuǎn)換成對用戶的響應(yīng)。它的這種設(shè)計思路能夠和ServletAPI分離,鑒于我們的上篇博客介紹的struts1的缺點,所以webwork框架解決了struts1的這個缺點。
我們來看一下webwork框架的結(jié)構(gòu)圖:
有了這個流程圖,我就不給大家講解具體的原理流程了,它采用的是攔截鏈的機(jī)制,通過這些攔截鏈完成用戶的相應(yīng)請求,從而與servletAPI分離,當(dāng)與servlet分離開的時候,也就是表明和容器解耦了;另外,我們從結(jié)構(gòu)圖中看到它的視圖模版有jsp、FreeMarker等等,它的表示層技術(shù)比struts1框架的飽滿許多。
所以,webwork框架解決了struts1框架存在的問題,而且它的設(shè)計思路是非常好的,鑒于此,struts2框架就在struts1框架的基礎(chǔ)上引入了webwork框架的設(shè)計思路應(yīng)運而生了。所以我們就能夠發(fā)現(xiàn)struts2兼具struts1的特性而且通過引入webwork框架的設(shè)計思路解決了struts1的一些缺點。
struts2框架的大致的體系圖:
從圖中我們能夠看出它是引入的webwork框架的設(shè)計思路,而且它也是基于mvc的一個開源的框架。之后我們來說一下struts2框架的一個執(zhí)行流程(流程圖和webwork框架非常類似):
瀏覽器發(fā)送請求,通過幾層過濾器完成一些功能,之后到actionmapper中,之后將請求傳到核心控制器中核心控制器filterDispatcher根據(jù)請求決定調(diào)用合適的Action調(diào)用webwork的攔截器鏈自動請求通用功能,如校驗之類的操作回調(diào)action的execute方法,獲取用戶請求執(zhí)行相應(yīng)的業(yè)務(wù)邏輯之后返回字符串,匹配result,之后跳轉(zhuǎn)到相應(yīng)的視圖或其他的文檔之后在執(zhí)行相應(yīng)的攔截器鏈自動請求功能,隨后轉(zhuǎn)到web客戶端。
這樣我們就對struts2框架的結(jié)構(gòu)上的東西做了一個簡單的介紹。在上篇博客講解了struts1框架,所以有必要在這里對他倆進(jìn)行一下對比(我僅僅總結(jié)了五條我認(rèn)為比較重要的,以后如果發(fā)現(xiàn)其他的在隨時補充):
在Action實現(xiàn)類方面的對比(struts1的Action繼承action,struts2實現(xiàn)接口,也可以不實現(xiàn),可以定制服務(wù))線程模式方面的對比(struts1存在線程安全問題,struts2不存在)
ServletAPI依賴方面的對比(struts1依賴servletAPI,struts2不是)可測性方面的對比(struts1難測試,依賴容器,struts2不是)封裝請求參數(shù)的對比(struts1使用actionform;struts2直接寫到action,并且支持pojo對象)
在上篇博客中介紹了struts2框架的原理和流程分析,可以說struts框架一路走來,改變非常大,而且讓我們開發(fā)人員變得更加輕松,里面的設(shè)計理念的改變也是讓我們編程人員的思路得到更大的擴(kuò)展。
可以說,一個先進(jìn)的技術(shù)或者框架就是要不斷的進(jìn)步才能永遠(yuǎn)讓編程人員喜歡和使用,一個優(yōu)秀的編程人員也是要不斷的進(jìn)步才能永遠(yuǎn)讓這個世界變得更加絢麗多彩。
其實編程就是這樣有意思的!
前面說了一些宏觀上學(xué)習(xí)框架相關(guān)的思想方面的東西,下面繼續(xù)來介紹我經(jīng)常使用的框架和框架的分析,這篇博客主要介紹的是hibernate框架。
首先說hibernate框架是數(shù)據(jù)持久層的框架,這個框架是非常強大的,它讓編程人員純粹的用面向?qū)ο蟮姆绞絹碜鲩_發(fā),讓編程人員所面對的都是對象。僅僅從這一點它的設(shè)計思路就是非常讓編程人員喜愛的。
回想我們普通的開發(fā)流程,和客戶溝通定需求,抽象出來原型,從原型中建立數(shù)據(jù)模型到庫表結(jié)構(gòu)的建立,之后在映射成對象模型,之后在用oo的設(shè)計思想完成后續(xù)的程序開發(fā)。但是當(dāng)我們使用了hibernate框架以后,原先的設(shè)計思路就顯得不再那么具有優(yōu)勢了。我們直接建立對象模型,之后利用hibernate框架映射成數(shù)據(jù)模型,我們不再去考慮數(shù)據(jù)庫關(guān)系模型的東西,僅僅考慮的東西僅僅就是類和對象,這樣的開發(fā)才是面向?qū)ο蟮拈_發(fā),也才是最接近人類思考問題的方式。所以hibernate框架的設(shè)計思路是非常好的。
hibernate框架設(shè)計思路的優(yōu)越性其實體現(xiàn)在了它本身的框架的原理上。hibernate封裝了JDBC,減輕了開發(fā)人員在持久層的大量重復(fù)性工作,它利用了java反射機(jī)制來實現(xiàn)程序的透明性;它就是通過這兩點才達(dá)到從對象出發(fā)而非關(guān)系數(shù)據(jù)庫出發(fā)的效果。
介紹這么多理論性的東西之后我們能夠感覺到hibernate框架的強大,來看看它的結(jié)構(gòu)圖:
在hibernate框架中有幾個比較重要的接口和類:Query接口:Query負(fù)責(zé)執(zhí)行各種數(shù)據(jù)庫查詢。它可以使用HQL語句或SQL語句兩種表達(dá)方式。Configuration類:Configuration類負(fù)責(zé)配置并啟動Hibernate,創(chuàng)建SessionFactory對象SessionFactory接口:SessionFactory接口負(fù)責(zé)初始化Hibernate。它充當(dāng)數(shù)據(jù)存儲源的代理,并負(fù)責(zé)創(chuàng)建Session對象Session接口:Session接口負(fù)責(zé)執(zhí)行被持久化對象的CRUD操作Transaction接口:Transaction接口負(fù)責(zé)事務(wù)相關(guān)的操作
hibernate框架就是在利用這幾個接口來封裝了JDBC,而且我們用這些接口來操作數(shù)據(jù)庫變得非常簡單,減少了我們在持久層的代碼量。
從這個結(jié)構(gòu)圖和我的一些分析就能發(fā)現(xiàn)hibernate框架是非常強大,而且它給我們開發(fā)人員的開發(fā)帶來了非常大的便利,尤其是他的設(shè)計思路還有它的“全自動”的映射對象模型和關(guān)系模型。
但是hibernate框架也有它的一些缺點:既然是封裝了JDBC,所以很明顯它沒有JDBC的效率高,尤其是在大量的處理表更新操作的時候。它有局限性,一個持久化類不能映射多個表它應(yīng)對大數(shù)量的時候顯得非常笨拙,這一點沒有JDBC和接下來要介紹的IBatis框架
其實一項技術(shù)或者一個框架都有它的優(yōu)缺點,選擇最合適的才是王道。
這篇博客主要是介紹了hibernate框架的結(jié)構(gòu)和分析,闡述了hibernate框架的優(yōu)缺點,【具體詳細(xì)使用要等到我的框架學(xué)習(xí)的后續(xù)文章】??偟膩碚fhibernate框架在持久層的作用非常明顯,我們懂得了它的優(yōu)缺點之后,才能做到我們是否是要選擇這個框架作為我們持久層開發(fā)的必須的技術(shù)支撐,所以這些我常用的框架結(jié)構(gòu)和分析不單單是在介紹一些框架學(xué)習(xí)的宏觀知識把控,更多的是在為將來做項目開發(fā)中選擇合適的技術(shù)支撐做鋪墊。
后續(xù)的博客在不斷更新,希望這些博客能夠?qū)ψx者的開發(fā)過程帶來幫助,當(dāng)然如果讀者對我的博客有什么好的建議或者意見,請與我聯(lián)系。聯(lián)系方式見博客側(cè)邊欄!
先看MVC模式流程圖(其實MVC設(shè)計模式就是java中的model2。):
就像圖上所標(biāo)識的C層主要是Servlet層控制頁面跳轉(zhuǎn),M層就是具體的業(yè)務(wù)處理邏輯,而JSP就是所謂的V層。MVC是有別于我們所說的三層,我們平常所說的三層是UI層、BLL層、DAL層,具體的區(qū)別如圖:
從圖上能看出來,JSP和Servlet構(gòu)成了UI層,而Model層分成了BLL層和DAL層(也就是業(yè)務(wù)邏輯和數(shù)據(jù)持久層)。
從理論上認(rèn)清了MVC設(shè)計模式之后,下面開始動手敲一個MVC設(shè)計模式示例代碼:
JSP索引頁面index.jsp:
[html]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?<%@
page
language="java"
contentType="text/html;
charset=GB18030"
pageEncoding="GB18030"%>
<!DOCTYPE
html
PUBLIC
"-//W3C//DTD
HTML
4.01
Transitional//EN"
"/TR/html4/loose.dtd">
<html>
<head>
<meta
http-equiv="Content-Type"
content="text/html;
charset=GB18030">
<title>Insert
title
here</title>
</head>
<body>
<form
action="servlet/addUser.action"
method="post">
姓名:<input
type="text"
name="username"
>
<input
type="submit"
value="提交">
</form>
</body>
</html>
業(yè)務(wù)邏輯代碼UserManager:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.util.ArrayList;
import
java.util.List;
public
class
UserManager
{
public
void
addUser(String
username){
System.out.println("UserManager.addUsre()>username:"+username);
}
public
void
delUser(String
username){
System.out.println("UserManager.delUser()>username:"+username);
}
public
void
modifyUser(String
username){
System.out.println("UserManager.modifyUser()>username"+username);
}
public
List
queryUser(String
username){
System.out.println("UserManager.queryUser()>username"+username);
List
userList=new
ArrayList();
userList.add("a");
userList.add("b");
userList.add("c");
return
userList;
}
}
Servlet控制代碼:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
//userManager.addUser(username);
String
forward="";
if("/servlet/delUser".equals(path)){
userManager.delUser(username);
forward="/del_success.jsp";
}else
if("/servlet/addUser".equals(path)){
userManager.addUser(username);
forward="/add_success.jsp";
}else
if("/servlet/modifyUser".equals(path)){
userManager.modifyUser(username);
forward="/modify_success.jsp";
}else
if("/servlet/queryUser".equals(path)){
List
userList=userManager.queryUser(username);
request.setAttribute("userList",
userList);
forward="/query_success.jsp";
}else{
throw
new
RuntimeException("請求失敗");
}
request.getRequestDispatcher(forward).forward(request,
response);
}
這個servlet代碼主要實現(xiàn)的功能判斷是那個頁面請求服務(wù)器做那些操作,之后調(diào)用業(yè)務(wù)邏輯實現(xiàn)相應(yīng)業(yè)務(wù)操作。
配置Servlet:
[html]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?<?xml
version="1.0"
encoding="UTF-8"?>
<web-app
xmlns:xsi="/2001/XMLSchema-instance"
xmlns="/xml/ns/javaee"
xmlns:web="/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="/xml/ns/javaee
/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID"
version="3.0">
<display-name>test_Servlet</display-name>
<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>
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.cjq.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
輸出結(jié)果:
通過上面的示例已經(jīng)對MVC設(shè)計模式有了初步的認(rèn)識,其實這個示例是對Struts框架學(xué)習(xí)的基礎(chǔ),只有弄清楚了這個實例才能弄清楚Struts框架的實現(xiàn)原理和Struts框架使用。
那么我們怎么才能通過這個示例引入Struts框架呢?這個問題從IF-Eles開始。
首先我們看到了TestServlet中出現(xiàn)了許多if-else語句,這樣是非常不穩(wěn)定的,這樣的程序是非常不靈活的,以后如果有變化,那么維護(hù)是非常差的;而且我們在if-else中出現(xiàn)了大量的字符串,這樣在coding的時候會出現(xiàn)寫錯,這樣無形中給調(diào)試帶來了麻煩。所以去掉if-else成了我們重構(gòu)的第一步,也是我們進(jìn)行Struts框架學(xué)習(xí)的第一步。
如何才能去掉If-ELSE呢?請看下一篇文章《深入淺出學(xué)習(xí)Struts1框架(二):重構(gòu)MVC模式代碼中跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯》。
在上篇博文《深入淺出學(xué)習(xí)Struts1框架(一):一個簡單mvc模式代碼示例開始》中簡單說了一下MVC模式代碼的實現(xiàn)和MVC模式和三層架構(gòu)的區(qū)別,并且留下一個問題—如何去掉TestServlet中的IF-Else語句塊。
因為在TestServlet中出現(xiàn)了If-Else語句塊,所以讓程序變得不再靈活,讓應(yīng)付需求變化時變得笨拙。所以就承接上篇文章來重構(gòu)一下TestServlet代碼,主要是用繼承多肽來進(jìn)一步對TestServlet進(jìn)行重構(gòu)。雖然這一篇文章最后沒有將if-else徹底去掉,但是比起上篇文章的代碼顯得更加靈活,也為下一篇徹底去掉If-else埋下伏筆。
下面進(jìn)入重構(gòu)階段:
先看一下上篇文章的TestServlet代碼:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
//userManager.addUser(username);
String
forward="";
if("/servlet/delUser".equals(path)){
userManager.delUser(username);
forward="/del_success.jsp";
}else
if("/servlet/addUser".equals(path)){
userManager.addUser(username);
forward="/add_success.jsp";
}else
if("/servlet/modifyUser".equals(path)){
userManager.modifyUser(username);
forward="/modify_success.jsp";
}else
if("/servlet/queryUser".equals(path)){
List
userList=userManager.queryUser(username);
request.setAttribute("userList",
userList);
forward="/query_success.jsp";
}else{
throw
new
RuntimeException("請求失敗");
}
request.getRequestDispatcher(forward).forward(request,
response);
}
}
首先我們看到了在每個語句塊中都出現(xiàn)了給forward賦值,其實也就是給頁面跳轉(zhuǎn)的路徑賦值,針對每個請求路徑判斷來賦值跳轉(zhuǎn)路徑。另外每個IF-Else語句塊中都有業(yè)務(wù)處理,我們要把這些業(yè)務(wù)處理分別放到類里面,讓職責(zé)更加單一,這樣更加符合面向?qū)ο蟮乃悸贰?/p>
就從這里我們開始重構(gòu),我們可以將這個跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯封裝起來。
既然封裝,那么我們就抽象出來一個借口,主要完成一個方法,這個方法主要的功能就是要完成業(yè)務(wù)邏輯封裝和路徑跳轉(zhuǎn)的返回。隨后建立四個類,主要實現(xiàn)相應(yīng)的增刪改查的業(yè)務(wù)處理和處理之后的跳轉(zhuǎn)路徑返回。
代碼如下:
接口Action:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
interface
Action
{
public
String
execute(HttpServletRequest
request,HttpServletResponse
response)
throws
Exception;
}
增刪改查實現(xiàn)類:
添加用戶實現(xiàn)類:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?<pre
name="code"
class="java">package
com.cjq.servlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
AddUserAction
implements
Action
{
public
String
execute(HttpServletRequest
request,
HttpServletResponse
response)
throws
Exception
{
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
userManager.addUser(username);
return
"/add_success.jsp";
}
}</pre><br><br>
刪除用戶實現(xiàn)類:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
DelUserAction
implements
Action
{
public
String
execute(HttpServletRequest
request,
HttpServletResponse
response)
throws
Exception
{
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
userManager.delUser(username);
return
"/del_success.jsp";
}
}
更新用戶實現(xiàn)類:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
ModifyUserAction
implements
Action
{
@Override
public
String
execute(HttpServletRequest
request,
HttpServletResponse
response)
throws
Exception
{
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
userManager.modifyUser(username);
return
"/modify_success.jsp";
}
}
查詢用戶實現(xiàn)類:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.util.List;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
QueryUserAction
implements
Action
{
@Override
public
String
execute(HttpServletRequest
request,
HttpServletResponse
response)
throws
Exception
{
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
List
userList=userManager.queryUser(username);
request.setAttribute("userList",
userList);
return
"/query_success.jsp";
}
}
TestServlet類重構(gòu)如下:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
Action
action=null;
if("/servlet/delUser".equals(path)){
action=new
DelUserAction();
}else
if("/servlet/addUser".equals(path)){
action=new
AddUserAction();
}else
if("/servlet/modifyUser".equals(path)){
action=new
ModifyUserAction();
}else
if("/servlet/queryUser".equals(path)){
action=new
QueryUserAction();
}else{
throw
new
RuntimeException("請求失敗");
}
String
forward=null;
try{
forward=action.execute(request,
response);
}catch(Exception
e){
e.printStackTrace();
}
request.getRequestDispatcher(forward).forward(request,
response);
}
}
運行結(jié)果:
這樣TestServlet類雖然沒有徹底去掉If-Else,但是這樣的代碼變得更加簡練,利用多肽實現(xiàn)業(yè)務(wù)邏輯處理和路徑跳轉(zhuǎn)返回。職責(zé)更加清晰,讓維護(hù)變得更加輕松。
問題遺留:
If-else語句塊沒有徹底剔除,而且程序中依舊出現(xiàn)了過多的字符串,所以程序依舊是不靈活,而且字符串過多增加調(diào)試的復(fù)雜性。所以下一篇文章就把if-else語句塊剔除,并且把字符串放到配置文件來用dom4j來動態(tài)讀取。
我們離Struts框架越來越近,當(dāng)我們把if-else和字符串剔除之后就會出現(xiàn)Struts框架的雛形。期待下一篇文章。
在《深入淺出學(xué)習(xí)Struts1框架(一):一個簡單mvc模式代碼示例開始》和《深入淺出學(xué)習(xí)Struts1框架(二):重構(gòu)MVC模式代碼中跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯》文章中已經(jīng)說了分層和mvc模式的區(qū)別,和一些為了去掉mvc模式代碼中的TestServlet類中的if-else。因為if-else在程序代碼中是相對不穩(wěn)定的,所以通過去掉if-else來引入對struts框架的學(xué)習(xí)。
在《深入淺出學(xué)習(xí)Struts1框架(二):重構(gòu)MVC模式代碼中跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯》中我們已經(jīng)抽象出來了一個接口和四個實現(xiàn)類,主要封裝了業(yè)務(wù)處理和頁面跳轉(zhuǎn)路徑字符串放回,以便利用多肽來重構(gòu)了TestServlet代碼(具體見博客)。
在上兩篇博客我們遺留了兩個問題,一是if-else,二是字符串太多。今天這篇博客就要解決這兩個問題。
上一篇TestServlet重構(gòu)后的代碼:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
Action
action=null;
if("/servlet/delUser".equals(path)){
action=new
DelUserAction();
}else
if("/servlet/addUser".equals(path)){
action=new
AddUserAction();
}else
if("/servlet/modifyUser".equals(path)){
action=new
ModifyUserAction();
}else
if("/servlet/queryUser".equals(path)){
action=new
QueryUserAction();
}else{
throw
new
RuntimeException("請求失敗");
}
String
forward=null;
try{
forward=action.execute(request,
response);
}catch(Exception
e){
e.printStackTrace();
}
request.getRequestDispatcher(forward).forward(request,
response);
}
}
解決字符串問題,當(dāng)然就要用到配置文件了,用到配置文件就要有用來讀取配置文件的相關(guān)的類和方法,這里就用dom4j中的類來讀取配置文件,這里的配置文件的書寫是有點邏輯上的難度的。
我們來看TestServlet中的代碼,我們要在這個testservlet中實現(xiàn)讀取配置文件和path比較,還有利用多肽實例化相應(yīng)的實現(xiàn)類,最后通過實例化的實現(xiàn)類的方法來返回跳轉(zhuǎn)路徑,最終跳轉(zhuǎn)到相應(yīng)的頁面。
所以我們的配置文件就要不僅配上testservlet中出現(xiàn)的字符串,還要配置相應(yīng)的Action接口的實現(xiàn)類(我們可以利用反射來實例化該類的對象,進(jìn)而使用這個類的所有屬性和方法),另外還有跳轉(zhuǎn)路徑字符串。這樣我們的配置文件就變成了如下代碼所示:[html]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?<?xml
version="1.0"
encoding="UTF-8"?>
<action-config>
<action
path="/servlet/delUser"
type="com.cjq.servlet.DelUserAction">
<forward
name="success">/del_success.jsp</forward>
<forward
name="error">/del_error.jsp</forward>
</action>
<action
path="/servlet/addUser"
type="com.cjq.servlet.AddUserAction">
<forward
name="success">/add_success.jsp</forward>
<forward
name="error">/add_error.jsp</forward>
</action>
<action
path="/servlet/modifyUser"
type="com.cjq.servlet.ModifyUserAction">
<forward
name="success">/modify_success.jsp</forward>
<forward
name="error">/modify_error.jsp</forward>
</action>
<action
path="/servlet/queryUser"
type="com.cjq.servlet.QueryUserAction">
<forward
name="success">/query_success.jsp</forward>
<forward
name="error">/query_error.jsp</forward>
</action>
</action-config>
我們有了配置文件之后就要想法通過相關(guān)類讀取,并且實現(xiàn)相應(yīng)的功能。所以這里用dom4j來讀取完成。其實如果能把這個邏輯捋順之后就能發(fā)現(xiàn),其實懂我們利用dom4j讀取完配置文件的時候,我們是取得的是一個配套的匹配路徑字符串、相應(yīng)業(yè)務(wù)邏輯類還有處理業(yè)務(wù)邏輯之后跳轉(zhuǎn)頁面路徑字符串。這樣我們就能直截了當(dāng)?shù)娜サ袅薸f-else。(這里可能邏輯上會出現(xiàn)一些困難,但是看到下面的重構(gòu)之后的testservlet中的代碼和讀取配置文件之后的代碼就會一目了然)。
現(xiàn)在等待解決的問題就是我們要把從配置文件取得的一整套內(nèi)容放到那里,當(dāng)然這是毋庸置疑的要放到類中。所以我們就建立一個ActionMapping類來放我們的那一整套內(nèi)容。
ActionMapping中的代碼如下:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.util.Map;
public
class
ActionMapping
{
private
String
path;
private
Object
type;
private
Map
forwardMap;
public
String
getPath()
{
return
path;
}
public
void
setPath(String
path)
{
this.path
=
path;
}
public
Object
getType()
{
return
type;
}
public
void
setType(Object
type)
{
this.type
=
type;
}
public
Map
getForwardMap()
{
return
forwardMap;
}
public
void
setForwardMap(Map
forwardMap)
{
this.forwardMap
=
forwardMap;
}
}
現(xiàn)在ActionMapping類已經(jīng)有了,剩下的工作就是要利用dom4j來讀取配置文件類,具體代碼如下:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.InputStream;
import
java.util.HashMap;
import
java.util.Iterator;
import
java.util.Map;
import
org.dom4j.Document;
import
org.dom4j.DocumentException;
import
org.dom4j.Element;
import
org.dom4j.io.SAXReader;
public
class
XmlConfigReader
{
private
static
XmlConfigReader
instance=new
XmlConfigReader();
ActionMapping
actionMapping=new
ActionMapping();
private
Document
doc;
private
Map
actionMap=new
HashMap();
private
XmlConfigReader(){
try
{
SAXReader
reader=new
SAXReader();
InputStream
in=Thread.currentThread().getContextClassLoader().getResourceAsStream("action_config.xml");
doc=reader.read(in);
}
catch
(DocumentException
e)
{
//
TODO
Auto-generated
catch
block
e.printStackTrace();
}
}
public
ActionMapping
getActionMapping(String
path){
synchronized(this){
Object
type=null;
/*if(action.containsKey(path)){
type=action.get(path);
}*/
Element
eltAction
=
(Element)doc.selectObject("http://action[@path=\""
+
path
+
"\"]");
try{
type=Class.forName(eltAction.attributeValue("type")).newInstance();
}catch(Exception
e){
e.printStackTrace();
}
Element
eltForwards
=
eltAction.element("forward");
for
(Iterator
iter
=
eltForwards.elementIterator();
iter.hasNext();)
{
Element
eltForward
=
(Element)
iter.next();
actionMap.put(
eltForward.attributeValue("name"),eltForward.getTextTrim());
}
actionMapping.setPath(path);
actionMapping.setType(type);
actionMapping.setForwardMap(actionMap);
return
actionMapping;
}
}
public
static
synchronized
XmlConfigReader
getInstance(){
return
instance;
}
/**
*
@param
args
*/
public
static
void
main(String[]
args)
{
//
TODO
Auto-generated
method
stub
ActionMapping
actionMapping=XmlConfigReader.getInstance().getActionMapping("/servlet/delUser");
System.out.println(actionMapping.getPath());
System.out.println(actionMapping.getType());
System.out.println(actionMapping.getForwardMap().toString());
}
}
我們通過返回ActionMapping來動態(tài)創(chuàng)建出action相應(yīng)的實現(xiàn)類,進(jìn)而完成業(yè)務(wù)邏輯和頁面跳轉(zhuǎn),重構(gòu)之后的TestServlet代碼如下:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
String
forward="";
ActionMapping
actionMapping=XmlConfigReader.getInstance().getActionMapping(path);
Action
action=(Action)actionMapping.getType();
try
{
forward=action.execute(request,
response);
}
catch
(Exception
e)
{
//
TODO
Auto-generated
catch
block
e.printStackTrace();
}
request.getRequestDispatcher(forward).forward(request,
response);
}
protected
void
doPost(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
doGet(request,response);
}
}
我們可以清晰的看到if-else已經(jīng)沒有了,字符串也已經(jīng)沒有了。通過這篇文章對if-else還有字符串問題的解決,又一次重構(gòu)了testservlet代碼,程序相對靈活許多。通過這一次的重構(gòu),我們已經(jīng)看到了struts框架的雛形,下一篇文章就真正開始了struts框架的學(xué)習(xí)。
下一篇引子:
其實框架就是對程序的高度封裝,我們經(jīng)歷了這三篇文章之后,一步一步重構(gòu),一步一步封裝,逐步向框架靠攏,其實框架沒有什么難的,其實沒有學(xué)習(xí)框架之前感覺挺神秘,其實如果一步一步來研究之后發(fā)現(xiàn)框架就是封裝的高度化,分層的高度化。
下一篇文章《深入淺出學(xué)習(xí)struts1框架(四):從MVC模式代碼認(rèn)識struts框架》就借助剛剛完成的實例來簡單認(rèn)識struts框架,看看真正的struts框架和我們這個mvc小實例有什么相同和相異之處。《深入淺出學(xué)習(xí)Struts1框架(一):一個簡單mvc模式代碼示例開始》分析mvc和三層關(guān)系開始,引出這個mvc設(shè)計模式實例,到《深入淺出學(xué)習(xí)Struts1框架(二):重構(gòu)MVC模式代碼中跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯》抽象封裝業(yè)務(wù)處理和路徑跳轉(zhuǎn),再到《深入淺出學(xué)習(xí)Struts1框架(三):徹底去掉TestServlet中的字符串和if-else語句塊》去掉if-else語句塊和字符串,經(jīng)過三篇文章循序漸進(jìn)的重構(gòu)了一個mvc設(shè)計模式實例,其實也就是重構(gòu)出來了一個struts框架雛形。今天來看看什么是struts1框架。1.
框架
框架(Framework)是整個或部分系統(tǒng)的可重用設(shè)計,表現(xiàn)為一組抽象構(gòu)件及構(gòu)件實例間交互的方法。也就是說框架是一個半成品的應(yīng)用程序。我們所面對的應(yīng)用程序一般都是分為兩部分,一部分是業(yè)務(wù)相關(guān)的組件部分,另一部分是和業(yè)務(wù)無關(guān)的組件部分。而我們知道和業(yè)務(wù)相關(guān)的組件部分的重用性是非常低的,這也是顯而易見的事情;而和業(yè)務(wù)無關(guān)的組件部分,如驗證、異常、程序流程控制等等服務(wù)組件的復(fù)用性是非常高的。所以當(dāng)人們在不同的應(yīng)用程序中抽出共性的組件,構(gòu)成一個半成品應(yīng)用程序,這時候框架就應(yīng)運而生了。2.
Struts1
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 都會廣場整合策略提案
- 豎紋課件大班教學(xué)課件
- 石油合同模板
- 放射技術(shù)三基課件
- 【口才訓(xùn)練】第4課 觀察物體并確定主題《飛機(jī)模型》小學(xué)二年級 課后服務(wù)
- 2024人教版數(shù)學(xué)一年級上冊教案5.6 練一練
- 電器購買押金合同模板
- 2024-2025學(xué)年山東省桓臺一中高三第三次診斷性考試化學(xué)試題試卷含解析
- 第九章 簡單機(jī)械 功 第四節(jié) 功率 教學(xué)設(shè)計
- 竹料運輸合同模板
- 人教版 七年級上冊 音樂 第2單元 祖國頌歌-歌唱祖國 教案
- 第10課《往事依依》教學(xué)課件+2024-2025學(xué)年統(tǒng)編版語文七年級上冊
- 廣東省深圳市2023-2024學(xué)年六年級上學(xué)期語文期中考試試卷(含答案)
- (人教2024版)九年級化學(xué)新教材新教材培訓(xùn) 課件(新標(biāo)題、新框架、新內(nèi)容、新理念、新思路)
- Unit 1 This is me 單元話題滿分范文必背-2024-2025學(xué)年七年級英語上冊
- 2024-2030年中國玻璃鋼酸堿儲罐市場競爭態(tài)勢與發(fā)展現(xiàn)狀調(diào)研研究報告
- 教育中心校文印室外包服務(wù) 投標(biāo)方案(技術(shù)方案)
- 公安招聘輔警考試筆試題及答案
- 08第二部分一考點7各類細(xì)節(jié)信息判斷(教學(xué)設(shè)計)2025版高中英語聽力Ⅰ(高一強化篇)
- 醫(yī)保網(wǎng)絡(luò)安全管理規(guī)章制度
- 安徽2024年安徽機(jī)電職業(yè)技術(shù)學(xué)院人才招聘78人筆試歷年典型考題及考點附答案解析
評論
0/150
提交評論