Liferay Portal额外研究-银狐999
Liferay Portal額外研究(一):初步在新Tomcat下部署
開發(fā)者在線 Builder.com.cn 更新時間:2008-03-19作者:銀狐999 來源:CSDN
本文關鍵詞: 部署 tomcat JAVA
Liferay額外研究(一):初步在新Tomcat下部署 從現(xiàn)在開始,會把我最近在研究的開源Portal Liferay一些心得貼出來。研究Liferay版本:Liferay Professional 4.0.0 柯自聰兄弟寫過一系列的Liferay Portal開發(fā)文章,參考http://www.blogjava.net/eamoi/。所以基礎性內容,本文不再細說,可參考柯自聰?shù)奈恼禄?/span>Blog。 (一)部署Liferay Portlet ?????? Liferay簡單部署一個portlet并不是很復雜,通過WEB-INF目錄下的portlet.xml、liferay-portlet.xml、liferay-display.xml描述即可。| 描述 | |
| portlet.xml | portlet.xml用來定義Portlet的諸如部署名稱、初始化參數(shù)、支持模式、resource bundle等普通的初始化信息,包括:portlet-name、display-name、portlet-class、init-param、expiration-cathe、supports、portlet-info、security-role-ref等等。其正式的規(guī)范請參考:http://java.sun.com/xml/ns/Portlet/Portlet-app_1_0.xsd |
| liferay-portlet.xml | 定義Portlet默認可用的用戶組、默認模板、是否支持多個實例等,規(guī)范由http://www.liferay.com/dtd/liferay-Portlet-app_3_5_0.dtd |
| liferay-display.xml | 定義Portlet默認的所屬類別。Liferay Portal對Portlet實行按類別管理和劃分用戶權限。 |
| <Context docBase="D:Tomcat5028 liferay" path="" reloadable="true"> <Resource name="jdbc/LiferayPool" auth="Container" ???????? ????? type="javax.sql.DataSource"??? /> <ResourceParams name="jdbc/LiferayPool"> ??? ???????<parameter> <name>factory</name> ????? ?????????<value>org.apache.commons.dbcp.BasicDataSourceFactory</value> </parameter> XXX(其他配置,此處略) ?????</ResourceParams> </Context> 有關Liferay對連接池的引用,可以去Portal.properties配置文件中修改。默認此配置文件已經(jīng)被打在了liferay的portal-ejb.jar中。 |
| //注意,暫時必須把liferay應用配置成為默認根應用,否則不可以正確運行。 <Context docBase="D:Tomcat5028 liferay" path="" reloadable="true"> <Realm className="org.apache.catalina.realm.JAASRealm" ???????? ?appName="PortalRealm" ???? ????? userClassNames="com.liferay.portal.security.jaas.PortalPrincipal" ???????? ?roleClassNames="com.liferay.portal.security.jaas.PortalRole" ???????? ?debug="99" ???????? ?useContextClassLoader="false" />????? </Context> |
| PortalRealm { ???? com.liferay.portal.shared.security.jaas.PortalLoginModule required; }; |
Liferay Portal額外研究(二):對Liferay進行瘦身
Spring配置管理XML應用服務器Struts Liferay的體系是很龐雜的,居然有些文章對外宣稱Liferay是微內核,我想寫這文章的哥們沒有搞清楚什么是“微內核”。 ? ?????? Liferay 受其企業(yè)版本影響不小,畢竟Liferay公司主要還是“企業(yè)行為”,而不是一個單純的一個“開源團體”行為。所以Liferay Portal本身內嵌了大量的Portlet,而且這些Portlet和Liferay Portal Framework甚至還有些交融。這就是為什么liferay portal-ejb.jar會有3M多。 ? ?????? 雖然我們可以通過修改system.properties,portlet.properties,protal-spring這些基礎配置文件來修改聲明哪些服務不需要加載,也可以通過修改 WEB-INF目錄下的portlet.xml,liferay-portlet.xml以及l(fā)iferay-display.xml這些文件來刪除一些不需要的portlet。 ? ?????? 但是,我想真正敢真么干的,估計很少。這是為什么呢,就是應為Liferay內部實現(xiàn)的結構和代碼,并不是非常良好。而對于這一塊的優(yōu)化,也沒有很詳細的幫助使用手冊。在Liferay的網(wǎng)站上,只有一些教開發(fā)人員如何部署在不同服務器和數(shù)據(jù)庫,如何新增一些portlet和theme,以及如何修改權限方面的淺顯參考手冊。 ? ?????? 接下來就講一講對Liferay的瘦身操作,讓Liferay變成一個只提供最基本的Portal框架和部署機制的portal context,而去掉那些多余的portlet?!?因為這些多余的portlet大多國內的項目沒有任何利用價值,但是如果需要部署的話,則會大大影響系統(tǒng)響應性能,而且讓開發(fā)也變得比較麻煩。 ? ?????? 當然,是否按照我今天說的方式對Liferay進行瘦身,這全憑習慣。有些朋友不愿改變Liferay的結構,只希望單純通過配置來加載,也是可以的。 ? (1)保留Liferay最基本的一些組件 ?????? ?????? Liferay提供了一些基本組件,這些組件不屬于Portal框架之內,但是整個portal服務是基于這些組件。| 包結構 | 說明 |
| com.liferay.counter | 主要提供主建操作服務,Liferay內部的提供的組織結構表維護,就是采用counter提供的主建自增機制 |
| com.liferay.filters | 提供一些基礎的基于servlet filter的過濾器 |
| com.liferay.taglib | 提供最基本的web展示標簽 |
| com.liferay.util | 提供最基本的一些公共組件 |
| 包結構 | 說明 |
| com.liferay.portal | 此包下放置了portal服務相關的一些異常 |
| com.liferay.portal.action | 負責一些struts action處理,比如Login等 |
| com.liferay.portal.definitions | 此包不是類包,而是負責放置一些定義相關的dtd文件資源。具體需要哪些dtd,可以參考com.liferay.portal.util. EntityResolver類 |
| com.liferay.portal.dependencies | 此包也不是類包,而是負責一些依賴性的資源文件。 |
| com.liferay.portal.deploy | 負責自動部署和熱部署 |
| com.liferay.portal.events | 這個包內主要是一些行為處理類 |
| com.liferay.portal.im | 即時消息的支持 |
| com.liferay.portal.jcr | 提供JSR-170 JCR的支持,并內部提供Jackrabbit的實現(xiàn)支持 |
| com.liferay.portal.job | 對一些時間調度性Job的支持 |
| com.liferay.portal.language | 對語言的支持包 |
| com.liferay.portal.lucene | 對全文檢索的支持 |
| com.liferay.portal.model | 一些模型對象的集合 |
| com.liferay.portal.security | ? |
| com.liferay.portal.servlet | ? |
| com.liferay.portal.spring | ? |
| com.liferay.portal.struts | ? |
| com.liferay.portal.theme | 提供對“主題”,也就是界面風格的支持 |
| com.liferay.portal.tools | ? |
| com.liferay.portal.util | ? |
| com.liferay.portal.velocity | ? |
| com.liferay.portal.wsrp | ? |
| 包結構 | 說明 |
| com.liferay.portlet | Liferay Portlet的一些基礎類 |
| com.liferay.portlet.admin | 管理portlet |
| com.liferay.portlet.calendar | 日期portlet雖然可以不需要,但是其內部提供對job的調度。 |
| com.liferay.portlet.communities | 這個是負責配置用戶其所在的group,利用可以配置用戶所擁有的工作區(qū)。 |
| com.liferay.portlet.enterpriseadmin | ? |
| com.liferay.portlet.language | ? |
| com.liferay.portlet.layoutconfiguration | ? |
| com.liferay.portlet.login | ? |
| com.liferay.portlet.myaccount | 用于配置用戶信息 |
| com.liferay.portlet.myplaces | 用于控制用戶的工作區(qū)選擇 |
| com.liferay.portlet.portletconfiguration | ? |
| com.liferay.portlet.themegallery | 用于控制主題風格 |
| com.liferay.portlet.translator | 這個包必須要,雖然portlet可以不用,但是被portal.language包引入了 |
| com.liferay.portlet.wsrp | 這個包必須要。 |
| 位置 | 配置文件說明 |
| /WEB-INF | portlet描述和struts等配置文件 |
| /WEB-INF/classes | system.properties和portal.properties配置文件 |
| /WEB-INF/classes/META-INF | portal-spring.xml,portal-hbm.xml,portal-log4j.xml配置文件。此位置可調,具體可以修改portal.properties內容。 |
Liferay Portal額外研究(三):IFrame Portlet地session丟失疑難處理
分類: Liferay Portal 2011-08-19 10:59 39人閱讀 評論(0) 收藏 舉報Liferay提供了一種非常的簡單web應用整合和單點登陸的方式:Iframe Portlet。利用Iframe Portlet可以很容易將一個已經(jīng)存在的web應用納入,并且支持利用form的post或get方式,實現(xiàn)用戶的登陸。 對于Liferay這樣的機制沒有任何問題,實現(xiàn)的也非常巧妙;但是對于很多web應用系統(tǒng)來說,使用Liferay IFrame Portlet的form方式實現(xiàn)登陸后,雖然可以成功登陸,但是在顯示的新頁面中,卻發(fā)現(xiàn)用戶信息丟失,或者更準確的說,是session丟失。 其實,這種現(xiàn)象跟Liferay關系不大,而是應用本身決定的。事實上,所有的portal context的iframe 方式,都有可能發(fā)生這個情況。 因為很多web應用系統(tǒng),在執(zhí)行Login操作的后,習慣性的選擇redirect操作,這樣會強制瀏覽器中的顯示地址變更為轉移的地址。事實上這是個很正確的做法,在正常境況下,不會有任何問題,而且還可以很好的防止頁面刷新等所帶來的問題。 但是在Liferay的IFrame Portlet中,web應用這樣的Redirect操作,造成了調轉到新頁面后,session變成了一個新的,從而造成放置在原有session中的login user信息丟失。 跟蹤并做了如下的一組測試(Liferay和webapp在不同的JVM環(huán)境下):
| 應用 | 位置 | session id |
| (Liferay) | 執(zhí)行form post前 | D03E1B828395EF5BCB1063A8290BD254 |
| (APP_A) | Login操作 | 397BB3656E2A12A96CE3F16E0A89C607 |
| (APP_A) | 登陸后的新頁面 | 58A1054C6EDE4A7D6CFA2FCDBB3E0736 |
| ServletContext sc = getServletContext(); RequestDispatcher rd = null; rd = sc.getRequestDispatcher("/index.jsp"); rd.forward(request, response); |
| response.sendRedirect(“ index.jsp;jsessionid=397BB3656E2A12A96CE3F16E0A89C607”) |
Liferay Portal額外研究(4):修改用戶登錄后的默認布局和內容
開發(fā)者在線 Builder.com.cn 更新時間:2008-03-19作者:銀狐999 來源:CSDN
本文關鍵詞: 用戶登錄 JAVA
Liferay在用戶第一次登陸后,都會為其產(chǎn)生一個默認的私有首頁Layout。?在Liferay早期版本,可以在系統(tǒng)管理員管理界面中,配置默認的group layout。但是在4.1版本中已經(jīng)沒有這個功能,所以默認情況下,新注冊的用戶,在登陸后,首先看到的其私有place都是一樣的內容,而這些內容都是liferay提供的。 對我們自定的Company來說,這肯定是不合適的,我們需要自己定義用戶登錄后,默認顯示的內容和布局。 ??? 后來在Liferay forum中,找到了一篇帖子,給了解決此種問題的解決辦法:在portlet-ext.properties中配置一個 default.user.layout.group 屬性(自定義的),用于指明默認的layout-group。在ServicePreAction類的擴展修改 addDefaultLayouts 操作,滿足特定的需求應用。這種擴展的方式就是,將指定layout-group拷貝給用戶第一默認的,這樣就不會再使用liferay默認的了?!?當然這樣的方式是比較簡單的,可能在系統(tǒng)實施過程中,有比這更加復雜的需求。? 新建默認的Community 首先,通過新增一個新的Community,命名為User_Default,并新增一個private的page與內容. 配置默認的Community 首先在ext項目的 ext-ejb目錄下,修改portal-ext.properties文件,增加如下設置:
| default.user.layout.group=User_Default |
????
????private?static?Log?_log?=?LogFactory.getLog(LayoutCopy.class);
????
????private?User?user;
????private?String?ownerId;
???private?Group?userGroup;
???public?LayoutCopy(User?user)?...{
???????super();
???????this.user?=?user;
????????this.ownerId?=?getOwnerId(user.getGroup().getGroupId(),?false);
???????this.userGroup?=?user.getGroup();
???}
???public?void?copyDefaultUserLayout(HttpServletRequest?httpReq)
???????????throws?SystemException,?PortalException?...{
??????//?set?in?the?portal-ext.properties:
???????//?default.user.layout.group=Default?User
???????//?and?create?then?group/community?"Default?User"?
???????//?CWPPropsUtil.DEFUALT_USER_LAYOUT_GROUP?=?"default.user.layout.group"
???????Group?group?=?GroupLocalServiceUtil.getGroup(user.getCompanyId(),
???????????????PropsUtil.get("default.user.layout.group"));
???????try?...{
???????????String?groupOwnerId?=?getOwnerId(group.getGroupId(),?true);
???????????List?privateLayouts?=?LayoutLocalServiceUtil
???????????????????.getLayouts(groupOwnerId);
???????????for?(Iterator?itr?=?privateLayouts.iterator();?itr.hasNext();)?...{
???????????????Layout?layout?=?(Layout)?itr.next();
???????????????Layout?newLayout?=?copyLayout(layout);
???????????????copyPreferences(httpReq,?newLayout,?layout);
???????????}
???????}?catch?(PortalException?e)?...{
???????????_log.error("Cannot?copy?private?layouts",?e);
???????}?catch?(Exception?e)?...{
???????????_log.error("Cannot?copy?public?layouts",?e);
???????}
???????try?...{
???????????String?groupOwnerId?=?getOwnerId(group.getGroupId(),?false);
???????????List?publicLayouts?=?LayoutLocalServiceUtil
???????????????????.getLayouts(groupOwnerId);
???????????for?(Iterator?itr?=?publicLayouts.iterator();?itr.hasNext();)?...{
???????????????Layout?layout?=?(Layout)?itr.next();
???????????????Layout?newLayout?=?copyLayout(layout);
???????????????copyPreferences(httpReq,?newLayout,?layout);
???????????}
???????}?catch?(PortalException?e)?...{
???????????_log.error("Cannot?copy?public?layouts",?e);
???????}?catch?(Exception?e)?...{
???????????_log.error("Cannot?copy?public?layouts",?e);
???????}
???}
???public?void?resetLayout(HttpServletRequest?httpReq)?throws?SystemException,?PortalException?...{
???????String?ownerId?=?getOwnerId(user.getGroup().getGroupId(),?false);
???????LayoutLocalServiceUtil.deleteLayouts(ownerId);
???????PortletPreferencesLocalServiceUtil.deletePortletPreferences(ownerId);
???????ownerId?=?getOwnerId(user.getGroup().getGroupId(),?true);
???????LayoutLocalServiceUtil.deleteLayouts(ownerId);
???????PortletPreferencesLocalServiceUtil.deletePortletPreferences(ownerId);
???????copyDefaultUserLayout(httpReq);
???}
???public?Layout?copyLayout(Layout?groupDefaultLayout)?throws?SystemException,
???????????PortalException?...{
???????Layout?layout?=?LayoutLocalServiceUtil.addLayout(
???????????????userGroup.getGroupId(),?user.getUserId(),?groupDefaultLayout
??????????????????????.isPrivateLayout(),?groupDefaultLayout
???????????????????????.getParentLayoutId(),?groupDefaultLayout.getName(user
???????????????????????.getLocale()),?groupDefaultLayout.getType(),
???????????????groupDefaultLayout.isHidden(),?null);
???????LayoutLocalServiceUtil.updateLayout(layout.getLayoutId(),?layout
????????.getOwnerId(),?groupDefaultLayout.getTypeSettings());
???????layout?=?LayoutLocalServiceUtil.updateLookAndFeel(layout.getLayoutId(),
???????????????layout.getOwnerId(),?groupDefaultLayout.getThemeId(),
???????????????groupDefaultLayout.getColorSchemeId());
???????//?layoutMapping.put(groupDefaultLayout.getPrimaryKey(),
???????//?layout.getPrimaryKey());
???????return?layout;
???}
???protected?void?copyPreferences(HttpServletRequest?httpReq,?Layout?layout,
???????????Layout?copyLayout)?throws?Exception?...{
???????String?companyId?=?layout.getCompanyId();
???????LayoutTypePortlet?copyLayoutTypePortlet?=?(LayoutTypePortlet)?copyLayout
???????????????.getLayoutType();
???????List?copyPortletIds?=?copyLayoutTypePortlet.getPortletIds();
???????for?(int?i?=?0;?i?<?copyPortletIds.size();?i++)?...{
???????????String?copyPortletId?=?(String)?copyPortletIds.get(i);
???????????//?Copy?preference
???????????PortletPreferencesPK?prefsPK?=?PortletPreferencesFactory
???????????????????.getPortletPreferencesPK(httpReq,?copyPortletId,?layout
???????????????????????????.getPlid());
???????????PortletPreferencesLocalServiceUtil.getPreferences(companyId,
???????????????????prefsPK);
???????????PortletPreferencesPK?copyPrefsPK?=?PortletPreferencesFactory
???????????????????.getPortletPreferencesPK(httpReq,?copyPortletId,?copyLayout
???????????????????????????.getPlid());
???????????PortletPreferencesImpl?copyPrefsImpl?=?(PortletPreferencesImpl)?PortletPreferencesLocalServiceUtil
???????????????????.getPreferences(companyId,?copyPrefsPK);
???????????PortletPreferencesLocalServiceUtil.updatePreferences(prefsPK,
???????????????????copyPrefsImpl);
???????????//?Copy?portlet?setup
???????????prefsPK?=?new?PortletPreferencesPK(copyPortletId,?layout
???????????????????.getLayoutId(),?layout.getOwnerId());
???????????PortletPreferencesLocalServiceUtil.getPreferences(companyId,
???????????????????prefsPK);
???????????copyPrefsPK?=?new?PortletPreferencesPK(copyPortletId,?copyLayout
???????????????????.getLayoutId(),?copyLayout.getOwnerId());
???????????copyPrefsImpl?=?(PortletPreferencesImpl)?PortletPreferencesLocalServiceUtil
???????????????????.getPreferences(companyId,?copyPrefsPK);
???????????PortletPreferencesLocalServiceUtil.updatePreferences(prefsPK,
???????????????????copyPrefsImpl);
???????}
???}
???private?String?getOwnerId(String?groupId,?boolean?privateLayout)?...{
???????if?(privateLayout)?...{
???????????return?Layout.PRIVATE?+?groupId;
???????}?else?...{
???????????return?Layout.PUBLIC?+?groupId;
???????}
???}
} 修改com.liferay.portal.events.ServicePreAction類 是在 ext工程的?ext-ejb/src下修改,新建com.liferay.portal.events包,并把原始的ServicePreAction類拷貝至此,然后修改,修改后通過ext-ejb下的build.xml編譯部署。 在ServicePreAction類中新增一個addDefaultLayouts方法:
| protected void addDefaultLayouts(HttpServletRequest httpReq, User user) throws PortalException, SystemException { if (user.hasPrivateLayouts()) { return; } (new LayoutCopy(user)).copyDefaultUserLayout(httpReq); } |
| if (layoutsRequired) {? String user_layout_group = PropsUtil.get("default.user.layout.group"); if(user_layout_group==null || user_layout_group.length()==0){ addDefaultLayouts(user); }else{ addDefaultLayouts(req, user); } } |
作者:胡長城(銀狐999)
時間:2006年9月3日晚
???? Liferay默認提供的基于Struts Action擴展的PortletAction是不支持多分發(fā)命令的,也就是我們一般常用的DispatchAction。但在我們日?;赟truts處理的操作中,已經(jīng)大量的沿用了DispatchAction處理方式,采用“cmd=queryall”諸如此類的方式。 本文就來給大家講解如何通過擴展,讓Liferay實現(xiàn)對多分發(fā)命令Action的支持。 首先讓我們來看看Liferay是如何處理的: 在portlet.XML中,我們一般會配置如下: <portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class>
<init-param>
????<name>view-action</name>
????<value>/ext/reports/view_reports</value>
</init-param> 這樣Liferay面對一個Portlet請求的時候,會根據(jù)請求model來執(zhí)行Portlet的doView或doEdit方式。當執(zhí)行doView的時候就會請求其view-action所配置的Action URL所代表的Action來處理。 其處理流程大致是:Portlet類——〉RequestProcessor——〉StrutsAction處理類。
? 我們可以通過兩種擴展方案來實現(xiàn)對多分發(fā)的支持: 方案(一):擴展Liferay的StrutsPortlet類,并寫一個DispatchPortletAction類,這樣不用擴展RequestProcessor實現(xiàn)。 方案(二):擴展RequestProcessor與,并寫一個DispatchPortletAction類,這樣可以直接使用Liferay所提供的StrutsPortlet類。對于RequestProcessor的擴展,在通過portal.properties文件中通過配置“struts.portlet.request.processor”屬性來設置。 接下來就兩種方案做分別的詳細講解(本篇先講方案一):
? 方案(一) 首先讓我們寫一個DispatchPortletAction類,此類可以通過擴展Liferay本身的PortletAction實現(xiàn),也可以通過擴展Struts本身的DispatchAction實現(xiàn)。本人是選擇后一種方式,這樣擴展的代碼量較少,都不要自己寫execute方式,直接使用基類的即可。 對于DispatchPortletAction主要擴展dispatchMethod和getMethodName方法。注意在getMechodName方法中,還追加了從request.getAttribute(parameter)獲取方法名稱,并注意unspecified方法,這個是在沒有指明訪問方法的時候默認執(zhí)行的,所以開發(fā)人員在后續(xù)寫自己的Action一定要實現(xiàn)這個。
public?class?DispatchPortletAction?extends?DispatchAction?...{
????protected?ActionForward?dispatchMethod(ActionMapping?mapping,
????????????ActionForm?form,?HttpServletRequest?request,
????????????HttpServletResponse?response,?String?name)?throws?Exception?...{
????????PortletConfig?portletConfig?=?(PortletConfig)?request
????????????????.getAttribute(WebKeys.JavaX_PORTLET_CONFIG);
????????RenderRequest?renderRequest?=?(RenderRequest)?request
????????????????.getAttribute(WebKeys.JAVAX_PORTLET_REQUEST);
????????RenderResponse?renderResponse?=?(RenderResponse)?request
????????????????.getAttribute(WebKeys.JAVAX_PORTLET_RESPONSE);
????????if?(name?==?null)?...{
????????????return?this.unspecified(mapping,?form,?portletConfig,
????????????????????renderRequest,?renderResponse);
????????}
????????Method?method?=?null;
????????try?...{
????????????method?=?getMethod(name);
????????}?catch?(NoSuchMethodException?e)?...{
????????????String?message?=?messages.getMessage("dispatch.method",
????????????????????mapping.getPath(),?name);
????????????log.error(message,?e);
????????????String?userMsg?=?messages.getMessage("dispatch.method.user",
????????????????????mapping.getPath());
????????????throw?new?NoSuchMethodException(userMsg);
????????}
????????ActionForward?forward?=?null;
????????try?...{
????????????Object?args[]?=?...{?mapping,?form,?portletConfig,?renderRequest,
????????????????????renderResponse?};
????????????forward?=?(ActionForward)?method.invoke(this,?args);
????????}?catch?(ClassCastException?e)?...{
????????????String?message?=?messages.getMessage("dispatch.return",
????????????????????mapping.getPath(),?name);
????????????log.error(message,?e);
????????????throw?e;
????????}?catch?(IllegalAccessException?e)?...{
????????????String?message?=?messages.getMessage("dispatch.error",
????????????????????mapping.getPath(),?name);
????????????log.error(message,?e);
????????????throw?e;
????????}?catch?(InvocationTargetException?e)?...{
????????????Throwable?t?=?e.getTargetException();
????????????if?(t?instanceof?Exception)?...{
????????????????throw?((Exception)?t);
????????????}?else?...{
????????????????String?message?=?messages.getMessage("dispatch.error",
????????????????????????mapping.getPath(),?name);
????????????????log.error(message,?e);
????????????????throw?new?ServletException(t);
????????????}
????????}
????????return?(forward);
????}
????protected?String?getMethodName(ActionMapping?mapping,?ActionForm?form,
????????????HttpServletRequest?request,?HttpServletResponse?response,
????????????String?parameter)?throws?Exception?...{
????????String?methodName?=?request.getParameter(parameter);
????????if?(methodName?==?null?||?methodName.length()?==?0)?...{
?????????????methodName?=?(String)?request.getAttribute(parameter);
????????}
????????return?methodName;
????}
????public?ActionForward?unspecified(ActionMapping?mapping,?ActionForm?form,
????????????PortletConfig?config,?RenderRequest?req,?RenderResponse?res)
????????????throws?Exception?...{
????????return?null;
????}
????private?static?Log?log?=?LogFactory.getLog(DispatchPortletAction.class);
????protected?Class[]?types?=?...{?ActionMapping.class,?ActionForm.class,
????????????PortletConfig.class,?RenderRequest.class,?RenderResponse.class?};
}
??????? 這樣后續(xù)多分發(fā)Action在書寫的時候,只需要定義不同的方法即可,但是方法的參數(shù)需要依照如下規(guī)范,如下一個queryAll的方法:
public?ActionForward?queryAll(ActionMapping?mapping,?ActionForm?form,
????????????PortletConfig?config,?RenderRequest?req,?RenderResponse?res)
????????????throws?Exception?{
????//業(yè)務處理
//返回ActionForward即可
}
?
???????? 在那些portlet配置文件的view-action屬性中,是不能夠增加參數(shù)的,比如你不能夠采用 /ext/reports/view_reports?cmd=queryAll這種方式。所以我們需要在擴展的Portlet中做一些攔截。 可能有人會說,我不需要在初始的view-action中增加參數(shù)。事實上這個的確不是強制,如果不追加參數(shù),則會訪問unspecified方法。但是對于Portlet的顯示,其Normal和Max頁面顯示,都會請求默認的view-action。所以我們需要在Portlet類實現(xiàn)上擴展,于是擴展了一個DispachStrutsPortlet,如下:
public?class?DispachStrutsPortlet?extends?StrutsPortlet?{
?????? public?void?doView(RenderRequest?req,?RenderResponse?res)
????????????????????????????????????????????????????????????????? ?throws?IOException,?PortletException?{
??????????????? //注意我的命令參數(shù)是cmdx,而不是通常的cmd。
????????????????String?cmd?=?req.getParameter("cmdx");
????????????????if(cmd==null?||?cmd.length()==0){
??????????????????????? if?(req.getWindowstate().equals(Windowstate.?MAXIMIZED))?{
??????????????????????? req.setAttribute("cmdx","queryAll");
??????????????? }
????????????????super.doView(req,?res);
??????? }
} ?
如上面的實現(xiàn),則表示,如果Portlet是Normal頁面狀態(tài)請求的時候,則在view-action的時候,則僅訪問默認的unspecified方法;如果是Max頁面狀態(tài),則執(zhí)行queryAll方法。 有一個需要注意的地方,由于“cmd”參數(shù)已經(jīng)被Liferay使用,所以我們需要用另外的變量來表示方法。這里我采用的是“cmdx”。
Liferay Portal額外研究(六):Portlet附件上傳處理的點滴
首先更正上一篇有關多分發(fā)Action處理的一些嚴重Bug。 ? 更正一:在上篇中,我比較傾向于直接基于Struts DispatchAction擴展,這是錯誤的,應該盡量基于PortletAction,雖然這樣會讓擴展增加一些Struts DispatchAction本已有的代碼,但是這才是符合Portlet Action處理思想的。并且在Liferay的內部處理中,對于actionurl處理的情況下,是強制必須基于PortletAction擴展的。 更正二:在上篇中,多分發(fā)處理的樣例代碼只側重對Render的多分發(fā),其實這是不完善的,也容易造成誤導。在Porttal的Portlet請求處理,是分為:Action和Render兩個階段的。其實真正的多業(yè)務處理更應該在Action階段來完成,Render則主要負責對push位置和頁面數(shù)據(jù)進行渲染。 ? 在Liferay中開發(fā)附件上傳處理應用,要比在單純Servlet和Struts Action中開發(fā)簡單很多。但是需要注意的是,必須在Action階段才能處理附件File對象,而在Render階段已經(jīng)不能處理了。 ? 讓我們首先來看一下com.liferay.portal.servlet.MainServlet 類,此類是所有“/c”請求的轉移控制類。在此類中,liferay對含有文件上傳的請求做了攔截和封裝,利用UploadServletRequest 類來包裝原始的http request請求if?((contentType?!=?null)?&&
????????????(contentType.startsWith("multipart/form-data")))?{
????????????req?=?new?UploadServletRequest(req);
}
??????? 在UploadServletRequest類中,則將所有當前請求參數(shù)進行了提取,并對上傳的文件做了臨時存儲。實際上內部是采用Apache Commons Upload進行的封裝。
??? ??? 這樣在PortletAction的procesAction處理中,可以對上傳附件進行業(yè)務處理和存儲。?????? 當然,你可以通過ActionRequest來強制自己獲取原始的UploadServletRequest對象,可以如下操作:
?
public?class?NewFileUploadAction?extends?PortletAction?{????public?void?processAction(
????????????ActionMapping?mapping,?ActionForm?form,?PortletConfig?config,
????????????ActionRequest?req,?ActionResponse?res)
????????throws?Exception?{
????????
?????????//注意這里面是獲取UploadPortletRequest對象
????????UploadPortletRequest?urequest?=?PortalUtil.getUploadPortletRequest(req);
?????????File?f?=?urequest.getFile("file1");
}
?
?
?
//req是ActionRequest對象ActionRequestImpl?reqImpl?=?(ActionRequestImpl)req;
HttpServletRequest?httpReq?=?reqImpl.getHttpServletRequest();
UploadServletRequest?urequest?=?(UploadServletRequest)httpReq;
?
????? 置于在Action處理階段,獲取到UploadServletRequest對象后存儲附件、過濾附件類型等操作就很容易實現(xiàn)了,此處不再累贅敘述。
??? ? 不過在附件上傳中都會涉及到一個問題:控制附件上傳的大小和類型。對于類型的控制,liferay沒有提供任何控制和擴展實現(xiàn)機制,這個只能開發(fā)人員在外圍自己實現(xiàn)。
?
<%PortletURL?portletURL?=?renderResponse.createActionURL();
portletURL.setWindowState(WindowState.MAXIMIZED);
portletURL.setParameter("struts_action",?"/venus/template/fileupload/FileUpoadAction");
portletURL.setParameter("cmdx",?"uploadfile");
portletURL.setParameter("cmd",?"add");
%>
<form?name="testForm"?method="post"?
action="<%=?portletURL.toString()?%>"?
enctype="multipart/form-data">
</form>
?
Liferay Portal額外研究(7):修改用戶登錄首頁布局之方案二
ZDNet軟件頻道 時間:2007-12-15 作者:胡長城 | CSDN 我要評論()本文關鍵詞:首頁布局 用戶登錄 修改 Liferay Portal額外研究(7):修改用戶登錄首頁布局之方案二
在第四篇《Liferay Portal額外研究(4):修改用戶登錄后的默認布局和內容》中,我講了修改用戶登錄首頁布局的方案,此篇再給提供一種更簡潔的處理方案。
??????? 在第四篇的方案,其實有些違背Liferay的擴展本意,Liferay提供了在外圍配置的方式,來統(tǒng)一設置用戶的第一次默認登陸首頁。
??????? 在portal_ext.properties中通過修改相應參數(shù)來控制:
default.user.layout.name=Home
#?Set?the?layout?template?id?that?matches?an?existing?TPL.
default.user.layout.template.id=2_columns_ii
#?Set?the?layout?ids?for?the?column?specified?in?the?layout?template.
default.user.layout.column-1=82,23,61,65,
default.user.layout.column-2=8,11,36,33,
default.user.layout.column-3=
default.user.layout.column-4=
#?Enter?either?"800x600"?or?"1024x768"?to?set?the?layout?resolution.
default.user.layout.resolution=800x600
??? 可以通過修改“default.user.layout.template.id”屬性來控制頁面的布局格式;通過修改“default.user.layout.column-X”的屬性來控制不同列防止的portlet。
???但如果為了更加符合一些商業(yè)性的需求,比如同一個Location的下的user默認布局相同,等等,這些則需要重載ServicePreAction類,重載 addDefaultLayouts 方法來實現(xiàn),然后再在portal_ext.properties修改相應屬性即可。
?
總結
以上是生活随笔為你收集整理的Liferay Portal额外研究-银狐999的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Liferay Portal学习笔记-c
- 下一篇: Liferay门户与CAS实现SSO单点