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

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

我們所學(xué)習(xí)的技術(shù)框架有很多,例如struts1、struts2、JSF、Spring、SpringMVC、Hibernate、ibatis····在上篇博客我說(shuō)了我們可能在開(kāi)發(fā)的路途上會(huì)要學(xué)習(xí)這些框架,我也給出了我對(duì)框架學(xué)習(xí)的幾點(diǎn):

我們首先要看一下這個(gè)框架屬于開(kāi)發(fā)結(jié)構(gòu)中的那一層。因?yàn)槲覀兊拈_(kāi)發(fā)都是要用分層的思想來(lái)做的,所以我們第一個(gè)就要看看我們開(kāi)發(fā)分層中,各個(gè)層次之間有哪些框架。

我們從圖上看到了那些框架屬于哪一層的(這里還有很多框架沒(méi)有涉及到)。之后我們來(lái)看一些常用的框架(這個(gè)常用相對(duì)于個(gè)人而言,我這里所說(shuō)的常用針對(duì)我自己來(lái)說(shuō),如果這里我沒(méi)有介紹全的話(huà),大家可以到相關(guān)的框架官網(wǎng)去查閱一下資料自主學(xué)習(xí))。

下面我就簡(jiǎn)單的介紹一些我經(jīng)常使用的框架的結(jié)構(gòu)和一些分析:

Struts框架(分為struts1和struts2):

一、Struts框架結(jié)構(gòu)圖:

優(yōu)點(diǎn):

1.Struts框架是一個(gè)基于mvc的框架,所以它繼承了所有mvc的優(yōu)點(diǎn),例如:復(fù)用性好,團(tuán)隊(duì)開(kāi)發(fā)分工明確,結(jié)構(gòu)層次分明等

2.給程序開(kāi)發(fā)者在servlet層上節(jié)約了大量的開(kāi)發(fā)時(shí)間,應(yīng)用程序開(kāi)發(fā)者不再去觸及大量的servlet的編寫(xiě),僅僅變換為配置文件。

二、Struts1框架

1.框架的結(jié)構(gòu)圖:

2.Struts1框架有五個(gè)常用對(duì)象:actionservlet、actionmapping、actionform、action、actionforward

a)Actionservlet是核心控制,URL地址映射、ActionForm的匹配、Action的執(zhí)行都需要這個(gè)類(lèi)來(lái)進(jìn)行導(dǎo)航

b)Actionmapping:它們可將請(qǐng)求URI映射到Action類(lèi),并且將Action類(lèi)與ActionFormbean相關(guān)聯(lián)

c)Actionform:收集表單數(shù)據(jù)

d)Action:完成所需的業(yè)務(wù)邏輯,確定要跳轉(zhuǎn)的頁(yè)面

e)Actionforward:用來(lái)封裝轉(zhuǎn)發(fā)路徑的

3.Struts1框架的執(zhí)行流程:

1)檢索和用戶(hù)匹配的ActionMapping實(shí)例,如果不存在,就返回請(qǐng)求路徑無(wú)效的錯(cuò)誤信息

2)如果ActionForm實(shí)例不存在,就創(chuàng)建一個(gè)ActionForm的對(duì)象,把客戶(hù)提交的表單數(shù)據(jù)封裝到ActionForm對(duì)象中。

3)根據(jù)配置信息決定是否要進(jìn)行表單驗(yàn)證,如果需要,就調(diào)用ActionForm的validate()方法

4)如果validate()方法放回null,或者并不包含ActionMessage的ActionError對(duì)象,就表示驗(yàn)證成功

5)ActionServlet根據(jù)ActionMapping所包含的映射信息決定將請(qǐng)求轉(zhuǎn)發(fā)給那個(gè)action,如果相應(yīng)的action實(shí)例不存在,就先創(chuàng)建這個(gè)action對(duì)象,然后再調(diào)用這個(gè)action的excute()方法

6)action的execute()方法返回一個(gè)ActionForword對(duì)象,ActionServlet會(huì)把客戶(hù)請(qǐng)求轉(zhuǎn)發(fā)給ActionForword對(duì)象所指向的JSP組件

7)ActionForword對(duì)象指向JSP組件生成動(dòng)態(tài)網(wǎng)頁(yè)返回給客戶(hù)

4.優(yōu)點(diǎn):和struts框架的優(yōu)點(diǎn)相同

