免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
使用 Easy Struts for Eclipse 開發(fā) Struts
如何使用 Easy Struts 插件

Nancy Chen Junhua
軟件顧問和開發(fā)者
2004 年 4 月

本文向您介紹了如何在 Eclipse IDE 中使用 Easy Struts 插件開發(fā) Struts 應(yīng)用程序。本文首先對(duì) Easy Struts 及其安裝配置步驟進(jìn)行了簡(jiǎn)介,并通過一個(gè)循序漸進(jìn)的例子介紹了如何構(gòu)建一個(gè)基本的 Struts 應(yīng)用程序。本文還介紹了增強(qiáng) Struts 應(yīng)用程序的各種方法,例如連接數(shù)據(jù)庫,對(duì)應(yīng)用程序進(jìn)行模塊化,內(nèi)容的國(guó)際化和本地化,異常處理和創(chuàng)建自定義插件等等。最后,您將學(xué)習(xí)如何將自己的 Struts 應(yīng)用程序部署到 Tomcat Web 服務(wù)器上。

由于 Easy Struts 插件可以管理所有的復(fù)雜配置文件,因此您可以將精力集中在程序邏輯的開發(fā)上?,F(xiàn)在讓我們先來看一下 Easy Struts中可以幫助您構(gòu)建一個(gè)完整的應(yīng)用程序的 10 個(gè)功能:

  1. Add Easy Struts support。向項(xiàng)目的 classpath 中添加所有必需的 Struts 庫,并創(chuàng)建配置文件和默認(rèn)的資源屬性文件。
  2. Easy Form。創(chuàng)建一個(gè)具有表單屬性的 JSP 文件,以及一個(gè)具有表單屬性的 getter 方法和 setter方法的 Form bean,并向配置文件中添加一個(gè) Form bean 的定義。
  3. Easy Action。創(chuàng)建一個(gè) Action 類,并向配置文件中添加一個(gè)操作映射的定義。
  4. Easy Action associated with a form。創(chuàng)建一個(gè)具有表單屬性的 JSP 文件,一個(gè)具有g(shù)etter 方法和 setter 方法的 Form bean 類,以及一個(gè) Action 類;并向配置文件中添加一個(gè) Form bean的定義和一個(gè)操作映射的定義。
  5. Easy Forward。創(chuàng)建局部轉(zhuǎn)發(fā)和全局轉(zhuǎn)發(fā),它們定義了控制應(yīng)該轉(zhuǎn)向何處。
  6. Easy Exception。處理異常。
  7. Easy Message resources。創(chuàng)建資源屬性文件,這對(duì)于內(nèi)容的國(guó)際化和本地化特別重要。
  8. Easy Plug-in。創(chuàng)建插件。
  9. Easy Datasource。將應(yīng)用程序連接到一個(gè)數(shù)據(jù)源上。
  10. Easy Module。模塊化應(yīng)用程序。

在本文中,我們將介紹這 10 個(gè)功能中的 8 個(gè)(我們將不會(huì)介紹功能 2 和 3)。在開始開發(fā) Struts 應(yīng)用程序之前,您應(yīng)該首先安裝好所有必需的程序和插件,并要了解有關(guān) Java 編程、HTML、JSP 腳本以及 XML 和 XSLT 的基本知識(shí)。

安裝和配置準(zhǔn)備

您需要安裝 Eclipse 2.1、Struts 1.1、Tomcat Web 服務(wù)器和 Easy Struts,同時(shí)還要安裝 SysdeoTomcat plug-ins for Eclipse、MySQL 數(shù)據(jù)庫服務(wù)器以及 JDBC driver for MySQL。Eclipse是一個(gè) IDE 開發(fā)環(huán)境。Struts 1.1 提供了運(yùn)行 Struts 應(yīng)用程序所需要的庫。Tomcat 是宿主應(yīng)用程序的 Web 容器。Sysdeo Tomcat 插件可以讓開發(fā)人員在 Eclipse 環(huán)境中啟動(dòng)或停止 Tomcat Web 服務(wù)器。JDBC driverfor MySQL 可以將 JDBC 調(diào)用轉(zhuǎn)換成 MySQL 所使用的網(wǎng)絡(luò)協(xié)議。安裝好這些軟件之后,還需要為 Eclipse 配置兩個(gè)插件。

安裝

關(guān)于在哪里下載以下軟件的鏈接,請(qǐng)參閱 參考資料部分:

  1. 從 Eclipse 的 Web 站點(diǎn)上下載 Eclipse v2.1。您可以通過將其解壓到任何一個(gè)選定的目錄(這個(gè)目錄在本文中稱為 eclipse_home )中來安裝它。
  2. 從 Apache 的 Web 站點(diǎn)上下載 Struts 1.1。您可以通過將其解壓到任何一個(gè)選定的目錄(這個(gè)目錄在本文中稱為 struts_home )來安裝它。
  3. 從 Apache 的 Web 站點(diǎn)上下載 Tomcat Web 服務(wù)器。您可以通過將其解壓到任何一個(gè)選定的目錄(這個(gè)目錄在本文中稱為 tomcat_home )中來安裝它。本文假設(shè) Tomcat 的版本是 v4.1.18。
  4. 從 Sysdeo 的 Web 站點(diǎn)上下載最新的 Tomcat for Eclipse 插件。您可以通過將其解壓到 eclipse_home/eclipse/plugins目錄中來安裝它。本文假設(shè) Tomcat for Eclipse 插件的版本是 v2.2。
  5. 從 SourceForge 上下載 Easy Struts for Eclipse 插件 v0.6.4。您可以通過將其解壓到 eclipse_home/eclipse/plugins目錄中來安裝它。
  6. 從 Sun 的 Web 站點(diǎn)上下載 J2SE SDK。您可以將其安裝到任何一個(gè)選定的目錄(這個(gè)目錄在本文中稱為 java_home )中。本文假設(shè)J2SE SDK 的版本是 v1.4.2。
  7. 從 MySQL 的 Web 站點(diǎn)上下載 MySQL 數(shù)據(jù)庫。您可以將其安裝到任何一個(gè)選定的目錄中。
  8. 從 MySQL 的 Web 站點(diǎn)上下載 JDBC driver for MySQL。您應(yīng)該先解壓下載的文件包,并將 mysql-connector-java-x.x.xx-stable/mysql-connector-java-x.x.xx-stable-bin.jar拷貝到您的項(xiàng)目工作空間中。后面還需要回到這個(gè)步驟。本文假設(shè) JDBC driver for MySQL 的版本是 v3.0。

