没有mutators和访问器(setter / getters)的参数以及Struts 2中的参数拦截器

时间:2014-02-06 15:31:44

标签: jsp struts2 interceptor struts2-interceptors

在下面的动作类中,我正在使用参数拦截器。

@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value = "struts-default")
@InterceptorRefs(@InterceptorRef(value="store", params={"operationMode", "AUTOMATIC"}))
public final class TestAction extends ActionSupport implements Serializable, ValidationAware, Preparable
{
    private static final long serialVersionUID = 1L;

    private String param1;
    private String param2;

    //Getters and setters.

    public TestAction() {}

    @Action(value = "TestMessage",
        results = {
            @Result(name=ActionSupport.SUCCESS, type="redirectAction", params={"namespace", "/admin_side", "actionName", "Test"}),
            @Result(name = ActionSupport.INPUT, location = "Test.jsp")},
        interceptorRefs={
            @InterceptorRef(value="paramsPrepareParamsStack", params={"params.acceptParamNames", "param1, param2", "params.excludeParams", "extraParam", "validation.validateAnnotatedMethodOnly", "true"})
        })
    public String insert() {
        // Do something. Add or update a row to the database (one at a time).
        addActionMessage("Action message");
        addActionError("Error message");
        return ActionSupport.SUCCESS;
    }

    @Action(value = "Test",
    results = {
        @Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
        @Result(name = ActionSupport.INPUT, location = "Test.jsp")},
    interceptorRefs = {
        @InterceptorRef(value = "paramsPrepareParamsStack", params = {"params.acceptParamNames", "param1, param2", "params.excludeParams", "extraParam", "validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "load"})})
    public String load() throws Exception {
        // This method is just required to return an initial view on page load.
        return ActionSupport.SUCCESS;
    }

    @Override
    public void prepare() throws Exception {}
}

以下是<s:form>

<s:form namespace="/admin_side" action="Test" validate="true" id="dataForm" name="dataForm">
    <s:if test="hasActionMessages()">
        <s:actionmessage theme="jquery"/>
    </s:if>

    <s:if test="hasActionErrors()">
        <s:actionerror theme="jquery"/>
    </s:if>

    <s:hidden name="param1"/>
    <s:hidden name="param2"/>
    <s:hidden name="extraParam"/>
    <s:submit value="Submit" action="TestMessage"/>
</s:form>

此处,隐藏的表单字段extraParam未声明,因此在操作类中没有setter和getter。

在这种情况下,提交此表单时,服务器终端上会显示以下消息。

  

SEVERE:开发人员通知(将struts.devMode设置为false以禁用   此消息):Unexpected Exception捕获设置'extraParam'   'class actions.TestAction:错误设置表达式'extraParam'   值['',]

params.excludeParams不排除动作类中的参数extraParam

我们可以在使用参数拦截器时以某种方式防止此类异常。此类消息不必要地添加到操作消息中,并在<s:actionmessage/>显示时显示,如果使用的话,根本不应显示这些消息。


如果此动作类中的paramsPrepareParamsStackdefaultStack替换,则不会显示此类消息。它只是发出如下警告。

  

警告:参数[extraParam]位于excludeParams列表中   图案!

请不要只是说,struts.devMode设置为false以禁用 这样的消息。

3 个答案:

答案 0 :(得分:2)

我已经在评论中说过,如果您定义了一组覆盖默认设置的参数,拦截器参数不会被父包的拦截器配置继承。见Interceptor Parameter Overriding Inheritance

还有一些技术用于获取两个不同的拦截器参数图,请参阅Getting Interceptor Parameters in Struts2

约定插件创建从某个父包继承的XWork包配置。请参阅我对Struts 2 Convention Plugin Define Multiple Parent Packages的回答。

因此,如果要将自己的参数添加到集合中,您所要做的就是覆盖父配置设置的默认参数。 interceptor代码或interceptor-stack代码,您应该为每个interceptor-ref代码执行此操作。

约定插件使用@InterceprorRef注释用于相同的目的,但有一个警告,如果应用于类,它适用于该类的每个操作。因此,在类级别上使用此批注时要小心。您正在覆盖拦截器堆栈参数,因此您应该为每个参数名称使用堆栈中引用的拦截器名称的前缀后跟,但这仅在堆栈中具有interceptor-ref的唯一名称时才有效。

如果params中有paramsPrepareParamsStack拦截器的两个引用,则除非您创建自己的拦截器堆栈,否则无法覆盖第二个params interceptor-ref并在拦截器的每个引用上指定参数覆盖。

答案 1 :(得分:1)

让我们看看paramsPrepareParamsStack

 <interceptor-stack name="paramsPrepareParamsStack">
      <interceptor-ref name="exception"/>
      <interceptor-ref name="alias"/>
      <interceptor-ref name="i18n"/>
      <interceptor-ref name="checkbox"/>
      <interceptor-ref name="multiselect"/>
      <interceptor-ref name="params">
          <param name="excludeParams">dojo\..*,^struts\..*</param>
      </interceptor-ref>
      <interceptor-ref name="servletConfig"/>
      <interceptor-ref name="prepare"/>
      <interceptor-ref name="chain"/>
      <interceptor-ref name="modelDriven"/>
      <interceptor-ref name="fileUpload"/>
      <interceptor-ref name="staticParams"/>
      <interceptor-ref name="actionMappingParams"/>
      <interceptor-ref name="params">
          <param name="excludeParams">dojo\..*,^struts\..*</param>
       </interceptor-ref>
       <interceptor-ref name="conversionError"/>
       <interceptor-ref name="validation">
           <param name="excludeMethods">input,back,cancel,browse</param>
       </interceptor-ref>
       <interceptor-ref name="workflow">
           <param name="excludeMethods">input,back,cancel,browse</param>
       </interceptor-ref>
 </interceptor-stack>

有2个params拦截器。当您在动作类中设置excludeParams参数时,可能会为第一个params拦截器设置此参数 - 第二个拦截器的参数保持默认值。现在,当调用第二个params拦截器(默认为excludeParams)时,抛出给定的异常。

您可以尝试复制excludeParams参数的设置,以便为第二个拦截器设置它:

 @InterceptorRef(value = "paramsPrepareParamsStack", params = {"params.acceptParamNames", "param1, param2", "params.excludeParams", "extraParam", "params.excludeParams", "extraParam", "validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "load"})})

答案 2 :(得分:1)

我不是说完全,

示例代码如下:

<s:form action="save" method="post">
    <s:textfield key="personBean.firstName" /> 
    <s:textfield key="personBean.lastName" /> 
    <s:textfield key="personBean.email" />
    <s:textfield key="personBean.phoneNumber" />
    <s:select key="personBean.sport" list="sports" />
    <s:radio key="personBean.gender" list="genders" />
    <s:select key="personBean.residency" list="states" listKey="stateAbbr" listValue="stateName"/>
    <s:checkbox key="personBean.over21" />
    <s:checkboxlist key="personBean.carModels" list="carModelsAvailable" />
    <s:submit key="submit" />
</s:form>

也许它无法正常转到此链接: