You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Liferay 7中JournalArticleLocalServiceUtil无法返回articleDisplay内容

解决Liferay 7 GA5中Portlet编程访问Web内容的articleDisplay问题

我来帮你搞定这个问题——在Liferay 7 GA5的OSGI模块里,JournalArticleLocalServiceUtil确实拿不到你需要的articleDisplay内容。原因很简单:这个工具类负责的是获取原始的JournalArticle实体数据,而articleDisplay是经过FreeMarker模板渲染、合并了themeDisplay、serviceContext等上下文信息后的最终展示内容,得用专门的方法来生成。

下面是具体的实现步骤和代码示例:

1. 优先用OSGI服务注入,替代静态Util类

在Liferay 7的OSGI环境中,静态工具类(比如*Util)容易出现类加载器冲突或者服务无法正确获取的问题,官方推荐用**声明式服务(Declarative Services)**依赖注入所需的服务。

2. 调用getArticleDisplay方法获取渲染后的内容

JournalArticleLocalService提供了getArticleDisplay方法,专门用来生成经过模板渲染的Web内容展示字符串。你需要传入正确的上下文参数,和你FreeMarker模板里用到的上下文保持一致。

完整的Portlet代码示例

import com.liferay.journal.service.JournalArticleLocalService;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.WebKeys;

import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import java.io.IOException;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

@Component(
    immediate = true,
    property = {
        "com.liferay.portlet.display-category=category.sample",
        "com.liferay.portlet.instanceable=true",
        "javax.portlet.display-name=Custom Journal Content Portlet",
        "javax.portlet.init-param.template-path=/",
        "javax.portlet.init-param.view-template=/view.jsp",
        "javax.portlet.resource-bundle=content.Language",
        "javax.portlet.security-role-ref=power-user,user"
    },
    service = MVCPortlet.class
)
public class CustomJournalPortlet extends MVCPortlet {

    @Reference
    private JournalArticleLocalService _journalArticleLocalService;

    @Override
    public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
            throws IOException, PortletException {

        // 获取当前请求的ThemeDisplay(和你模板里的上下文一致)
        ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
        long groupId = themeDisplay.getScopeGroupId(); // Web内容所在的站点ID
        String articleId = "YOUR_WEB_CONTENT_ID"; // 替换成你的Web内容ID
        String languageId = themeDisplay.getLanguageId(); // 当前用户的语言ID

        try {
            // 获取Web内容的最新版本号(如果你需要指定版本,可以直接传数字,比如1.0)
            double latestVersion = _journalArticleLocalService.getLatestArticleVersion(groupId, articleId);

            // 生成渲染后的articleDisplay内容
            String articleDisplay = _journalArticleLocalService.getArticleDisplay(
                groupId, articleId, latestVersion, languageId, themeDisplay, null
            );

            // 将内容放到request中,供JSP渲染使用
            renderRequest.setAttribute("articleDisplay", articleDisplay);
        } catch (Exception e) {
            e.printStackTrace();
            // 这里可以添加异常处理逻辑,比如给用户返回错误提示
        }

        super.doView(renderRequest, renderResponse);
    }
}

对应的view.jsp渲染代码

在你的Portlet的view.jsp中,直接输出获取到的articleDisplay即可:

<%@ page contentType="text/html; charset=UTF-8" %>
<div class="journal-content">
    <%= request.getAttribute("articleDisplay") %>
</div>

几个关键注意点

  • 权限检查:确保当前用户有访问目标Web内容的权限,否则getArticleDisplay可能返回空或者抛出权限异常。可以添加权限检查逻辑,比如用PermissionChecker验证用户权限。
  • 参数正确性:groupId必须是Web内容所在的站点ID,articleId要和你创建Web内容时的ID完全匹配,语言ID要对应Web内容已有的本地化版本。
  • ServiceContext参数:getArticleDisplay的最后一个参数是serviceContext,可以传null,方法内部会自动基于当前请求生成合适的serviceContext,和你模板里的上下文保持一致。

内容的提问来源于stack exchange,提问作者Alessandra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:21:04