配置

配置 Sysdeo Tomcat 插件

要配置 Sysdeo Tomcat 插件,執(zhí)行以下步驟:

  1. 啟動(dòng)Eclipse。
  2. 配置 Tomcat 插件。要實(shí)現(xiàn)這個(gè)功能,請(qǐng)單擊“Window”菜單,然后選擇“Preferences”菜單項(xiàng),然后在彈出的菜單中選擇“Tomcat”。然后執(zhí)行以下步驟:
    • 將“Tomcat version”設(shè)置成 Tomcat 的版本號(hào)。
    • 將“Tomcat home”設(shè)置成 tomcat_home/jakarta-tomcat-4.1.18。
    • 將“Perspective to switch when Tomcat is started”設(shè)置成 Java。
    • 在“Tomcat”選項(xiàng)的子選項(xiàng)“JVM Settings” -> “Classpath”中,添加 Jar/Zip fortools.jar,該值應(yīng)該是 java_home/lib/。這用于編譯 JSP 文件。
  3. 為項(xiàng)目的 classpath 引用設(shè)置 classpath 變量 TOMCAT_HOME。要完成這一任務(wù),請(qǐng)?jiān)谂c步驟 2 相同的彈出菜單中選擇“Java”選項(xiàng),然后選擇“ClasspathVariables”子選項(xiàng),并添加一個(gè)新的變量“TOMCAT_HOME”,其路徑是 tomcat_home/jakarta-tomcat-4.1.18。
  4. 確保“Tomcat”菜單和 3 個(gè)工具欄按鈕可用。到現(xiàn)在為止,我們應(yīng)該在 Java 視圖中可以看到一個(gè)“Tomcat”菜單和 3 個(gè) Tomcat 工具欄按鈕(如 圖 1所示)。如果您沒有看到這些內(nèi)容,回到“Window”菜單中,選擇“Customize Perspective...”項(xiàng),打開選項(xiàng)樹,選中“Other”項(xiàng)并選中“Tomcat”子選項(xiàng)。
  5. 確保 Sysdeo Tomcat 插件可以正常工作。要驗(yàn)證這一點(diǎn),請(qǐng)使用菜單或工具條來啟動(dòng)/停止 Tomcat。

圖 1. Tomcat 工具欄按鈕

配置Easy Struts 插件

要配置 Easy Struts 插件,請(qǐng)參考 圖 2的內(nèi)容,并執(zhí)行以下步驟:

  1. 選擇一個(gè) Struts 版本。要完成這步操作,請(qǐng)單擊“Window”菜單,選擇“Preference”項(xiàng),選擇“Easy Struts”選項(xiàng),并選擇“Struts 1.1”選項(xiàng)卡。
  2. 添加 JARs。應(yīng)該為 struts_home\jakarta-struts-1.1\lib 目錄中的所有的 .jar 文件都添加“AddJARs”。
  3. 添加 TLDs。接下來,為 struts_home\ jakarta-struts-1.1\lib 目錄中的所有 .tld 文件添加“AddTLDs”。

圖 2. 配置 Easy Struts 插件

開發(fā) Struts 應(yīng)用程序

在本節(jié)中,我們將介紹使用 Easy Struts 插件構(gòu)建 Struts 應(yīng)用程序的基本步驟。首先,您將創(chuàng)建一個(gè) Tomcat 項(xiàng)目。然后,您將添加Easy Struts 對(duì) Tomcat 項(xiàng)目的支持。接下來,您可以體驗(yàn)一下“Easy Action associated with a form”的功能。之后,您將對(duì)前一個(gè)步驟中自動(dòng)生成的源代碼進(jìn)行必要的修改。再之后,您可以測(cè)試一下應(yīng)用程序在Tomcat Web 服務(wù)器上的運(yùn)行情況。最后,您可以體驗(yàn)一下“Easy Forward”功能。

創(chuàng)建 Tomcat 項(xiàng)目

要?jiǎng)?chuàng)建一個(gè) Tomcat 項(xiàng)目,回到“File”菜單,選擇“New”項(xiàng),并在子菜單中選擇“Project”。然后執(zhí)行以下步驟:

  1. 進(jìn)入“Java”選項(xiàng),選擇“Tomcat Project”并單擊“Next”(參見 圖 3)。
  2. 填上項(xiàng)目名,并單擊“Next”(參見 圖 4)。
  3. 選中“Can update server.xml file”。系統(tǒng)會(huì)自動(dòng)更新 Tomcat Web 服務(wù)器的 server.xml文件?,F(xiàn)在單擊“Finish”就可以完成任務(wù)了(參見 圖 5)。

創(chuàng)建 Tomcat 項(xiàng)目的結(jié)果如 圖 6所示。

圖 3. 創(chuàng)建 Tomcat 項(xiàng)目 - 步驟 1

圖 4. 創(chuàng)建 Tomcat 項(xiàng)目 - 步驟 2

圖 5. 創(chuàng)建 Tomcat 項(xiàng)目- 步驟 3

圖 6. 創(chuàng)建 Tomcat 項(xiàng)目- 最終結(jié)果

添加 Easy Struts 支持

要添加 Easy Struts 對(duì) Tomcat 項(xiàng)目的支持,執(zhí)行以下兩個(gè)步驟:

  1. 單擊“New”工具欄按鈕,在“Java”選項(xiàng)下面選擇“Easy Struts”自選項(xiàng),選擇“Add Easy Struts support”并單擊“Next”,轉(zhuǎn)入下一個(gè)步驟(請(qǐng)參看 圖 7-- 在本文的后文中我們將這個(gè)視圖稱為 EasyStruts 功能視圖 )。
  2. 設(shè)置如 圖 8所示的配置。確保選中“Copy Struts binary”和“Copy Struts TLD”。

添加 Easy Struts 支持的結(jié)果如 圖 9所示。

圖 7. Easy Struts 功能視圖

在圖8 中:
通過請(qǐng)求容器轉(zhuǎn)發(fā)它們到活動(dòng) servlet,URL 模式塊告訴 Struts 處理所有匹配模式 *.do 的請(qǐng)求。 所有其他模式的請(qǐng)求都不是 Struts 處理的。

Default 應(yīng)用程序資源將在 WEB-INF/classes/base package/ 目錄中創(chuàng)建。

圖 8. 添加 Easy Struts 支持

圖 9. 添加 Easy Struts 支持 - 最終結(jié)果

圖7顯示了 Easy Struts 所提供的 10 個(gè)功能。我們已經(jīng)看過了“Add Easy Struts Support”的功能。在本文的其余部分中,我們將介紹一下剩下的7 個(gè)功能(“Easy Action” 和 “Easy Form”功能不介紹)。在本節(jié)的后續(xù)部分中,我們將使用“Easy Action associatedwith a form”功能和“Easy Forward”功能來構(gòu)建一個(gè)簡(jiǎn)單卻又完整的 Struts 應(yīng)用程序。下一節(jié)將介紹“Easy Messageresources”、“Easy Plug In”、“Easy Datasource”、“Easy Exception”和“Easy Module”功能。

使用 Easy Action Associated with a Form 功能

回到 Easy Struts 功能視圖,選擇“Easy Action associated with a form”,并執(zhí)行以下步驟來配置表單:

  1. 在 Use case 中輸入內(nèi)容;Form 名和 Form 類型都會(huì)根據(jù)系統(tǒng)的 Use case 自動(dòng)生成。您可以手工修改 Form名和 Form 類型(參見 圖 10)。
  2. 在 Form 屬性部分中單擊“Add”;使用如 圖 11所示的視圖添加表單屬性。例如,我們按照?qǐng)D中所示的一樣視圖添加一個(gè)文本輸入域:該域名為“tel”,值為“tel”,類型為 int。我們將“tel”的初值設(shè)置為 0。在設(shè)置“Type”時(shí),我們可以直接輸入,也可以使用“Browse”功能來選擇。對(duì)于“JSP input type”的設(shè)置,我們也是既可以直接輸入,也可以從下拉列表中選擇。Struts 系統(tǒng)會(huì)在 Form bean 類中為每個(gè)表單屬性生成一對(duì)getter 方法和setter 方法。因此,對(duì)于一個(gè)選擇列表來說,您應(yīng)該只創(chuàng)建一個(gè) <html:select> 即可,而不用創(chuàng)建所有的 <html:option>。
  3. 由于您正在開發(fā)一個(gè) Web 應(yīng)用程序,因此請(qǐng)選中前兩個(gè)檢查框。
  4. 單擊“Next”繼續(xù)。

圖 10. 配置表單

注意

  • 表單屬性名不能以大寫字母開頭。否則,系統(tǒng)就會(huì)警告您在調(diào)用操作時(shí)找不到 getter 方法。
  • 表單屬性名不能重復(fù)。如果您真想使用兩個(gè)相同的屬性名,可以使用空格作為前綴或后綴來解決這個(gè)問題。

圖 11. 關(guān)系的圖形化表示

到現(xiàn)在為止,您應(yīng)該會(huì)看到一些非常類似于 圖12的內(nèi)容。默認(rèn)情況下,輸入的值是“/form/owner.jsp”,這意味著 JSP 文件被放在“easyStruts/form”文件夾中。您可以手工修改JSP 文件的位置,或者 preference 的設(shè)置。要修改 preference 的設(shè)置,進(jìn)入“Window”菜單,選擇“Preferences”,單擊“EasyStruts”選項(xiàng),選擇“Style”選項(xiàng)卡,并將“JSP form location”設(shè)置為空。例如,在本文中,我們傾向于將這些 JSP文件直接保存在 easyStruts (項(xiàng)目名)文件夾中。因此,請(qǐng)將其修改為“/owner.jsp”,如 圖12所示。

圖 12中所顯示的操作映射的屬性如下:

  • Path。所提交請(qǐng)求的相對(duì)路徑。路徑名必須以“/”開頭而且唯一。
  • Type。這個(gè) ActionMapping 正在描述的 Action 類的名字。
  • Attribute??梢栽L問這個(gè) Form bean 的請(qǐng)求范圍或會(huì)話范圍的屬性名,條件是名字與這個(gè) bean 指定的名字不同。
  • Scope。規(guī)定與這個(gè)映射相關(guān)的 Form bean 的值應(yīng)該可以保存多少位。
  • input。規(guī)定如果碰到驗(yàn)證錯(cuò)誤時(shí)控制流程應(yīng)該返回到輸入表單的相對(duì)路徑。
  • Validate。如果這個(gè)屬性被設(shè)置為 true,就會(huì)對(duì)與這個(gè)映射關(guān)聯(lián)的表單調(diào)用 ActionForm.validate()方法。
  • Parameter??捎糜谙蛴蛇@個(gè)映射選擇的 Action 傳遞其他信息。

圖 12. 配置操作

單擊“Next”,您應(yīng)該可以看到類似于如 圖 13所示的內(nèi)容。 圖 13中所顯示的是操作映射屬性,如下:

  • Forward。指定要處理這個(gè)請(qǐng)求的 servlet 或 JSP 資源的相對(duì)路徑。ActionMapping 可以使用findForward() 將控制流程轉(zhuǎn)換到這個(gè) servlet 或 JSP 資源上。
  • Exception。與這個(gè)映射相關(guān)的 ExceptionHandlers。

此處的轉(zhuǎn)發(fā)和異常都是本地的,稍后我們會(huì)討論全局轉(zhuǎn)發(fā)和全局異常。

圖 13. 配置轉(zhuǎn)發(fā)

局部轉(zhuǎn)發(fā)屬性:

  • name 是唯一的標(biāo)識(shí)符,在操作映射的 findForward() 方法中可以用它來返回這個(gè)路徑。
  • contextRelative 標(biāo)簽告訴 Struts 以下信息:
    • 如果該值被設(shè)置為 true,那么路徑就被認(rèn)為是相對(duì)于整個(gè) Web 應(yīng)用的相對(duì)路徑。
    • 如果該值被設(shè)置為 false,那么路徑就被認(rèn)為是相對(duì)于一個(gè)模塊化應(yīng)用程序的這個(gè)模塊的相對(duì)路徑。
  • 如果 redirect 為 true,那么控制流程就會(huì)被轉(zhuǎn)到一個(gè)重定向的頁中,而不是一個(gè)轉(zhuǎn)發(fā)的頁中。這意味著創(chuàng)建一個(gè)新請(qǐng)求。

