高级通配符映射在Prepare()方法中找不到参数

时间:2013-10-21 13:03:19

标签: java xml regex struts2 interceptor

来自文档: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>
     

在此示例中,如果网址为/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. -->

这适用于来自页面的参数,但不适用于Advanced Wildcards设置的参数。它们仍然是空的。

如何解决此问题?

2 个答案:

答案 0 :(得分:4)

这些参数不是由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,它完美无缺。

答案 1 :(得分:0)

@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的答案。