LIFERAY中ASSET FRAMEWORK的使用

1.liferay中有asset框架,其主要有下列功能:

1.关联标签到自定义的内容类型,当作者指定新标签给内容时,新的标签将会被自动创建。

2.关联类别到自定义的内容类型。作者只能在预定义的词汇中的类别中进行选择。

3.在控制面板中管理标签。

4.在控制面板中管理类别,包括创建完整的层级关系。

5.将评论关联到内容。

6.通过0到5颗星的评级功能来对内容进行评级。

7.分配链接到内容的社交标签,例如google+ 或者twitter。

8.对asset增加自定义属性。

9.将一个asset与另一个asset设置为相关联(即相关文章)。

10.标记不妥的文章。

11.追踪文章的浏览次数

12.将工作流整合到asset

13.通过资源发布器(Asset Publisher)portlet来发布和管理内容。可以不用开发(实际上经常要自己开发,因为客户经常不想用这个portlet)portlet来做展示和管理界面。

2.在自定义的portlet中使用Asset Framework

想使用这个框架,思路上来说是两点:

1.当你增删改你的自定义内容的时候,需要让这个框架知道这个行为的发生。

2.通过liferay的标签来配合你的内容使用标签 分类 评论 评级 等功能。

2.1增删改内容时

我们一般来说要调用AssetLocalServiceUtil的静态方法,或者是由spring注入的AssetEntryLocalService 实例中的方法。一般来说为了保持代码的纯净,我们选择调用AssetLocalServiceUtil的静态方法

2.1.1增加修改内容时的调用

我们需要调用的方法的方法签名如下

AssetEntry updateEntry(
        long userId, long groupId, String className, long classPK,
        String classUuid, long classTypeId, long[] categoryIds,
        String[] tagNames, boolean visible, Date startDate, Date endDate,
        Date publishDate, Date expirationDate, String mimeType,
        String title, String description, String summary, String url,
        String layoutUuid, int height, int width, Integer priority,
        boolean sync)
    throws PortalException, SystemException

下面的代码是liferay源码中blog portlet调用这个方法时的代码

assetEntryLocalService.updateEntry(
        userId, entry.getGroupId(), BlogsEntry.class.getName(),
        entry.getEntryId(), entry.getUuid(), 0, assetCategoryIds,
        assetTagNames, visible, null, null, entry.getDisplayDate(), null,
        ContentTypes.TEXT_HTML, entry.getTitle(), null, summary, null, null,
        0, 0, null, false);

下面是各个参数的快速指导:

userId是用户的唯一标识,可以通过PortalUtil.getUserId(request);来获取

groupId用来界定你的文章的所处的范围维度,如果不支持界限范围。那么直接传0. 获取groupId的代码为 PortalUtil.getScopeGroupId(renderRequest);

className定义了asset的类型,一般来说用java的类名就可以。例如你自己开发的内容类型为MyBlog 那么这里就用 MyBlog.class.getName(); 这个值要注意的一点是应该是唯一的,不要和其他的类型重名

classPK就是MyBlog在MyBlog表里面的主键

assetCategoryIdsassetTagNames 记录着你的内容的分类和标签,asset框架会为你保存这两个值。获取他们的代码如下

ServiceContext serviceContext = ServiceContextFactory.getInstance(
			actionRequest);
long[] assetCategoryIds = serviceContext.getAssetCategoryIds();
String[] assetTagNames = serviceContext.getAssetTagNames();

visible决定内容是否可以被asset publisher portlet所展示

 

title, descriptionsummary是asset publisher portlet展示时所用的标题 描述 和摘要。summary一般设置为和description相同就可以。获取代码如下:

String title = ParamUtil.getString(actionRequest, "title");
String description = ParamUtil.getString(actionRequest, "description");

publishDate expirationDate 是控制用户可见这篇内容的时间范围

2.1.2删除内容时

删除内容时我们需要调用的方法签名如下:

void deleteEntry(String className, long classPK)

在blog portlet中的调用代码如下:

assetEntryLocalService.deleteEntry(
    BlogsEntry.class.getName(), entry.getEntryId());

这两个参数第一个就是你的类的类名,第二个就是你的记录在你自定义的表中的主键。

3输入和展示标签与分类

在JSP中使用liferay提供的liferay-ui标签在你的form表单中 就可以关联已有的标签和分类,并且可以新增标签。代码如下:

<label>Tags</label>
<liferay-ui:asset-tags-selector
    className="<%= entry.getClass().getName() %>"
    classPK="<%= entry.getPrimaryKey() %>"
/>

<label>Categories</label>
    <liferay-ui:asset-categories-selector
        className="<%= entry.getClass().getName() %>"
        classPK="<%= entry.getPrimaryKey() %>"
/>

如果你写页面的时候有使用AUI。那么这段代码可以修改为更简化的

<aui:input name="tags" type="assetTags" />
<aui:input name="categories" type="assetCategories" />

上面的代码是让你能够输入他们,如果你还想能够展示他们 那么应该用下面的代码

<label>Tags</label>
<liferay-ui:asset-tags-summary
    className="<%= entry.getClass().getName() %>"
    classPK="<%= entry.getPrimaryKey() %>"
/>

<label>Categories</label>
<liferay-ui:asset-categories-summary
    className="<%= entry.getClass().getName() %>"
    classPK="<%= entry.getPrimaryKey() %>"
/>

参数依旧是你的类名和你的记录在你的表中的主键

标签和分类还支持点击之后作为条件来查找符合条件的内容。

这需要在标签中设置portletURL属性,和tag或categoryId属性来实现。并且你还需要在你的portlet的action中做实现代码 通过portletURL(actionURL)来确定你的实现代码的方法,然后在方法中获取tag和categoryId的值,并调用AssetEntryService 来查询数据库。

4更多的aseet标签

评论与评论评级

<portlet:actionURL var="discussionURL">
    <portlet:param
       name="struts_action"
       value="/blogs/edit_entry_discussion"
    />
</portlet:actionURL>

<liferay-ui:discussion
    className="<%= BlogsEntry.class.getName() %>"
    classPK="<%= entry.getEntryId() %>"
    formAction="<%= discussionURL %>"
    formName="fm2"
    ratingsEnabled="<%= enableCommentRatings %>"
    redirect="<%= currentURL %>"
    subject="<%= entry.getTitle() %>"
    userId="<%= entry.getUserId() %>"
/>

文章评级

<liferay-ui:ratings
    className="<%= BlogsEntry.class.getName() %>"
    classPK="<%= entry.getEntryId() %>"
/>

社交标签

<liferay-ui:social-bookmarks
    displayStyle="<%= socialBookmarksDisplayStyle %>"
    target="_blank"
    title="<%= entry.getTitle() %>"
    url="<%= PortalUtil.getCanonicalURL(bookmarkURL.toString(),
        themeDisplay) %>"
/>

关联内容(相关文章)

<liferay-ui:input-asset-links
    className="<%= BlogsEntry.class.getName() %>"
    classPK="<%= entryId %>"
/>

标记为欠妥文章

<liferay-ui:flags
    className="<%= BlogsEntry.class.getName() %>"
    classPK="<%= entry.getEntryId() %>"
    contentTitle="<%= entry.getTitle() %>"
    reportedUserId="<%= entry.getUserId() %>"
/>

5通过资源发布器(asset publisher)来发布内容

资源发布器可以动态的获取你的内容的列表 或者手动指定你的内容。来确定展示内容,并且你可以通过资源发布器来增加和编辑内容。

AssetRendererFactory

这个类可以通过你的类名和主键(classPK)来从数据库中获取数据。