在單擊“Finish”之后(參見 圖14),系統(tǒng)會(huì)在 easyStruts/WEB-INF/src/ 目錄中生成 com.asprise.struts.form.OwnerForm.java和 com.asprise.struts.action.OwnerAction.java。同時(shí)還會(huì)生成另外一個(gè)文件:easyStruts/owner.jsp。在接下來的幾節(jié)中,您將對(duì)這三個(gè)文件進(jìn)行一些修改,從而完成整個(gè)表單,添加用戶輸入的驗(yàn)證方法并處理驗(yàn)證錯(cuò)誤。

圖 14. 添加轉(zhuǎn)發(fā)

修改 ActionForm 類
將 ActionForm.java 中的所有“Integer”修改為“int”,這是因?yàn)槟鷦偛艅?chuàng)建的表單屬性“tel”的類型是 java.lang.Integer。然后編寫 validate() 方法的代碼,對(duì)用戶輸入的表單屬性進(jìn)行驗(yàn)證。validate() 方法的完整代碼如 清單 1所示。

ActionError(“error.noEmail”)中的“error.noEmail”是資源屬性文件中定義的一個(gè)關(guān)鍵字,它等價(jià)于“<li><fontcolor=red>Enter your email</font> ”。在資源屬性文件中,可以使用 <html>代碼。ActionErrors 中 add(java.lang.String property, ActionError error) 方法的參數(shù)property 是一個(gè)表單屬性名。這個(gè) ActionError 只能與一個(gè)指定的表單屬性相關(guān)。例如,如果 email 地址為空,或者只包含空格字符,那么在對(duì)表單進(jìn)行驗(yàn)證時(shí)就會(huì)顯示“Enteryour email”消息。如果在 email 地址中沒有“@”字符,那么就會(huì)顯示“Correct your email”消息,這是在資源屬性文件中使用“error.wrongEmail”關(guān)鍵字定義的。這兩個(gè)錯(cuò)誤都只與表單屬性“email”有關(guān)(參見 清單1)。我們稍后再回來介紹。

清單 1. OwnerForm.java
package com.asprise.struts.form;import javax.servlet.http.HttpServletRequest;import org.apache.struts.action.ActionErrors;                import org.apache.struts.action.ActionError;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionMapping;public class OwnerForm extends ActionForm {   private String email;   private String greet = "Mr.";   private String address;                   private int tel = 0;   private String name;                   public ActionErrors validate(      ActionMapping mapping,      HttpServletRequest request) {      ActionErrors errors = new ActionErrors();      if (greet == null || greet.trim().equals("")) {         errors.add("greet", new ActionError("error.greet"));      }      if (name == null || name.trim().equals("")) {         errors.add("name", new ActionError("error.name"));      }      if (address == null || address.trim().equals("")) {         errors.add("address", new ActionError("error.address"));      }      if (email == null || email.trim().equals("")) {         errors.add("email", new ActionError("error.noEmail"));      }      else if (email.indexOf("@")==-1) {         errors.add("email", new ActionError("error.wrongEmail"));      }      if (tel==0) {         errors.add("tel", new ActionError("error.tel"));      }      return errors;      }      ...   public String getEmail() {      return email;   }   public void setEmail(String email) {      this.email = email;   }   ...}                            

在資源屬性文件中可以使用 <html> 代碼。資源屬性文件的內(nèi)容是一些鍵-值對(duì)(參見 清單2)。在源代碼文件中可以調(diào)用這些關(guān)鍵字。在每個(gè)資源屬性文件中系統(tǒng)都需要 errors.header 和 errors.footer這兩個(gè)關(guān)鍵字。

清單 2. ApplicationResources.properties
errors.header=<h4>Validation Error(s)</h4><ul>errors.footer=</ul><hr>error.greet=<li>Choose your greeterror.name=<li>Enter your nameerror.address=<li>Enter your addresserror.tel=<li>Enter your contact numbererror.wrongEmail=<li>Correct your emailerror.noEmail=<li>Enter your email                

修改 Action 類
OwnerAction 類會(huì)在局部轉(zhuǎn)發(fā)路徑“success”中簡(jiǎn)單地顯示一條諸如“Thank you, Miss Nancy Chen”之類的消息。請(qǐng)修改OwenerAction 類的 execute() 方法來實(shí)現(xiàn)您的邏輯,(每個(gè) action 類都必須實(shí)現(xiàn) execute() 方法)。參見 清單3,它會(huì)將控制流程轉(zhuǎn)向 success.jsp。

