Struts2 portlet正在刷新Liferay时执行默认操作(而不是当前操作)

时间:2012-04-18 08:56:22

标签: java struts2 liferay portlet

编辑:编辑标题以反映新发现。第二个portlet是什么类型的portlet并不重要。请参阅以下一般行为:

  1. 我在页面上有一个Struts2 portlet,它的默认“索引”操作是pageA1。
  2. 点击A1上的链接,然后转到第A2页。
  3. 我刷新页面,portlet A仍显示pageA2。
  4. 页面上还有其他portlet。我选择任何一个portlet B并单击B1上的链接。
  5. Portlet B导航到B2。同时,Liferay刷新页面上的其他portlet,包括Struts2 portlet A.
  6. portlet刷新后的预期结果是pageA2,但显示的页面是pageA1!
  7. 症状:

    我在struts动作中添加了一些日志记录来显示传递的参数。在正常导航期间(即我只是单独使用struts2 portlet A),将显示参数struts.portlet.action和struts.portlet.mode。但是,如果由于另一个portlet B的渲染/操作阶段而在struts2 portlet A上发生自动刷新,那么这些参数似乎不会传递给struts2,因此portlet A默认返回其索引pageA1,而不是页面在刷新之前显示(pageA2)。

    这是否意味着由于struts2没有检测到struts.portlet.action参数,它会调用默认操作(在这种情况下,我将其设置为“index” - > pageA1)?


    旧详情

    我有一个项目设置,它有两个portlet,都使用Struts2框架。这两个portlet实际上彼此非常相似,但它们的代码存在于不同的包中,而在struts.xml中,它们的Actions在具有自己的命名空间的单独模块中定义。但它们仍然是一个项目的一部分,并且被打包在一个WAR文件中。

    我将WAR部署到Liferay,并将两个portlet添加到单个页面。使用这两个portlet时会出现以下行为:

    1. 单击Portlet A上的链接。
    2. Portlet A加载到屏幕A2。
    3. 单击Portlet B上的链接。
    4. Portlet B加载到屏幕B2。
    5. 但是,作为副作用,Portlet A刷新,显示的屏幕是其“索引”页面(而不是屏幕A2)。
    6. 这是预期的行为,还是我应该做些什么来使这个特定的设置在单个门户页面中工作?

      修改 我点击的链接是renderURLs(使用s:url标记生成)。两个portlet的第二页都包含表单,我不确定它们是否有任何意义。

      我添加了一些简单的日志记录,基于它,我发现每次刷新页面时,两个portlet都会呈现两次。我认为这不是一种自然行为。

      这是我的struts.xml,如果它有用:

      <package name="portletA" extends="struts-portlet-default" namespace="/portletA">
      
          <action name="index" class="my.a.DisplayFirstPageAction">
              <result name="success">/pageA1.jsp</result>
          </action>
      
          <action name="displayForm" class="my.a.DisplaySecondPageAction">
              <result name="input">/pageA2.jsp</result>
          </action>
      </package>
      <package name="portletB" extends="struts-portlet-default" namespace="/portletB">
      
          <action name="index" class="my.b.DisplayFirstPageAction">
              <result name="success">/pageB1.jsp</result>
          </action>
      
          <action name="displayForm" class="my.b.DisplaySecondPageAction">
              <result name="input">/pageB2.jsp</result>
          </action>
      </package>
      

      在两个portlet上,pageA1.jsp都有一个调用struts动作“displayForm”的链接。 FirstPageAction的execute方法返回SUCCESS,而SecondPageAction的execute方法返回INPUT。

      我认为可能是因为我的第二个动作没有“成功”结果(我的execute()方法返回“输入”,因为我在页面中有一个表单)。但是,添加结果=成功标记无济于事。

      大声思考,如果我在B2渲染时点击A1的链接,应该调用B2的渲染/执行动作,但似乎会调用B1的渲染/执行动作。

1 个答案:

答案 0 :(得分:1)

检查http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/understanding-the-two-phases-of-portlet-execution,特别是下面的段落:

portlet规范为portlet的每个请求定义了两个阶段,允许门户网站区分执行某个操作(并且不应该重复)以及何时生成(呈现)内容:

  • 行动阶段 :只能为一个portlet调用操作阶段 一个时间,通常是用户与之交互的结果 门户。在此阶段,portlet可以更改其状态 实例更改portlet的用户首选项。也是 建议在数据库中进行任何插入和修改 不应重复的操作在此阶段执行。
  • 渲染阶段 :始终为所有portlet调用渲染阶段 行动阶段之后的页面(可能存在或不存在)。这个 包括也已执行其动作阶段的portlet。它的 重要的是要注意渲染阶段的顺序 portlet无法保证页面中的portlet被执行 规格。 Liferay通过扩展规范 liferay-portlet.xml中的元素render-weight。有一个Portlet 较高的渲染权重将在较低的渲染权重之前呈现 值。

[...]

portlet可以生成三种类型的URL:

  • renderURL :这是我们到目前为止使用的网址类型。它仅使用渲染阶段调用portlet。
  • actionURL :这种类型的URL告诉portlet它应该在呈现页面中的所有portlet之前执行其操作阶段。
  • resourceURL :此类型的网址可用于检索图片,XML,JSON或任何其他类型的资源。它通常用于动态生成图像或其他媒体类型。向服务器发出AJAX请求也非常有用。与其他两种URL类型相比,此URL类型的主要区别在于,portlet可以完全控制将作为响应发送的数据。

所以我猜您使用 actionURL 转到第A2页而不是 renderURL