5.缺點(diǎn):

1)表現(xiàn)層技術(shù)單一:僅能用jsp

2)與servletAPI耦合性高,難于測(cè)試(httpservletrequest、httpservletresponse)

3)嚴(yán)重依賴(lài)于ServletAPI(繼承action,繼承actionform),與struts1框架耦合性太高

這篇博客就寫(xiě)到這里,如果再寫(xiě)篇幅可能會(huì)過(guò)長(zhǎng),對(duì)讀者的閱讀造成負(fù)面影響,所以我會(huì)在下面的博客中陸續(xù)介紹我經(jīng)常使用的框架,當(dāng)然我也會(huì)在這些同層之間的框架的分析中加入各個(gè)框架的區(qū)別,當(dāng)然在適當(dāng)?shù)牡胤綍?huì)畫(huà)一些圖片來(lái)表示他們之間的知識(shí)關(guān)聯(lián)性,希望讀者能夠我一些建議和意見(jiàn)。

在上篇博客中,我簡(jiǎn)單的介紹了我們分層開(kāi)發(fā)中每一層中擁有的框架,而且介紹了我常用的框架struts1的結(jié)構(gòu)和原理分析,那么今天我繼續(xù)介紹我熟悉的框架struts2的框架的結(jié)構(gòu)和原理分析。

在說(shuō)struts2框架之前,我要先介紹另外一個(gè)框架webwork框架,這個(gè)框架也是一個(gè)mvc的框架,這個(gè)框架的設(shè)計(jì)思路是采用攔截鏈將用戶(hù)的請(qǐng)求的數(shù)據(jù)轉(zhuǎn)發(fā)到Action中,并負(fù)責(zé)將Action的處理結(jié)果轉(zhuǎn)換成對(duì)用戶(hù)的響應(yīng)。它的這種設(shè)計(jì)思路能夠和ServletAPI分離,鑒于我們的上篇博客介紹的struts1的缺點(diǎn),所以webwork框架解決了struts1的這個(gè)缺點(diǎn)。

我們來(lái)看一下webwork框架的結(jié)構(gòu)圖:

有了這個(gè)流程圖,我就不給大家講解具體的原理流程了,它采用的是攔截鏈的機(jī)制,通過(guò)這些攔截鏈完成用戶(hù)的相應(yīng)請(qǐng)求,從而與servletAPI分離,當(dāng)與servlet分離開(kāi)的時(shí)候,也就是表明和容器解耦了;另外,我們從結(jié)構(gòu)圖中看到它的視圖模版有jsp、FreeMarker等等,它的表示層技術(shù)比struts1框架的飽滿(mǎn)許多。

所以,webwork框架解決了struts1框架存在的問(wèn)題,而且它的設(shè)計(jì)思路是非常好的,鑒于此,struts2框架就在struts1框架的基礎(chǔ)上引入了webwork框架的設(shè)計(jì)思路應(yīng)運(yùn)而生了。所以我們就能夠發(fā)現(xiàn)struts2兼具struts1的特性而且通過(guò)引入webwork框架的設(shè)計(jì)思路解決了struts1的一些缺點(diǎn)。

struts2框架的大致的體系圖:

從圖中我們能夠看出它是引入的webwork框架的設(shè)計(jì)思路,而且它也是基于mvc的一個(gè)開(kāi)源的框架。之后我們來(lái)說(shuō)一下struts2框架的一個(gè)執(zhí)行流程(流程圖和webwork框架非常類(lèi)似):

瀏覽器發(fā)送請(qǐng)求,通過(guò)幾層過(guò)濾器完成一些功能,之后到actionmapper中,之后將請(qǐng)求傳到核心控制器中核心控制器filterDispatcher根據(jù)請(qǐng)求決定調(diào)用合適的Action調(diào)用webwork的攔截器鏈自動(dòng)請(qǐng)求通用功能,如校驗(yàn)之類(lèi)的操作回調(diào)action的execute方法,獲取用戶(hù)請(qǐng)求執(zhí)行相應(yīng)的業(yè)務(wù)邏輯之后返回字符串,匹配result,之后跳轉(zhuǎn)到相應(yīng)的視圖或其他的文檔之后在執(zhí)行相應(yīng)的攔截器鏈自動(dòng)請(qǐng)求功能,隨后轉(zhuǎn)到web客戶(hù)端。