清單 3. OwnerAction.java
public class OwnerAction extends Action {   public ActionForward execute(      ActionMapping mapping,      ActionForm form,      HttpServletRequest request,      HttpServletResponse response)      throws Exception {      OwnerForm ownerForm = (OwnerForm) form;                            String greet = ownerForm.getGreet();      String name = ownerForm.getName();      request.setAttribute("name", name);      request.setAttribute("greet", greet);      // Forward control to the specified success target      return (mapping.findForward("success"));      }}                            

修改 JSP 文件
首先,為 <html:select> 添加 <html:option>,完成表單(參見 清單4)。然后在表單后面添加一個(gè) <html:errors />,這用來演示一個(gè)與屬性為“proerty”的 <html:error>不同的行為。例如,<html:errors property="name"> 只會(huì)反映與表單屬性“name”相關(guān)的用戶輸入的驗(yàn)證??梢允褂肁ctionErrors 類的 add(String property, ActionError error) 方法為一個(gè)表單屬性關(guān)聯(lián)一些錯(cuò)誤。<html:errors/> 則會(huì)反映這個(gè)表單中所有的驗(yàn)證錯(cuò)誤。這些錯(cuò)誤會(huì)在調(diào)用 <html:error> 的地方顯示。

清單 4. owner.jsp
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%><%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%><html>   <head>      <meta         name = "Generator"         content = "Easy Struts Xslt generator for Eclipse (http://easystruts.sf.net).">      <title>Struts Form for ownerForm</title>   </head>   <body>      <html:form action="/owner">                         greet : <html:select property="greet">                    <html:option value=""></html:option>                    <html:option value="Mr.">Mr.</html:option>                    <html:option value="Miss">Miss</html:option>                    <html:option value="Mrs.">Mrs.</html:option>                 </html:select><html:errors property="greet"/>          name : <html:text property="name"/><html:errors property="name"/></br>          address : <html:text property="address"/><html:errors property="address"/></br>          email : <html:text property="email"/><html:errors property="email"/></br>          tel : <html:text property="tel"/><html:errors property="tel"/></br>         <html:submit/><html:cancel/>      </html:form>                     <html:errors />   <body></html>                            

現(xiàn)在,代碼 success.jsp 會(huì)顯示一條諸如“Thank you, Miss Nancy Chen”之類的消息。其中“Miss”是所有者的問候,而“NancyChen”是所有者的名字。最終的文件如 清單5所示。

清單 5. success.jsp
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%><%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><logic:present name="name" scope="request">Thank you,   <logic:present name="greet" scope="request">      <bean:write name="greet" scope="request"/>   </logic:present>   <bean:write name="name" scope="request"/></logic:present>                

<logic:present> 是一個(gè) Struts logic 標(biāo)簽。當(dāng)邏輯標(biāo)簽具有屬性“name”時(shí),就應(yīng)該檢查是否存在這個(gè)指定名的JSP bean。關(guān)于 <logic:present> 的屬性完整列表和 Struts logic 標(biāo)簽的完整列表,請(qǐng)參閱 Struts用戶指南。

<bean:write> 是一個(gè) Struts bean 標(biāo)簽。它被用來將指定的 bean 屬性的值傳遞給當(dāng)前的 JspWriter。當(dāng)bean 標(biāo)簽具有屬性“name”和屬性“property”時(shí),就是指其屬性被訪問以獲取由“property”所指定的值的 bean 的屬性名。如果沒有指定“property”屬性,那么就會(huì)傳遞這個(gè) bean 本身的值。關(guān)于 <logic:present> 屬性以及 Strutslogic 標(biāo)簽的完整列表,請(qǐng)參閱 Struts用戶指南。

檢查 struts-config.xml
當(dāng)您在 Eclipse 環(huán)境中單擊“struts-config.xml”時(shí),就會(huì)在一個(gè)圖形用戶界面中顯示 struts-config.xml,如 圖15所示。這樣可以允許開發(fā)人員方便地編輯大部分 Easy Struts 功能。也可以通過單擊“source”選項(xiàng)卡來查看 struts-config.xml的源代碼。

圖 15. struts-config.xml

測(cè)試應(yīng)用程序
單擊 Tomcat 工具欄按鈕,重新啟動(dòng) Tomcat 服務(wù)器。然后在 URL 地址欄中輸入“http://127.0.0.1:8080/easyStruts/owner.jsp”?,F(xiàn)在屏幕上就會(huì)顯示 圖16。驗(yàn)證結(jié)果如 圖17所示。注意有無屬性“property”時(shí) <html:errors> 的不同行為。如果有“property”屬性,系統(tǒng)只會(huì)返回與該屬性有關(guān)的錯(cuò)誤。如果沒有屬性“property”,那么系統(tǒng)就會(huì)返回該表單中的所有錯(cuò)誤。當(dāng)所有的輸入都正確無誤時(shí),系統(tǒng)會(huì)將控制流程轉(zhuǎn)到 success.jsp 上,這樣會(huì)顯示一條消息:“Thankyou, Miss Nancy Chen”(參見 圖18)。

圖 16. owner.jsp

圖 17. Form 驗(yàn)證錯(cuò)誤

圖 18. 成功

使用 Easy Forward

Struts 的配置提供了兩種 ActionForwards,分別是全局轉(zhuǎn)發(fā)和局部轉(zhuǎn)發(fā)。全局的 ActionForwards 對(duì)于整個(gè)應(yīng)用程序中的任何Action 對(duì)象都是可見的。局部 ActionForwards 只對(duì)哪些在從 ActionMapping 中調(diào)用的 Action 對(duì)象可用,這些對(duì)象就是局部ActionForwards 所關(guān)聯(lián)的對(duì)象。從上一節(jié)中,您已經(jīng)看到了如何在“Easy Action associated with a form”的過程中創(chuàng)建一個(gè)局部轉(zhuǎn)發(fā)。在本節(jié)中,您將學(xué)習(xí)如何使用“EasyForward”創(chuàng)建局部轉(zhuǎn)發(fā)或全局轉(zhuǎn)發(fā)。

進(jìn)入 Easy Struts 功能視圖,并單擊“Easy Forward”。這樣做的結(jié)果是應(yīng)該可以看到類似于如 圖19所示的內(nèi)容。如果您保留“Visibility”為空不變,那么最終的轉(zhuǎn)發(fā)就是全局的。如果單擊“Browse”按鈕并選擇“/owner”,如 圖20所示,那么最終的轉(zhuǎn)發(fā)就是局部轉(zhuǎn)發(fā)。不管轉(zhuǎn)發(fā)是全局的還是局部的,在 Action 類中都以 mapping.findForward("failure")的形式引用。

在“Easy Action associated with a form”一節(jié)中,我們已經(jīng)討論了“name”、“Redirect”和“Context relative”屬性,如 圖 19所示。

圖 19. Easy Forward - 全局

圖 20. Easy Forward - 局部

增強(qiáng)應(yīng)用程序功能

在上一節(jié)中,我們體驗(yàn)了 Easy Struts 的 3 個(gè)功能。在本節(jié),您將編寫自己的 XSLT 文件代碼,以統(tǒng)一定制 JSP 文件的風(fēng)格,并使用其他功能對(duì)內(nèi)容進(jìn)行國(guó)際化/本地化、連接到數(shù)據(jù)源、處理自定義異常、對(duì)應(yīng)用程序進(jìn)行模塊化和創(chuàng)建自定義插件。

使用 XSLT 文件定制 JSP 文件的風(fēng)格

可以通過編寫 .xsl 文件并配置 Easy Struts 的參數(shù)來按照需要的格式生成 JSP 文件。要進(jìn)行參數(shù)配置,進(jìn)入“Window”菜單中,選擇“Preferences”項(xiàng),選擇“EasyStruts”選項(xiàng),并單擊“XSLT stylesheet”選項(xiàng)卡,為“Jsp file stylesheet”單擊“Browse”,添加自己的.xsl 文件。

例如,如 清單6所示的代碼是我們的 .xsl 文件。對(duì)于每個(gè)表單屬性來說,它都生成“property”和“value”屬性。例如,如果將一個(gè)名為“name”的文本輸入?yún)^(qū)初值設(shè)置為“nancy”,那么在JSP 文件中生成的代碼行就是 name: <html:text property="name" value="nancy"></html:text>。

清單 6. myJsp.xsl

使用 Easy Message Resource
對(duì)內(nèi)容進(jìn)行本地化
可以通過創(chuàng)建本地化的資源屬性文件對(duì)應(yīng)用程序進(jìn)行本地化。要?jiǎng)?chuàng)建一個(gè)新的資源屬性文件,進(jìn)入 Easy Struts 功能視圖,選擇“Easy MessageResource”。按照如 圖21所示進(jìn)行配置,這樣將創(chuàng)建一個(gè)中文消息資源。注意資源屬性文件名必須是 ApplicationResources_xx_XX.properties。小寫的xx 表示本地語言,它是一個(gè) ISO-639 語言編代碼,為兩個(gè)字母;大寫的 XX 表示本地國(guó)家,它是一個(gè) ISO-3166 國(guó)家代碼,為兩個(gè)字母。

