日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Struts 2配置详解

發布時間:2024/1/23 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Struts 2配置详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學習內容

?Struts 2配置文件

?Action的配置

?Result的配置

?屬性驅動與模型驅動

能力目標

?熟練進行Struts 2配置

?熟練使用屬性驅動和模型驅動

本章簡介

上一章我們初步學習了Struts 2框架,包括Struts 2體系結構和運行流程,并通過登錄案例介紹了使用Struts 2進行開發的基本步驟。

本章將深入學習Struts 2框架,主要內容是Struts 2的配置文件,包括Action的配置、Result的配置等等,只有掌握了配置文件,才能更好的使用和擴展Struts 2的功能。

核心技能部分

4.1?Struts 2的配置文件

通過上一章的學習,我們知道Struts 2框架默認的配置文件是struts.xml,該文件通常放在WEB-INF\classes目錄下,該目錄下的struts.xml會自動被Struts 2框架加載。本節將詳細介紹該配置文件各元素的含義和使用。

4.1.1?中文亂碼處理

在Struts 2中,如果客戶端請求中包含有中文數據,那就很容易出現中文亂碼問題。當然我們會有很多方法來解決這個問題,在struts.xml中可以通過<constant>配置更簡單的解決中文亂碼問題,參考代碼如下所示。

<struts> <constant name="struts.i18n.encoding" value="utf-8"></constant> <package name="admin" extends="struts-default"> <action name="login" class="com.zy.AdminAction"> <result name="success" type="dispatcher">/index.jsp</result> <result name="error" type="redirect">/fail.jsp</result> </action> </package> </struts>

在struts.xml中,<constant>元素用來配置常量,配置時必須指定兩個屬性:name和value。上述代碼中的struts.i18n.encoding是Struts 2中已經存在的常量屬性,用來配置Web應用程序默認的編碼集,相當于調用HttpServletRequset對象的setCharacterEncoding方法。

4.1.2?包配置

在Java項目中,類通常都需要“包(package”來進行組織和管理。同樣的道理,struts.xml中眾多的Action也需要進行統一的組織和管理,所以Struts 2的配置文件也引入了“包(package”,并通過“包(package”來管理Action和攔截器。

在struts.xml文件中,package元素用來配置包,配置時通常需要指定以下三個屬性:

?name:必需屬性,指定包的名字,不允許重復。

extends:可選屬性,指定要繼承的包,可以繼承其它包中定義的action、攔截器等。

?namespace:可選屬性,定義該包的命名空間(命名空間將在下一節講述)。

<struts> <package name="admin" extends="struts-default"> <action name="login" class="com.zy.AdminAction"> <result name="success" type="dispatcher">/index.jsp</result> <result name="error" type="redirect">/fail.jsp</result> </action> </package> </struts>

在上述代碼中,我們使用package元素配置了一個包,名字是“admin”,并繼承了“struts-default”包。

通過使用extends,你可以指定本package繼承另外一個package的所有的配置。當某個package繼承了另外一個package的所有配置,那么你就無需對父package中已經聲明過的配置定義做再次的定義。?
???同時,如果重復定義父package中已聲明過的配置定義,那么這些重復定義聲明將覆蓋父package中的相關定義。

上例中,我們讓admin包繼承了struts-default包,那么這個包又在哪里呢?struts-default是Struts 2默認的包,該包定義在struts-defalut.xml文件中。該文件是Struts 2框架自帶的配置文件,為框架提供諸多默認配置并在運行時自動被加載。

現在我們打開struts2-core-2.1.8.1.jar,在jar包中可以找到struts-default.xml文件。打開struts-default.xml后,內容如下:

<?xml version="1.0" encoding="UTF-8"?><struts> <bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork" /> <bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" class="org.apache.struts2.impl.StrutsObjectFactory" /> <bean type="com.opensymphony.xwork2.ActionProxyFactory" name="xwork" class="com.opensymphony.xwork2.DefaultActionProxyFactory"/> <bean type="com.opensymphony.xwork2.ActionProxyFactory" name="struts" class="org.apache.struts2.impl.StrutsActionProxyFactory"/> <!-- 省略了其他的bean節點的定義 --> <!-- Only have static injections --> <bean class="com.opensymphony.xwork2.ObjectFactory" static="true" /> <bean class="com.opensymphony.xwork2.util.XWorkConverter" static="true" /> <!-- 省略了其他的靜態注入的定義 --> <package name="struts-default" abstract="true"> <result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <!-- 省略了其他的ResultType的定義 --> </result-types> <interceptors> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> <!-- 省略了其他的Interceptor的定義 --> <!-- Basic stack --> <interceptor-stack name="basicStack"> <interceptor-ref name="exception"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> </interceptor-stack> <!-- A complete stack with all the common interceptors in place. Generally, this stack should be the one you use, though it may do more than you need. Also, the ordering can be switched around (ex: if you wish to have your servlet-related objects applied before prepare() is called, you'd need to move servlet-config interceptor up. This stack also excludes from the normal validation and workflow the method names input, back, and cancel. These typically are associated with requests that should not be validated. --> <interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="i18n"/> <interceptor-ref name="chain"/> <interceptor-ref name="debugging"/> <interceptor-ref name="profiling"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*</param> </interceptor-ref> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> </interceptor-stack> <!-- 省略了其他的interceptor-stack節點的定義 --> </interceptors> <default-interceptor-ref name="defaultStack"/> </package> </struts>

在上面的內容中,我們看到定義了一個包?名字是struts-default,其中引用了一系列的系統攔截器,并定義了一些攔截器棧和默認攔截器,admin包就是繼承了這個struts-default包,也就繼承到了里面的默認攔截器的配置,通過第一章的學習,我們知道action運行前后會有一系列的攔截器自動運行,也就是因為繼承了struts-default包的緣故!

因此,正常情況下,自定義的action在配置的時候要確保直接或者間接的繼承到struts-default,否則action可能無法正常工作。因為struts2很多核心功能都是攔截來實現的,如,從請求中把請求參數封閉到action,文件上傳和數據驗證等都是通過攔截器實現的,struts-default定義了這些攔截器和Result類型,可以這么說,當包繼承了struts-default才能使用struts2提供的核心功能,

?4.1.3?命名空間配置

在實際應用中,同一個struts.xml文件中可能會出現同名的Action,為了便于管理,Struts 2通過命名空間來區分同名Action,即Struts 2通過Action的邏輯名和其所在的命名空間來標識一個Action。一個命名空間中不能存在同名的Action,不同的命名空間可以存在同名的Action。在struts.xml文件中,通過給包(package)指定namespace屬性來為Action設置命名空間。

<struts> <package name="admin" extends="struts-default" namespace="/admin"> <action name="query" class="com.zy.QueryAction"> <result name="success" type="dispatcher">/list.jsp</result> </action> </package> </struts>

在上述代碼中,我們配置了一個名字是“admin”的包,并指定其命名空間為“/admin”,這時在訪問包中名字是“query”的action時,應該這樣寫:

http://localhost:8080/web應用名/admin/query.action

在URL中必須指明命名空間的名字,如果一個包沒有配置命名空間,那默認為“”。此時就應該這樣寫:

http://localhost:8080/web應用名/query.action

4.1.4?包含配置

在實際應用中,Struts 2配置文件可能會變的十分龐大,這不利于管理和維護。這時我們可以把一個Struts 2配置文件拆分成若干個配置文件,這樣也有利用團隊協作開發。

<struts> <package name="admin" extends="struts-default"> <action name="login" class="com.zy.AdminAction"> <result name="success" type="dispatcher">/index.jsp</result> <result name="error" type="redirect">/fail.jsp</result> </action> <action name="query" class="com.zy.QueryAction"> <result name="success" type="dispatcher">/list.jsp</result> </action> <action name="add" class="com.zy.AddAction"> <result name="success" type="redirect">query.action</result> <result name="error" type="redirect">/error.jsp</result> </action> </package> </struts>

上述代碼配置了三個Action,下面我們把這個配置文件拆分成兩個,分別是struts1.xml和struts2.xml,代碼如下所示。

struts1.xml

<struts> <package name="p1" extends="struts-default"> <action name="login" class="com.zy.AdminAction"> <result name="success" type="dispatcher">/index.jsp</result> <result name="error" type="redirect">/fail.jsp</result> </action> </package> </struts> struts2.xml <struts> <package name="p2" extends="struts-default"> <action name="query" class="com.zy.QueryAction"> <result name="success" type="dispatcher">/list.jsp</result> </action> <action name="add" class="com.zy.AddAction"> <result name="success" type="redirect">query.action</result> <result name="error" type="redirect">/error.jsp</result> </action> </package> </struts> 拆分之后,在struts.xml文件中通過include元素來包含struts1.xml和struts2.xml,代碼如下所示。 <struts> <include file="struts1.xml"/> <include file="struts2.xml"/> </struts>

include元素的file屬性用來設置配置文件的路徑。

4.1.5?struts.properties

Struts 2框架有兩個配置文件,一個是我們前面常用的struts.xml,另一個是struts.properties。這個文件是struts2框架的全局屬性配置文件。

struts.properties是一個標準的Properties文件,該文件是由一系列的key-value(鍵值對)組成,每個key就是一個Struts 2的屬性,該key對應的value就是一個Struts 2的屬性值。該文件通常放在Web應用的WEB-INF/classes目錄下,Struts 2框架會自動加載這個文件。

下面將該文件常用的配置屬性詳細地列舉出來。

?struts.i18n.encoding

設置Web應用的默認編碼集。此屬性對于處理中文請求參數很有用,通常設置為GB2312或者utf-8。

?struts.multipart.parser

該屬性設置處理multipart/form-data的MIME類型請求的框架,該屬性支持cos、pell和jakarta等屬性值,即分別對應使用cos的文件上傳框架、pell上傳及common-fileupload文件上傳框架,該屬性的默認值為jakarta。文件上傳會在后面的章節中介紹。

?struts.multipart.saveDir

該屬性設置上傳文件的臨時保存路徑,該屬性的默認值是javax.servlet.context.tempdir。

?struts.multipart.maxSize

該屬性設置Struts 2文件上傳中整個請求內容允許的最大字節數。

struts.action.extension

該屬性設置需要Struts 2處理的請求后綴,該屬性的默認值是action,即所有匹配*.action的請求都由Struts 2處理。如果用戶需要指定多個請求后綴,則多個后綴之間以英文逗號(,)隔開。

?struts.configuration.xml.reload

該屬性設置當struts.xml文件改變后,系統是否自動重新加載該文件。該屬性的默認值是false。

?struts.custom.i18n.resources

該屬性指定Struts 2應用所需要的國際化資源文件,如果有多個國際化資源文件,則多個資源文件的文件名以英文逗號(,)隔開。

?struts.configuration.files

該屬性指定Struts 2框架默認加載的配置文件,如果需要指定默認加載多個配置文件,則多個配置文件的文件名之間以英文逗號(,)隔開。該屬性的默認值為struts-default.xml,struts-plugin.xml,struts.xml,看到該屬性值后大家應該明白為什么Struts 2框架會默認加載struts.xml文件了。

struts.properties文件的內容均可在struts.xml中以<constant>元素進行配置。如果這兩個文件中的配置有沖突,那么將以struts.properties文件的內容為準,這與struts的搜索順序有關。

sturt2中搜索加載常量的順序是:

struts-default.xml ????

struts-plugin.xml ?????

struts.xml ????????????

sturts.propreties ????

web.xml ???????????????

如果在struts.xml中做了主題的配置:

<constant name="struts.ui.theme" value="xhtml"></constant>

同時在struts.properties中做了主題的配置:

struts.ui.theme=simple

并使用struts2標簽開發頁面如下:

<s:form action="">

???? <s:textfield name="uname" label="用戶名"></s:textfield>

???? <s:password name="paw" label="密碼"></s:password>

???? <s:submit value="登錄"></s:submit>

???? </s:form>

運行程序效果如圖4.1.1所示:

?

圖4.1.1 主題配置

顯然?Struts.properties中的主題配置效力高于struts.xml。

4.2?Struts 2的Action

在使用Struts 2框架進行開發時,開發者需要編寫大量的Action,這是應用的核心。Action的主要作用有三個:

??封裝客戶端請求數據

??處理業務

??返回結果

在上一章我們說過Struts 2的Action可以不用繼承任何類和實現任何接口,它可以作為一個普通的JavaBean來使用。但是在實際應用中,我們仍需要一些接口和類來簡化Action。

1.?Action接口

為了使開發者編寫的Action更加規范,Struts 2提供了Action接口,下面是該接口的源代碼。

package com.opensymphony.xwork2; public interface Action {public static final String SUCCESS = "success";public static final String NONE = "none";public static final String ERROR = "error";public static final String INPUT = "input";public static final String LOGIN = "login";public String execute() throws Exception; }

由上述代碼可知,Action接口中定義了五個字符串常量:SUCCESS、NONE、ERROR、INPUT、LOGIN。我們在execute方法中返回的字符串就來自這里。自定義的Action可以不實現該接口,開發者可以在execute方法中自定義返回字符串。

2.?ActionSupport類

我們自定義的Action通常繼承com.opensymphony.xwork2.ActionSupport類,此類實現了一些有用的接口(包括上面的Action接口),提供了國際化、數據驗證等很多實用功能。該類的內容會在后續章節中學習。

4.2.1?動態方法調用

在上一章的任務實訓部分,我們使用Struts 2實現了對管理員的增、刪、改、查等操作。在實現過程中,每個請求都對應一個Action,例如:添加管理員對應的是AddAction,查詢管理員對應的是QueryAction,刪除管理員對應的是DelAction。在實際應用中,類似的情況經常出現,即:隨著項目規模的擴大,我們不得不管理大量的Action,Struts 2框架提供了動態方法調用來解決這個問題,也就是說我們可以在一個Action中自定義不同的方法來處理多個請求。

DMI(Dynamic Method Invocation)即動態方法調用,這時不能只請求某個Action,還要使用感嘆號(!)來標識出要調用的方面名,語法如下所示:

語法

Action的邏輯名!Action中的方法名?.action

示例4.1

下面我們把上一章的實訓任務通過動態方法調用進行優化,這時只需要一個Action,代碼如下所示:

public class AdminAction { private int id; private String logName; private String logPwd1; private AdminDao ad=new AdminDao(); public String addAdmin() { //添加管理員 if(ad.addAdmin(logName, logPwd1)) return "success"; else return "fail"; } public String queryAdmin() { //查詢管理員 List<Admin> adminList=ad.getAllAdmin(); Map req=(Map)ActionContext.getContext().get("request"); req.put("adminList", adminList); return "list"; } public String delAdmin(){ //刪除管理員 if(ad.delAdmin(id)) return "success"; else return "fail"; } //省略getter和setter方法 }

在上述代碼中,AdminAction沒有繼承任何類和實現任何接口,我們在該類中自定義了三個方法分別實現對管理員的增加、刪除和查詢,返回字符串也是自定義的。

提示

Action中的自定義方法必須是無參的,返回類型必須是String

下面是struts.xml的代碼,這時的配置文件就精簡了許多。

<struts> <constant name="struts.i18n.encoding" value="utf-8"></constant> <package name="admin" extends="struts-default"> <action name="admin" class="com.zy.AdminAction"> <resultname="success" type="redirect">admin!queryAdmin.action</result> <result name="fail" type="redirect">/error.jsp</result> <result name="list" type="dispatcher">/list.jsp</result> </action> </package> </struts> addAdmin.html視圖頁面的表單修改如下,其他代碼不變。 <form action="admin!addAdmin.action" method="post"> ... ... </form>

list.jsp視圖頁面的【刪除】超鏈接修改如下,其他代碼不變。

<a href="admin!delAdmin.action?id=<%=admin.getId() %>">刪除</a>

?通過動態方法調用優化后的項目更加精煉,方便以后的維護。?

4.2.2?method屬性

DMI在實際應用中可能會出現安全隱患,因為一旦某人知道了Action的名字和其中的方法名,他就可以通過URL進行任意的調用。Struts 2框架提供了一種更加安全的方式來實現DMI,在配置Action時可以通過method屬性來指定需要調用的方法。

示例4.2

下面我們通過method屬性來修改示例4.1,struts.xml代碼如下所示:

<struts> <constant name="struts.i18n.encoding" value="utf-8"></constant> <package name="admin" extends="struts-default"> <action name="query" class="com.zy.AdminAction" method="queryAdmin"> <result name="fail" type="redirect">/error.jsp</result> <result name="list" type="dispatcher">/list.jsp</result> </action> <action name="add" class="com.zy.AdminAction" method="addAdmin"> <result name="success" type="redirect">query.action</result> <result name="fail" type="redirect">/error.jsp</result> </action> <action name="del" class="com.zy.AdminAction" method="delAdmin"> <result name="success" type="redirect">query.action</result> <result name="fail" type="redirect">/error.jsp</result> </action> </package> </struts>

在上述代碼中,我們配置了三個<action>,并分別設置了method屬性,屬性的值就是Action中的方法名。雖然通過method屬性實現動態方法調用可以避免安全隱患,但是這種方法會導致struts.xml中的<action>越來越多,不利于管理和維護,為了解決這個問題我們可以使用通配符。

4.2.3?通配符的使用

在struts.xml文件中可以通過通配符簡化<action>的配置,<action>元素的name屬性支持通配符,通配符用星號(*)表示,用于匹配0到多個字符串。

示例4.3

下面我們把示例4.2通過通配符進行優化,代碼如下所示。

<struts> <package name="admin" extends="struts-default"> <action name="*" class="com.zy.AdminAction" method="{1}"> <result name="success" type="redirect">queryAdmin.action</result> <result name="fail" type="redirect">/error.jsp</result> <result name="list" type="dispatcher">/list.jsp</result> </action> </package> </struts>

name屬性的值是“*”,表示允許這個Action可以匹配任何以“.action”結束的URL。method屬性的值是“{1}”,表示該屬性的值是name屬性值中的第一個“*”。例如:

http://localhost:8080/Struts6/queryAdmin.action

當使用上面的URL請求時,“*”和“{1}”就變成了“queryAdmin”,正好是Action中實現添加管理員的方法名。

http://localhost:8080/Struts6/delAdmin.action?id=40

當使用上面的URL請求時,“*”和“{1}”就變成了“delAdmin”,正好是Action中實現刪除管理員的方法名。

通過通配符實現動態方法調用不僅避免了安全隱患,還簡化了struts.xml的配置,建議在實際應用中使用這種方法進行開發。

4.2.4?配置默認Action

如果請求的Action不存在,那么頁面上可能會呈現HTTP 404錯誤,為了避免這種情況的發生,Struts 2框架可以指定一個默認的Action,如果沒有一個Action匹配客戶端請求,那么這個默認的Action就會被執行。

在struts.xml中,通過<default-action-ref />元素來配置默認的Action。每個<default-action-ref />元素配置一個默認的Action。

<struts> <package name="admin" extends="struts-default"> <action name="defaultAction"> <result>/error.jsp</result> </action> ... ... <default-action-ref name="defaultAction"/> </package> </struts>
如果action元素的class屬性省略了,表示將使用默認的ActionSupport類。?

4.3?Result配置

Struts 2的Action處理完用戶請求后會返回一個字符串,該字符串表示邏輯視圖名。struts.xml文件通過<result>元素配置邏輯視圖名,并實現與物理視圖資源的映射。<result>元素的配置包含兩部分:由name屬性設置邏輯視圖名,由type屬性設置視圖類型。

常用的結果類型有dispatcher類型和redirect類型。

??dispatcher類型相當于“轉發”,request、session等對象都會被轉發到視圖頁面。

??redirect類型相當于“重定向”,將會丟失request、session等對象。

如果不設置type屬性,默認的類型是dispatcher。

4.3.1?動態結果

在某些情況下,事先并不能確定使用哪個結果視圖,必須在程序運行期間才能確定,這時如何在struts.xml中進行配置呢?我們可以在配置時使用表達式,在程序運行時,由框架根據表達式的值來確定要使用哪個結果視圖,這就是動態結果。

下面我們通過一個案例來演示動態結果的用法,完善登錄案例,如果是普通用戶就跳轉到user.jsp,如果是管理員就跳轉到admin.jsp。用戶的身份必須在程序運行過程中才能確定。

示例4.4

需要在原來的Action中增加一個屬性用來標識用戶的身份,并提供getter/setter方法,代碼如下所示。

public class AdminAction { //省略其他屬性 private String flag; public String login() { if(user.isAdmin()) flag="admin"; else flag="user"; return "success"; } public String getFlag() { return flag; } public void setFlag(String flag) { this.flag = flag; }//省略其他業務方法//省略其他getter和setter方法 }

如果是普通用戶,那么flag屬性的值被設置為“user”,如果是管理員,那么flag屬性的值被設置為“admin”。

下面我們看一下在struts.xml文件中如何配置,代碼如下所示。

<struts> <package name="admin" extends="struts-default"> <action name="login" class="com.zy.AdminAction"> <result name="success" type="dispatcher">/${flag}.jsp</result> <result name="error" type="redirect">/fail.jsp</result> </action> </package> </struts>

注意上述代碼中的加粗部分,我們把視圖頁面的名字用“${ flag }”代替,“${ flag }”表達式可以獲得Action中flag屬性的值。在程序運行時,如果是管理員登錄,該表達式的值為admin,即跳轉到admin.jsp;如圖是普通用戶登錄,該表達式的值為user,即跳轉到user.jsp。

4.3.2?全局結果

在之前的項目中,我們都是把<result>元素配置到了<action>元素內部,這些<result>不能被其他Action使用。但是某些<result>可能是公用的,即多個Action都需要同一個<result>,這時我們可以通過配置全局結果來滿足需求。

全局結果定義在包(package)中,而不是某個<action>元素內部,包(package)中的所有Action都可以使用這個結果。

<struts> <package name="admin" extends="struts-default"> <global-results> <result name="error" type="redirect">/error.jsp</result> </global-results> <action name="login" class="com.zy.AdminAction"> <result name="success" type="dispatcher">/index.jsp</result> </action> </package> </struts>

在struts.xml文件中使用<global-results>元素配置全局結果,可以配置多個全局結果。

?

4.4?屬性驅動與模型驅動

4.4.1?屬性驅動

在Struts 1中,ActionForm用來封裝客戶端請求數據。在Struts 2中,沒有了ActionForm,使用Action就可以封裝客戶端請求數據,例如登錄案例中的Action,代碼如下所示。

public class AdminAction extends ActionSupport { private int id; private String name; private String pwd; public String execute() { } //省略getter和setter方法 } 與之對應的表單如下所示。 <form action="login.action" method="post"><table width="397" height="169" border="0" align="center"><tr><td colspan="2" align="center">管理員登錄</td></tr><tr><td width="163" align="right">登錄名稱:</td><td width="218"><input name="name" type="text" class="txt"></td></tr><tr><td align="right">登錄密碼:</td><td><input name="pwd" type="password" class="txt"></td></tr><tr><td colspan="2" align="center"><input type="submit" value="提交"></td></tr> </table> </form>

注意上述代碼中的加粗部分,表單中每一個元素的name都對應Action中的一個屬性,程序在運行時,Struts 2通過Action的屬性來封裝客戶端請求數據,這種方式稱之為屬性驅動。我們前面所編寫的案例采用的都是這種方式。

4.4.2?模型驅動

屬性驅動使得Action既要封裝客戶端請求數據,還要處理業務,這就造成Action承擔了過多的職責,分工也不夠清晰。更好的解決辦法就是采用單獨的Model(模型)來封裝請求數據,這就是模型驅動。模型驅動中的Model(模型)其實就是一個實體類或POJO,專門用來封裝客戶端請求數據。

示例4.5

下面我們把前面的登錄案例改成模型驅動。首先需要一個封裝登錄表單的實體類Admin作為模型,代碼如下所示。

public class Admin {

private String name; ?//登錄名稱

private String pwd; ??//登錄密碼

//省略getter和setter方法

}

Action就不需要分散的屬性來封裝表單數據了,只需要一個Admin類型的屬性即可,代碼如下所示。

public class LoginAction extends ActionSupport { private Admin admin; public String execute() { AdminDao ad=new AdminDao(); if(ad.checkLogin(admin.getName(), admin.getPwd())) return SUCCESS; else return ERROR; } public Admin getAdmin() { return admin; } public void setAdmin(Admin admin) { this.admin = admin; } } 與之對應的表單需要進行如下修改。 <form action="login.action" method="post"><table width="397" height="169" border="0" align="center"><tr><td colspan="2" align="center">管理員登錄</td></tr><tr><td width="163" align="right">登錄名稱:</td><td width="218"><input name="admin.name" type="text" class="txt"></td></tr><tr><td align="right">登錄密碼:</td><td><input name="admin.pwd" type="password" class="txt"></td></tr><tr><td colspan="2" align="center"><input type="submit" value="提交"></td></tr> </table> </form>

注意上述代碼中的加粗部分,在使用模型驅動時,表單元素name屬性的值由兩部分組成,第一部分是Action中模型對象的名字,第二部分是模型對象的屬性名。如果在實際應用中需要在頁面上輸出模型對象中屬性的值,則可以使用“${ admin.name }”進行輸出。

本章總結

?Struts 2的配置文件

(1)中文亂碼處理。可以通過名為struts.i18n.encoding的常量配置字符集。

(2)包配置。包的常用屬性有name, extends和namaspaces。

(3)包含配置。

?Struts 2的Action

(1)動態方法調用。

(2)Method參數和通配符的使用。

Result配置

屬性驅動和模型驅動

任務實訓部分

1:查詢圖書

訓練技能點

??method屬性

??通配符

??需求說明

在第二章的核心任務部分我們講解了一個查詢圖書的案例,現在要求使用Struts 2進行

重構,并應用method屬性和通配符進行優化處理

??實現步驟

(1)?創建對應圖書表的實體類Book.java

(2)?創建實現數據庫連接和關閉的工廠類DaoFactory.java

(3)?創建實現圖書查詢功能的Dao類BookDao.java

(4)?創建實現圖書查詢業務的Action類QueryAction.java,參考代碼如下所示。

public class QueryAction{ private String keywords; private BookDao bd=new BookDao(); private List bookList=new ArrayList(); private ActionContext ac=ActionContext.getContext(); private Map req=(Map)ac.get("request"); public String queryByName() //按書名查詢 { bookList=bd.getBooks("name", keywords); req.put("bookList", bookList); return "success"; } public String queryByAuthor() //按作者查詢 { bookList=bd.getBooks("author", keywords); req.put("bookList", bookList); return "success"; } public String queryByPublisher() //按出版社查詢 { bookList=bd.getBooks("publish", keywords); req.put("bookList", bookList); return "success"; } //省略getter和setter方法 }

(5)?創建實現查詢界面的視圖query.html,參考代碼如下所示。 ?

<body><form name="f" method="post"><table width="330" height="94" border="0" align="center"><tr><td align="center">關鍵字:<input type="text" name="keywords"></td></tr><tr><td align="center"><input name="rd" type="radio" value="queryByName" checkedοnclick="change(this.value)">按書名查詢<input name="rd" type="radio" value="queryByAuthor"οnclick="change(this.value)">按作者查詢<input name="rd" type="radio" value="queryByPublisher"οnclick="change(this.value)">按出版社查詢</td></tr><tr><td align="center"><input type="button" value="查詢"οnclick="submitForm()"></td></tr></table></form></body> <script> var v="queryByName"; function change(val) { v=val; } function submitForm() { f.action=v+".action"; f.submit(); } </script>

由于本案例要使用動態方法調用,所以在該頁面我們需要使用JS動態合成請求URL,運行效果如圖4.2.1所示。


圖4.2.1 查詢界面

(6)?編輯struts.xml,參考代碼如下所示。

<struts> <constant name="struts.i18n.encoding" value="utf-8"></constant> <package name="book" extends="struts-default"> <action name="*" class="com.zy.QueryAction" method="{1}"> <result name="success" type="dispatcher">/list.jsp</result> </action> </package> </struts>

(7)?顯示查詢結果的視圖頁面list.jsp這里不再多述,運行效果如圖4.2.2所示。

?


圖4.2.2 查詢結果

2:實現簡易計算器

訓練技能點

?動態方法調用

?模型驅動

??需求說明

使用動態方法調用和模型驅動優化上一章的實訓任務4

??實現步驟

(1)?創建實體類Calculator.java,參考代碼如下所示。

public class Calculator { private double num1; private double num2; private double result;//省略getter和setter方法 }

(2)?創建Action類CalculatorAction.java,參考代碼如下所示。

public class CalculatorAction { private Calculator cal; public String jia() //加法運算 { cal.setResult(cal.getNum1()+cal.getNum2()); return "result"; } public String jian() //減法運算 { cal.setResult(cal.getNum1()-cal.getNum2()); return "result"; } public String cheng() //乘法運算 { cal.setResult(cal.getNum1()*cal.getNum2()); return "result"; } public String chu() //除法運算 { cal.setResult(cal.getNum1()/cal.getNum2()); return "result"; } //省略getter和sertter方法 }

(3)?創建計算器的視圖頁面,參考代碼如下所示。

<form name="frm" method="post"><table width="298" border="0" align="center"><tr><td colspan="2" align="center">簡易計算器</td></tr><tr><td width="76" align="center">第一個數</td><td width="206"><input type="text" name="cal.num1"value="${cal.num1}"></td></tr><tr><td align="center">第二個數</td><td><input type="text" name="cal.num2" value="${cal.num2}"></td></tr><tr><td colspan="2" align="center"><input type="button" value="+" οnclick="submitForm('jia')"><input type="button" value="-" οnclick="submitForm('jian')"><input type="button" value="*" οnclick="submitForm('cheng')"><input type="button" value="/" οnclick="submitForm('chu')"></td></tr><tr><td align="center">結果</td><td><input type="text" name="result" readonlyvalue="${cal.result}"></td></tr></table> </form></body> <script> function submitForm(op) { frm.action="cal_"+op+".action"; frm.submit(); } </script>

由于要使用動態方法調用和通配符,所以在頁面中我們使用JS合成請求URL。同時我們使用EL表達式輸出了Action中屬性的值。

(4)?配置struts.xml,代碼如下所示。

<package name="calculator" extends="struts-default"> <action name="cal_*" class="com.test.CalculatorAction" method="{1}"> <result name="result" type="dispatcher">/calculator.jsp</result> </action> </package>

圖4.2.3 計算器

3:模型驅動

訓練技能點

模型驅動

??需求說明

把上一章的前三個實訓任務使用模型驅動進行優化

鞏固練習

一、選擇題

1. 以下關于<action>元素的說法錯誤的是()。

A.?name屬性是必須的

B.?name屬性不能唯一確定一個Action

C.?method屬性表示調用Action中的哪個方法

D.?通配符除了星號(*)還有下劃線(_)

2. 以下關于<result>元素的說法錯誤的是()。

A. ?type屬性指定結果類型

B. ?name屬性指定結果的邏輯名

C. ?name屬性的值必須是Action接口中的某個常量

D. 默認的類型是dispatcher

3. Struts 2的結果類型有()。

A. ?dispatcher

B.?redirect

C. ?chain

D. ?success

4. DMI的正確寫法是()。

A.?Action的邏輯名!Action中的方法名?.action

B.?Action的邏輯名_Action中的方法名?.action

C.?Action的邏輯名!Action中的方法名?.do

D.?Action的邏輯名_Action中的方法名?.do

5. 以下關于Struts 2配置文件說法正確的是()。

A.?struts.properties是必須的配置文件

E.?struts.properties通過標簽元素進行配置

F.?只能同時使用struts.properties與struts.xml中的一個

G.?struts.properties中的配置通常都可以在struts.xml中進行配置?

二、上機練習

?把上一章的課后上機練習使用模型驅動和動態方法調用進行重構。運行效果圖如下。?

圖4.3.1 增加【修改】超鏈接

?

圖4.3.2 密碼修改頁面

?

總結

以上是生活随笔為你收集整理的Struts 2配置详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。