這樣我們就對(duì)struts2框架的結(jié)構(gòu)上的東西做了一個(gè)簡(jiǎn)單的介紹。在上篇博客講解了struts1框架,所以有必要在這里對(duì)他倆進(jìn)行一下對(duì)比(我僅僅總結(jié)了五條我認(rèn)為比較重要的,以后如果發(fā)現(xiàn)其他的在隨時(shí)補(bǔ)充):

在Action實(shí)現(xiàn)類(lèi)方面的對(duì)比(struts1的Action繼承action,struts2實(shí)現(xiàn)接口,也可以不實(shí)現(xiàn),可以定制服務(wù))線(xiàn)程模式方面的對(duì)比(struts1存在線(xiàn)程安全問(wèn)題,struts2不存在)

ServletAPI依賴(lài)方面的對(duì)比(struts1依賴(lài)servletAPI,struts2不是)可測(cè)性方面的對(duì)比(struts1難測(cè)試,依賴(lài)容器,struts2不是)封裝請(qǐng)求參數(shù)的對(duì)比(struts1使用actionform;struts2直接寫(xiě)到action,并且支持pojo對(duì)象)

在上篇博客中介紹了struts2框架的原理和流程分析,可以說(shuō)struts框架一路走來(lái),改變非常大,而且讓我們開(kāi)發(fā)人員變得更加輕松,里面的設(shè)計(jì)理念的改變也是讓我們編程人員的思路得到更大的擴(kuò)展。

可以說(shuō),一個(gè)先進(jìn)的技術(shù)或者框架就是要不斷的進(jìn)步才能永遠(yuǎn)讓編程人員喜歡和使用,一個(gè)優(yōu)秀的編程人員也是要不斷的進(jìn)步才能永遠(yuǎn)讓這個(gè)世界變得更加絢麗多彩。

其實(shí)編程就是這樣有意思的!

前面說(shuō)了一些宏觀上學(xué)習(xí)框架相關(guān)的思想方面的東西,下面繼續(xù)來(lái)介紹我經(jīng)常使用的框架和框架的分析,這篇博客主要介紹的是hibernate框架。

首先說(shuō)hibernate框架是數(shù)據(jù)持久層的框架,這個(gè)框架是非常強(qiáng)大的,它讓編程人員純粹的用面向?qū)ο蟮姆绞絹?lái)做開(kāi)發(fā),讓編程人員所面對(duì)的都是對(duì)象。僅僅從這一點(diǎn)它的設(shè)計(jì)思路就是非常讓編程人員喜愛(ài)的。

回想我們普通的開(kāi)發(fā)流程,和客戶(hù)溝通定需求,抽象出來(lái)原型,從原型中建立數(shù)據(jù)模型到庫(kù)表結(jié)構(gòu)的建立,之后在映射成對(duì)象模型,之后在用oo的設(shè)計(jì)思想完成后續(xù)的程序開(kāi)發(fā)。但是當(dāng)我們使用了hibernate框架以后,原先的設(shè)計(jì)思路就顯得不再那么具有優(yōu)勢(shì)了。我們直接建立對(duì)象模型,之后利用hibernate框架映射成數(shù)據(jù)模型,我們不再去考慮數(shù)據(jù)庫(kù)關(guān)系模型的東西,僅僅考慮的東西僅僅就是類(lèi)和對(duì)象,這樣的開(kāi)發(fā)才是面向?qū)ο蟮拈_(kāi)發(fā),也才是最接近人類(lèi)思考問(wèn)題的方式。所以hibernate框架的設(shè)計(jì)思路是非常好的。

hibernate框架設(shè)計(jì)思路的優(yōu)越性其實(shí)體現(xiàn)在了它本身的框架的原理上。hibernate封裝了JDBC,減輕了開(kāi)發(fā)人員在持久層的大量重復(fù)性工作,它利用了java反射機(jī)制來(lái)實(shí)現(xiàn)程序的透明性;它就是通過(guò)這兩點(diǎn)才達(dá)到從對(duì)象出發(fā)而非關(guān)系數(shù)據(jù)庫(kù)出發(fā)的效果。

介紹這么多理論性的東西之后我們能夠感覺(jué)到hibernate框架的強(qiáng)大,來(lái)看看它的結(jié)構(gòu)圖:

在hibernate框架中有幾個(gè)比較重要的接口和類(lèi):Query接口:Query負(fù)責(zé)執(zhí)行各種數(shù)據(jù)庫(kù)查詢(xún)。它可以使用HQL語(yǔ)句或SQL語(yǔ)句兩種表達(dá)方式。Configuration類(lèi):Configuration類(lèi)負(fù)責(zé)配置并啟動(dòng)Hibernate,創(chuàng)建SessionFactory對(duì)象SessionFactory接口:SessionFactory接口負(fù)責(zé)初始化Hibernate。它充當(dāng)數(shù)據(jù)存儲(chǔ)源的代理,并負(fù)責(zé)創(chuàng)建Session對(duì)象Session接口:Session接口負(fù)責(zé)執(zhí)行被持久化對(duì)象的CRUD操作Transaction接口:Transaction接口負(fù)責(zé)事務(wù)相關(guān)的操作

hibernate框架就是在利用這幾個(gè)接口來(lái)封裝了JDBC,而且我們用這些接口來(lái)操作數(shù)據(jù)庫(kù)變得非常簡(jiǎn)單,減少了我們?cè)诔志脤拥拇a量。

從這個(gè)結(jié)構(gòu)圖和我的一些分析就能發(fā)現(xiàn)hibernate框架是非常強(qiáng)大,而且它給我們開(kāi)發(fā)人員的開(kāi)發(fā)帶來(lái)了非常大的便利,尤其是他的設(shè)計(jì)思路還有它的“全自動(dòng)”的映射對(duì)象模型和關(guān)系模型。

但是hibernate框架也有它的一些缺點(diǎn):既然是封裝了JDBC,所以很明顯它沒(méi)有JDBC的效率高,尤其是在大量的處理表更新操作的時(shí)候。它有局限性,一個(gè)持久化類(lèi)不能映射多個(gè)表它應(yīng)對(duì)大數(shù)量的時(shí)候顯得非常笨拙,這一點(diǎn)沒(méi)有JDBC和接下來(lái)要介紹的IBatis框架

其實(shí)一項(xiàng)技術(shù)或者一個(gè)框架都有它的優(yōu)缺點(diǎn),選擇最合適的才是王道。

這篇博客主要是介紹了hibernate框架的結(jié)構(gòu)和分析,闡述了hibernate框架的優(yōu)缺點(diǎn),【具體詳細(xì)使用要等到我的框架學(xué)習(xí)的后續(xù)文章】??偟膩?lái)說(shuō)hibernate框架在持久層的作用非常明顯,我們懂得了它的優(yōu)缺點(diǎn)之后,才能做到我們是否是要選擇這個(gè)框架作為我們持久層開(kāi)發(fā)的必須的技術(shù)支撐,所以這些我常用的框架結(jié)構(gòu)和分析不單單是在介紹一些框架學(xué)習(xí)的宏觀知識(shí)把控,更多的是在為將來(lái)做項(xiàng)目開(kāi)發(fā)中選擇合適的技術(shù)支撐做鋪墊。

后續(xù)的博客在不斷更新,希望這些博客能夠?qū)ψx者的開(kāi)發(fā)過(guò)程帶來(lái)幫助,當(dāng)然如果讀者對(duì)我的博客有什么好的建議或者意見(jiàn),請(qǐng)與我聯(lián)系。聯(lián)系方式見(jiàn)博客側(cè)邊欄!

先看MVC模式流程圖(其實(shí)MVC設(shè)計(jì)模式就是java中的model2。):

就像圖上所標(biāo)識(shí)的C層主要是Servlet層控制頁(yè)面跳轉(zhuǎn),M層就是具體的業(yè)務(wù)處理邏輯,而JSP就是所謂的V層。MVC是有別于我們所說(shuō)的三層,我們平常所說(shuō)的三層是UI層、BLL層、DAL層,具體的區(qū)別如圖:

從圖上能看出來(lái),JSP和Servlet構(gòu)成了UI層,而Model層分成了BLL層和DAL層(也就是業(yè)務(wù)邏輯和數(shù)據(jù)持久層)。

從理論上認(rèn)清了MVC設(shè)計(jì)模式之后,下面開(kāi)始動(dòng)手敲一個(gè)MVC設(shè)計(jì)模式示例代碼:

JSP索引頁(yè)面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("請(qǐng)求失敗");

}

request.getRequestDispatcher(forward).forward(request,

response);

}