注意:關(guān)于 ISO-639 語言代碼的完整列表,請(qǐng)?jiān)L問 Unicode.org 上的 languagespage。關(guān)于 ISO-3166 國(guó)家代碼的完整列表,請(qǐng)?jiān)L問 Unicode.org 上的 countriespage

Easymessage resource 屬性:

  • 如果 null 屬性設(shè)置為 true,會(huì)引起空字符串返回,造成未知的消息關(guān)鍵字。
  • 當(dāng)消息資源綁定時(shí),這個(gè)參數(shù)被交給出工廠。“parameter”的值是基于 property-file 工廠的屬性文件的路徑。
  • 這個(gè)關(guān)鍵字屬性定義了ServletContext 屬性關(guān)鍵字,這一消息資源綁定到它上面。

圖 21. 創(chuàng)建中文消息資源

資源屬性文件很容易編輯。您可以使用記事本來編輯中文資源屬性文件。ApplicationResources_zh_CN.properties應(yīng)該被保存為 Unicode (UTF-8) 編碼。然后,將本地語言設(shè)置為 Chinese,將位置設(shè)置為 China (在 Windows上,可以使用控制面板中的區(qū)域和語言選項(xiàng)進(jìn)行設(shè)置)。重新啟動(dòng) Tomcat 以啟用修改過的設(shè)置,并轉(zhuǎn)到 http://127.0.0.1:8080/easyStruts/owner.jsp上?,F(xiàn)在驗(yàn)證錯(cuò)誤就是用中文顯示的了,如 圖22所示。

圖 22. 中文的驗(yàn)證錯(cuò)誤

使用 Easy Datasource
連接到數(shù)據(jù)庫
在本節(jié)中,您將把 Web 應(yīng)用程序連接到一個(gè) MySQL 數(shù)據(jù)庫上。要實(shí)現(xiàn)這種功能,進(jìn)入 Easy Struts 功能視圖,選擇“EasyDatasource”,并按照 圖23所示的一樣進(jìn)行配置。注意應(yīng)該將 JDBC driver 放到 eclipse_home\eclipse\workspace\easyStruts\WEB-INF\lib 目錄中。

圖 23. 配置 MySQL 數(shù)據(jù)庫

接下來,啟動(dòng) MySQL 服務(wù)器,并按照如 清單 7所示的方式創(chuàng)建數(shù)據(jù)庫“crm”和表“owner”。

清單 7. owner 表
# Database : ‘crm‘# Table structure for table ‘owner‘#CREATE TABLE ‘owner‘ (  ‘id‘ int(6) NOT NULL default ‘0‘,  ‘greet‘ varchar(5) NOT NULL default ‘‘,  ‘name‘ varchar(50) NOT NULL default ‘‘,  ‘email‘ varchar(50) NOT NULL default ‘‘,  ‘a(chǎn)ddress‘ varchar(100) NOT NULL default ‘‘,  ‘tel‘ int(10) NOT NULL default ‘0‘,  PRIMARY KEY  (‘id‘)) TYPE=MyISAM;                

接下來,修改 OwnerAction 類中的 execute() 方法,使其連接到數(shù)據(jù)庫上(參見 清單8)。如您所見,Easy Datasource 就是在這里使用這些 key 屬性。“org.apache.struts.action.DATA_SOURCE”是數(shù)據(jù)源使用的關(guān)鍵字。注意我們捕獲了SQLException 異常并將其重新拋出。在下一節(jié)中,您將對(duì)異常處理程序進(jìn)行編碼,以便處理 SQLException 異常。

清單 8. OwnerAction.java - 數(shù)據(jù)庫連接
public ActionForward execute(   ActionMapping mapping,   ActionForm form,   HttpServletRequest request,   HttpServletResponse response)   throws Exception {   OwnerForm ownerForm = (OwnerForm) form;   String greet = ownerForm.getGreet();   String name = ownerForm.getName();   request.setAttribute("name", name);   request.setAttribute("greet", greet);                   String address = ownerForm.getAddress();   String email = ownerForm.getEmail();   int tel = ownerForm.getTel();   Connection conn = null;   Statement stmt = null;   ResultSet rs = null;   DataSource dataSource = (DataSource)servlet.getServletContext().getAttribute(      "org.apache.struts.action.DATA_SOURCE");      try {         conn = dataSource.getConnection();         stmt = conn.createStatement();         int id = 0;         rs = stmt.executeQuery("select max(id) as counter from owner");         while(rs.next()){            id = rs.getInt("counter");         }         id += 1;         stmt.executeUpdate("insert into owner values(            "+id+", ‘"+greet+"‘, ‘"+name+"‘, ‘"+email+"‘, ‘"+address+"‘, "+tel+")");         rs.close();         stmt.close();         conn.close();      }      catch(SQLException e){         throw new SQLException("database error");      }      // Forward control to the specified success target      return (mapping.findForward("success"));}                            

您應(yīng)該重新啟動(dòng) Tomcat 服務(wù)器,讓其在啟動(dòng)時(shí)就連接到數(shù)據(jù)源上,并轉(zhuǎn)到 http://127.0.0.1:8080/easyStruts/owner.jsp頁面上。如果所有的輸入都正確,那么就會(huì)向“owner”表中插入一條記錄,并將控制轉(zhuǎn)到 success.jsp 頁面。您可以對(duì)數(shù)據(jù)庫進(jìn)行檢查,確認(rèn)是否在表“owner”中新插入了一條記錄。

使用 Easy Exception
處理異常
正如上一節(jié)中提到的一樣,您可以編寫自己的異常處理程序來處理 SQLException 異常。首先,進(jìn)入 Easy Struts 功能視圖,選擇Easy Exception 對(duì)異常進(jìn)行聲明。使用如 圖24所示的配置。資源包名中存放了這個(gè)異常的消息資源,這是在 bundle 屬性中指定的。這個(gè)異常屬性指明了當(dāng)發(fā)生這個(gè)異常時(shí)被調(diào)用來處理這個(gè)異常的類。這個(gè)關(guān)鍵字是在消息資源包中定義的。當(dāng)異常發(fā)生時(shí),控制流程就被重定向到在path 屬性中給定的文件上。scope 屬性告訴 Struts ActionErrors(在處理異常時(shí)被創(chuàng)建)應(yīng)該被保存多長(zhǎng)時(shí)間(會(huì)話或請(qǐng)求)。type屬性指定了這個(gè)異常處理程序會(huì)截獲的異常類型。

圖 24. 配置異常

單擊“Finish”之后,異常就被聲明了。然后就應(yīng)該編寫 MyExceptionHandler.java 的代碼(參見 清單9)。它對(duì) ExceptionHandler 類進(jìn)行了擴(kuò)展,與 Action 類很類似,同時(shí)還實(shí)現(xiàn)了 execute() 方法,并返回一個(gè)ActionForward 對(duì)象。正如您所見,Easy Exception 的“path” 屬性可以使用 ExceptionConfig 類的getPath() 方法獲得。您可以使用 ExceptionConfig 類的 getKey() 方法獲得這個(gè) key 屬性。

清單 9. MyExceptionHandler.java
package com.asprise.struts.exception;import javax.servlet.*;import javax.servlet.http.*;import org.apache.struts.action.*;import org.apache.struts.config.*;public class MyExceptionHandler extends ExceptionHandler {   public ActionForward execute(      Exception ex,      ExceptionConfig ae,      ActionMapping mapping,      ActionForm formInstance,      HttpServletRequest request,      HttpServletResponse response)   throws ServletException {      request.setAttribute("myException",ex);      request.setAttribute("myForm",formInstance);      request.setAttribute("myKey",ae.getKey());      return new ActionForward(ae.getPath());   }}                

在異常聲明中,如果發(fā)生一個(gè) SQLException 異常,那么控制流程就會(huì)被重定向到 exception.jsp 文件。我們的 exception.jsp會(huì)顯示默認(rèn)的資源屬性文件中關(guān)鍵字為“error.database”的消息,以及異常被拋出時(shí)的異常類型和異常消息。您可以在 MyExceptionHandler中獲取這個(gè)異常關(guān)鍵字。您也可以將這個(gè)關(guān)鍵字提供給 <bean:message> 標(biāo)簽使用,如 清單10所示。

清單 10. exception.jsp
<%@ page import="java.sql.SQLException" %><%@ page import="com.asprise.struts.form.*" %><%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%><%   OwnerForm myForm = (OwnerForm)request.getAttribute("myForm");   if (myForm != null) {      out.println("<font color=red>Sorry, "+myForm.getGreet());      out.println(" "+myForm.getName()+"</font>");   }%>                <ul><bean:message key="<%=request.getAttribute(\"myKey\").toString()%>" /><%   Object obj = request.getAttribute("myException");   if (obj != null) {      Throwable ex = (Throwable)obj;      out.println("<li><b>Type:</b>"+ex.toString());      out.println("<li><b>Message:</b>"+ex.getMessage());   }%>                            

定義“error.database=<h3>An Exception Handled by MyExceptionHandler:</h3>”。當(dāng)發(fā)生一個(gè)SQLException 異常時(shí),您應(yīng)該會(huì)看到類似于 圖25所示的內(nèi)容。

圖 25. 處理異常 - 測(cè)試結(jié)果

使用 Easy Module
對(duì)應(yīng)用程序進(jìn)行模塊化
在本節(jié)中,我們將創(chuàng)建一個(gè)名為“newModule”的新模塊。要實(shí)現(xiàn)這個(gè)功能,進(jìn)入 Easy Struts 功能視圖,選擇“Easy Module”,并在Module name 中輸入“newModule”,如 圖26所示。

圖 26. 配置模塊

重新啟動(dòng) Eclipse,以啟用新的模塊。如果在啟動(dòng) Web 應(yīng)用程序時(shí)出現(xiàn)這樣一個(gè)錯(cuò)誤: org.xml.sax.SAXParseException:The content of element type "servlet" must match "(icon?,servlet-name,display-name?,description?,(servlet-class|jsp-file),init-param*,load-on-startup?,run-as?,security-role-ref*)" ,通過將新的模塊配置部分直接移動(dòng)到web.xml 中的一個(gè)默認(rèn)模塊下面,您可以來解決這個(gè)問題。

有兩種方法可以切換到新模塊上。首先,您可以在 struts-config.xml 中創(chuàng)建一個(gè)新的全局或局部轉(zhuǎn)發(fā)“success”(參見 清單11)。然后可以使用 mapping.findForward("success") 切換到這個(gè)新模塊上來。

清單 11. 轉(zhuǎn)發(fā)
<forward name="success"   contextRelative="true"   path="/newModule/index.do"   redirect="true"/>                

其次,創(chuàng)建一個(gè)如下所示的操作,其類型是一個(gè) SwitchAction 操作:

 <action path="/switchTo" type="org.apache.struts.actions.SwitchAction" validate="false" />                

然后在 struts-config-newModule.xml 中創(chuàng)建如 清單 12所示的操作映射。

清單 12. 操作映射
<action-mappings>   <action path="/index" type="com.asprise.struts.newmodule.action.IndexAction">      <forward name="success" path="/index.jsp"/>   </action></action-mappings>                

接下來,編寫 easyStruts/newModule/index.jsp 的代碼。index.jsp 只會(huì)顯示一條消息“<h1>Youare in module: newModule</h1>”。

現(xiàn)在,啟動(dòng) Tomcat 服務(wù)器,并輸入 http://127.0.0.1:8080/easyStruts/switchTo.do?prefix=/newModule&page=/index.do。結(jié)果如 圖 27所示。如果您想切換回默認(rèn)的模塊,只需輸入 http://127.0.0.1:8080/easyStruts/switchTo.do?prefix=&page=/owner.jsp 即可。

圖 27. 在模塊間進(jìn)行切換

注意:您可以在除“Add Easy Struts support”之外的所有 Easy Struts 功能中指定模塊名。

使用 Easy Plug-in 創(chuàng)建定制插件

在本節(jié)中,您將學(xué)習(xí) Easy Struts 的最后一個(gè)功能 -- Easy Plug-in。 Plug-in Action 的一個(gè)常見用法是在Web 應(yīng)用程序在啟動(dòng)時(shí),配置或裝載特定應(yīng)用程序的數(shù)據(jù)。自定義插件實(shí)現(xiàn)了 Plug-in 接口。這個(gè)接口的實(shí)現(xiàn)需要一個(gè)零參數(shù)的構(gòu)造函數(shù),供ActionServlet 使用,從而確保插件可以正確創(chuàng)建。接口中定義的兩個(gè)方法分別是 init() 和 destroy(),這兩個(gè)方法分別在啟動(dòng)和關(guān)閉應(yīng)用程序時(shí)被調(diào)用。您必須實(shí)現(xiàn)這兩個(gè)方法。

要?jiǎng)?chuàng)建一個(gè)插件,進(jìn)入 Easy Struts 功能視圖,選擇 Easy Plugin,在 Plugin class 中輸入內(nèi)容,并為添加一些屬性。我們要添加proxy 和 port 屬性,如 圖28所示。

