第2.8式. 有選擇地禁止Action
問題
你想要是使用一個定制屬性來禁止(disable)一個,并且該屬性能夠在struts-config.xml文件的action元素中進行設置;轉發到該disabled action 的任何請求都會得到"under construction" 頁面。
動作要領
創建一個定制的ActionMapping擴展(如Example 2-16) ,它可以提供一個boolean 類型的屬性來指示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;
}
}

這個action mapping 就可以在struts-config.xml文件中指定。如果你想要一個action被禁止,你可以設置disabled屬性為True :
<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>

然后創建一個定制的RequestProcessor,比如Example 2-17中的那個,它可以處理DisablingActionMapping.
Example 2-17. 處理對被禁止的actions的請求
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;
}
}

動作變化
Struts 通過兩種機制來對action提供定制屬性的能力。
首先,每個Struts action 都可以通過一個通用參數parameter值來傳遞:
<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的實現中,parameter的值可以通過下面的代碼來訪問:
String parameterValue = mapping.getParameter( );
然而,某些Struts所提供的子類,比如DispatchAction 已經使用了parameter屬性。因為你只可以指定一個parameter屬性,所以,如果你使用這些預定義的Action子類,便不能再將parameter用作定制屬性值。
對于完整的擴展,你可以擴展ActionMapping類,可選地為你所選擇的定制屬性提供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文件中引用這個擴展。如果定制action mapping 將被用于所有action,請將action-mappings元素的type屬性設置為定制擴展的全限定類名:
<action-mappings type="com.oreilly.strutsckbk.MyCustomActionMapping">
否則,為定制action mapping所需的action元素設置className屬性。這兩種情況下,set-property元素都可以用來針對特定的action元素為定制擴展中的JavaBean 屬性設置值:
<action path="/someAction"
type="com.oreilly.strutsckbk.SomeAction"
className="com.oreilly.strutsckbk.MyCustomActionMapping">
<set-property property="customValue" value="some value"/>
</action>

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

相關招式
你也可以使用授權(authorization) servlet 過濾器來解決這個問題。那是第11.8式的動作。