第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式的动作。