天天看點

Struts 2基礎第2章 Struts 2

<a target="_blank" href="http://blog.csdn.net/javaeeteacher/article/details/4202741">struts 2基礎</a>

struts現在分兩個版本:struts 1.x和struts 2.x。struts 1.x已經有很多年了,可以說非常流行,但是因為其他架構的快速發展以及自身存在的問題,struts 2誕生了,struts 2與struts 1的差別非常大,實際上struts 2的核心思想是基于另外一個非常成功的web架構webwork。兩者的差別如表20.1所示。下面主要針對struts 2進行介紹。

表2.1 struts1和struts2的比較

feature

struts 1

struts 2

action類

在struts 1中要求action類繼承抽象的基類。在struts 1中一個普遍存在的問題就是面向抽象類程式設計,而不是面向接口程式設計。

struts 2中的action可以實作一個action接口,同時可以實作其他的接口,這樣可以使使用者有選擇性地使用其它自定義的服務。struts 2提供了基礎類actionsupport,該類實作了一些通用的接口。action接口不是必須的。任何具有execute方法的pojo對象都可以用作struts 2的action對象。

線程模型

struts 1的actions是單例的,因為隻有一個類的執行個體來處理所有對這個action的請求,是以必須是線程安全的。單例政策對struts 1的action的能夠完成的功能有很大限制,有些功能需要額外的努力才能完成。action資源必須是線程安全的或者synchronized

struts 2的action對象是為每個請求執行個體化的,是以沒有線程安全的問題。(在實踐中,servlet容器會為每個請求生成多個throw-away對象,增加的對象不會對性能産生太大影響或者對垃圾回收産生影響)

servlet依賴

struts 1的action依賴servlet api,因為當調用action的execute方法時需要傳參數httpservletrequest和httpservletresponse。

struts 2的action與容器不是緊密結合在一起的。多數情況下,servlet上下文被表示為map對象,允許對action進行獨立的測試。如果需要,struts 2的action仍然可以通路原始的request和response對象。 然而,其它架構元素可以減少或者消除對httpservetrequest和httpservletresponse對象進行直接通路的必要。

可測試性

測試struts 1 action的一個主要障礙就是execute方法使用了servlet api。1個第三方擴充struts testcase,為struts 1提供了一組模拟(mock)對象。

struts 2的action可以通過執行個體化、設定屬性和調用方法進行測試。依賴注入支援使測試更簡單。

擷取輸入

struts 1使用actionform對象來擷取輸入。像action一樣,所有的actionform必須繼承一個基類。因為其它的javabean不能用作actionform,開發人員經常需要建立多餘的類來擷取輸入。可以使用動态form來替換傳統的actionform類,但是開發人員同樣可能需要重新描述已有的javabean。

struts 2使用action的屬性作為輸入屬性,不用建立第二個輸入對象。輸入屬性可以是複雜的對象類型,還可以有自己的屬性。可以在頁面中通過taglib通路action屬性。struts 2也支援actionform模式,以及pojo表單對象和pojo action。複雜對象類型,包括業務或者域對象,都可以作為輸入/輸出對象。模型驅動的特性簡化了标簽庫對pojo輸入對象的引用。

表達式語言

struts 1內建了jstl,是以可以使用jstl的el語言,el提供了基本的對象結構周遊(object graph traversal),但是集合以及索引屬性支援比較弱。

struts 2可以使用jstl,同時struts還支援另外一種功能更強大、使用更靈活的表達式語言,這種語言是object graph notation language,簡稱ognl。

值與視圖的綁定

struts 1使用了标準的jsp機制把對象與要通路的頁面上下文綁定。

struts 2使用了一種valuestack技術,這樣标簽庫不用把視圖與要呈現的對象類型關聯就可以通路值。valuestack政策允許重用涉及多個類型的視圖,這些類型可能有相同的屬性名,但是屬性類型不同。

類型轉換

