我們所學(xué)習(xí)的技術(shù)框架有很多_第1頁
我們所學(xué)習(xí)的技術(shù)框架有很多_第2頁
我們所學(xué)習(xí)的技術(shù)框架有很多_第3頁
我們所學(xué)習(xí)的技術(shù)框架有很多_第4頁
我們所學(xué)習(xí)的技術(shù)框架有很多_第5頁
已閱讀5頁,還剩121頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論