你的factory实现类会从asset中抓取记录。并可以通过设置一个可以链接到你自己的portlet中实现的编辑页面的URL来实现进入编辑画面。这里最好通过继承BaseAssetRendererFactory 来自定义一个实现类。这样更为灵活,也在liferay的升级时更轻松。

AssetRenderer

这个接口提供到特定asset的一些元数据信息。它可以对用户的修改或查看这篇内容的权限进行校验,并且能通过跳转到不同的页面来实现通过不同的模板来渲染展示内容。

下面是  Blog Portlet中的AssetRendererFactory的代码

public class BlogsEntryAssetRendererFactory extends BaseAssetRendererFactory {

    public static final String CLASS_NAME = BlogsEntry.class.getName();

    public static final String TYPE = "blog";

    public AssetRenderer getAssetRenderer(long classPK, int type)
        throws PortalException, SystemException {

        BlogsEntry entry = BlogsEntryLocalServiceUtil.getEntry(classPK);

        return new BlogsEntryAssetRenderer(entry);
    }

    @Override
    public AssetRenderer getAssetRenderer(long groupId, String urlTitle)
        throws PortalException, SystemException {

        BlogsEntry entry = BlogsEntryServiceUtil.getEntry(groupId, urlTitle);

        return new BlogsEntryAssetRenderer(entry);
    }

    public String getClassName() {
        return CLASS_NAME;
    }

    public String getType() {
        return TYPE;
    }

    @Override
    public PortletURL getURLAdd(
            LiferayPortletRequest liferayPortletRequest,
            LiferayPortletResponse liferayPortletResponse)
        throws PortalException, SystemException {

        HttpServletRequest request =
            liferayPortletRequest.getHttpServletRequest();

        ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
            WebKeys.THEME_DISPLAY);

        if (!BlogsPermission.contains(
            themeDisplay.getPermissionChecker(),
            themeDisplay.getScopeGroupId(), ActionKeys.ADD_ENTRY)) {

            return null;
        }

    PortletURL portletURL = PortletURLFactoryUtil.create(
        request, PortletKeys.BLOGS, getControlPanelPlid(themeDisplay),
        PortletRequest.RENDER_PHASE);

        portletURL.setParameter("struts_action", "/blogs/edit_entry");

        return portletURL;
    }

    @Override
    public boolean hasPermission(
            PermissionChecker permissionChecker, long classPK, String actionId)
        throws Exception {

        return BlogsEntryPermission.contains(
            permissionChecker, classPK, actionId);
    }

    @Override
    public boolean isLinkable() {
        return _LINKABLE;
    }

    @Override
    protected String getIconPath(ThemeDisplay themeDisplay) {
        return themeDisplay.getPathThemeImages() + "/blogs/blogs.png";
    }

    private static final boolean _LINKABLE = true;
}

下面是AssetRenderer 的实现

public class BlogsEntryAssetRenderer extends BaseAssetRenderer {

    public BlogsEntryAssetRenderer(BlogsEntry entry) {
        _entry = entry;
    }

    public long getClassPK() {
        return _entry.getEntryId();
    }

