第2.8式. 有選擇地禁止Action
問(wèn)題
你想要是使用一個(gè)定制屬性來(lái)禁止(disable)一個(gè),并且該屬性能夠在struts-config.xml文件的action元素中進(jìn)行設(shè)置;轉(zhuǎn)發(fā)到該disabled action 的任何請(qǐng)求都會(huì)得到"under construction" 頁(yè)面。
動(dòng)作要領(lǐng)
創(chuàng)建一個(gè)定制的ActionMapping擴(kuò)展(如Example 2-16) ,它可以提供一個(gè)boolean 類(lèi)型的屬性來(lái)指示action 是否被禁止。
Example 2-16. 定制ActionMapping
import org.apache.struts.action.ActionMapping;


public class DisablingActionMapping extends ActionMapping
{

private String disabled;
private boolean actionDisabled = false;

public String getDisabled( )
{
return disabled;
}


public void setDisabled(String disabled)
{
this.disabled = disabled;
actionDisabled = new Boolean(disabled).booleanValue( );
}

public boolean isActionDisabled( )
{
return actionDisabled;
}
}

這個(gè)action mapping 就可以在struts-config.xml文件中指定。如果你想要一個(gè)action被禁止,你可以設(shè)置disabled屬性為T(mén)rue :
<action-mappings type="com.oreilly.strutsckbk.DisablingActionMapping">

<!-- Edit mail subscription -->
<action path="/editSubscription"
type="org.apache.struts.webapp.example.EditSubscriptionAction"
attribute="subscriptionForm"
scope="request"
validate="false">
<set-property property="disabled" value="true"/>
<forward name="failure" path="/mainMenu.jsp"/>
<forward name="success" path="/subscription.jsp"/>
</action>

然后創(chuàng)建一個(gè)定制的RequestProcessor,比如Example 2-17中的那個(gè),它可以處理DisablingActionMapping.
Example 2-17. 處理對(duì)被禁止的actions的請(qǐng)求
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.RequestProcessor;


public class CustomRequestProcessor extends RequestProcessor
{
protected ActionForward processActionPerform(HttpServletRequest request,
HttpServletResponse response, Action action,ActionForm form,

ActionMapping mapping) throws IOException, ServletException
{
ActionForward forward = null;

if (!(mapping instanceof DisablingActionMapping))
{
forward = super.processActionPerform( request, response,
action, form, mapping);
}

else
{
DisablingActionMapping customMapping =
(DisablingActionMapping) mapping;

if (customMapping.isActionDisabled( ))
{
forward = customMapping.findForward("underConstruction");
}

else
{
forward = super.processActionPerform( request, response,
action, form, mapping);
}
}
return forward;
}
}

動(dòng)作變化
Struts 通過(guò)兩種機(jī)制來(lái)對(duì)action提供定制屬性的能力。
首先,每個(gè)Struts action 都可以通過(guò)一個(gè)通用參數(shù)parameter值來(lái)傳遞:
<action path="/editRegistration"
type="org.apache.struts.webapp.example.EditRegistrationAction"
attribute="registrationForm"
scope="request"
validate="false"
parameter="disabled">
<forward name="success" path="/registration.jsp"/>
</action>

其次,在Action的實(shí)現(xiàn)中,parameter的值可以通過(guò)下面的代碼來(lái)訪問(wèn):
String parameterValue = mapping.getParameter( );
然而,某些Struts所提供的子類(lèi),比如DispatchAction 已經(jīng)使用了parameter屬性。因?yàn)槟阒豢梢灾付ㄒ粋€(gè)parameter屬性,所以,如果你使用這些預(yù)定義的Action子類(lèi),便不能再將parameter用作定制屬性值。
對(duì)于完整的擴(kuò)展,你可以擴(kuò)展ActionMapping類(lèi),可選地為你所選擇的定制屬性提供accessor 和 mutator :
package com.oreilly.strutsckbk;

import org.apache.struts.ActionMapping


public class MyCustomActionMapping extends ActionMapping
{
private String customValue;

public String getCustomValue( )
{ return customValue; }

public String setCustomValue(String s)
{ customValue = s; }
}


你可以在struts-config.xml文件中引用這個(gè)擴(kuò)展。如果定制action mapping 將被用于所有action,請(qǐng)將action-mappings元素的type屬性設(shè)置為定制擴(kuò)展的全限定類(lèi)名:
<action-mappings type="com.oreilly.strutsckbk.MyCustomActionMapping">
否則,為定制action mapping所需的action元素設(shè)置className屬性。這兩種情況下,set-property元素都可以用來(lái)針對(duì)特定的action元素為定制擴(kuò)展中的JavaBean 屬性設(shè)置值:
<action path="/someAction"
type="com.oreilly.strutsckbk.SomeAction"
className="com.oreilly.strutsckbk.MyCustomActionMapping">
<set-property property="customValue" value="some value"/>
</action>

這種方案使用一個(gè)定制的RequestProcessor來(lái)處理定制ActionMapping的disabled 屬性。如果你對(duì)特定的action使用定制的ActionMapping,你可以在Action.execute()訪法中直接訪問(wèn)定值A(chǔ)ctionMapping的屬性:
boolean disabled = ((DisablingActionMapping) mapping).isActionDisabled( );
if (disabled) return mapping.findForward("underConstruction");

相關(guān)招式
你也可以使用授權(quán)(authorization) servlet 過(guò)濾器來(lái)解決這個(gè)問(wèn)題。那是第11.8式的動(dòng)作。