圖 28. 配置插件

接下來,編寫 MyPlugin 類的代碼,如 清單13所示。這段代碼實(shí)現(xiàn)了 Plugin 類。當(dāng)啟動(dòng) Web 應(yīng)用程序時(shí),會(huì)顯示一條消息說“MyPlugin starting”,并設(shè)置系統(tǒng)的proxy 和 port 屬性。當(dāng)關(guān)閉應(yīng)用程序時(shí),就會(huì)顯示一條“MyPlugin Stopping”消息。

清單 13. MyPlugin.java
package com.asprise.struts.plugin;import org.apache.struts.action.PlugIn;import org.apache.struts.config.ModuleConfig;import org.apache.struts.action.ActionServlet;public class MyPlugin implements PlugIn{   public String proxy;   public String port;   public MyPlugin(){   }   public void init(ActionServlet servlet, ModuleConfig config){      System.err.print("********* MyPlugin Starting *******");      System.setProperty("https.proxyHost", getProxy());      System.setProperty("https.proxyPort", getPort());      servlet.getServletContext().setAttribute("proxy", getProxy());      servlet.getServletContext().setAttribute("port", getPort());   }      public void destroy(){         System.err.print("********* MyPlugin Stopping *******");      }      public void setProxy(String prox){         proxy = prox;      }      public String getProxy(){         return this.proxy;      }      public void setPort(String por){         port = por;      }      public String getPort(){         return this.port;      }}                

在這個(gè) JSP 或其他 Java 文件的源代碼中,可以使用 getServletContext().getAttribute("proxy")來獲取 proxy 的值。

部署應(yīng)用程序

要將 Struts 應(yīng)用程序部署到客戶端上,可以簡(jiǎn)單地將應(yīng)用程序?qū)С鰹橐粋€(gè) WAR 文件,并將其分發(fā)到您的客戶端上,讓它們把這個(gè) WAR 文件放到自己Web 服務(wù)器的“webapps” 目錄中即可。下面是將應(yīng)用程序?qū)С鰹?WAR 文件的步驟:

  1. 進(jìn)入“Project”菜單,選擇“Properties”菜單,選擇“Tomcat”選項(xiàng),并單擊“Export to WAR settings”選項(xiàng)卡。
  2. 單擊“WAR file for export”邊上的“Browse”,將其設(shè)置為您選定的文件夾 /easyStruts.war,并保存設(shè)置。
  3. 然后進(jìn)入 project 彈出菜單,選擇“Tomcatproject”,并在子菜單中單擊“Export to the WAR file sets in projectproperties”。
  4. 在顯示“Operationsuccessful”消息之后,您可以轉(zhuǎn)到第 2 步中指定的位置獲取 WAR 文件。

結(jié)束語

在本文中,我們介紹了 Easy Struts 在開發(fā)在 Tomcat Web 服務(wù)器上運(yùn)行的 Struts 應(yīng)用程序方面的功能。您已經(jīng)學(xué)習(xí)了如何處理表單驗(yàn)證,如何創(chuàng)建局部和全局的轉(zhuǎn) 發(fā)和異常,同時(shí)還知道了如何進(jìn)行異常處理,如何連接數(shù)據(jù)源,內(nèi)容的國(guó)際化和本 地化,對(duì)應(yīng)用程序進(jìn)行模塊化,創(chuàng)建自定義插件,以及將應(yīng)用程序部署到客戶端等知識(shí)。

參考資料

關(guān)于作者
Nancy Chen Junhua 是一位具有多年經(jīng)驗(yàn)的自由軟件顧問和開發(fā)人員。她也在新加坡南洋科技大學(xué)從事 agent learning 方面的研究??梢酝ㄟ^ nancy_chenjunhua
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
MyEclipse + struts + Hibernate配置開發(fā)手冊(cè)
Struts2 初探
JR 精品文章 - eclipse插件集錦
為Struts 2.0做好準(zhǔn)備
Zihuatanejo--Struts的HTML標(biāo)簽庫
第二章 一個(gè)簡(jiǎn)單的Login 應(yīng)用程序(Struts2)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服