Struct(二)

struct2 權威指南html

這一節經過一個詳細的實例來說解Struct2框架的應用java

 

1 下載和安裝Struts 2框架web

(1) 登陸http://struts.apache.org/download.cgi#Struts206站點,下載Struts 2的最新GA版。在Struts 2.06下有以下幾個選項:數據庫

—  Full Distribution:下載Struts 2的完整版。一般建議下載該選項apache

—  Example Applications:下載Struts 2的示例應用,這些示例應用對於學習Struts 2有很大的幫助,下載Struts 2的完整版時已經包含了該選項下所有應用。數組

—  Blank Application only:僅下載Struts 2的空示例應用,這個空應用已經包含在Example Applications選項下。session

—  Essential Dependencies:僅僅下載Struts 2的核心庫,下載Struts 2的完整版時將包括該選項下的所有內容。app

—  Documentation:僅僅下載Struts 2的相關文檔,包含Struts 2的使用文檔、參考手冊和API文檔等。下載Struts 2的完整版時將包括該選項下的所有內容。框架

—  Source:下載Struts 2的所有源代碼,下載Struts 2的完整版時將包括該選項下的所有內容。webapp

—  Alternative Java 4 JARs:下載可選的JDK 1.4的支持JAR。下載Struts 2的完整版時將包括該選項下的所有內容。

一般建議讀者下載第一個選項:下載Struts 2的完整版,將下載到的Zip文件解壓縮,該文件就是一個典型的Web結構,該文件夾包含以下文件結構:

—  apps:該文件夾下包含了基於Struts 2的示例應用,這些示例應用對於學習者是很是有用的資料。

—  docs:該文件夾下包含了Struts 2的相關文檔,包括Struts 2的快速入門、Struts 2的文檔,以及API文檔等內容。

—  j4:該文件夾下包含了讓Struts 2支持JDK 1.4的JAR文件。

—  lib:該文件夾下包含了Struts 2框架的核心類庫,以及Struts 2的第三方插件類庫。

—  src:該文件夾下包含了Struts 2框架的所有源代碼。

(2)將lib文件夾下的Struts2-core-2.0.6.jar、xwork-2.0.1.jar和ognl-2.6.11.jar等必需類庫複製到Web應用的WEB-INF/lib路徑下。固然,若是你的Web應用須要使用Struts 2的更多特性,則須要將更多的JAR文件複製到Web應用的WEB-INF/lib路徑下。若是須要在DOS或者Shell窗口下手動編譯Struts 2相關的程序,則還應該將Struts2-core-2.0.6.jar和xwork-2.0.1.jar添加到系統的CLASSPATH環境變量裏。

 

(3)編輯Web應用的web.xml配置文件

-----------------------------------------------------

<?xml version="1.0" encoding="GBK"?>

