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