    @Override
    public String getDiscussionPath() {
        if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
            return "edit_entry_discussion";
        }
        else {
            return null;
        }
    }

    public long getGroupId() {
        return _entry.getGroupId();
    }

    public String getSummary(Locale locale) {
        return HtmlUtil.stripHtml(_entry.getDescription());
    }

    public String getTitle(Locale locale) {
        return _entry.getTitle();
    }

    @Override
    public PortletURL getURLEdit(
            LiferayPortletRequest liferayPortletRequest,
            LiferayPortletResponse liferayPortletResponse)
        throws Exception {

        PortletURL portletURL = liferayPortletResponse.createLiferayPortletURL(
            getControlPanelPlid(liferayPortletRequest), PortletKeys.BLOGS,
            PortletRequest.RENDER_PHASE);

        portletURL.setParameter("struts_action", "/blogs/edit_entry");
        portletURL.setParameter("entryId", String.valueOf(_entry.getEntryId()));

        return portletURL;
    }

    @Override
    public String getUrlTitle() {
        return _entry.getUrlTitle();
    }

    @Override
    public PortletURL getURLView(
            LiferayPortletResponse liferayPortletResponse,
            WindowState windowState)
        throws Exception {

        PortletURL portletURL = liferayPortletResponse.createLiferayPortletURL(
            PortletKeys.BLOGS, PortletRequest.RENDER_PHASE);

        portletURL.setWindowState(windowState);

        portletURL.setParameter("struts_action", "/blogs/view_entry");
        portletURL.setParameter("entryId", String.valueOf(_entry.getEntryId()));

        return portletURL;
    }

    @Override
    public String getURLViewInContext(
        LiferayPortletRequest liferayPortletRequest,
        LiferayPortletResponse liferayPortletResponse,
        String noSuchEntryRedirect) {

        ThemeDisplay themeDisplay =
            (ThemeDisplay)liferayPortletRequest.getAttribute(
                WebKeys.THEME_DISPLAY);

        return themeDisplay.getPortalURL() + themeDisplay.getPathMain() +
            "/blogs/find_entry?noSuchEntryRedirect=" +
                HttpUtil.encodeURL(noSuchEntryRedirect) + "&entryId=" +
                    _entry.getEntryId();
    }

    public long getUserId() {
        return _entry.getUserId();
    }

    public String getUuid() {
        return _entry.getUuid();
    }

    @Override
    public boolean hasEditPermission(PermissionChecker permissionChecker) {
        return BlogsEntryPermission.contains(
            permissionChecker, _entry, ActionKeys.UPDATE);
    }

    @Override
    public boolean hasViewPermission(PermissionChecker permissionChecker) {
        return BlogsEntryPermission.contains(
            permissionChecker, _entry, ActionKeys.VIEW);
    }

    @Override
    public boolean isPrintable() {
        return true;
    }

    public String render(
            RenderRequest renderRequest, RenderResponse renderResponse,
            String template)
        throws Exception {

        if (template.equals(TEMPLATE_ABSTRACT) ||
            template.equals(TEMPLATE_FULL_CONTENT)) {

            renderRequest.setAttribute(WebKeys.BLOGS_ENTRY, _entry);

            return "/html/portlet/blogs/asset/" + template + ".jsp";
        }
        else {
            return null;
        }
    }

    @Override
    protected String getIconPath(ThemeDisplay themeDisplay) {
        return themeDisplay.getPathThemeImages() + "/blogs/blogs.png";
    }

    private BlogsEntry _entry;

}

在展示内容时分为摘要型展示模板和全文展示模板。摘要型展示模板是非必需的,liferay自己也有简单的实现,全文展示的Blog Portlet的实现代码如下

<%@ include file="/html/portlet/blogs/init.jsp" %>

<%
BlogsEntry entry = (BlogsEntry)request.getAttribute(WebKeys.BLOGS_ENTRY);
%>

<%= entry.getContent() %>

<liferay-ui:custom-attributes-available
    className="<%= BlogsEntry.class.getName() %>"
>

    <liferay-ui:custom-attribute-list
        className="<%= BlogsEntry.class.getName() %>"
        classPK="<%= (entry != null) ? entry.getEntryId() : 0 %>"
        editable="<%= false %>"
        label="<%= true %>"
    />

</liferay-ui:custom-attributes-available>

以上内容是我看的liferay的官网的开发者文档之后 翻译和修改总结的。难免有词不达意的地方,就当是给英语不好的朋友的一个小福利了。如果觉得有不正确的地方,欢迎指正。您也看以看英文的文档。官网上关于这部分的讲解的URL为 https://www.liferay.com/zh/documentation/liferay-portal/6.2/development/-/ai/asset-framework-liferay-portal-6-2-dev-guide-06-en