這個(gè)servlet代碼主要實(shí)現(xiàn)的功能判斷是那個(gè)頁(yè)面請(qǐng)求服務(wù)器做那些操作,之后調(diào)用業(yè)務(wù)邏輯實(shí)現(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é)果:

通過(guò)上面的示例已經(jīng)對(duì)MVC設(shè)計(jì)模式有了初步的認(rèn)識(shí),其實(shí)這個(gè)示例是對(duì)Struts框架學(xué)習(xí)的基礎(chǔ),只有弄清楚了這個(gè)實(shí)例才能弄清楚Struts框架的實(shí)現(xiàn)原理和Struts框架使用。

那么我們?cè)趺床拍芡ㄟ^(guò)這個(gè)示例引入Struts框架呢?這個(gè)問(wèn)題從IF-Eles開(kāi)始。

首先我們看到了TestServlet中出現(xiàn)了許多if-else語(yǔ)句,這樣是非常不穩(wěn)定的,這樣的程序是非常不靈活的,以后如果有變化,那么維護(hù)是非常差的;而且我們?cè)趇f-else中出現(xiàn)了大量的字符串,這樣在coding的時(shí)候會(huì)出現(xiàn)寫(xiě)錯(cuò),這樣無(wú)形中給調(diào)試帶來(lái)了麻煩。所以去掉if-else成了我們重構(gòu)的第一步,也是我們進(jìn)行Struts框架學(xué)習(xí)的第一步。

如何才能去掉If-ELSE呢?請(qǐng)看下一篇文章《深入淺出學(xué)習(xí)Struts1框架(二):重構(gòu)MVC模式代碼中跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯》。

在上篇博文《深入淺出學(xué)習(xí)Struts1框架(一):一個(gè)簡(jiǎn)單mvc模式代碼示例開(kāi)始》中簡(jiǎn)單說(shuō)了一下MVC模式代碼的實(shí)現(xiàn)和MVC模式和三層架構(gòu)的區(qū)別,并且留下一個(gè)問(wèn)題—如何去掉TestServlet中的IF-Else語(yǔ)句塊。

因?yàn)樵赥estServlet中出現(xiàn)了If-Else語(yǔ)句塊,所以讓程序變得不再靈活,讓?xiě)?yīng)付需求變化時(shí)變得笨拙。所以就承接上篇文章來(lái)重構(gòu)一下TestServlet代碼,主要是用繼承多肽來(lái)進(jìn)一步對(duì)TestServlet進(jìn)行重構(gòu)。雖然這一篇文章最后沒(méi)有將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("請(qǐng)求失敗");

}

request.getRequestDispatcher(forward).forward(request,

response);

}

}

首先我們看到了在每個(gè)語(yǔ)句塊中都出現(xiàn)了給forward賦值,其實(shí)也就是給頁(yè)面跳轉(zhuǎn)的路徑賦值,針對(duì)每個(gè)請(qǐng)求路徑判斷來(lái)賦值跳轉(zhuǎn)路徑。另外每個(gè)IF-Else語(yǔ)句塊中都有業(yè)務(wù)處理,我們要把這些業(yè)務(wù)處理分別放到類(lèi)里面,讓職責(zé)更加單一,這樣更加符合面向?qū)ο蟮乃悸贰?/p>

就從這里我們開(kāi)始重構(gòu),我們可以將這個(gè)跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯封裝起來(lái)。

既然封裝,那么我們就抽象出來(lái)一個(gè)借口,主要完成一個(gè)方法,這個(gè)方法主要的功能就是要完成業(yè)務(wù)邏輯封裝和路徑跳轉(zhuǎn)的返回。隨后建立四個(gè)類(lèi),主要實(shí)現(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;

}

增刪改查實(shí)現(xiàn)類(lèi):

添加用戶(hù)實(shí)現(xiàn)類(lèi):[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>

刪除用戶(hù)實(shí)現(xiàn)類(lèi):[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";

}

}

更新用戶(hù)實(shí)現(xiàn)類(lèi):[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";

}

}

查詢(xún)用戶(hù)實(shí)現(xiàn)類(lèi):[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類(lèi)重構(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("請(qǐng)求失敗");

}

String

forward=null;

try{

forward=action.execute(request,

response);

}catch(Exception

e){

e.printStackTrace();

}

request.getRequestDispatcher(forward).forward(request,

response);

}

}

