3.Struts的分析與設(shè)計
???應(yīng)用:
??????電子通訊薄addressbook
???這一章的重點(diǎn)在于引導(dǎo)進(jìn)入Struts應(yīng)用的 分析與設(shè)計, 要體現(xiàn)軟件開發(fā)流程
分析需求:
???該應(yīng)用實(shí)現(xiàn)一個較簡單的通訊簿
??????.登錄
??????.添加好友聯(lián)系方式
??????.查詢
??????.根據(jù)要求查詢
??????.顯示全部信息
??????.注銷
???在分析中可以發(fā)現(xiàn),登錄是整個應(yīng)用的入口,其它的模塊都依賴于此,因此貫穿整個應(yīng)用應(yīng)該有一個已登錄檢查的要求
數(shù)據(jù)庫設(shè)計:
???根據(jù)需求,需要兩張表:
???1.address
??????該應(yīng)用的主體數(shù)據(jù)表,里邊存放應(yīng)用中所需的聯(lián)系方式信息
??????ID(int,key) 記錄ID,僅作主鍵使用
??????name(varchar,not null) 聯(lián)系人的姓名
??????telephone(varchar)聯(lián)系人的電話
??????address(varchar)聯(lián)系人的地址
???2.userInfo
??????該表保存登錄用戶信息,用于登錄檢驗(yàn)
??????例程中改用XML數(shù)據(jù)文件的方式加以替代
用戶界面設(shè)計:
???對應(yīng)于需求可設(shè)計:
??????登錄界面
??????菜單界面
??????添加界面
?????????數(shù)據(jù)的更改是一項(xiàng)權(quán)重的動作,因此提供一個添加結(jié)果界面
??????查詢條件界面
??????查詢結(jié)果界面
??????對于注銷需求,其對應(yīng)于一個簡單動作,可以不提供界面
詳細(xì)設(shè)計:
???登錄
??????數(shù)據(jù)項(xiàng)userName,password
??????視圖(login.jsp)
?????????userName,password的輸入;
?????????userName不能為空;
??????控制器
?????????成功:
????????????將userName存入session, forward到menu.jsp
?????????失敗:
????????????login.jsp
??????模型
?????????連接數(shù)據(jù)源(此處是XML數(shù)據(jù)文件);
?????????數(shù)據(jù)的邏輯有效性檢查(userName,password必須完全一致)
???添加
??????數(shù)據(jù)項(xiàng)name,telephone,address
??????視圖(insert.jsp)
?????????name,telephone,address的輸入;
?????????name,telephone不能為空;
??????控制器
?????????成功:
????????????insertOk.jsp
?????????失敗:
????????????insert.jsp
??????模型
?????????insert條目
???查詢
??????數(shù)據(jù)項(xiàng)name,telephone,address
??????視圖(search.jsp)
?????????name,telephone,address的輸入;
?????????name,telephone,address不能同時為空;
??????控制器
?????????display.jsp
??????模型
?????????select條目
???注銷
??????控制器
?????????login.jsp
??????模型
?????????銷毀session中的userName
???登錄檢查
??????由于需要在JSP頁面被載入前調(diào)用, 以標(biāo)簽提供
??????檢查session("userName")對象是否為空,否則forward到login.jsp
?????????只要給它一個對象,Struts控制器就會認(rèn)為是按下了Cancel,這樣的話也可以繞過ActionForm中的validate(),而且從正常的Input JSP頁面提交的話,ActionForm.validate()方法還是可以產(chǎn)生作用的.
???后記:
??????Myeclipse里面配置Action時能夠設(shè)置的屬性并不多,也不包含這個validate屬性,需要自己手工處理struts-config.xml
??????如果技術(shù)上達(dá)不到,暫時取取巧還是可以的,隨著技術(shù)的深入,解決問題的方法也會越來越中規(guī)中矩
?????????(2)修改web.xml文件中的<servlet-class>元素,把這個標(biāo)簽的內(nèi)容指向自己的類;
???到此問題解決,不過我在使用中也注意到一個有趣的現(xiàn)象,運(yùn)行后生成的Web頁面有一個特點(diǎn),就是從IE的 "查看/編碼方式" 上可以看到IE自動使用的是UTF-8編碼,而你如果換成 "簡體中文GB2312"的話得到的將是一個亂碼頁面
???Java Web應(yīng)用的核心技術(shù)是Servlet和JSP
???Struts框架中JSP位于視圖層,而Servlet位于控制層
???幾個重要的API
??????HttpServletRequest:由Servlet容器把用戶的請求存在此對象中
??????HttpServletResponse:用于生成Http響應(yīng)結(jié)果
??????HttpSession:容器為每個Http會話而創(chuàng)建的一個實(shí)例,用于保存會話中的共享數(shù)據(jù)
??????ServletContext:為每個Web應(yīng)用而創(chuàng)建的實(shí)例,存放application范圍內(nèi)的數(shù)據(jù)
??????HttpServletRequest,HttpSession,ServletContext都提供了操作共享數(shù)據(jù)的方法
??????setAttribute(String key,Object value)
??????getAttribute(String key)
??????與容器提供的接口一樣,因此getAttribute(String key)方法返回的是Object,需要做強(qiáng)制轉(zhuǎn)型
???HttpSession的生存期有:
??????客戶端關(guān)閉瀏覽器;
??????會話過期;
??????服務(wù)端調(diào)用HttpSession.invalidate()方法.
???相對來說Session的生存期較長,因此如果可以的話應(yīng)將數(shù)據(jù)保存在Request范圍內(nèi),這樣可以縮短對象的生存期;另外象Tomcat這樣的容器提供了管理Session的功能,可以對其做持久化管理.
???Web應(yīng)用中數(shù)據(jù)生存的范圍:
??????1.page
??????2.request
??????3.session
??????4.application
???JavaBean:
??????就是符合特定規(guī)范的Java對象,在JSP中提供了標(biāo)簽便于處理
??????JSP中操作JavaBean常用標(biāo)簽有:
?????????<jsp:useBean id="bean名稱" scope="生存期" class="ddm.MyBean" />
?????????<jsp:getProperty name="bean名稱" property="屬性名" />
?????????<jsp:setProperty name="bean名稱" property="屬性名" value="值" />
???JavaBean常位于模型層,由它提供數(shù)據(jù)及邏輯
???Struts中的ActionForm Bean就是一種JavaBean,它僅在視圖層和控制層之間傳遞用戶輸入的表單數(shù)據(jù),位于視圖層,它只能有兩種生存范圍:request,session
???客戶化JSP標(biāo)簽
??????在Jsp1.1中出現(xiàn),支持用戶在JSP中自定義客戶化標(biāo)簽,這些標(biāo)簽常用于處理復(fù)雜的邏輯運(yùn)算和事務(wù)以及定義JSP的輸出內(nèi)容和格式.
??????優(yōu)點(diǎn):
.?????????標(biāo)簽具有可重用性,因此可以提供開發(fā)效率
????????????類似于asp中的JS函數(shù),jsp中的嵌入頁
.?????????可以在JSP頁面中以靜態(tài)或動態(tài)的方式設(shè)置標(biāo)簽的屬性
.?????????標(biāo)簽可以訪問JSP網(wǎng)頁中的所有對象
.?????????標(biāo)簽可以相互嵌套,來完成復(fù)雜的邏輯
.?????????可以使JSP頁面更簡潔,提高可讀性
????????????對于這個有不同的意見,我認(rèn)為實(shí)際上降低了可讀性;因?yàn)槌绦虻目勺x性實(shí)際上是適用于程序開發(fā)/測試人員的,除此之外別無他人,而引用各種技術(shù),只會提升技術(shù)上的復(fù)雜度,增加修改的難度;所謂的"類的可重用性",就我看來是指特定人群的,對于專業(yè)的高手來說是可以提升效率的,但是對于某種技術(shù)一知半解的人來說,只會提升開發(fā)難度.一旦類被重用,錯誤的影響面也會非常之廣.
???Struts提供了五種標(biāo)簽庫:
??????1.Bean
??????2.HTML
??????3.Logic
??????4.Nested
??????5.Tiles
???EJB
??????EJB(企業(yè)JavaBean)組件是基于標(biāo)準(zhǔn)分布式對象技術(shù),CORBA,RMI的服務(wù)端Java組件
??????它與JavaBean的聯(lián)系
?????????相同點(diǎn):都用于實(shí)現(xiàn)企業(yè)應(yīng)用的業(yè)務(wù)邏輯,都位于模型層
?????????區(qū)別:EJB總是分布式的;EJB需要運(yùn)行于應(yīng)用服務(wù)器中,而JavaBean只需要Servlet/JSP容器
???XML
??????應(yīng)用廣泛,它可以描述結(jié)構(gòu)化的數(shù)據(jù),通常與DTD一起使用(聲明標(biāo)記使用規(guī)則),常用于配置文件
??????Struts中的兩種重要的XML文件
??????web.xml
?????????普通的Web應(yīng)用都有,它用于配置Web應(yīng)用,如配置Servlet
.?????struts-config.xml(可以使用別的名稱,需要在web.xml中對應(yīng))
?????????Struts框架的配置文件,主要是Action的配置,這個XML文件包含了幾個標(biāo)簽,在書寫時各子標(biāo)簽的書寫順序有著嚴(yán)格要求
???Web組件的關(guān)聯(lián)關(guān)系
??????1.請求轉(zhuǎn)發(fā)
?????????只能發(fā)生在同一個Web應(yīng)用中,在服務(wù)端完成轉(zhuǎn)發(fā)
?????????RequestDespatcher rd = request.getRequestDispatcher("hello.jsp");
?????????rd.forward(request,response);
?????????JSP中使用的標(biāo)簽:
????????????<jsp:forward page="hello.jsp" />
?????????這種方式可以共享request范圍內(nèi)的數(shù)據(jù)
??????2.重定向
?????????與轉(zhuǎn)發(fā)類似,但是可以將請求轉(zhuǎn)發(fā)到不同的Web應(yīng)用,在客戶端完成定向(由服務(wù)端發(fā)一個信息給客戶端瀏覽器,瀏覽器將新發(fā)一個請求)
?????????response.sendRedirect("
http://www.javablog.net/tw-ddm
");
?????????由于可能發(fā)生在不同的Web應(yīng)用,因此不能共享request范圍的數(shù)據(jù)
??????3.包含
?????????是一個聚集的概念,可以共享request數(shù)據(jù),常用于模板,程序的控制權(quán)在調(diào)用者,被包含者只是暫時有控制權(quán),執(zhí)行完畢后需要傳回
?????????RequestDispatcher rd;
?????????rd = request.getRequestDispatcher("/header.jsp");
?????????rd.include(request,response);
?????????包含由于不會產(chǎn)生控制權(quán)的轉(zhuǎn)移,因此能夠在一個組件中包含多個
?????????JSP中使用標(biāo)簽:
????????????<jsp:include page="/hello.jsp" flush="true">
???????????????<jsp:param name="username" value="ddm"/>
????????????</jsp:include>
?????????這是動態(tài)包含,它可以傳遞參數(shù),它可以包含動態(tài)或靜態(tài)文件,每次運(yùn)行時容器都會去檢查文件是否發(fā)生變化
?????????<% @include file="/hello.jsp" %>,容器不會每次去檢查文件,常用于包含靜態(tài)頁面
???Struts是實(shí)現(xiàn)MVC模式的框架
??????視圖層:
?????????JSP作為MVC中的視圖,它沒有業(yè)務(wù)邏輯,也沒有模型信息,只有標(biāo)簽
?????????ActionForm bean 由于只處理表單數(shù)據(jù),聯(lián)系視圖和控制器,因此也被分為視圖層
??????模型層:
?????????由JavaBean和EJB來實(shí)現(xiàn),某些簡單的功能,有時也直接讓Action扮演控制器和模型兩種角色
??????控制器:
?????????由ActionSevlet和Action來實(shí)現(xiàn).
?????????ActionSevlet類是Struts框架中的核心組件.繼承了HttpServlet,在MVC中作為中央控制器存在,因此只能有一個
????????????這個核心玩意也是可以替換的,只要新類是從ActionServlet派生即可,同時也需要在web.xml中改變對應(yīng)的class名稱
?????????Action由ActionServlet根據(jù)Struts-config.xml配置文件來產(chǎn)生,它負(fù)責(zé)調(diào)用合適的模型(JavaBean,EJB),因此它也具有適配器的作用,相當(dāng)于控制器和模型之間的隔離層(適配器)
?????????Action必須實(shí)現(xiàn)基類的execute()方法,此方法返回一個ActionForward對象,由ActionForward對象封裝響應(yīng),為增加應(yīng)用的可配置,提倡從配置文件中findForward
???配置文件:
??????struts-config.xml
??????配置文件中描述了多個Action的映射信息,初始化時被封裝在ActionMapping對象中,每個action元素對應(yīng)一個ActionMapping對象
??????該配置文件中有個<controller>元素,是用于配置ActionServlet的,比較有用的是:<controller contentType="text/html;charset=UTF-8" locale="true" />,這里的contentType應(yīng)用于全局范圍,如果在JSP文件中指定將在局部履蓋這個選項(xiàng),換句話說這里指定了,就可以在JSP頁面省心了,另外說一句,用Myeclipse生成的JSP,如果是從ActionForm生成則不會有這些信息,只有要設(shè)計視圖中單獨(dú)拖一個出來時才會具有.
???工作流程:
??????1.檢索與用戶請求匹配的ActionMapping對象,如果不存在則返回路徑無效的信息.
??????2.檢查有無ActionForm對象,如果沒有則創(chuàng)建,并將用戶提交的表單數(shù)據(jù)保存在其中.
??????3.根據(jù)配置決定表單是否需要驗(yàn)證,如果需要驗(yàn)證,則調(diào)用ActionForm的validate()方法.
??????4.如果validate()方法返回null或不含ActionMessage的ActionErrors對象,則表示成功.失敗則返回input頁面
??????5.根據(jù)ActionMapping包含的映射信息,查找及新建Action對象,然后調(diào)用該對象的execute()方法.
??????6.Action對象的execute()返回一個ActionForward對象,然后由ActionServlet轉(zhuǎn)發(fā)客戶請求給ActionForward中指向的JSP組件
??????7.由該JSP生成網(wǎng)頁以響應(yīng)客戶請求.
?