struts 1的actionform屬性通常都是字元串類型。struts 1 使用commons-beanutils進行類型轉換。轉換器是針對每個類的,而不能為每個執行個體配置。

struts 2使用ognl進行類型轉換,架構包含了常用對象類型和基本資料類型的轉換器。

驗證

struts 1支援手動驗證,通過actionform的validate方法或者通過繼承通用的驗證器來完成。對于同一個類可以有不同的驗證上下文環境,但是不能連結到對子類型的驗證。

struts 2支援通過驗證方法進行手工驗證和xwork驗證架構。xwork驗證架構支援對子屬性的連結驗證,使用為屬性類型定義的驗證規則和上下文。

action執行的控制

struts 1支援為每個子產品提供獨立的請求處理器(生命周期),但是同一個子產品中的所有action具有相同的生命周期。

struts 2通過攔截器棧支援為每個action建立不同的生命周期。必要的時候,可以使用不同的actio建立和使用自定義棧。

注:來自struts的官方網站:http://struts.apache.org/2.0.11.2/docs/comparing-struts-1-and-2.html

strust 2結構圖如圖2.1(原圖來自strust 2文檔)所示:

圖2.1 struts2結構圖

在處理一個請求的時候,主要使用3個類:action、interceptor和result

處理流程:

u  請求到達伺服器之後,首先經過一系列過濾器,有的是可選的,最主要的過濾器是filterdispatcher。所有的請求都會送出給它處理,該過濾器是在web.xml中配置的。配置代碼如下:

    &lt;filter&gt;

        &lt;filter-name&gt;struts2&lt;/filter-name&gt;

        &lt;filter-class&gt;org.apache.struts2.dispatcher.filterdispatcher&lt;/filter-class&gt;

    &lt;/filter&gt;

    &lt;filter-mapping&gt;

        &lt;url-pattern&gt;/*&lt;/url-pattern&gt;

    &lt;/filter-mapping&gt;

u  filterdispatcher過濾器接收到請求之後調用actionmapper檢視是否需要調用action。actionmapper提供了httprequest與action調用請求之間的映射關系,可以決定目前請求是否需要調用action。如果actionmapper傳回的資訊表明需要調用action。filterdispatcher過濾器把控制前交給actionproxy;

u  actionproxy調用配置檔案管理器configurationmanager,該管理器從struts.xml配置檔案中擷取配置資訊,擷取的資訊主要包括目前請求對應哪個action(對使用者的請求進行處理),對應哪些result(決定了如何對使用者響應),有時候還涉及攔截器。然後根據這些資訊建立actioninvocation對象,該對象負責具體的調用過程。struts.xml是使用者需要提供的最主要的配置檔案。下面是一個struts.xml配置檔案的部分内容。

&lt;struts&gt;

    &lt;package name="default" extends="struts-default"&gt;

        &lt;action name="logon" class="mailreader2.logon"&gt;

            &lt;result name="input"&gt;/pages/logon.jsp&lt;/result&gt;

            &lt;result name="cancel" type="redirectaction"&gt;welcome&lt;/result&gt;

            &lt;result type="redirectaction"&gt;mainmenu&lt;/result&gt;

            &lt;result name="expired" type="chain"&gt;changepassword&lt;/result&gt;

        &lt;/action&gt;

        &lt;action name="logoff" class="mailreader2.logoff"&gt;

            &lt;result type="redirectaction"&gt;welcome&lt;/result&gt;

    &lt;/package&gt;

&lt;/struts&gt;

u  actioninvocation對象按照順序執行目前請求所對應的攔截器,攔截器能夠對請求進行預處理,例如驗證、檔案上傳等,并能夠對響應内容進行再處理。通常攔截器是由系統提供的,如果需要,程式設計人員隻需要進行配置即可。在調用action的方法之前,會調用攔截器的預處理方法;

u  actioninvocation對象調用攔截器的預處理方法之後會調用action的execute方法,action中的代碼主要由程式設計人員根據功能進行編寫的,通常從資料庫檢索資訊或者向資料庫存儲資訊。action的方法傳回一個字元串。下面是一個簡單的action例子。

package simple;

import java.util.map;

import javax.servlet.http.httpsession;

import com.opensymphony.webwork.servletactioncontext;

import com.opensymphony.xwork.actionsupport;

public class logoutaction extends actionsupport {

    public string execute() throws exception {

     map session = actioncontext.getcontext().getsession();

     session.remove("logined");

     session.remove("context");

        return success;

    }

}

u  actioninvocation對象根據action方法的傳回結果以及struts配置檔案生成result對象。result對象選擇一個模闆檔案來響應使用者,模闆檔案可以是jsp、freemarker和velocity。

u  容器加載并執行模闆檔案,使用在action中擷取的資訊對模版中的變量進行指派,也可能從資源檔案或者其他内部對象中擷取資訊。最終向浏覽器呈現的是html、pdf或者其他内容。

u  模闆檔案執行的結果會經過攔截器進行再處理,最後通過過濾器傳回給用戶端。

在該結構圖中,既包含了struts架構提供的基礎接口,也包括了使用者要編寫的檔案。其中,actionmapper、actionproxy、configurationmanager、actioninvocation和result是架構提供的核心類。過濾器和攔截器是架構提供的,使用者可以根據需要進行配置,當然也可以編寫自己的過濾器和攔截器。使用者需要編寫的檔案是struts.xml、action和模闆檔案,這些也是使用者在使用struts 2架構時需要做的工作。

架構為開發人員提供了大量的輔助類,使用者在使用架構開發的時候隻需要編寫很少檔案。在使用struts 2開發的時候,首先應該把環境搭建起來,然後使用struts 2提供的标簽開發界面,然後編寫action類,最後進行配置。

在進行具體的開發之前,需要先搭建環境。包括如下過程:

u  建立web工程;

u  加載struts 2的核心類庫,核心類庫包括commons-logging-1.0.4.jar、freemarker-2.3.8.jar、ognl-2.6.11.jar、struts2-core-2.0.11.2.jar和xwork-2.0.5.jar,把這些類庫放到web工程的web-inf/lib下面;

u  配置web.xml,主要配置struts中心控制器filterdispatcher,下面是1個例子。

&lt;?xml version="1.0" encoding="utf-8"?&gt;

&lt;web-app id="webapp_9" 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"&gt;

    &lt;display-name&gt;struts blank&lt;/display-name&gt;

    &lt;welcome-file-list&gt;

        &lt;welcome-file&gt;index.html&lt;/welcome-file&gt;

    &lt;/welcome-file-list&gt;

&lt;/web-app&gt;

u  建立struts.xml配置檔案,與類檔案放在一起,空白的struts檔案如下所示。在使用struts 2進行開發所有的配置基本上都在這個檔案中完成。也可以根據需要建立多個配置檔案,然後在這個配置檔案中使用&lt;include file="example.xml"/&gt;進行包含。

&lt;?xml version="1.0" encoding="utf-8" ?&gt;

&lt;!doctype struts public

    "-//apache software foundation//dtd struts configuration 2.0//en"

    "http://struts.apache.org/dtds/struts-2.0.dtd"&gt;

    &lt;constant name="struts.enable.dynamicmethodinvocation" value="false" /&gt;

    &lt;constant name="struts.devmode" value="false" /&gt;

    &lt;include file="example.xml"/&gt;

    &lt;!-- add packages here --&gt;

環境搭建完之後,在具體開發過程中主要完成3個方面的工作:

u  制作模闆檔案,可以使用jsp、freemarker或者velocity等;

u  編寫action,基本上每個動作對應1個action;

u  配置,主要在struts.xml中進行配置。

下面分别介紹。

模版檔案的主要作用是接收使用者輸入的資訊,并向使用者展示資訊。struts提供了多個标簽庫來簡化頁面的代碼量,使用标簽之後頁面也更容易維護。下面是一段标簽:

&lt;s:actionerror/&gt;

&lt;s:form action="profile_update" validate="true"&gt;

  &lt;s:textfield label="username" name="username"/&gt;

  &lt;s:password label="password" name="password"/&gt;

  &lt;s:password label="(repeat) password" name="password2"/&gt;

  &lt;s:textfield label="full name" name="fullname"/&gt;

  &lt;s:textfield label="from address" name="fromaddress"/&gt;

  &lt;s:textfield label="reply to address" name="replytoaddress"/&gt;

  &lt;s:submit value="save" name="save"/&gt;

  &lt;s:submit action="register_cancel" value="cancel" name="cancel"

            onclick="form.onsubmit=null"/&gt;

&lt;/s:form&gt;

struts 2中提供了兩類通用标簽和3類界面标簽:

u  控制标簽

u  資料标簽

u  form标簽

u  non-form使用者接口标簽

u  ajax标簽

下面對這些類型的标簽進行介紹。

控制标簽及其用法如表2.2所示。

表2.2 控制标簽

标簽名

描述

例子

if

與java中的if基本相同

&lt;s:if test="%{false}"&gt;

    &lt;div&gt;will not be executed&lt;/div&gt;

&lt;/s:if&gt;

&lt;s:elseif test="%{true}"&gt;

    &lt;div&gt;will be executed&lt;/div&gt;

&lt;/s:elseif&gt;

&lt;s:else&gt;

&lt;/s:else&gt;

else if

與java中的else if基本相同

else

與java中的else基本相同

append

按照順序把多個疊代器的元素組合到一個疊代器中,保持原來的順序不變。

&lt;s:append var="myappenditerator"&gt;

     &lt;s:param value="%{mylist1}" /&gt;

     &lt;s:param value="%{mylist2}" /&gt;

     &lt;s:param value="%{mylist3}" /&gt;

&lt;/s:append&gt;

&lt;s:iterator value="%{#myappenditerator}"&gt;

     &lt;s:property /&gt;

&lt;/s:iterator&gt;

generator

根據val屬性的給定的值生成疊代器對象。

&lt;s:generator val="%{'aaa,bbb,ccc,ddd,eee'}"&gt;

 &lt;s:iterator&gt;

     &lt;s:property /&gt;&lt;br/&gt;

 &lt;/s:iterator&gt;

&lt;/s:generator&gt;

iterator

對疊代器或者集合進行周遊,類似于java中的for-each循環。

&lt;s:iterator value="#it.days" status="rowstatus"&gt;

  &lt;tr&gt;

    &lt;s:if test="#rowstatus.odd == true"&gt;

      &lt;td style="background: grey"&gt;&lt;s:property/&gt;&lt;/td&gt;

    &lt;/s:if&gt;

    &lt;s:else&gt;

      &lt;td&gt;&lt;s:property/&gt;&lt;/td&gt;

    &lt;/s:else&gt;

  &lt;/tr&gt;

merge

把多個疊代器的元素合并到一個疊代器中,合并後的順序為1.1,2.1,3.1,1.2,1.3…,1.1表示第1個疊代器的第1個元素。

&lt;s:merge var="mymergediterator1"&gt;

&lt;/s:merge&gt;

&lt;s:iterator value="%{#mymergediterator1}"&gt;

sort

對list進行排序。

&lt;s:sort var="mysortedlist" comparator="mycomparator" source="mylist" /&gt;

subset

擷取集合的子集。

&lt;s:subset var="mysubset" source="mylist" count="13" start="3" /&gt;

資料标簽及其用法如表2.3所示。

表2.3 資料标簽

a

生成html的&lt;a&gt;

&lt;s:a href="%{testurlid}"&gt;&lt;img src="&lt;s:url

value="/images/delete.gif"/&gt;" border="none"/&gt;&lt;/s:a&gt;

action

在jsp頁面中直接調用action

&lt;s:action name="actiontagaction" executeresult="true" /&gt;

bean

執行個體化javabean對象

&lt;s:bean name="org.apache.struts2.example.counter.simplecounter" var="counter"&gt;

  &lt;s:param name="foo" value="bar" /&gt;

  the value of foot is : &lt;s:property value="foo"/&gt; &lt;br /&gt;

&lt;/s:bean&gt;

date

建立date對象

&lt;s:date name="person.birthday" format="dd/mm/yyyy" /&gt;

debug

i18n

得到resourcebundle對象。

&lt;s:i18n name="mycustombundle"&gt;

&lt;/s:i18n&gt;

include

包含1個jsp或者servlet的輸出。

&lt;s:include value="myjsp.jsp"&gt;

   &lt;s:param name="param1" value="value2" /&gt;

&lt;/s:include&gt;

param

為其他标簽提供參數

參考上面的例子

property

擷取屬性值

參考bean标簽的例子

push

把值儲存起來使用

&lt;s:push value="user"&gt;

    &lt;s:propery value="firstname" /&gt;

    &lt;s:propery value="lastname" /&gt;

&lt;/s:push&gt;

set

把某個值儲存到某個作用範圍的變量中。

&lt;s:set name="personname" value="person.name"/&gt;

hello, &lt;s:property value="#personname"/&gt;. how are you?

text

呈現i18n的文本消息

&lt;s:i18n name="struts.action.test.i18n.shop"&gt;

    &lt;s:text name="main.title"/&gt;

url

用于生成url

&lt;s:url value="editgadget.action"&gt;

    &lt;s:param name="id" value="%{selected}" /&gt;

&lt;/s:url&gt;

form标簽及其用法如表2.4所示。

表2.4 form标簽

checkbox

生成複選框

&lt;s:checkbox label="checkbox test" name="checkboxfield1"

value="aboolean" fieldvalue="true"/&gt;

checkboxlist

生成多個複選框

&lt;s:checkboxlist name="foo" list="bar"/&gt;

combobox

輸入框與下拉框的組合。

&lt;s:combobox

    label="my favourite fruit"

    name="myfavouritefruit"

    list="{'apple','banana','grape','pear'}"

    headerkey="-1"

    headervalue="--- please select ---"

    emptyoption="true"

    value="banana" /&gt;

doubleselect

生成關聯菜單

&lt;s:doubleselect label="doubleselect test1" name="menu"

list="{'fruit','other'}" doublename="dishes"

doublelist="top == 'fruit' ? {'apple', 'orange'} : {'monkey', 'chicken'}" /&gt;

head

生成html的head部分。

&lt;head&gt;

  &lt;title&gt;my page&lt;/title&gt;

  &lt;s:head/&gt;

&lt;/head&gt;

file

生成檔案輸入框

&lt;s:file name="anuploadfile" accept="text/*" /&gt;

form

生成form表單

&lt;p/&gt;

&lt;s:form ... /&gt;

hidden

生成隐藏域

&lt;s:hidden name="foo" value="bar" /&gt;

label

生成标簽

&lt;s:label key="username" /&gt;

optiontrans

-ferselect

生成兩個清單框,可以通過中間的按鈕把左邊的選項移動到右邊,也可以把右邊的選項移動到左邊。

&lt;s:optiontransferselect

     label="favourite cartoons characters"

     name="leftsidecartooncharacters"

     list="{'popeye', 'he-man', 'spiderman'}"

    doublename="rightsidecartooncharacters"

     doublelist="{'superman', 'mickey mouse', 'donald duck'}"

 /&gt;

optgroup

在select中提供選項

&lt;s:select label="my selection"

           name="myselection"

           value="%{'popeye'}"

           list="%{#{'superman':'superman', 'spiderman':'spiderman'}}"&gt;

   &lt;s:optgroup label="adult"

                list="%{#{'south_park':'south park'}}" /&gt;

   &lt;s:optgroup label="japanese"

                list="%{#{'pokemon':'pokemon','digimon':'digimon',

'sailormoon':'sailormoon'}}" /&gt;

&lt;/s:select&gt;

select

生成下拉框

password

密碼輸入框

&lt;s:password label="%{text('password')}" name="password"

size="10" maxlength="15" /&gt;

radio

單選按鈕

&lt;s:radio label="gender" name="male" list="#genders.genders"/&gt;

reset

重值按鈕

&lt;s:reset value="reset" /&gt;

submit

送出按鈕

&lt;s:submit value="ok" /&gt;

textarea

生成文本域

&lt;s:textarea label="comments" name="comments" cols="30" rows="8"/&gt;

textfield

生成輸入框

&lt;s:textfield key="user" /&gt;

token

阻止表單重複送出

updownselect

建立元素能夠上下移動的清單框

&lt;s:updownselect

list="#{'england':'england', 'america':'america', 'germany':'germany'}"

name="prioritisedfavouritecountries"

headerkey="-1"

headervalue="--- please order them accordingly ---"

emptyoption="true" /&gt;

non-form ui标簽及其用法如表2.5所示。

表2.5 non-form标簽

actionerror

呈現錯誤資訊

&lt;s:actionerror /&gt;

actionmessage

呈現提示資訊

&lt;s:actionmessage /&gt;

component

建立自定義元件

&lt;s:component template="/my/custom/component.vm"/&gt;

div

生成html &lt;div&gt;

fielderror

輸出關于輸入元素的錯誤資訊

   &lt;s:fielderror&gt;

        &lt;s:param&gt;field1&lt;/s:param&gt;

        &lt;s:param&gt;field2&lt;/s:param&gt;

   &lt;/s:fielderror&gt;

   &lt;s:form .... &gt;

      ....

   &lt;/s:form&gt;

ajax标簽包括a、autocompleter、bind、datetimepicker、div、head、submit、tabbedpanel、textarea、tree、treenode等。具體用法參考struts 2幫助文檔。

針對每個功能可以編寫1個action,也可以多個功能共享1個action。action完成的主要功能包括:

u  擷取使用者的輸入資訊,這個擷取的過程是由架構完成的,但是使用者需要在action中定義與使用者輸入表單元素名字相同的成員變量,關鍵是要提供對成員變量指派的set方法,這樣架構在擷取使用者輸入資訊之後會調用set方法把值賦給action的成員變量。

u  根據使用者的請求資訊,調用完成業務邏輯的javabean。如果希望要把某些執行結果傳遞給模闆檔案(jsp、freemarker和velocity等),需要在action中定義成員變量來表示這些結果,最關鍵的是要定義get方法,這樣在執行模版檔案的時候會通過get方法來擷取這些資訊。

u  根據執行的結果,傳回1個字元串,這個字元串決定了使用什麼模闆對使用者進行響應。

下面是1個簡單的例子。

public class loginaction extends actionsupport {

    private string userid;

    private string passwd;

    // 對userid和passwd操作的setter和getter方法

        if ("admin".equals(userid) &amp;&amp; "password".equals(passwd)) {

            map session = actioncontext.getcontext().getsession();

            session.put("logined","true");

            session.put("context", new date());

            return success;

        }

        return error;

注意:并不是必須繼承actionsupport,主要提供execute方法即可。

通過配置檔案struts.xml對web應用的流程進行管理,包括action映射和result處理,前者把請求與action關聯起來,後者把action執行的結果與響應界面關聯起來。下面是一段配置。下面是一個簡單的例子。

struts 2中完成的主要配置如表2.6所示。

表2.6 struts 2的主要配置資訊

配置元素

javabean

&lt;bean type="com.opensymphony.xwork2.objectfactory"

name="myfactory" class="com.company.myapp.myobjectfactory" /&gt;

常量

&lt;constant name="struts.devmode" value="true" /&gt;

&lt;package name="employee" extends="struts-default" namespace="/employee"&gt;

   ...

&lt;/package&gt;

命名空間

包含

&lt;include file="home.xml"/&gt;

攔截器

&lt;interceptors&gt;

  &lt;interceptor name="security"

 class="com.company.security.securityinterceptor"/&gt;

  &lt;interceptor-stack name="securestack"&gt;

    &lt;interceptor-ref name="security"/&gt;

    &lt;interceptor-ref name="defaultstack"/&gt;

  &lt;/interceptor-stack&gt;

&lt;/interceptors&gt;

引用攔截器

&lt;action name="velocitycounter"

class="org.apache.struts2.example.counter.simplecounter"&gt;

    &lt;result name="success"&gt;...&lt;/result&gt;

    &lt;interceptor-ref name="defaultcomponentstack"/&gt;

&lt;/action&gt;

全局result:

&lt;global-results&gt;

    &lt;result name="error"&gt;/error.jsp&lt;/result&gt;

    &lt;result name="invalid.token"&gt;/error.jsp&lt;/result&gt;

&lt;/global-results&gt;

result

異常配置

在action中使用:

&lt;exception-mapping exception="com.company.securityexception" result="login"/&gt;

全局:

&lt;global-exception-mappings&gt;

&lt;exception-mapping exception="java.sql.sqlexception" result="sqlexception"/&gt;

&lt;exception-mapping exception="java.lang.exception" result="exception"/&gt;

&lt;/global-exception-mappings&gt;

struts 2提供了大量的攔截器,使用者可以根據需要調用。

struts 2的配置檔案struts.xml的dtd定義如下。

&lt;!--

   struts configuration dtd.

   use the following doctype

   &lt;!doctype struts public

          "-//apache software foundation//dtd struts configuration 2.0//en"

          "http://struts.apache.org/dtds/struts-2.0.dtd"&gt;

--&gt;

&lt;!element struts (package|include|bean|constant)*&gt;

&lt;!element package (result-types?, interceptors?, default-interceptor-ref?, default-action-ref?, default-class-ref?, global-results?, global-exception-mappings?, action*)&gt;

&lt;!attlist package

    name cdata #required

    extends cdata #implied

    namespace cdata #implied

    abstract cdata #implied

    externalreferenceresolver nmtoken #implied

&gt; 

&lt;!element result-types (result-type+)&gt;

&lt;!element result-type (param*)&gt;

&lt;!attlist result-type

    class cdata #required

    default (true|false) "false"

&lt;!element interceptors (interceptor|interceptor-stack)+&gt;

&lt;!element interceptor (param*)&gt;

&lt;!attlist interceptor

&lt;!element interceptor-stack (interceptor-ref*)&gt;

&lt;!attlist interceptor-stack

&lt;!element interceptor-ref (param*)&gt;

&lt;!attlist interceptor-ref

&lt;!element default-interceptor-ref (param*)&gt;

&lt;!attlist default-interceptor-ref

&lt;!element default-action-ref (param*)&gt;

&lt;!attlist default-action-ref

&lt;!element default-class-ref (param*)&gt;

&lt;!attlist default-class-ref

&lt;!element global-results (result+)&gt;

&lt;!element global-exception-mappings (exception-mapping+)&gt;

&lt;!element action (param|result|interceptor-ref|exception-mapping)*&gt;

&lt;!attlist action

    class cdata #implied

    method cdata #implied

    converter cdata #implied

&lt;!element param (#pcdata)&gt;

&lt;!attlist param

&lt;!element result (#pcdata|param)*&gt;

&lt;!attlist result

    name cdata #implied

    type cdata #implied

&lt;!element exception-mapping (#pcdata|param)*&gt;

&lt;!attlist exception-mapping

    exception cdata #required

    result cdata #required

&lt;!element include (#pcdata)&gt;

&lt;!attlist include

    file cdata #required

&lt;!element bean (#pcdata)&gt;

&lt;!attlist bean

    scope cdata #implied

    static cdata #implied

    optional cdata #implied

&lt;!element constant (#pcdata)&gt;

&lt;!attlist constant

    value cdata #required   

功能:登入。

涉及的檔案有:

l  login.jsp,用于輸入登入資訊;

l  welcome.jsp,登入之後的歡迎界面;

l  logincheck.jsp,判斷使用者是否登入;

l  loginaction.java,完成登入業務處理,正常情況下會調用其他業務邏輯javabean來完成;

l  logoutaction.java,完成退出業務處理;

l  struts.xml,應用的配置檔案。

源檔案:login.jsp

&lt;%@ page language="java" contenttype="text/html; charset=iso-8859-1"

 pageencoding="iso-8859-1"%&gt;

&lt;!doctype html public "-//w3c//dtd html 4.01 transitional//en"&gt;

&lt;html&gt;

&lt;meta http-equiv="content-type" content="text/html; charset=iso-8859-1"&gt;

&lt;title&gt;insert title here&lt;/title&gt;

&lt;/head&gt;&lt;body&gt;

&lt;form action="login.action" method="post"&gt;

user id&lt;input type="text" name="userid" /&gt; &lt;br/&gt;

password &lt;input type="password" name="passwd" /&gt; &lt;br /&gt;

&lt;input type="submit" value="login"/&gt;

&lt;/form&gt;

&lt;/body&gt;

&lt;/html&gt; 

    pageencoding="iso-8859-1"%&gt;

&lt;%@ taglib prefix="ww" uri="/webwork" %&gt;

&lt;jsp:include page="web-inf/inc/logincheck.jsp" /&gt;

&lt;title&gt;welcome&lt;/title&gt;

&lt;body&gt;welcome, you have logined. &lt;br /&gt;

the attribute of 'context' in session is

&lt;ww:property value="#session.context" /&gt;

&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;

&lt;a xhref="&lt;%= request.getcontextpath() %&gt;/logout.action"&gt;logout&lt;/a&gt;

&lt;br /&gt;

&lt;a xhref="&lt;%= request.getcontextpath() %&gt;/logout2.action"&gt;logout2&lt;/a&gt;

&lt;%@ taglib="/webwork" prefix="ww" %&gt;

&lt;ww:if test="#session.login != 'true'"&gt;

&lt;jsp:forward page="&lt;%= request.getcontextpath() %&gt;/login.jsp" /&gt;

&lt;/ww:if&gt; 

import java.util.date;import java.util.map;

//            httpsession session = servletactioncontext.getrequest().getsession();

//            session.setattribute("logined","true");

//            session.setattribute("context", new date());

// better is using actioncontext

  map session = actioncontext.getcontext().getsession();

session.put("logined","true");

    public string logout() throws exception {

//        httpsession session = servletactioncontext.getrequest().getsession();

//        session.removeattribute("logined");

//        session.removeattribute("context");

 map session = actioncontext.getcontext().getsession();

 session.remove("logined");

        session.remove("context");

    public string getpasswd() {

        return passwd;

    public void setpasswd(string passwd) {

        this.passwd = passwd;

    public string getuserid() {

        return userid;

    public void setuserid(string userid) {

        this.userid = userid;

session.remove("logined");

session.remove("context");

&lt;!doctype xwork public "-//opensymphony group//xwork 1.1.1//en" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd"&gt;

&lt;xwork&gt;

    &lt;include file="webwork-default.xml"/&gt;

    &lt;package name="default" extends="webwork-default"&gt;

        &lt;!-- add your actions here --&gt;

        &lt;action name="login" class="simple.loginaction" &gt;

            &lt;result name="success" type="dispatcher"&gt;/pages/welcome.jsp&lt;/result&gt;

            &lt;result name="error" type="redirect"&gt;/login.jsp&lt;/result&gt;

        &lt;action name="logout2" class="simple.loginaction" method="logout" &gt;

            &lt;result name="success" type="redirect"&gt;/login.jsp&lt;/result&gt;

        &lt;action name="logout" class="simple.logoutaction" &gt;

&lt;/xwork&gt;