【问题标题】:Advanced Wildcard Mappings Parameters not found in Prepare() method在 Prepare() 方法中找不到高级通配符映射参数
【发布时间】:2013-10-29 23:50:01
【问题描述】:

来自文档:Struts2's Advanced Wildcard Mappings

高级通配符

从 2.1.9+ 开始可以在动作中定义正则表达式 姓名。要使用这种形式的通配符,以下常量必须是 设置:

<constant name="struts.enable.SlashesInActionNames" value="true"/> 
<constant name="struts.mapper.alwaysSelectFullNamespace" value="false"/>
<constant name="struts.patternMatcher" value="regex" />

正则表达式可以有两种形式,最简单的一种是 {FIELD_NAME},在这种情况下,带有 FIELD_NAME 的字段在 操作将填充匹配的文本,例如:

<package name="books" extends="struts-default" namespace="/">
    <action name="/{type}/content/{title}" class="example.BookAction">
        <result>/books/content.jsp</result>
    </action> 
</package>

在本例中,如果 url /fiction/content/Frankenstein 是 请求时,BookAction 的字段“type”将设置为“fiction”,并且 字段“title”将设置为“Frankenstein”。

这绝对很棒,如果您在常规 Action 方法中读取这些变量(例如 execute()),则可以正常工作。

如果您尝试从prepare() 方法中读取它们,则它们为空,因为PrepareInterceptor 在其他负责设置参数的拦截器之前运行;解决此问题的常用方法是使用适当的拦截器堆栈来获取执行prepare() 方法时已填充的参数...

来自文档:ParamsPrepareParamStack

<!-- An example of the paramsPrepareParams trick. This stack
     is exactly the same as the defaultStack, except that it
     includes one extra interceptor before the prepare interceptor:
     the params interceptor.

     This is useful for when you wish to apply parameters directly
     to an object that you wish to load externally (such as a DAO
     or database or service layer), but can't load that object
     until at least the ID parameter has been loaded. By loading
     the parameters twice, you can retrieve the object in the
     prepare() method, allowing the second params interceptor to
     apply the values on the object. -->

这适用于来自页面的参数,但它不适用于高级通配符设置的参数。它们仍然为空。

如何解决这个问题?

【问题讨论】:

    标签: java xml regex struts2 interceptor


    【解决方案1】:

    这些参数不是由ParametersInterceptor 设置的(就像那些来自JSP 的),而是StaticParametersInterceptor
    要将它们填充到prepare() 方法中,必须应用 paramsPrepareParamsStack 的相同技巧。
    由于没有开箱即用的拦截器堆栈,因此您必须定义它。
    defaultStack开始,我们应该像这样创建一个堆栈:

    <interceptor-stack name="allYourParamsAreBelongToUsStack">
        <interceptor-ref name="exception"/>
        <interceptor-ref name="alias"/>
        <interceptor-ref name="servletConfig"/>
        <interceptor-ref name="i18n"/>
     <!-- THE TRICK: NOW PREPARE() WILL FIND EVERYTHING SET -->     
        <interceptor-ref name="staticParams"/>
        <interceptor-ref name="actionMappingParams"/>
        <interceptor-ref name="params">
            <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
        </interceptor-ref>
     <!-- END OF THE TRICK -->
        <interceptor-ref name="prepare"/>
        <interceptor-ref name="chain"/>
        <interceptor-ref name="scopedModelDriven"/>
        <interceptor-ref name="modelDriven"/>
        <interceptor-ref name="fileUpload"/>
        <interceptor-ref name="checkbox"/>
        <interceptor-ref name="multiselect"/>
        <interceptor-ref name="staticParams"/>
        <interceptor-ref name="actionMappingParams"/>
        <interceptor-ref name="params">
            <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</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-ref name="debugging"/>
    </interceptor-stack>
    

    注意:ActionMappingParams 不是必需的,只是为了将来使用。

    如果您发现与此相关的任何问题,请发表评论。 AFAIK,它完美无瑕。

    【讨论】:

      【解决方案2】:

      @Andrea 解决方案不错,但我遇到了一些问题:

      • staticParams、actionMappingParams 和 params 拦截器被调用两次
      • 文件上传失败

      所以,我改用这个非常接近的堆栈:

      <interceptor-stack name="myOwnParamsPrepareParamsStack">
        <interceptor-ref name="exception"/>
        <interceptor-ref name="alias"/>
        <interceptor-ref name="i18n"/>
        <!-- Needed for advanced wildcards parameters setted before prepare() -->
        <interceptor-ref name="fileUpload"/>
        <interceptor-ref name="staticParams"/>
        <interceptor-ref name="actionMappingParams"/>
        <interceptor-ref name="params"/>
        <!-- /Needed for advanced wildcards parameters setted before prepare() -->
        <interceptor-ref name="checkbox"/>
        <interceptor-ref name="datetime"/>
        <interceptor-ref name="multiselect"/>
        <interceptor-ref name="servletConfig"/>
        <interceptor-ref name="prepare"/>
        <interceptor-ref name="chain"/>
        <interceptor-ref name="modelDriven"/>
        <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>
      

      顺便说一句,这是基于默认的 paramsPrepareParamsStack 和 Andrea 的答案。

      【讨论】:

        猜你喜欢
        • 2011-08-21
        • 1970-01-01
        • 1970-01-01
        • 2013-10-07
        • 1970-01-01
        • 1970-01-01
        • 2019-07-04
        • 2018-07-26
        • 1970-01-01
        相关资源
        最近更新 更多