




已閱讀5頁(yè),還剩82頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第3章 Struts 2應(yīng)用,3.1 Struts 2概述,3.2 Struts 2基本應(yīng)用及工作流程,3.3 Struts 2標(biāo)簽庫(kù)應(yīng)用,3.4 Struts 2攔截器,3.5 Struts 2國(guó)際化應(yīng)用,3.6 Struts 2文件上傳,3.7 Struts 2綜合應(yīng)用實(shí)例添加學(xué)生信息,3.1 Struts 2概述,3.1.1 MVC簡(jiǎn)介 MVC有以下優(yōu)點(diǎn): 多個(gè)視圖可以對(duì)應(yīng)一個(gè)模型。按MVC設(shè)計(jì)模式,一個(gè)模型對(duì)應(yīng)多個(gè)視圖,可以減少代碼的復(fù)制及代碼的維護(hù)量,一旦模型發(fā)生改變,也易于維護(hù)。 模型返回的數(shù)據(jù)與顯示邏輯分離。模型數(shù)據(jù)可以應(yīng)用任何顯示技術(shù),例如,使用JSP頁(yè)面、Velocity模板或者直接產(chǎn)生Excel文檔等。 應(yīng)用被分隔為三層,降低了各層之間的耦合,提供了應(yīng)用的可擴(kuò)展性。 控制層的概念也很有效,由于它把不同的模型和不同的視圖組合在一起,完成不同的請(qǐng)求,因此控制層可以說是包含了用戶請(qǐng)求權(quán)限的概念。 MVC更符合軟件工程化管理的精神。不同的層各司其職,每一層的組件具有相同的特征,有利于通過工程化和工具化產(chǎn)生管理程序代碼。,3.1.2 Struts 2體系結(jié)構(gòu),Struts 2的基本流程如下: Web瀏覽器請(qǐng)求一個(gè)資源。 過濾器Dispatcher查找請(qǐng)求,確定適當(dāng)?shù)腁ction。 攔截器自動(dòng)對(duì)請(qǐng)求應(yīng)用通用功能,如驗(yàn)證和文件上傳等操作。 Action的execute方法通常用來存儲(chǔ)和(或)重新獲得信息(通過數(shù)據(jù)庫(kù))。, 結(jié)果被返回到瀏覽器??赡苁荋TML、圖片、PDF或其他。 其實(shí),Struts 2框架的應(yīng)用著重在控制上。簡(jiǎn)單的流程是:頁(yè)面控制器頁(yè)面。最重要的是控制器的取數(shù)據(jù)與處理后傳數(shù)據(jù)的問題。Struts 2的體系結(jié)構(gòu)還可以參考圖3.1,更直觀地展現(xiàn)出其流程。,圖3.1 Struts 2體系結(jié)構(gòu),3.2 Struts 2基本應(yīng)用及工作流程,3.2.1 簡(jiǎn)單Struts 2實(shí)例開發(fā) 1. 下載Struts 2框架 MyEclipse 6沒有對(duì)Struts 2的支持,所以需要用戶自己下載Struts 2開發(fā)包。登錄/下載Struts 2完整版,本書使用的是Struts 2.0.14。將下載的Zip文件解壓縮,它是一個(gè)典型的Web結(jié)構(gòu)。打開其文件夾,里面包含以下4個(gè)文件: apps:包含基于Struts 2的示例應(yīng)用,是學(xué)習(xí)Struts 2非常有用的資料。 docs:包含Struts 2的相關(guān)文檔,如Struts 2快速入門、Struts 2文檔、API文檔等內(nèi)容。 lib:包含Struts 2框架的核心類庫(kù),以及Struts 2的第三方插件類庫(kù)。 src:包含Struts 2框架的全部源代碼。 2. 建立一個(gè)Web項(xiàng)目 打開MyEclipse,建立一個(gè)Web項(xiàng)目,命名為“Struts 2.0”。,3.2.1 簡(jiǎn)單Struts 2實(shí)例開發(fā),3. 加載Struts 2基本類庫(kù) 下面把這幾個(gè)類庫(kù)添加到項(xiàng)目中。 右擊項(xiàng)目名,選擇【Build Path】【Configure Build Path】菜單項(xiàng),出現(xiàn)如圖3.2所示的對(duì)話框。單擊【Add External JARs】按鈕,進(jìn)入下載的Struts 2目錄的lib文件夾,選中上面的5個(gè)Jar包,單擊【OK】按鈕完成類庫(kù)的添加。,圖3.2 添加Struts 2的Jar包,3.2.1 簡(jiǎn)單Struts 2實(shí)例開發(fā),4. 修改web.xml文件 打開項(xiàng)目中的WebRoot/WEB-INF/web.xml文件,修改其代碼如下: struts 2 org.apache.struts2.dispatcher.FilterDispatcher struts 2 /* ,3.2.1 簡(jiǎn)單Struts 2實(shí)例開發(fā),5. 創(chuàng)建hello.jsp 選擇【W(wǎng)ebRoot】【new】【jsp】菜單項(xiàng),在File Name中輸入文件名“hello.jsp”,修改后的代碼如下: struts 2應(yīng)用 請(qǐng)輸入姓名: ,3.2.1 簡(jiǎn)單Struts 2實(shí)例開發(fā),6. Action實(shí)現(xiàn)類 右擊src文件夾,選擇【new】【Package】菜單項(xiàng),在name框中輸入包名“org.action”,右擊該包,依此類推,建立class,命名為“StrutsAction”,修改后的代碼如下: package org.action; import java.util.Map; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class StrutsAction extends ActionSupport private String name; public String getName() return name; public void setName(String name) =name; public String execute() throws Exception if(!name.equals(“HelloWorld“) Map request=(Map)ActionContext.getContext().get(“request“); request.put(“name“,getName(); return “success“; else return “error“; ,3.2.1 簡(jiǎn)單Struts 2實(shí)例開發(fā),7. 創(chuàng)建并配置struts.xml文件 任何一個(gè)Struts 2程序都不能缺少struts.xml文件,它是Struts 2運(yùn)行的核心。右擊src文件夾,選擇【new】【file】菜單項(xiàng),在File name框中輸入“struts.xml”,修改后的代碼如下: /welcome.jsp /hello.jsp ,3.2.1 簡(jiǎn)單Struts 2實(shí)例開發(fā),8. 創(chuàng)建welcome.jsp 創(chuàng)建welcome.jsp,其步驟和上面創(chuàng)建hello.jsp類似,這里不再重復(fù)敘述。其代碼如下: struts 2應(yīng)用 hello ! ,3.2.1 簡(jiǎn)單Struts 2實(shí)例開發(fā),9. 部署和運(yùn)行 啟動(dòng)Tomcat后,在瀏覽器中輸入“http:/localhost:8080/Struts2.0/hello.jsp”,會(huì)看到如圖3.3所示的界面。當(dāng)在輸入框中輸入“張三”時(shí),會(huì)出現(xiàn)如圖3.4所示界面。如果輸入“HelloWorld”,就會(huì)返回當(dāng)前頁(yè)面。,圖3.3 運(yùn)行界面 圖3.4 運(yùn)行成功界面,3.2.2 Struts 2工作流程及各種文件詳解,1. Struts 2的工作流程 Struts 2框架中的配置文件struts.xml會(huì)起映射作用,它會(huì)根據(jù)“*”來決定調(diào)用用戶定義的哪個(gè)Action類。例如在項(xiàng)目Struts 2.0中,請(qǐng)求為struts.action,前面“*”的部分是“struts”,所以在struts.xml中有個(gè)Action類的name為“struts”,這表示該請(qǐng)求與這個(gè)Action來匹配,就會(huì)調(diào)用該Action中class屬性指定的Action類。但是在Struts 2中,用戶定義的Action類并不是業(yè)務(wù)控制器,而是Action代理,其并沒有和Servlet API耦合。所以Struts 2框架提供了一系列的攔截器,它負(fù)責(zé)將HttpServletRequest請(qǐng)求中的請(qǐng)求參數(shù)解析出來,傳入到用戶定義的Action類中。,3.2.2 Struts 2工作流程及各種文件詳解,2. Struts 2中各種文件詳解 (1)web.xml文件 后面的webapp標(biāo)簽中配置了下面這樣一段: struts2 org.apache.struts2.dispatcher.FilterDispatcher struts2 /* 可以看出,里面配置了一個(gè)過濾器,那么就先來介紹過濾器的使用。 Filter過濾器是Java項(xiàng)目開發(fā)中的一種常用技術(shù)。它是用戶請(qǐng)求和處理程序之間的一層處理程序。它可以對(duì)用戶請(qǐng)求和處理程序響應(yīng)的內(nèi)容進(jìn)行處理,通常用于權(quán)限控制、編碼轉(zhuǎn)換等場(chǎng)合。,3.2.2 Struts 2工作流程及各種文件詳解,所有過濾器必須實(shí)現(xiàn)java.Serlvet.Filter接口,這個(gè)接口中含有3個(gè)過濾器類必須實(shí)現(xiàn)的方法: init(FilterConfig):Servlet過濾器的初始化方法,Servlet容器創(chuàng)建Servlet過濾器實(shí)例后將調(diào)用這個(gè)方法。 doFilter(ServletRequest,ServletResponse,FilterChain):完成實(shí)際的過濾操作,當(dāng)用戶請(qǐng)求與過濾器關(guān)聯(lián)的URL時(shí),Servlet容器將先調(diào)用過濾器的doFilter方法,返回響應(yīng)之前也會(huì)調(diào)用此方法。FilterChain參數(shù)用于訪問過濾器鏈上的下一個(gè)過濾器。 destroy():Servlet容器在銷毀過濾器實(shí)例前調(diào)用該方法,這個(gè)方法可以釋放Servlet過濾器占用的資源,過濾器類編寫完成后,必須要在web.xml中進(jìn)行配置,格式如下: 過濾器名 過濾器對(duì)應(yīng)類 參數(shù)名稱 參數(shù)值 ,3.2.2 Struts 2工作流程及各種文件詳解,過濾器的關(guān)聯(lián)方式有3種:與一個(gè)URL關(guān)聯(lián)、與一個(gè)URL目錄下的所有資源關(guān)聯(lián)、與一個(gè)Servlet關(guān)聯(lián)。 與一個(gè)URL資源關(guān)聯(lián): 過濾器名 xxx.jsp 與一個(gè)URL目錄下的所有資源關(guān)聯(lián): 過濾器名 /* 與一個(gè)Servlet關(guān)聯(lián): 過濾器名 Servlet名稱 ,3.2.2 Struts 2工作流程及各種文件詳解,(2)struts.xml文件 struts.xml文件通常放在Web應(yīng)用程序的WEB-INF/classes目錄下,該目錄下的struts.xml將被Struts 2框架自動(dòng)加載。 struts.xml文件是一個(gè)XML文件,文件前面是XML的頭文件,然后是標(biāo)簽,位于Struts 2配置的最外層,其他標(biāo)簽都是包含在它里面的。 (3)package元素 與Java中的包不同的是,Struts 2中的包可以擴(kuò)展另外的包,從而“繼承”原有包的所有定義,并可以添加自己包的特有配置,以及修改原有包的部分配置。從這一點(diǎn)上看,Struts 2中的包更像Java中的類。package有以下幾個(gè)常用屬性: name:該屬性是必選的,指定包的名字,這個(gè)名字將作為引用該包的鍵。 extends:該屬性是可選的,允許一個(gè)包繼承一個(gè)或多個(gè)先前定義的包。 abstract:該屬性是可選的,將其設(shè)置為true,可以把一個(gè)包定義為抽象的。,3.2.2 Struts 2工作流程及各種文件詳解,namespace:該屬性是可選的,將保存的action配置為不同的名稱空間。看下面這個(gè)例子: /foo.jsp /bar.jsp /moo.jsp /bar.jsp ,3.2.2 Struts 2工作流程及各種文件詳解,(4)Action元素 當(dāng)一個(gè)請(qǐng)求匹配到某個(gè)Action名字時(shí),框架就使用這個(gè)映射來確定如何處理請(qǐng)求。 /welcome.jsp /hello.jsp 如果一個(gè)請(qǐng)求要調(diào)用Action類中的其他方法,就需要在Action配置中加以配置。例如,如果在org.action.StrutsAction中有另外一個(gè)方法為: public String find() throws Exceptionreturn SUCCESS; 那么如果想要調(diào)用這個(gè)方法,就必須在Action中配置method屬性,其配置方法為: /welcome.jsp /hello.jsp ,3.2.2 Struts 2工作流程及各種文件詳解,(5)result元素 一個(gè)result代表一個(gè)可能的輸出。當(dāng)Action類中的方法執(zhí)行完成時(shí),返回一個(gè)字符串類型的結(jié)果代碼,框架根據(jù)這個(gè)結(jié)果代碼選擇對(duì)應(yīng)的result,向用戶輸出。 參數(shù)值 param中的name屬性有兩個(gè)值: location:指定邏輯視圖。 parse:是否允許在實(shí)際視圖名中使用OGNL表達(dá)式,參數(shù)默認(rèn)為true。 result中的name屬性有如下值: success:表示請(qǐng)求處理成功,該值也是默認(rèn)值。 error:表示請(qǐng)求處理失敗。 none:表示請(qǐng)求處理完成后不跳轉(zhuǎn)到任何頁(yè)面。 input:表示輸入時(shí)如果驗(yàn)證失敗應(yīng)該跳轉(zhuǎn)到什么地方(關(guān)于驗(yàn)證后面會(huì)介紹)。 login:表示登錄失敗后跳轉(zhuǎn)的目標(biāo)。,3.2.2 Struts 2工作流程及各種文件詳解,type(非默認(rèn)類型)屬性支持的結(jié)果類型有以下幾種: chain:用來處理Action鏈。 chart:用來整合JFreeChart的結(jié)果類型。 dispatcher:用來轉(zhuǎn)向頁(yè)面,通常處理JSP,該類型也為默認(rèn)類型。 freemarker:處理FreeMarker模板。 httpheader:控制特殊HTTP行為的結(jié)果類型。 jasper:用于JasperReports整合的結(jié)果類型。 jsf:JSF整合的結(jié)果類型。 redirect:重定向到一個(gè)URL。 redirect-action:重定向到一個(gè)Action。 stream:向?yàn)g覽器發(fā)送InputStream對(duì)象,通常用來處理文件下載,還可用于返回AJAX數(shù)據(jù)。 tiles:與Tiles整合的結(jié)果類型。 velocity:處理Velocity模板。 xslt:處理XML/XLST模板。 plaintext:顯示原始文件內(nèi)容,如文件源代碼。,3.2.2 Struts 2工作流程及各種文件詳解,edirect-action類型用于當(dāng)一個(gè)Action處理結(jié)束后,直接將請(qǐng)求重定向到另一個(gè)Action。如下列配置: /welcome.jsp /hello.jsp struts ,3.2.2 Struts 2工作流程及各種文件詳解,(6)ActionSupport類 ActionSupport類為Action提供了一些默認(rèn)實(shí)現(xiàn),主要包括預(yù)定義常量、從資源文件中讀取文本資源、接收驗(yàn)證錯(cuò)誤信息和驗(yàn)證的默認(rèn)實(shí)現(xiàn)。 下面是ActionSupport類所實(shí)現(xiàn)的接口: public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider,Serializable Action接口同樣位于com.opensymphony.xwork2包,定義了一些常量和一個(gè)execute()方法。 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=“l(fā)ogin“; public String execute() throws Exception; ,3.2.2 Struts 2工作流程及各種文件詳解,由于3.2.1節(jié)的例子中繼承了ActionSupport類,所以可以看出,在execute的返回值中,其代碼可以改為: public String execute() throws Exception if(!name.equals(“HelloWorld“) Map request=(Map)ActionContext.getContext().get(“request“); request.put(“name“,getName(); return SUCCESS; else return ERROR; ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,1. 數(shù)據(jù)校驗(yàn) 下面來看其實(shí)現(xiàn),可以把3.2.1節(jié)的例子中的Action類改寫成。 如果執(zhí)行該方法之后,Action類的fieldErrors中已經(jīng)包含了數(shù)據(jù)校驗(yàn)錯(cuò)誤信息,將把請(qǐng)求轉(zhuǎn)發(fā)到input邏輯視圖處,所以要在Action配置中加入以下代碼: /welcome.jsp /hello.jsp /hello.jsp ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,把JSP頁(yè)面改寫一下(標(biāo)簽的具體應(yīng)用會(huì)在3.3節(jié)具體講解): struts 2 ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,修改之后,部署運(yùn)行。不輸入任何姓名直接提交,將會(huì)看到如圖3.5所示的界面。,圖3.5 校驗(yàn)結(jié)果,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,2. Struts 2驗(yàn)證框架的應(yīng)用 Struts 2提供了校驗(yàn)框架,只需要增加一個(gè)校驗(yàn)配置文件,就可以完成對(duì)數(shù)據(jù)的校驗(yàn)。Struts 2提供了大量的數(shù)據(jù)校驗(yàn)器,包括表單域校驗(yàn)器和非表單域校驗(yàn)器兩種。 (1)必填字符串校驗(yàn)器 其校驗(yàn)規(guī)則定義文件如下: true 姓名是必需的! ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,下面具體介紹其他校驗(yàn)框架的應(yīng)用。 (2)必填校驗(yàn)器 該校驗(yàn)器的名字是required,也就是屬性中的type=“required“,該校驗(yàn)器要求指定的字段必須有值,與必填字符串校驗(yàn)器最大的區(qū)別就是可以有空字符串。如果把上例改為必填校驗(yàn)器,其代碼應(yīng)為: 姓名是必需的! ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,(3)整數(shù)校驗(yàn)器 該校驗(yàn)器的名字是int,該校驗(yàn)器要求字段的整數(shù)值必須在指定范圍內(nèi),故其有min和max參數(shù)。如果有個(gè)age輸入框,要求其必須是整數(shù),且輸入值必須在18與100之間,該校驗(yàn)器的配置應(yīng)該為: 18 100 年齡必須在18至100之間 ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,(4)日期校驗(yàn)器 該校驗(yàn)器的名字是date,該校驗(yàn)器要求字段的日期值必須在指定范圍內(nèi),故其有min和max參數(shù)。其配置格式如下: 1980-01-01 2009-12-31 日期必須在1980-01-01至2009-12-31之間 ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,(5)郵件地址校驗(yàn)器 該校驗(yàn)器的名稱是email,該校驗(yàn)器要求字段的字符如果非空,就必須是合法的郵件地址。如下面的代碼: 必須輸入有效的電子郵件地址 ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,(6)網(wǎng)址校驗(yàn)器 該校驗(yàn)器的名稱是url,該校驗(yàn)器要求字段的字符如果非空,就必須是合法的URL地址。如下面的代碼: 必須輸入有效的網(wǎng)址 ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,(7)字符串長(zhǎng)度校驗(yàn)器 該校驗(yàn)器的名稱是stringlength,該校驗(yàn)器要求字段的長(zhǎng)度必須在指定的范圍內(nèi),一般用于密碼輸入框。如下面的代碼: 6 20 密碼長(zhǎng)度必須在6到20之間 ,3.2.3 Struts 2數(shù)據(jù)驗(yàn)證及驗(yàn)證框架的應(yīng)用,(8)正則表達(dá)式校驗(yàn)器 該校驗(yàn)器的名稱是regex,它檢查被校驗(yàn)字段是否匹配一個(gè)正則表達(dá)式。如下面的代碼: 學(xué)號(hào)必須是6位的數(shù)字 ,3.3 Struts 2標(biāo)簽庫(kù)應(yīng)用,3.3.1 Struts 2的OGNL表達(dá)式 在介紹標(biāo)簽庫(kù)前,有必要先來學(xué)習(xí)Struts 2的OGNL表達(dá)式。 1. OGNL表達(dá)式 OGNL表達(dá)式是Struts 2框架的特點(diǎn)之一。 標(biāo)準(zhǔn)的OGNL會(huì)設(shè)定一個(gè)根對(duì)象(root對(duì)象)。假設(shè)使用標(biāo)準(zhǔn)OGNL表達(dá)式來求值(不是Struts 2 OGNL),如果OGNL上下文有兩個(gè)對(duì)象foo對(duì)象和bar對(duì)象,同時(shí)foo對(duì)象被設(shè)置為根對(duì)象(root),則利用下面的OGNL表達(dá)式求值。 #foo.blah / 返回foo.getBlah() #bar.blah / 返回bar.getBlah() blah / 返回foo.getBlah(),因?yàn)閒oo為根對(duì)象,3.3.1 Struts 2的OGNL表達(dá)式,在Struts 2框架中,值棧(Value Stack)就是OGNL的根對(duì)象。假設(shè)值棧中存在兩個(gè)對(duì)象實(shí)例Man和Animal,這兩個(gè)對(duì)象實(shí)例都有一個(gè)name屬性,Animal有一個(gè)species屬性,Man有一個(gè)salary屬性。假設(shè)Animal在值棧的頂部,Man在Animal后面,如圖3.6所示。,圖3.6 一個(gè)包含了Animal和Man的值棧,3.3.1 Struts 2的OGNL表達(dá)式,下面的代碼片段能更好地理解OGNL表達(dá)式。 species / 調(diào)用animal.getSpecies() salary / 調(diào)用man.getSalary() name / 調(diào)用animal.getName(),因?yàn)锳nimal位于值棧的頂部 最后一行實(shí)例代碼返回的是animal.getName()返回值,即返回了Animal的name屬性,因?yàn)锳nimal是值棧的頂部元素,OGNL將從頂部元素搜索,所以會(huì)返回Animal的name屬性值。如果要獲得Man的name值,則需要如下代碼: Struts 2允許在值棧中使用索引,實(shí)例代碼如下: 0.name / 調(diào)用animal.getName() 1.name / 調(diào)用man.getName(),3.3.1 Struts 2的OGNL表達(dá)式,Struts 2中的OGNL Context是ActionContext,如圖3.7所示。,圖3.7 Struts 2的OGNL Context結(jié)構(gòu)示意圖,3.3.1 Struts 2的OGNL表達(dá)式,由于值棧是Struts 2中OGNL的根對(duì)象。如果用戶需要訪問值棧中的對(duì)象,則可以通過如下代碼訪問值棧中的屬性: $foo / 獲得值棧中的foo屬性 如果訪問其他Context中的對(duì)象,由于不是根對(duì)象,在訪問時(shí)需要加#前綴。 application對(duì)象:用來訪問ServletContext,如#application.userName或者#application “userName“,相當(dāng)于調(diào)用Servlet的getAttribute(“userName“)。 session對(duì)象:用來訪問HttpSession,如#session.userName或者#session“userName“,相當(dāng)于調(diào)用session.getAttribute(“userName“)。 request對(duì)象:用來訪問HttpServletRequest屬性的Map,如#request.userName或者#request“userName“,相當(dāng)于調(diào)用request.getAttribute(“userName“)。如在3.2.1節(jié)中StrutsAction類中代碼: Map request=(Map)ActionContext.getContext().get(“request“); request.put(“name“,getName(); 這就是先得到request對(duì)象,然后把值放進(jìn)去,在該例的success.jsp中有: 其中#相當(dāng)于調(diào)用了request.getAttribute(“name“)。,3.3.1 Struts 2的OGNL表達(dá)式,2. OGNL集合操作 使用如下代碼直接生成一個(gè)List對(duì)象: e1, e2, e3 下面的代碼可以直接生成一個(gè)Map對(duì)象: #key: value1, key2: value2, 對(duì)于集合類型,OGNL表達(dá)式可以使用in和not in兩個(gè)元素符號(hào)。其中,in表達(dá)式用來判斷某個(gè)元素是否在指定的集合對(duì)象中;not in判斷某個(gè)元素是否不在指定的集合對(duì)象中,代碼如下所示: 或 ,3.3.1 Struts 2的OGNL表達(dá)式,除了in和not in之外,OGNL還允許使用某個(gè)規(guī)則獲得集合對(duì)象的子集,常用的有以下3個(gè)相關(guān)操作符。 ?:獲得所有符合邏輯的元素。 :獲得符合邏輯的第一個(gè)元素。 $:獲得符合邏輯的最后一個(gè)元素。 如下面的代碼: Person .relatives.?# this.gender=male 該代碼可以獲得Person的所有性別為male的relatives集合。,3.3.2 數(shù)據(jù)標(biāo)簽,數(shù)據(jù)標(biāo)簽屬于非UI標(biāo)簽,主要用于提供各種數(shù)據(jù)訪問相關(guān)的功能,數(shù)據(jù)標(biāo)簽主要包括以下幾個(gè)。 property:用于輸出某個(gè)值。 set:用于設(shè)置一個(gè)新變量。 param:用于設(shè)置參數(shù),通常用于bean標(biāo)簽和action標(biāo)簽的子標(biāo)簽。 bean:用于創(chuàng)建一個(gè)JavaBean實(shí)例。 action:用于在JSP頁(yè)面直接調(diào)用一個(gè)Action。 date:用于格式化輸出一個(gè)日期。 debug:用于在頁(yè)面上生成一個(gè)調(diào)試鏈接,當(dāng)單擊該鏈接時(shí),可以看到當(dāng)前值棧和Stack Context中的內(nèi)容。 il8n:用于指定國(guó)際化資源文件的baseName。 include:用于在JSP頁(yè)面中包含其他的JSP或Servlet資源。 push:用于將某個(gè)值放入值棧的棧頂。 text:用于輸出國(guó)際化(國(guó)際化內(nèi)容會(huì)在后面講解)。 url:用于生成一個(gè)URL地址。,3.3.2 數(shù)據(jù)標(biāo)簽,1. 標(biāo)簽 property標(biāo)簽的作用是輸出指定值。property標(biāo)簽輸出value屬性指定的值。如果沒有指定的value屬性,則默認(rèn)輸出值棧棧頂?shù)闹?。該?biāo)簽有如下幾個(gè)屬性: default:該屬性是可選的,如果需要輸出的屬性值為null,則顯示default屬性指定的值。 escape:該屬性是可選的,指定是否escape HTML代碼。 value:該屬性是可選的,指定需要輸出的屬性值,如果沒有指定該屬性,則默認(rèn)輸出值棧棧頂?shù)闹怠T搶傩砸彩亲畛S玫?,如前面用到的?id:該屬性是可選的,指定該元素的標(biāo)志。,3.3.2 數(shù)據(jù)標(biāo)簽,2. 標(biāo)簽 該標(biāo)簽有如下幾個(gè)屬性: name:該屬性是必選的,重新生成新變量的名字。 scope:該屬性是可選的,指定新變量的存放范圍。 id:該屬性是可選的,指定該元素的引用id。 下面是一個(gè)簡(jiǎn)單例子,展示了property標(biāo)簽訪問存儲(chǔ)于session中的user對(duì)象的多個(gè)字段: 使用set標(biāo)簽使得代碼易于閱讀: ,3.3.2 數(shù)據(jù)標(biāo)簽,3. 標(biāo)簽 param標(biāo)簽主要用于為其他標(biāo)簽提供參數(shù),該標(biāo)簽有如下幾個(gè)屬性: name:該屬性是可選的,指定需要設(shè)置參數(shù)的參數(shù)名。 value:該屬性是可選的,指定需要設(shè)置參數(shù)的參數(shù)值。 id:該屬性是可選的,指定引用該元素的id。 例如,要為name為fruit的參數(shù)賦值: apple 或者 如果想指定fruit參數(shù)的值為apple字符串,則應(yīng)該這樣寫: ,3.3.2 數(shù)據(jù)標(biāo)簽,4. 標(biāo)簽 該標(biāo)簽有如下幾個(gè)屬性: name:該屬性是必選的,用來指定要實(shí)例化的JavaBean的實(shí)現(xiàn)類。 id:該屬性是可選的,如果指定了該屬性,則該JavaBean實(shí)例會(huì)被放入Stack Context中,從而允許直接通過id屬性來訪問該JavaBean實(shí)例。下面是一個(gè)簡(jiǎn)單的例子: 有一個(gè)Student類,該類中有name屬性,并有其getter和setter方法: public class Student private String name; public String getName() return name; public void setName(String name) =name; 然后在JSP文件的body體中加入下面的代碼: ,3.3.2 數(shù)據(jù)標(biāo)簽,在項(xiàng)目中導(dǎo)入Struts 2的5個(gè)重要Jar包,再把Student類放在項(xiàng)目的src文件夾下,標(biāo)簽內(nèi)容放在一個(gè)JSP文件的body體內(nèi),再修改web.xml文件,就可以部署運(yùn)行該項(xiàng)目,會(huì)得到如圖3.8所示的界面。,圖3.8 bean標(biāo)簽實(shí)例界面,如果把bean標(biāo)簽的內(nèi)容改為: ,3.3.2 數(shù)據(jù)標(biāo)簽,5. 標(biāo)簽 使用action標(biāo)簽可以允許在JSP頁(yè)面中直接調(diào)用Action。該標(biāo)簽有以下幾個(gè)屬性: id:該屬性是可選的,該屬性將會(huì)作為該Action的引用標(biāo)志id。 name:該屬性是必選的,指定該標(biāo)簽調(diào)用哪個(gè)Action。 namespace:該屬性是可選的,指定該標(biāo)簽調(diào)用的Action所在的namespace。 executeResult:該屬性是可選的,指定是否要將Action的處理結(jié)果頁(yè)面包含到本頁(yè)面。如果值為true,就是包含,false就是不包含,默認(rèn)為false。 ignoreContextParam:該屬性是可選的,指定該頁(yè)面中的請(qǐng)求參數(shù)是否需要傳入調(diào)用的Action。如果值為false,將本頁(yè)面的請(qǐng)求參數(shù)傳入被調(diào)用的Action。如為true,不將本頁(yè)面的請(qǐng)求參數(shù)傳入到被調(diào)用的Action。,3.3.2 數(shù)據(jù)標(biāo)簽,6. 標(biāo)簽 date標(biāo)簽主要用于格式化輸出一個(gè)日期。該標(biāo)簽有如下屬性: format:該屬性是可選的,如果指定了該屬性,將根據(jù)該屬性指定的格式來格式化日期。 nice:該屬性是可選的,該屬性的取值只能是true或false,用于指定是否輸出指定日期和當(dāng)前時(shí)刻之間的時(shí)差。默認(rèn)為false,即不輸出時(shí)差。 name:屬性是必選的,指定要格式化的日期值。 id:屬性是可選的,指定引用該元素的id值。 nice屬性為true時(shí),一般不指定format屬性。因?yàn)閚ice為true時(shí),會(huì)輸出當(dāng)前時(shí)刻與指定日期的時(shí)差,不會(huì)輸出指定日期。當(dāng)沒有指定format,也沒有指定nice=“true“時(shí),系統(tǒng)會(huì)采用默認(rèn)格式輸出。其用法為: ,3.3.2 數(shù)據(jù)標(biāo)簽,7. 標(biāo)簽 include標(biāo)簽用于將一個(gè)JSP頁(yè)面或一個(gè)Servlet包含到本頁(yè)面中。該標(biāo)簽有如下屬性: value:該屬性是必選的,指定需要被包含的JSP頁(yè)面或Servlet。 id:該屬性是可選的,指定該標(biāo)簽的id引用。 用法如下: ,3.3.3 控制標(biāo)簽,控制標(biāo)簽有以下幾個(gè): if:用于控制選擇輸出的標(biāo)簽。 elseif:用于控制選擇輸出的標(biāo)簽,必須和if標(biāo)簽結(jié)合使用。 else:用戶控制選擇輸出的標(biāo)簽,必須和if標(biāo)簽結(jié)合使用。 append:用于將多個(gè)集合拼接成一個(gè)新的集合。 generator:用于將一個(gè)字符串按指定的分隔符分隔成多個(gè)字符串,臨時(shí)生成的多個(gè)子字符串可以使用iterator標(biāo)簽來迭代輸出。 iterator:用于將集合迭代輸出。 merge:用于將多個(gè)集合拼接成一個(gè)新的集合,但與append的拼接方式不同。 sort:用于對(duì)集合進(jìn)行排序。 subset:用于截取集合的部分元素,形成新的子集合。,3.3.3 控制標(biāo)簽,1. /標(biāo)簽 這3個(gè)標(biāo)簽可以組合使用,但只有if標(biāo)簽可以單獨(dú)使用,而elseif和else標(biāo)簽必須與if標(biāo)簽結(jié)合使用。if標(biāo)簽可以與多個(gè)elseif標(biāo)簽結(jié)合使用,但只能與一個(gè)else標(biāo)簽使用。其用法格式如下: 標(biāo)簽體 標(biāo)簽體 . 標(biāo)簽體 ,3.3.3 控制標(biāo)簽,2. 標(biāo)簽 該標(biāo)簽主要用于對(duì)集合進(jìn)行迭代,這里的集合包含List、Set,也可以對(duì)Map類型的對(duì)象進(jìn)行迭代輸出。該標(biāo)簽的屬性如下: value:該屬性是可選的,指定被迭代的集合,被迭代的集合通常都由OGNL表達(dá)式指定。如果沒有指定該屬性,則使用值棧棧頂?shù)募稀?id:該屬性是可選的,指定集合元素的id。 status:該屬性是可選的,指定迭代時(shí)的IteratorStatus實(shí)例,通過該實(shí)例可判斷當(dāng)前迭代元素的屬性。如果指定該屬性,其實(shí)例包含如下幾個(gè)方法: int getCount():返回當(dāng)前迭代了幾個(gè)元素。 int getIndex():返回當(dāng)前被迭代元素的索引。 boolean isEven:返回當(dāng)前被迭代元素的索引元素是否是偶數(shù)。 boolean isOdd:返回當(dāng)前被迭代元素的索引元素是否是奇數(shù)。 boolean isFirst:返回當(dāng)前被迭代元素是否是第一個(gè)元素。 boolean isLast:返回當(dāng)前被迭代元素是否是最后一個(gè)元素。,3.3.3 控制標(biāo)簽,應(yīng)用舉例: 控制標(biāo)簽 style=“background-color:silver“ ,3.3.3 控制標(biāo)簽,通過添加Struts 2必須的Jar包,再建立上面JSP文件,修改web.xml后,就可以部署運(yùn)行,運(yùn)行結(jié)果如圖3.9所示。,圖3.9 iterator標(biāo)簽實(shí)例運(yùn)行結(jié)果,3.3.3 控制標(biāo)簽,3. 標(biāo)簽 應(yīng)用舉例,可以把上例的JSP文件進(jìn)行修改,其代碼為: 控制標(biāo)簽 style=“background-color:silver“ ,3.3.3 控制標(biāo)簽,部署運(yùn)行,運(yùn)行結(jié)果如圖3.10所示。,圖3.10 append標(biāo)簽實(shí)例運(yùn)行界面,3.3.3 控制標(biāo)簽,4標(biāo)簽 假設(shè)有2個(gè)集合,第一個(gè)集合包含3個(gè)元素,第二個(gè)集合包含2個(gè)元素,分別用append標(biāo)簽和merge標(biāo)簽方式進(jìn)行拼接,它們產(chǎn)生新集合的方式有所區(qū)別。下面分別列出: 用append方式拼接,新集合元素順序?yàn)椋?第1個(gè)集合中的第1個(gè)元素 第1個(gè)集合中的第2個(gè)元素 第1個(gè)集合中的第3個(gè)元素 第2個(gè)集合中的第1個(gè)元素 第2個(gè)集合中的第2個(gè)元素 用merge方式拼接,新集合元素順序?yàn)椋?第1個(gè)集合中的第1個(gè)元素 第2個(gè)集合中的第1個(gè)元素 第1個(gè)集合中的第2個(gè)元素 第2個(gè)集合中的第2個(gè)元素 第1個(gè)集合中的第3個(gè)元素,3.3.4 表單標(biāo)簽,大部分的表單標(biāo)簽和HTML表單元素是一一對(duì)應(yīng)的關(guān)系,如下面的代碼片段: 對(duì)應(yīng)著: 對(duì)應(yīng)著: 用戶名: 對(duì)應(yīng)著: 密碼: 還有下面這種情況,如果有這樣一個(gè)JavaBean類,類名為“User”,該類中有兩個(gè)屬性:一個(gè)是username;另一個(gè)是password,并分別生成它們的getter和setter方法,在JSP頁(yè)面的表單中可以這樣為表單元素命名: ,3.3.4 表單標(biāo)簽,1. 標(biāo)簽 該標(biāo)簽需要指定一個(gè)list屬性。用法舉例: 或者為: 這兩種方式的區(qū)別:前一種根據(jù)name取值時(shí)取的是選中字符串的值;后一種在頁(yè)面上顯示的是value的值,而根據(jù)name取值時(shí)取的卻是對(duì)應(yīng)的key,這里就是1、2、3或4。 2. 標(biāo)簽 combobox標(biāo)簽生成一個(gè)單行文本框和下拉列表框的組合。兩個(gè)表單元素只能對(duì)應(yīng)一個(gè)請(qǐng)求參數(shù),只有單行文本框里的值才包含請(qǐng)求參數(shù),下拉列表框只是用于輔助輸入,并沒有name屬性,故不會(huì)產(chǎn)生請(qǐng)求參數(shù)。用法舉例: ,3.3.4 表單標(biāo)簽,3. 標(biāo)簽 datetimepicker標(biāo)簽用于生成一個(gè)日期、時(shí)間下拉列表框。當(dāng)使用該日期、時(shí)間列表框選擇某個(gè)日期、時(shí)間時(shí),系統(tǒng)會(huì)自動(dòng)將選中日期、時(shí)間輸出指定文本框中。用法舉例: 4. 標(biāo)簽 select標(biāo)簽用于生成一個(gè)下拉列表框,通過為該元素指定list屬性的值,來生成下拉列表框的選項(xiàng)。用法舉例: 或者為: ,3.3.4 表單標(biāo)簽,5. 標(biāo)簽 radio標(biāo)簽的用法與checkboxlist用法很相似,唯一的區(qū)別就是checkboxlist生成的是復(fù)選框,而radio生成的是單選框。用法舉例: 或者為: 6. 標(biāo)簽 head標(biāo)簽主要用于生成HTML頁(yè)面的head部分。在介紹標(biāo)簽時(shí)說過,要在head中加入該標(biāo)簽,主要原因是標(biāo)簽中有一個(gè)日歷小控件,其中包含了JavaScript代碼,所以要在head部分加入該標(biāo)簽。,3.3.5 非表單標(biāo)簽,非表單標(biāo)簽主要用于在頁(yè)面中生成一些非表單的可視化元素。這些標(biāo)簽不經(jīng)常用到,下面大致介紹一下這些標(biāo)簽: a:生成超鏈接。 actionerror:輸出Action實(shí)例的getActionMessage()方法返回的消息。 component:生成一個(gè)自定義組件。 div:生成一個(gè)div片段。 fielderror:輸出表單域的類型轉(zhuǎn)換錯(cuò)誤、校驗(yàn)錯(cuò)誤提示。 tablePanel:生成HTML頁(yè)面的Tab頁(yè)。 tree:生成一個(gè)樹形結(jié)構(gòu)。 treenode:生成樹形結(jié)構(gòu)的節(jié)點(diǎn)。,3.4 Struts 2攔截器,3.4.1 攔截器配置 定義攔截器使用元素。其格式為: 只要在與之間配置子元素即可傳入相應(yīng)的參數(shù)。其格式如下: 參數(shù)值 . 通常情況下,一個(gè)Action要配置不僅一個(gè)攔截器,往往多個(gè)攔截器一起使用來進(jìn)行過濾。這時(shí)就會(huì)把需要配置的幾個(gè)攔截器組成一個(gè)攔截器棧。定義攔截器棧用元素,由于攔截器棧是由各攔截器組合而成的,所以需要在該元素下面配置子元素來對(duì)攔截器進(jìn)行引用。其格式如下: ,3.4.1 攔截器,下面是默認(rèn)攔截器的配置方法: ,3.4.2 攔截器實(shí)現(xiàn)類,Struts 2提供了一些接口或類供程序員自定義攔截器。如Struts 2提供了com.opensymphony. erceptor.Interceptor接口,程序員只要實(shí)現(xiàn)該接口就可完成攔截器實(shí)現(xiàn)類。該接口的代碼如下: import java.io.Serializable; import com.opensymphony.xwork2.ActionInvocation; public interface Interceptor extends Serializable void init(); String intercept(ActionInvocation invocation) throws Exception; void destroy(); 該接口中有三個(gè)方法: init():該方法在攔截器被實(shí)例化之后、攔截器執(zhí)行之前調(diào)用。 intercept(ActionInvocation invocation):該方法用于實(shí)現(xiàn)攔截的動(dòng)作。 destroy():該方法與init()方法對(duì)應(yīng),攔截器實(shí)例被銷毀之前調(diào)用,用于銷毀在init()方法中打開的資源。,3.4.3 實(shí)例應(yīng)用自定義攔截器,下面來配置攔截器,如果輸入框中輸入的內(nèi)容是“hello”,返回當(dāng)前頁(yè)面。實(shí)現(xiàn)該功能只需要在原項(xiàng)目的基礎(chǔ)上配置攔截器即可。首先編寫攔截器實(shí)現(xiàn)類,代碼如下: package org.tool; import org.action.StrutsAction; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionInvocation; import erceptor.AbstractInterceptor; public class MyInterceptor extends AbstractInterceptor public String intercept(ActionInvocation arg0) throws Exception / 得到StrutsAction類對(duì)象 StrutsAction action=(StrutsAction)arg0.getAction(); / 如果Action類中的name屬性的值為“hello“,返回錯(cuò)誤頁(yè)面 if(action.getName().equals(“hello“) return Action.ERROR; / 繼續(xù)執(zhí)行其他攔截器或Action類中的方法 return arg0.invoke(); ,3.4.3 實(shí)例應(yīng)用自定義攔截器,在struts.xml配置文件中進(jìn)行攔截器配置,修改后的代碼如下: /welcome.jsp /hello.jsp /hello.jsp ,3.4.3 實(shí)例應(yīng)用自定義攔截器,經(jīng)過這樣簡(jiǎn)單的配置后,重新部署項(xiàng)目,在運(yùn)行界面輸入“hello”,也會(huì)經(jīng)過攔截返回到當(dāng)前頁(yè)面,如圖3.11、圖3.12所示。,圖3.11 運(yùn)行界面 圖3.12 提交后返回當(dāng)前頁(yè)面,3.5 Struts 2國(guó)際化應(yīng)用,下面以登錄界面為例,講解國(guó)際化應(yīng)用內(nèi)容。 1. 建立項(xiàng)目 打開MyEclipse,建立一個(gè)Web項(xiàng)目,命名為“Test”。 2. 加載Struts 2的基本類庫(kù) 該步驟與3.2.1節(jié)中的第3步步驟相同,這里不再贅述。 3. 修改web.xml 其內(nèi)容見3.2.1節(jié)第4步。,3.5 Struts 2國(guó)際化應(yīng)用,4. 建立資源文件 需要在項(xiàng)目的src文件夾下建立一個(gè)名為“perties”的文件。只需要在該文件中編寫下面代碼: struts.custom.il8n.resources=資源文件名 該例中資源文件名為“messgageResource”,故perties應(yīng)為: struts.custom.il8n.resources= messgageResource 下面來建立兩個(gè)資源文件,分別為中文和英文。 username=DLM password=KL login=login 可以看出,它們分別是一個(gè)key-value對(duì)。然后再提供下面的文件: username=登錄名 password=口令 login=登錄,3.5 Struts 2國(guó)際化應(yīng)用,將上面文件以“messageResource_perties”為文件名保存在項(xiàng)目的WEB-INF/classes文件夾下,因?yàn)樵撐募朔俏鳉W字符,所以必須用native2ascii命令來處理。選擇【開始】【運(yùn)行】菜單項(xiàng),輸入“cmd”,看到如圖3.13所示的界面。,圖3.13 輸入cmd后的界面,3.5 Struts 2國(guó)際化應(yīng)用,然后輸入找到項(xiàng)目的class路徑下,如“D:lybworkspaceTestWebRootWEB-INFclasses”,得到如圖3.14所示的界面。在命令行輸入“native2ascii messageResource_perties messageResource_zh_CN.properties”。這樣就會(huì)在class路徑下產(chǎn)生messageResource_zh _CN.properties文件。,圖3.14 找到項(xiàng)目的class路徑,3.5 Struts 2國(guó)際化應(yīng)用,5. 建立login.jsp文件 Struts 2訪問國(guó)際化消息主要有以下三種方式: 在JSP頁(yè)面中輸出國(guó)際化消息,可以使用Struts 2的標(biāo)簽,該標(biāo)簽可以指定name屬性,該屬性指定國(guó)際化資源文件中的key。 在Action中訪問國(guó)際化消息,可以使用ActionSupport類的getText()方法,該方法可以接收一個(gè)參數(shù),該參數(shù)指定了國(guó)際化資源文件中的key。 在表單元素的label屬性里輸出國(guó)際化信息,可以為該表單標(biāo)簽指定一個(gè)key屬性,該屬性指定了國(guó)際化資源文件中的key。,3.5 Struts 2國(guó)際化應(yīng)用,下面是login.jsp文件代碼: ,3.5 Struts 2國(guó)際化應(yīng)用,6. 部署運(yùn)行 部署運(yùn)行項(xiàng)目,右擊“IE瀏覽器”,選擇【屬性】【語言】菜單項(xiàng),修改瀏覽器應(yīng)用語言,當(dāng)中文在最上方時(shí)表示當(dāng)前為中文環(huán)境,而相應(yīng)的英文在最上面時(shí)表示當(dāng)前為英文環(huán)境??梢?
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國(guó)鐵蓋圓桶市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)輕型龍門刨床市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)線圈活頁(yè)本冊(cè)市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)瞬態(tài)電壓抑制二極管市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)瓷質(zhì)外墻磚市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)游泳館管理軟件市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)水晶大樓模型市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)木制穿線繞珠玩具市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)挖斗上料機(jī)市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)平面研磨開閥市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 拳擊入門-北京理工大學(xué)中國(guó)大學(xué)mooc課后章節(jié)答案期末考試題庫(kù)2023年
- 中石油職稱英語通用教材
- ICD-10疾病編碼完整版
- 智能客房控制器設(shè)計(jì)
- 滁州瑞芬生物科技有限公司年產(chǎn)1.5萬噸赤蘚糖醇項(xiàng)目環(huán)境影響報(bào)告書
- THMDSXH 003-2023 電商產(chǎn)業(yè)園區(qū)數(shù)字化建設(shè)與管理指南
- 新建ICU鎮(zhèn)痛、鎮(zhèn)靜藥物應(yīng)用幻燈片
- 橡膠和基材的粘接
- GB/T 10610-2009產(chǎn)品幾何技術(shù)規(guī)范(GPS)表面結(jié)構(gòu)輪廓法評(píng)定表面結(jié)構(gòu)的規(guī)則和方法
- GA/T 935-2011法庭科學(xué)槍彈痕跡檢驗(yàn)鑒定文書編寫規(guī)范
- 湖北省黃石市基層診所醫(yī)療機(jī)構(gòu)衛(wèi)生院社區(qū)衛(wèi)生服務(wù)中心村衛(wèi)生室信息
評(píng)論
0/150
提交評(píng)論