運(yùn)行結(jié)果:

這樣TestServlet類(lèi)雖然沒(méi)有徹底去掉If-Else,但是這樣的代碼變得更加簡(jiǎn)練,利用多肽實(shí)現(xiàn)業(yè)務(wù)邏輯處理和路徑跳轉(zhuǎn)返回。職責(zé)更加清晰,讓維護(hù)變得更加輕松。

問(wèn)題遺留:

If-else語(yǔ)句塊沒(méi)有徹底剔除,而且程序中依舊出現(xiàn)了過(guò)多的字符串,所以程序依舊是不靈活,而且字符串過(guò)多增加調(diào)試的復(fù)雜性。所以下一篇文章就把if-else語(yǔ)句塊剔除,并且把字符串放到配置文件來(lái)用dom4j來(lái)動(dòng)態(tài)讀取。

我們離Struts框架越來(lái)越近,當(dāng)我們把if-else和字符串剔除之后就會(huì)出現(xiàn)Struts框架的雛形。期待下一篇文章。

在《深入淺出學(xué)習(xí)Struts1框架(一):一個(gè)簡(jiǎn)單mvc模式代碼示例開(kāi)始》和《深入淺出學(xué)習(xí)Struts1框架(二):重構(gòu)MVC模式代碼中跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯》文章中已經(jīng)說(shuō)了分層和mvc模式的區(qū)別,和一些為了去掉mvc模式代碼中的TestServlet類(lèi)中的if-else。因?yàn)閕f-else在程序代碼中是相對(duì)不穩(wěn)定的,所以通過(guò)去掉if-else來(lái)引入對(duì)struts框架的學(xué)習(xí)。

在《深入淺出學(xué)習(xí)Struts1框架(二):重構(gòu)MVC模式代碼中跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯》中我們已經(jīng)抽象出來(lái)了一個(gè)接口和四個(gè)實(shí)現(xiàn)類(lèi),主要封裝了業(yè)務(wù)處理和頁(yè)面跳轉(zhuǎn)路徑字符串放回,以便利用多肽來(lái)重構(gòu)了TestServlet代碼(具體見(jiàn)博客)。

在上兩篇博客我們遺留了兩個(gè)問(wèn)題,一是if-else,二是字符串太多。今天這篇博客就要解決這兩個(gè)問(wèn)題。

上一篇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("請(qǐng)求失敗");

}

String

forward=null;

try{

forward=action.execute(request,

response);

}catch(Exception

e){

e.printStackTrace();

}

request.getRequestDispatcher(forward).forward(request,

response);

}

}

解決字符串問(wèn)題,當(dāng)然就要用到配置文件了,用到配置文件就要有用來(lái)讀取配置文件的相關(guān)的類(lèi)和方法,這里就用dom4j中的類(lèi)來(lái)讀取配置文件,這里的配置文件的書(shū)寫(xiě)是有點(diǎn)邏輯上的難度的。

我們來(lái)看TestServlet中的代碼,我們要在這個(gè)testservlet中實(shí)現(xiàn)讀取配置文件和path比較,還有利用多肽實(shí)例化相應(yīng)的實(shí)現(xiàn)類(lèi),最后通過(guò)實(shí)例化的實(shí)現(xiàn)類(lèi)的方法來(lái)返回跳轉(zhuǎn)路徑,最終跳轉(zhuǎn)到相應(yīng)的頁(yè)面。

所以我們的配置文件就要不僅配上testservlet中出現(xiàn)的字符串,還要配置相應(yīng)的Action接口的實(shí)現(xiàn)類(lèi)(我們可以利用反射來(lái)實(shí)例化該類(lèi)的對(duì)象,進(jìn)而使用這個(gè)類(lèi)的所有屬性和方法),另外還有跳轉(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ò)相關(guān)類(lèi)讀取,并且實(shí)現(xiàn)相應(yīng)的功能。所以這里用dom4j來(lái)讀取完成。其實(shí)如果能把這個(gè)邏輯捋順之后就能發(fā)現(xiàn),其實(shí)懂我們利用dom4j讀取完配置文件的時(shí)候,我們是取得的是一個(gè)配套的匹配路徑字符串、相應(yīng)業(yè)務(wù)邏輯類(lèi)還有處理業(yè)務(wù)邏輯之后跳轉(zhuǎn)頁(yè)面路徑字符串。這樣我們就能直截了當(dāng)?shù)娜サ袅薸f-else。(這里可能邏輯上會(huì)出現(xiàn)一些困難,但是看到下面的重構(gòu)之后的testservlet中的代碼和讀取配置文件之后的代碼就會(huì)一目了然)。

