2

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

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

症状:

我在 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 中,它们的Action 定义在具有自己名称空间的单独模块中。但是,它们仍然是一个项目的一部分,并且一起打包在一个 WAR 文件中。

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

  1. 单击 Portlet A 上的链接。
  2. Portlet A 加载到屏幕 A2 中。
  3. 单击 Portlet B 上的链接。
  4. Portlet B 加载到屏幕 B2 中。
  5. 然而,作为一个副作用,Portlet A 刷新并且显示的屏幕是它的“索引”页面(而不是屏幕 A2)。

这是预期的行为,还是我应该做些什么来使这个特定的设置在单个门户页面中工作?

编辑: 我单击的链接是 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 的执行方法返回 SUCCESS,而 SecondPageAction 的执行方法返回 INPUT。

我认为这可能是因为我的第二个操作没有“成功”结果(我的 execute() 方法返回“输入”,因为我在页面中有一个表单)。但是,添加 result=success 标签并没有帮助。

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

4

1 回答 1

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 的呈现阶段的执行顺序不受 portlet 规范的保证。Liferay 通过 liferay-portlet.xml 中的元素 render-weight 对规范进行了扩展。具有较高渲染权重的 Portlet 将在具有较低值的 Portlet 之前渲染。

[...]

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

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

所以我猜你正在使用actionURL去页面 A2 而不是renderURL

于 2012-04-18T10:39:06.337 回答