Liferay JSF Primefaces跨Portlet事件触发后如何避免Portlet2刷新?
解决方案:Liferay JSF Primefaces跨Portlet更新UI不刷新发起端
针对你遇到的Portlet2触发事件后自身刷新的问题,以下是几个可落地的解决思路:
方案一:用PrimeFaces异步命令链接发送事件
利用p:commandLink的ajax特性,限制请求范围并阻止自身刷新,同时通过Portlet API发送事件:
- 页面代码(Portlet2)
<p:commandLink value="更新Portlet1" actionListener="#{portlet2Bean.sendUpdateEvent}" ajax="true" process="@this" <!-- 仅处理当前按钮 --> update="@none" <!-- 不更新Portlet2任何组件 --> />
- 后端Bean代码(Portlet2)
用Liferay Faces工具类安全获取Portlet响应对象,避免类型转换错误:
import javax.portlet.ActionResponse; import javax.portlet.PortletException; import javax.faces.context.FacesContext; import com.liferay.faces.util.context.FacesContextHelper; public class Portlet2Bean { public void sendUpdateEvent() throws PortletException { FacesContext facesContext = FacesContext.getCurrentInstance(); ActionResponse actionResponse = (ActionResponse) FacesContextHelper.getPortletResponse(facesContext); // 发送自定义事件,QName需与Portlet1监听配置完全一致 actionResponse.setEvent("com.example.UpdatePortlet1Event", "更新内容"); } }
- Portlet1事件处理
处理事件后主动触发UI更新:
import javax.portlet.Event; import javax.portlet.EventRequest; import javax.portlet.EventResponse; import javax.portlet.ProcessEvent; import org.primefaces.context.RequestContext; @ProcessEvent(qname = "{com.example}UpdatePortlet1Event") public void handleUpdateEvent(EventRequest request, EventResponse response) { Event event = request.getEvent(); String updateData = (String) event.getValue(); // 执行业务逻辑,更新Bean数据 this.targetData = updateData; // 刷新Portlet1指定UI组件(替换为你的组件ID) RequestContext.getCurrentInstance().update("portlet1Form:contentPanel"); }
方案二:纯JS触发Portlet事件(无后端请求)
完全绕过JSF的action请求,用Liferay前端API直接发送事件,彻底避免Portlet2刷新:
- 页面代码(Portlet2)
<h:commandLink value="更新Portlet1" onclick="triggerPortletUpdate(); return false;" /> <script> function triggerPortletUpdate() { // 替换为Portlet1的实际实例ID(可从页面源码中查找,格式如_WAR_portlet1portlet_INSTANCE_xxx) const portlet1Instance = Liferay.Portlet.get('_WAR_portlet1portlet_INSTANCE_abc'); if (portlet1Instance) { // 发送事件,事件名需匹配Portlet1监听配置 portlet1Instance.fireEvent('com.example.UpdatePortlet1Event', {data: "前端触发更新"}); } } </script>
- 补充:确保Liferay JS加载
如果页面找不到Liferay对象,在Portlet2的view.xhtml中添加依赖:
<h:outputScript library="liferay" name="js/liferay.js" />
方案三:JSF原生异步请求配合事件发送
用f:ajax标记实现异步请求,限制Portlet2的刷新范围:
<h:commandLink value="更新Portlet1" action="#{portlet2Bean.sendUpdateEvent}"> <f:ajax execute="@this" render="@none" /> </h:commandLink>
后端Bean代码与方案一完全一致,此方式依赖JSF Portlet Bridge的异步支持。
关键注意事项
- 事件的QName必须完全一致:包括命名空间和事件名,需在
portlet.xml中统一配置双方的事件定义。 - Portlet1处理事件时,必须明确指定要刷新的UI组件ID,否则数据更新后UI不会同步。
- 若使用JS方式,需要确认Portlet1的实例ID可正确获取,可通过
Liferay.Portlet.list()打印所有Portlet实例信息排查。
内容的提问来源于stack exchange,提问作者dorcsi
相关产品推荐
相关产品推荐