現(xiàn)在等待解決的問(wèn)題就是我們要把從配置文件取得的一整套內(nèi)容放到那里,當(dāng)然這是毋庸置疑的要放到類(lèi)中。所以我們就建立一個(gè)ActionMapping類(lèi)來(lái)放我們的那一整套內(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類(lèi)已經(jīng)有了,剩下的工作就是要利用dom4j來(lái)讀取配置文件類(lèi),具體代碼如下:

[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());

}

}

我們通過(guò)返回ActionMapping來(lái)動(dòng)態(tài)創(chuàng)建出action相應(yīng)的實(shí)現(xiàn)類(lèi),進(jìn)而完成業(yè)務(wù)邏輯和頁(yè)面跳轉(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)沒(méi)有了,字符串也已經(jīng)沒(méi)有了。通過(guò)這篇文章對(duì)if-else還有字符串問(wèn)題的解決,又一次重構(gòu)了testservlet代碼,程序相對(duì)靈活許多。通過(guò)這一次的重構(gòu),我們已經(jīng)看到了struts框架的雛形,下一篇文章就真正開(kāi)始了struts框架的學(xué)習(xí)。

下一篇引子:

其實(shí)框架就是對(duì)程序的高度封裝,我們經(jīng)歷了這三篇文章之后,一步一步重構(gòu),一步一步封裝,逐步向框架靠攏,其實(shí)框架沒(méi)有什么難的,其實(shí)沒(méi)有學(xué)習(xí)框架之前感覺(jué)挺神秘,其實(shí)如果一步一步來(lái)研究之后發(fā)現(xiàn)框架就是封裝的高度化,分層的高度化。

下一篇文章《深入淺出學(xué)習(xí)struts1框架(四):從MVC模式代碼認(rèn)識(shí)struts框架》就借助剛剛完成的實(shí)例來(lái)簡(jiǎn)單認(rèn)識(shí)struts框架,看看真正的struts框架和我們這個(gè)mvc小實(shí)例有什么相同和相異之處?!渡钊霚\出學(xué)習(xí)Struts1框架(一):一個(gè)簡(jiǎn)單mvc模式代碼示例開(kāi)始》分析mvc和三層關(guān)系開(kāi)始,引出這個(gè)mvc設(shè)計(jì)模式實(shí)例,到《深入淺出學(xué)習(xí)Struts1框架(二):重構(gòu)MVC模式代碼中跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯》抽象封裝業(yè)務(wù)處理和路徑跳轉(zhuǎn),再到《深入淺出學(xué)習(xí)Struts1框架(三):徹底去掉TestServlet中的字符串和if-else語(yǔ)句塊》去掉if-else語(yǔ)句塊和字符串,經(jīng)過(guò)三篇文章循序漸進(jìn)的重構(gòu)了一個(gè)mvc設(shè)計(jì)模式實(shí)例,其實(shí)也就是重構(gòu)出來(lái)了一個(gè)struts框架雛形。今天來(lái)看看什么是struts1框架。1.

框架

框架(Framework)是整個(gè)或部分系統(tǒng)的可重用設(shè)計(jì),表現(xiàn)為一組抽象構(gòu)件及構(gòu)件實(shí)例間交互的方法。也就是說(shuō)框架是一個(gè)半成品的應(yīng)用程序。我們所面對(duì)的應(yīng)用程序一般都是分為兩部分,一部分是業(yè)務(wù)相關(guān)的組件部分,另一部分是和業(yè)務(wù)無(wú)關(guān)的組件部分。而我們知道和業(yè)務(wù)相關(guān)的組件部分的重用性是非常低的,這也是顯而易見(jiàn)的事情;而和業(yè)務(wù)無(wú)關(guān)的組件部分,如驗(yàn)證、異常、程序流程控制等等服務(wù)組件的復(fù)用性是非常高的。所以當(dāng)人們?cè)诓煌膽?yīng)用程序中抽出共性的組件,構(gòu)成一個(gè)半成品應(yīng)用程序,這時(shí)候框架就應(yīng)運(yùn)而生了。2.

Struts1

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論