環境Liferay6.2.1 + tomcat-7.0.42 + JAVA 7
使用postgreSQL 9版
本例以新聞發布為例。
先在 liferay-plugin-package.properties
加入 jdom.jar , dom4j.jar , rome.jar 這三個jar檔主要是用來產生RSS Feed。
連XML template都不用自己建。
如果沒有載入,<liferay-ui:rss> 與 <liferay-ui:rss-settings> 這兩個Tag會產生null的Exception。
portal-dependency-jars=\
jstl-api.jar,\
jstl-impl.jar,\
jdom.jar,\
dom4j.jar,\
rome.jar
這是這次所使用的model
<service-builder package-path="com.xxx.portlet">
<author>Danny</author>
<namespace>news</namespace>
<entity name="News" human-name="news" local-service="true"
remote-service="false" uuid="true">
<column name="newsId" type="long" primary="true" />
<column name="groupId" type="long" />
<column name="companyId" type="long" />
<column name="userId" type="long" />
<column name="userName" type="String" />
<column name="modifiedDate" type="Date" />
<column name="createDate" type="Date" />
<column name="title" type="String" />
<column name="content" type="String" />
<column name="viewCount" type="long" />
<column name="priority" type="boolean" />
<column name="category" type="String" />
<column name="copyToMainSite" type="boolean" />
<column name="urlTitle" type="String" />
<column name="resourcePrimKey" type="long"/>
<column name="status" type="int"/>
<column name="statusByUserId" type="long"/>
<column name="statusByUserName" type="String"/>
<column name="statusDate" type="Date"/>
<order by="desc">
<order-column name="createDate" />
</order>
<finder name="CD_T" return-type="Collection">
<finder-column name="createDate" comparator=">"/>
<finder-column name="title" comparator="LIKE"/>
</finder>
<finder name="CD_C" return-type="Collection">
<finder-column name="createDate" comparator=">"/>
<finder-column name="content" comparator="LIKE"/>
</finder>
<finder name="R_S" return-type="Collection">
<finder-column name="resourcePrimKey"/>
<finder-column name="status"/>
</finder>
<finder name="GroupId" return-type="Collection">
<finder-column name="groupId" />
</finder>
<finder name="CompanyId" return-type="Collection">
<finder-column name="companyId" />
</finder>
<finder name="G_UT" return-type="News" unique="true">
<finder-column name="groupId" />
<finder-column name="urlTitle" />
</finder>
<finder name="G_NotS" return-type="Collection">
<finder-column name="groupId" />
<finder-column name="status" comparator="!=" />
</finder>
<finder name="G_S" return-type="Collection">
<finder-column name="groupId" />
<finder-column name="status" />
</finder>
<reference package-path="com.liferay.portal" entity="Group" />
<reference package-path="com.liferay.portal" entity="WorkflowInstanceLink"/>
<reference package-path="com.liferay.portlet.asset" entity="AssetEntry" />
<reference package-path="com.liferay.portlet.asset" entity="AssetLink" />
<reference package-path="com.liferay.portlet.asset" entity="AssetTag" />
</entity>
</service-builder>
在init.jsp 上加入以下這幾四個參數,這是使用<liferay-ui:rss>所需要使用到的參數。
boolean enableRSS = !PortalUtil.isRSSFeedsEnabled() ? false : GetterUtil.getBoolean(portletPreferences.getValue("enableRss", null), true);
int rssDelta = GetterUtil.getInteger(portletPreferences.getValue("rssDelta", StringPool.BLANK), SearchContainer.DEFAULT_DELTA);
String rssDisplayStyle = portletPreferences.getValue("rssDisplayStyle", RSSUtil.DISPLAY_STYLE_DEFAULT);
String rssFeedType = portletPreferences.getValue("rssFeedType", RSSUtil.FEED_TYPE_DEFAULT);
latestnews_view.jsp 就可以使用 rss的Tag了。
<liferay-portlet:resourceURL varImpl="rssURL" >
</liferay-portlet:resourceURL>
<liferay-ui:rss
delta="<%= rssDelta %>"
displayStyle="<%= rssDisplayStyle %>"
feedType="<%= rssFeedType %>"
resourceURL="<%= rssURL %>" />
如以下,就會產生RSS的超連結出來。
當點下之後,會去呼叫 resourceURL。
就會導到Control的 public void serveResource(ResourceRequest request, ResourceResponse response)
方法。
在這裡取得RSS Feed的做法也就是在這裡開始產生。
如果是Struts的作法,就要去繼承 Struts.RSSAction.java 然後在裡面實作。
在這裡我們是採用MVCPortlet.java
public class NewsPortlet extends MVCPortlet{
@Override
public void serveResource(ResourceRequest request, ResourceResponse response)
throws PortletException, IOException {
response.setContentType(ContentTypes.TEXT_XML_UTF8);
ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
WebKeys.THEME_DISPLAY);
Layout layout = themeDisplay.getLayout();
long plid = themeDisplay.getPlid();
long groupId = themeDisplay.getScopeGroupId();
int max = ParamUtil.getInteger(request, "max", SearchContainer.DEFAULT_DELTA);
String type = ParamUtil.getString(request, "type", RSSUtil.FORMAT_DEFAULT);
double version = ParamUtil.getDouble(request, "version", RSSUtil.VERSION_DEFAULT);
String displayStyle = ParamUtil.getString(request, "displayStyle", RSSUtil.DISPLAY_STYLE_DEFAULT);
String feedURL = themeDisplay.getPortalURL() + themeDisplay.getPathMain() +
"/news/find_entry?";
_log.info("themeDisplay.getPortalURL():" + themeDisplay.getPortalURL() + "==");
_log.info("themeDisplay.getPathMain():" + themeDisplay.getPathMain() + "==");
String entryURL = feedURL;
String rss = StringPool.BLANK;
try {
if (layout != null) {
groupId = themeDisplay.getScopeGroupId();
feedURL = PortalUtil.getLayoutFullURL(themeDisplay) +
Portal.FRIENDLY_URL_SEPARATOR + "news/rss";
_log.info("feedURL:" + feedURL + "==");
entryURL = feedURL;
rss = NewsLocalServiceUtil.getGroupNewsesRSS(
groupId, max, type, version, displayStyle,
feedURL, entryURL, themeDisplay);
}
} catch (SystemException e) {
e.printStackTrace();
} catch (PortalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// return rss.getBytes(StringPool.UTF8);
PrintWriter writer = response.getWriter();
writer.print(rss);
}
}
這當中有去呼叫到 NewsLocalServiceUtil.getGroupNewsesRSS();
這是自己定義的method。
所以在NewsLocalServiceImpl.java內要實作這個method
public String getGroupNewsesRSS(
long groupId, int max, String type,
double version, String displayStyle, String feedURL,
String entryURL, ThemeDisplay themeDisplay)
throws PortalException, SystemException {
Group group = groupPersistence.findByPrimaryKey(groupId);
String name = group.getDescriptiveName();
List<News> newses = getGroupNewses(groupId, 0, max);
return exportToRSS(
name, name, type, version, displayStyle, feedURL, entryURL,
newses, themeDisplay);
}
protected String exportToRSS(
String name, String description, String type, double version,
String displayStyle, String feedURL, String entryURL,
List<News> newses, ThemeDisplay themeDisplay)
throws SystemException {
SyndFeed syndFeed = new SyndFeedImpl();
syndFeed.setDescription(description);
List<SyndEntry> syndEntries = new ArrayList<SyndEntry>();
syndFeed.setEntries(syndEntries);
for (News news : newses) {
SyndEntry syndEntry = new SyndEntryImpl();
String author = PortalUtil.getUserName(news);
syndEntry.setAuthor(author);
SyndContent syndContent = new SyndContentImpl();
syndContent.setType(RSSUtil.ENTRY_TYPE_DEFAULT);
String value = null;
if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
String summary = news.getTitle();
if (Validator.isNull(summary)) {
summary = StringUtil.shorten(
HtmlUtil.extractText(news.getContent()),
200, StringPool.BLANK);
}
value = StringUtil.shorten(
HtmlUtil.extractText(summary),
200, StringPool.BLANK);
}
else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
value = StringPool.BLANK;
}
else {
value = StringUtil.replace(
news.getContent(),
new String[] {
"href=\"/", "src=\"/"
},
new String[] {
"href=\"" + themeDisplay.getURLPortal() + "/",
"src=\"" + themeDisplay.getURLPortal() + "/"
});
}
syndContent.setValue(value);
syndEntry.setDescription(syndContent);
StringBundler sb = new StringBundler(4);
if (entryURL.endsWith("/news/rss")) {
sb.append(entryURL.substring(0, entryURL.length() -11 ));
sb.append(StringPool.QUESTION);
sb.append("p_p_id=");
sb.append(PortletKeys.LATESTNEWS_PORTLET);
sb.append(StringPool.AMPERSAND); //&
sb.append("p_p_lifecycle=0&p_p_state=normal&p_p_mode=view&p_p_col_id=column-1&p_p_col_count=1&");
sb.append(PortletKeys.NEWS_NAMESPACE + "jspPage=");
sb.append("%2Fhtml%2Fnews%2Flatestnews_view.jsp");
sb.append(StringPool.AMPERSAND); //&
sb.append(PortletKeys.NEWS_NAMESPACE + "newsId=");
sb.append(news.getNewsId());
_log.info("if=>sb:" + sb + "==");
}
else {
sb.append(entryURL);
_log.info("else=>sb:" + sb + "==");
if (!entryURL.endsWith(StringPool.QUESTION)) {
sb.append(StringPool.AMPERSAND);
}
}
String link = sb.toString();
syndEntry.setLink(link);
syndEntry.setPublishedDate(news.getCreateDate());
syndEntry.setTitle(news.getTitle());
syndEntry.setUpdatedDate(news.getModifiedDate());
syndEntry.setUri(link);
syndEntries.add(syndEntry);
}
syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
List<SyndLink> syndLinks = new ArrayList<SyndLink>();
syndFeed.setLinks(syndLinks);
SyndLink selfSyndLink = new SyndLinkImpl();
syndLinks.add(selfSyndLink);
selfSyndLink.setHref(feedURL);
selfSyndLink.setRel("self");
if (feedURL.endsWith("/-/news/rss")) {
SyndLink alternateSyndLink = new SyndLinkImpl();
syndLinks.add(alternateSyndLink);
alternateSyndLink.setHref(
feedURL.substring(0, feedURL.length() - 11));
alternateSyndLink.setRel("alternate");
}
syndFeed.setPublishedDate(new Date());
syndFeed.setTitle(name);
syndFeed.setUri(feedURL);
try {
return RSSUtil.export(syndFeed);
}
catch (FeedException fe) {
throw new SystemException(fe);
}
}
當中的entryURL 和 FeedURL 是比較難搞的,
FeedURL = 消息來源網址。
entryURL = 消息來源之內部每單一筆的導向網址,點擊RSS其中一筆後,會開啟該篇新聞的來源網址。
上面每一筆的entryURL 都是仿照PortletURL在網址上的參數,
有用到portletKeys,我是這樣寫,
public static final String LATESTNEWS_PORTLET = "News_WAR_Newsportlet";
public static final String NEWS_NAMESPACE = "_News_WAR_Newsportlet_";
portletId 與 namespace的差別 在於 左右兩側的底線。
另外這是設定RSS的型態,可以寫在Portlet-Configuration上。
<%@include file="/html/init.jsp"%>
<liferay-portlet:actionURL portletConfiguration="true"
var="configurationURL" />
<aui:form action="<%=configurationURL%>" method="post">
<aui:input name="<%=Constants.CMD%>" type="hidden"
value="<%=Constants.UPDATE%>" />
<aui:fieldset>
<liferay-ui:rss-settings
delta="<%= rssDelta %>"
displayStyle="<%= rssDisplayStyle %>"
enabled="<%= enableRSS %>"
feedType="<%= rssFeedType %>"/>
<aui:button type="submit" />
</aui:fieldset>
</aui:form>
沒有留言:
張貼留言