<!-- web-app是Web應用配置文件的根元素,指定Web應用的Schema信息 -->

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"

                                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                                 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.

                                    com/xml/ns/j2ee/web-app_2_4.xsd">

                                 <!-- 定義Struts 2的FilterDispatcher的Filter -->

                                  <filter>

                                    <!-- 定義核心Filter的名字 -->

                                  <filter-name>struts2</filter-name>

                                    <!-- 定義核心Filter的實現類 -->

                                  <filter-class>org.apache.Struts2.dispatcher.FilterDispatcher

                                        </ filter-class>

                                  </filter>

                                 <!-- FilterDispatcher用來初始化Struts 2而且處理全部的Web請求 -->

                                  <filter-mapping>

                                  <filter-name>Struts2</filter-name>

                                  <url-pattern>/*</url-pattern>

                                  </filter-mapping>

</web-app>

2 建立一個JSP頁面

----------------------------------------------------

<%@ page language="java" contentType="text/html; charset=GBK"%>

<html>

<head>

<title>登陸頁面</title>

</head>

<body>

<!-- 提交請求參數的表單 -->

<form action="Login.action" method="post">

                                  <table align="center">

                                  <caption><h3>用戶登陸</h3></caption>

                                  <tr>

                                        <!-- 用戶名的表單域 -->

                                   <td>用戶名:<input type="text" name="username"/></td>

                                  </tr>

                                  <tr>

                                        <!-- 密碼的表單域 -->

                                   <td>密&nbsp;&nbsp;碼:<input type="text" name="password"/></td>

                                  </tr>

                                  <tr align="center">

                                   <td colspan="2"><input type="submit" value="登陸"/><input

                                            type="reset" value="重填" /></td>

                                  </tr>

                                  </table>

</form>

</body>

</html>

 

3. 建立WEB應用

創建一個Web應用請按以下步驟進行。

 在任意目錄新建一個文件夾,筆者將以該文件夾創建一個Web應用。

 (1)在第1步所建的文件夾內建一個WEB-INF文件夾。

 (2)進入Tomcat,或任何Web容器內,找到任何一個Web應用,將Web應用的WEB-INF下的web.xml文件複製到第2步所建的WEB-INF文件夾下。

 (3) 修改複製的web.xml文件,將該文件修改爲只有一個根元素的XML文件,修改後的web.xml文件代碼以下

-------------------------------------------------

<?xml version="1.0" encoding="GBK"?>

<!-- web-app是Web應用配置文件的根元素,指定Web應用的Schema信息 -->

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"

                                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                                 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.

                                    com/xml/ns/j2ee/web-app_2_4.xsd">

</web-app>

(4) 在第2步所建的WEB-INF路徑下,新建兩個文件夾:classes和lib,它們分別用於保存單個*.class文件和JAR文件。

(5)通過上面步驟,已經創建了一個空Web應用。將該Web應用複製到Tomcat的webapps路徑下,該Web應用將能夠自動部署在Tomcat中。

將2.2節所定義的JSP頁面文件複製到第1步所建的文件夾下,該JSP頁面將成爲該Web應用的一個頁面。該Web將有以下文件結構:

Struts2qs

|-WEB-INF

|     |-classes

|     |-lib

|     |-web.xml

|-login.jsp

上面的Struts2qs是Web應用所對應文件夾的名字,能夠更改;login.jsp是該Web應用下JSP頁面的名字,也能夠修改。其餘文件夾、配置文件都不能夠修改。

 

4. 增長Struct2的功能

爲了給Web應用增長Struts 2功能,只須要將Struts 2安裝到Web應用中便可。在Web應用中安裝Struts 2框架核心只須要通過以下三個步驟。

 (1) 修改web.xml文件,在web.xml文件中配置Struts 2的核心Filter。

 (2)將Struts 2框架的類庫複製到Web應用的WEB-INF/lib路徑下。

 (3) 在WEB-INF/classes下增長struts.xml配置文件。

下面是增長了Struts 2功能後Web應用的文件結構:

----------------------------------------------------------

Struts2qs

|-WEB-INF

|     |-classes(struts.xml)

|     |-lib(commons-logging.jar,freemarker.jar,ognl.jar,struts2-core.jar,xwork.jar)

|     |-web.xml

|-login.jsp

在上面的文件結構中,lib下Struts 2框架的類庫可能有版本後綴。例如commons-logging.jar,多是commons-logging-1.1.jar;struts2-core.jar多是struts2-core-2.0.6.jar。

修改後的web.xml文件在2.1節已經給出了,故此處再也不贅述。

4.1 實現控制器

 

Struts 2下的控制器再也不像Struts 1下的控制器,須要繼承一個Action父類,甚至能夠無需實現任何接口,Struts 2的控制器就是一個普通的POJO。

實際上,Struts 2的Action就是一個包含execute方法的普通Java類,該類裏包含的多個屬性用於封裝用戶的請求參數。下面是處理用戶請求的Action類的代碼:

//Struts 2的Action類就是一個普通的Java類

public class LoginAction

{

                                 //下面是Action內用於封裝用戶請求參數的兩個屬性

                                  private String username;

                                  private String password;

                                  //username屬性對應的getter方法

                                  public String getUsername()

                                 {

                                  return username;

                                  }

                                 //username屬性對應的setter方法

                                  public void setUsername(String username)

                                  {

                                  this.username = username;

                                  }

                                  //password屬性對應的getter方法

                                  public String getPassword()

                                 {

                                  return password;

                                  }

                                 //password屬性對應的setter方法

                                  public void setPassword(String password)

                                 {

                                  this.password = password;

                                  }

                                 //處理用戶請求的execute方法

                                 public String execute() throws Exception

                                 {

                                    //當用戶請求參數的username等於scott,密碼請求參數爲tiger時,返回success

                                      字符串

                                    //不然返回error字符串

                                  if (getUsername().equals("scott")

                                        && getPassword().equals("tiger") )

                                    {

                                   return "success";

                                  }

                                    else

                                    {

                                   return "error";

                                  }

                                  }

}

4.2  配置Action

前面已經介紹過了,struts.xml文件應該放在classes路徑下,該文件主要放置Struts 2的Action定義。定義Struts 2 Action時,除了須要指定該Action的實現類外,還須要定義Action處理結果和資源之間的映射關係。下面是該應用的struts.xml文件的代碼:

-----------------struts.xml-------------------

<?xml version="1.0" encoding="GBK"?>

<!-- 指定Struts 2配置文件的DTD信息 -->

<!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

        "http://struts.apache.org/dtds/struts-2.0.dtd">

<!-- struts是Struts 2配置文件的根元素 -->

<struts>

                                 <!-- Struts 2的Action必須放在指定的包空間下定義 -->

                                 <package name="strutsqs" extends="struts-default">

                                    <!-- 定義login的Action,該Action的實現類爲lee.Action類 -->

                                  <action name="Login" class="lee.LoginAction">

                                        <!-- 定義處理結果和資源之間映射關係。 -->

                                   <result name="error">/error.jsp</result>

                                   <result name="success">/welcome.jsp</result>       

                                  </action>

                                  </package>

</struts>

上面映射文件定義了name爲login的Action,即:該Action將負責處理向login.action URL請求的客戶端請求。該Action將調用自身的execute方法處理用戶請求,若是execute方法返回success字符串,請求將被轉發到/welcome.jsp頁面;若是execute方法返回error字符串,則請求被轉發到/error.jsp頁面。

 

 

 

 

 

 

 

咱們再增長兩個頁面 error.jsp和welcome.jsp也就完成了基本屬性的配置

 

第二部分 功能擴展:

5. 改進控制器

5.1  實現Action接口

public interface Action

{

                                 //下面定義了5個字符串常量

                                  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";

                                 //定義處理用戶請求的execute抽象方法

                                  public String execute() throws Exception;

}

在上面的Action代碼中,咱們發現該Action接口裏已經定義了5個標準字符串常量:SUCCESS、NONE、ERROR、INPUT和LOGIN,它們能夠簡化execute方法的返回值,並可使用execute方法的返回值標準化。例如對於處理成功,則返回SUCCESS常量,避免直接返回一個success字符串(程序中應該儘可能避免直接返回數字常量、字符串常量等)。

所以,藉助於上面的Action接口,咱們能夠將原來的Action類代碼修改成以下:

//實現Action接口來實現Struts 2的Action類

public class LoginAction implements Action

{

                                 //下面是Action內用於封裝用戶請求參數的兩個屬性

                                  private String username;

                                 private String password;

                                 //username屬性對應的getter方法

                                  public String getUsername()

                                 {

                                  return username;

                                  }

                                 //username屬性對應的setter方法

                                  public void setUsername(String username)

                                 {

                                  this.username = username;

                                 }

                                 //password屬性對應的getter方法

                                  public String getPassword()

                                 {

                                  return password;

                                  }

                                 //password屬性對應的setter方法

                                  public void setPassword(String password)

                                 {

                                  this.password = password;

                                  }

                                 //處理用戶請求的execute方法

                                 public String execute() throws Exception

                                 {

                                    //當用戶請求參數的username等於scott,密碼請求參數爲tiger時,返回success

                                      字符串

                                    //不然返回error的字符串

                                  if (getUsername().equals("scott")

                                        && getPassword().equals("tiger") )

                                    {

                                   return SUCCESS;

                                  }

                                    else

                                    {

                                   return ERROR;

                                  }

                                  }

}

對比前面Action和此處的Action實現類,咱們發現兩個Action類的代碼基本類似,除了後面的Action類實現了Action接口。由於實現了Action接口,故Action類的execute方法能夠返回Action接口裏的字符串常量。

5.2  跟蹤用戶狀態

前面的Action處理完用戶登陸後,僅僅執行了簡單的頁面轉發,並未跟蹤用戶狀態信息——一般,當一個用戶登陸成功後,須要將用戶的用戶名添加爲Session狀態信息

爲了訪問HttpSession實例,Struts 2提供了一個ActionContext類,該類提供了一個getSession的方法,但該方法的返回值類型並非HttpSession,而是Map。這又是怎麼回事呢?實際上,這與Struts 2的設計哲學有關,Struts 2爲了簡化Action類的測試,將Action類與Servlet API徹底分離,所以getSession方法的返回值類型是Map,而不是HttpSession。

雖然ActionContext的getSession返回的不是HttpSession對象,但Struts 2的系列攔截器會負責該Session和HttpSession之間的轉換。

爲了能夠跟蹤用戶信息,咱們修改Action類的execute方法,在execute方法中經過ActionContext訪問Web應用的Session。修改後的execute方法代碼以下:

//處理用戶請求的execute方法

public String execute() throws Exception

{

                                 //當用戶請求參數的username等於scott,密碼請求參數爲tiger時,返回success字符串

                                 //不然返回error的字符串

                                  if (getUsername().equals("scott")

                                    && getPassword().equals("tiger") )

                                 {

                                    //經過ActionContext對象訪問Web應用的Session

                                    ActionContext.getContext().getSession().put("user" , getUsername());

                                  return SUCCESS;

                                  }

                                 else

                                 {

                                  return ERROR;

                                  }

}

上面的代碼僅提供了Action類的execute方法,該Action類的其餘部分與前面的Action類代碼徹底同樣。在上面的Action類經過ActionContext設置了一個Session屬性:user。爲了檢驗咱們設置的Session屬性是否成功,咱們修改welcome.jsp頁面,在welcome.jsp頁面中使用JSP 2.0表達式語法輸出Session中的user屬性。下面是修改後的welcome.jsp頁面代碼:

<%@ page language="java" contentType="text/html; charset=GBK"%>

<html>

    <head>

        <title>成功頁面</title>

    </head>

    <body>

        歡迎,${sessionScope.user},您已經登陸!

    </body>

</html>

上面的JSP頁面與前面的JSP頁面沒有太大改變,除了使用了JSP 2.0語法來輸出Session中的user屬性。關於JSP 2.0表達式的知識,請參看筆者所著的《輕量級J2EE企業應用實戰》一書的第2章。

在如圖2.1所示頁面的「用戶名」輸入框中輸入scott,在「密碼」輸入框中輸入tiger,而後單擊「登陸」按鈕,將看到如圖2.4所示的頁面。

在上面登陸成功的頁面中,已經輸出登陸所用的用戶名:scott,可見在Action經過ActionContext設置Session是成功的。

 

5.3  添加處理信息

到目前爲止,Action僅僅控制轉發用戶請求,JSP頁面並未得到Action的處理結果。對於大部分Web應用而言,用戶須要得到請求Action的處理結果,例如,在線購物系統須要查詢某個種類下的商品,則Action調用業務邏輯組件的業務邏輯方法獲得該種類下的所有商品,而JSP頁面則獲取該Action的處理結果,並將所有結果迭代輸出。

下面將爲應用增長一個Action,該Action負責獲取某個系列的所有書籍。爲了讓該Action能夠獲取這系列的書籍,咱們增長一個業務邏輯組件,它包含一個業務邏輯方法,該方法能夠獲取某個系列的所有書籍。

下面是系統所用的業務邏輯組件的代碼:

public class BookService

{

                                 //以一個常量數組模擬了從持久存儲設備(數據庫)中取出的數據

                                 private String[] books =

                                    new String[]{

                                    "Spring2.0寶典" ,

                                    "輕量級J2EE企業應用實戰",

                                    "基於J2EE的Ajax寶典",

                                    "Struts,Spring,Hibernate整合開發"

                                 };

                                 //業務邏輯方法,該方法返回所有圖書

                                 public String[] getLeeBooks()

                                 {

                                    return books;

                                 }

}

上面的業務邏輯組件實際上就是MVC模式中的Model,它負責實現系統業務邏輯方法。理論上,業務邏輯組件實現業務邏輯方法時,必須依賴於底層的持久層組件,但此處的業務邏輯組件則只是返回一個靜態的字符串數組——由於這只是一種模擬。

 注意  此處的業務邏輯組件只是模擬實現業務邏輯方法,並未真正調用持久層組件來獲取數據庫信息。

在系統中增長以下Action類,該Action類先判斷Session中user屬性是否存在,而且等於scott字符串——這要求查看圖書以前,用戶必須已經登陸本系統。若是用戶已經登陸本系統,則獲取系統中所有書籍,不然返回登陸頁面。

新增的Action類的代碼以下:

public class GetBooksAction implements Action

{

                                 //該屬性並不用於封裝用戶請求參數,而用於封裝Action須要輸出到JSP頁面信息

                                 private String[] books;

                                 //books屬性的setter方法

                                 public void setBooks(String[] books)

                                 {

                                    this.books = books;

                                 }

                                 //books屬性的getter方法

                                 public String[] getBooks()

                                 {

                                    return books;

                                 }

                                 //處理用戶請求的execute方法

                                 public String execute() throws Exception

                                 {

                                    //獲取Session中的user屬性

                                    String user = (String)ActionContext.getContext().getSession().

                                        get("user");

                                    //若是user屬性不爲空,且該屬性值爲scott

                                    if (user != null && user.equals("scott"))

                                    {

                                        //建立BookService實例

                                        BookService bs = new BookService();

                                        //將業務邏輯組件的返回值設置成該Action的屬性

                                        setBooks(bs.getLeeBooks());

                                        return SUCCESS;

                                    }

                                    else

                                    {

                                        return LOGIN;

                                    }

    }

}

經過上面的Action類,咱們發現Action類中的成員屬性,並不必定用於封裝用戶的請求參數,也多是封裝了Action須要傳入下一個JSP頁面中顯示的屬性。

 提示  Action中的成員屬性,並必定用於封裝用戶的請求參數,也多是封裝了Action須要傳入下一個頁面顯示的值。實際上,這些值將被封裝在ValueStack對象中。

當咱們的控制器須要調用業務邏輯方法時,咱們直接建立了一個業務邏輯組件的實例,這並非一種好的作法,由於控制器不該該關心業務邏輯組件的實例化過程。比較成熟的作法能夠利用工廠模式來管理業務邏輯組件;固然,目前最流行的方式是利用依賴注入——這將在後面章節裏介紹。

 注意  實際項目中不會在控制器中直接建立業務邏輯組件的實例,而是經過工廠模式管理業務邏輯組件實例,或者經過依賴注入將業務邏輯組件實例注入控制器組件。

該Action處理用戶請求時,無需得到用戶的任何請求參數。將該Action配置在struts.xml文件中,配置該Action的配置片斷以下:

<!-- 定義獲取系統中圖書的Action,對應實現類爲lee.GetBooksAction -->

<action name="GetBooks" class="lee.GetBooksAction">

                                 <!-- 若是處理結果返回login,進入login.jsp頁面 -->

                                 <result name="login">/login.jsp</result>

                                 <!-- 若是處理結果返回success,進入showBook.jsp頁面 -->

                                  <result name="success">/showBook.jsp</result>

</action>

當用戶向getBooks.action發送請求時,該請求將被轉發給lee.GetBooksAction處理。

相關文章
相關標籤/搜索