hook开发是Liferay客制扩展的一种方式,比插件灵活,即可以扩展liferay门户,也能对原有特性进行更改,Liferay有许多内置的服务,比如用hook甚至可以覆盖Liferay服务。

可作为系统服务挂钩(Liferay Service Hook),还有其他类型的hook...

Liferay6.2 时的hook开发比较有限,而在Liferay7则大为不同,OSGi services的彻底改进至Liferay的底层模型框架,使得Liferay可以支持更多的定制扩展!
OSGi plugins可以快速部署到Liferay,就和其他类型的插件一样。

名词:

FQPN: a fully qualified portlet name

正在不断整理完善中...

PollerProcessor

com.liferay.portal.kernel.poller.PollerProcessor
集成点:"javax.portlet.name" : a FQPN
用途: 轮训消息机制,用于类似Ajax在页面显示信息
例子:
JS:

  1. AUI()
  2. .use('aui-base','aui-delayed-task', 'liferay-poller',
  3. function(A) {
  4.  
  5. Liferay.namespace('BladePoller');
  6.  
  7. Liferay.BladePoller.Manager = {
  8. init: function() {
  9.  
  10. var instance = this;
  11.  
  12. instance._portletId = A.one("#pollerPortletId").val();
  13.  
  14. instance._bladePollerContainer = A.one('#bladePollerContainer');
  15.  
  16. console.log("Init: portletId:"+instance._portletId+
  17. ", containerId:"+instance._bladePollerContainer);
  18.  
  19. instance._updateTask = new A.debounce(instance._updateMessage,30000,
  20. instance);
  21.  
  22. instance._updateTask.delay(0);
  23.  
  24. Liferay.Poller.addListener(instance._portletId,instance._onPollerUpdate, instance);
  25.  
  26. Liferay.on(
  27. 'sessionExpired',
  28. function(event) {
  29. Liferay.Poller.removeListener(instance._portletId);
  30. instance._bladePollerContainer.hide();
  31. }
  32. );
  33.  
  34. },
  35.  
  36. send: function(options, id) {
  37.  
  38. console.log("Options:" + options + ", id:" + id);
  39.  
  40. var instance = this;
  41.  
  42. Liferay.Poller.submitRequest(instance._portletId, options, id);
  43.  
  44. instance._updateTask();
  45. },
  46.  
  47. _updateMessage: function() {
  48. console.log("Update Message");
  49. var instance = this;
  50. instance.send( {
  51. status : 'OK'
  52. });
  53. },
  54.  
  55. _onPollerUpdate : function(response, chunkId) {
  56.  
  57. console.log("updating...");
  58.  
  59. var instance = this;
  60.  
  61. instance._bladePollerContainer.text(response.content.message);
  62.  
  63. instance._bladePollerContainer.show();
  64.  
  65. instance.send(
  66. {
  67. status : 'OK'
  68. }
  69. );
  70.  
  71. }
  72.  
  73. };
  74.  
  75. A.augment(Liferay.BladePoller.Manager, A.Attribute, true);
  76.  
  77. Liferay.publish(
  78. 'pollerPortletReady',
  79. {
  80. defaultFn: A.bind('init', Liferay.BladePoller.Manager),
  81. fireOnce: true
  82. }
  83. );
  84.  
  85. A.on(
  86. 'domready',
  87. function() {
  88. Liferay.fire('pollerPortletReady');
  89. }
  90. );
  91.  
  92. }
  93.  
  94. );

jsp:

  1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
  2.  
  3. <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
  4.  
  5. <%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %><%@
  6. taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %><%@
  7. taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %><%@
  8. taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
  9.  
  10. <liferay-theme:defineObjects />
  11.  
  12. <portlet:defineObjects />
  13. <p>
  14. <b><liferay-ui:message
  15. key="blade_portlet_BladePollProcessorPortlet.title" /></b>
  16. </p>
  17.  
  18. <input id="pollerPortletId" type="hidden" value="<%= portletDisplay.getId() %>" />
  19.  
  20. <p id="bladePollerContainer"></p>

Java:

  1. import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
  2. import javax.portlet.Portlet;
  3. import org.osgi.service.component.annotations.Component;
  4.  
  5. @Component(
  6. immediate = true,
  7. property = {
  8. "com.liferay.portlet.css-class-wrapper=portlet-pollprocessor-blade",
  9. "com.liferay.portlet.display-category=category.sample",
  10. "com.liferay.portlet.header-portlet-javascript=/js/main.js",
  11. "com.liferay.portlet.poller-processor-class=blade.portlet.BladePollProcessor",
  12. "com.liferay.portlet.private-request-attributes=false",
  13. "com.liferay.portlet.private-session-attributes=false",
  14. "com.liferay.portlet.remoteable=true",
  15. "com.liferay.portlet.render-weight=50",
  16. "javax.portlet.display-name=BLADE PollProcessor",
  17. "javax.portlet.expiration-cache=0",
  18. "javax.portlet.init-param.template-path=/",
  19. "javax.portlet.init-param.view-template=/view.jsp",
  20. "javax.portlet.portlet.info.keywords=blade,pollprocessor",
  21. "javax.portlet.portlet.info.short-title=BLADE PollProcessor",
  22. "javax.portlet.portlet.info.title=BLADE PollProcessor",
  23. "javax.portlet.resource-bundle=content.Language",
  24. "javax.portlet.security-role-ref=power-user,user"
  25. },
  26. service = Portlet.class
  27. )
  28. public class BladePollProcessorPortlet extends MVCPortlet {
  29. }
  30.  
  31. import com.liferay.portal.kernel.json.JSONFactoryUtil;
  32. import com.liferay.portal.kernel.json.JSONObject;
  33. import com.liferay.portal.kernel.log.Log;
  34. import com.liferay.portal.kernel.log.LogFactoryUtil;
  35. import com.liferay.portal.kernel.poller.BasePollerProcessor;
  36. import com.liferay.portal.kernel.poller.DefaultPollerResponse;
  37. import com.liferay.portal.kernel.poller.PollerProcessor;
  38. import com.liferay.portal.kernel.poller.PollerRequest;
  39. import com.liferay.portal.kernel.poller.PollerResponse;
  40. import java.util.Date;
  41. import org.osgi.service.component.annotations.Component;
  42.  
  43. @Component(
  44. immediate = true,
  45. property = {"javax.portlet.name=blade_portlet_BladePollProcessorPortlet"},
  46. service = PollerProcessor.class
  47. )
  48. public class BladePollProcessor extends BasePollerProcessor {
  49.  
  50. @Override
  51. protected PollerResponse doReceive(PollerRequest pollerRequest)
  52. throws Exception {
  53.  
  54. if (_log.isDebugEnabled()) {
  55. _log.debug("Recevied the poller request" + pollerRequest);
  56. }
  57.  
  58. JSONObject responseJSON = JSONFactoryUtil.createJSONObject();
  59. PollerResponse pollerResponse = new DefaultPollerResponse();
  60. responseJSON.put(
  61. "message", "Hello from BLADE Poller, time now is:" + new Date());
  62. pollerResponse.setParameter("content", responseJSON);
  63.  
  64. return pollerResponse;
  65. }
  66.  
  67. @Override
  68. protected void doSend(PollerRequest pollerRequest) throws Exception {
  69. String status = getString(pollerRequest, "status");
  70.  
  71. if (_log.isInfoEnabled()) {
  72. _log.info("Poller status:" + status);
  73. }
  74. }
  75.  
  76. private final Log _log = LogFactoryUtil.getLog(BladePollProcessor.class);
  77.  
  78. }

===================

AuthFailure & Authenticator

com.liferay.portal.security.auth.AuthFailure
集成点:"key" : "auth.failure" | "auth.max.failures"
用途: 用户登录失败处理

com.liferay.portal.security.auth.Authenticator
集成点:"key" : "auth.pipeline.post" | "auth.pipeline.post"
用途: 用户登录验证
例子:

Liferay7 BPM门户开发之32: 实现自定义认证登陆(定制Authentication Hook)

===================

StrutsAction & StrutsPortletAction

com.liferay.portal.kernel.struts.StrutsAction
集成点:"path" : a struts path (starting with "/portal")
用途: HttpServletRequest方式的Struts Action跳转

com.liferay.portal.kernel.struts.StrutsPortletAction
集成点:"path" : a portlet struts path
用途: StrutsPortletAction方式的Struts Action跳转

StrutsAction和StrutsPortletAction都不是官方推荐方式

例子:

  1. @Component(
  2. immediate = true, property = {"path=/login/login"},
  3. service = StrutsPortletAction.class
  4. )
  5. public class BladePortletAction extends BaseStrutsPortletAction {
  6.  
  7. @Override
  8. public void processAction(
  9. StrutsPortletAction originalStrutsPortletAction,
  10. PortletConfig portletConfig, ActionRequest actionRequest,
  11. ActionResponse actionResponse)
  12. throws Exception {
  13.  
  14. if (_log.isDebugEnabled()) {
  15. _log.debug("BladePortletAction - procesAction");
  16. }
  17.  
  18. ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
  19. WebKeys.THEME_DISPLAY);
  20.  
  21. User loggedinUser = themeDisplay.getUser();
  22.  
  23. if ((loggedinUser != null) && _log.isInfoEnabled()) {
  24. _log.info(
  25. "Logging in with user:[" + loggedinUser.getFirstName() + " " +
  26. loggedinUser.getLastName() + "]");
  27.  
  28. _log.info(
  29. "Logged in user: Current Greetings[" +
  30. loggedinUser.getGreeting() + "]");
  31. }
  32.  
  33. originalStrutsPortletAction.processAction(
  34. originalStrutsPortletAction, portletConfig, actionRequest,
  35. actionResponse);
  36. }
  37.  
  38. @Override
  39. public String render(
  40. StrutsPortletAction originalStrutsPortletAction,
  41. PortletConfig portletConfig, RenderRequest renderRequest,
  42. RenderResponse renderResponse)
  43. throws Exception {
  44.  
  45. if (_log.isDebugEnabled()) {
  46. _log.debug("BladePortletAction - render");
  47. }
  48.  
  49. ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
  50. WebKeys.THEME_DISPLAY);
  51.  
  52. User loggedinUser = themeDisplay.getUser();
  53.  
  54. if (loggedinUser != null) {
  55. loggedinUser.setLastName("BLADE");
  56.  
  57. loggedinUser.setGreeting(
  58. "Hello," + loggedinUser.getFirstName() + " from BLADE!");
  59.  
  60. _userLocalService.updateUser(loggedinUser);
  61. }
  62.  
  63. return originalStrutsPortletAction.render(
  64. originalStrutsPortletAction, portletConfig, renderRequest,
  65. renderResponse);
  66. }
  67.  
  68. @Override
  69. public void serveResource(
  70. StrutsPortletAction originalStrutsPortletAction,
  71. PortletConfig portletConfig, ResourceRequest resourceRequest,
  72. ResourceResponse resourceResponse)
  73. throws Exception {
  74.  
  75. if (_log.isDebugEnabled()) {
  76. _log.debug("BladePortletAction - serveResource");
  77. }
  78.  
  79. originalStrutsPortletAction.serveResource(
  80. originalStrutsPortletAction, portletConfig, resourceRequest,
  81. resourceResponse);
  82. }
  83.  
  84. @Reference(unbind = "-")
  85. public void setUserService(UserLocalService userService) {
  86. _userLocalService = userService;
  87. }
  88.  
  89. private static final Log _log = LogFactoryUtil.getLog(
  90. BladePortletAction.class);
  91.  
  92. private UserLocalService _userLocalService;
  93.  
  94. }

===================

ResourceBundle

java.util.ResourceBundle
集成点:"javax.portlet.name" : a FQPN
用途: 用于国际化字符串
例子:https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/localizing-your-application

demo:

  1. import com.liferay.portal.kernel.language.UTF8Control;
  2. import java.util.Enumeration;
  3. import java.util.ResourceBundle;
  4. import org.osgi.service.component.annotations.Component;
  5.  
  6. @Component(
  7. immediate = true, property = {"language.id=en_US"},
  8. service = ResourceBundle.class
  9. )
  10. public class CustomResourceBundle extends ResourceBundle {
  11.  
  12. @Override
  13. public Enumeration<String> getKeys() {
  14. return _resourceBundle.getKeys();
  15. }
  16.  
  17. @Override
  18. protected Object handleGetObject(String key) {
  19. return _resourceBundle.getObject(key);
  20. }
  21.  
  22. private final ResourceBundle _resourceBundle = ResourceBundle.getBundle(
  23. "content.Language", UTF8Control.INSTANCE);
  24.  
  25. }

===================

ActionCommand

com.liferay.util.bridges.mvc.ActionCommand
集成点:"action.command.name" : an MVCPortlet action command name
集成点:"javax.portlet.name" : a FQPN
用途: Action周期处理

定义:https://docs.liferay.com/portal/7.0/javadocs/portal-kernel/com/liferay/portal/kernel/portlet/bridges/mvc/BaseMVCActionCommand.html#doProcessAction(javax.portlet.ActionRequest,%20javax.portlet.ActionResponse))

例子:https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/mvc-action-command

demo:

  1. @Component(
  2. immediate = true,
  3. property = {
  4. "javax.portlet.name=com_liferay_blade_samples_portlet_actioncommand_GreeterPortlet",
  5. "mvc.command.name=greet"
  6. },
  7. service = MVCActionCommand.class
  8. )
  9. public class GreeterActionCommand implements MVCActionCommand {
  10.  
  11. @Override
  12. public boolean processAction(
  13. ActionRequest actionRequest, ActionResponse actionResponse)
  14. throws PortletException {
  15.  
  16. _handleActionCommand(actionRequest);
  17.  
  18. return true;
  19. }
  20.  
  21. private void _handleActionCommand(ActionRequest actionRequest) {
  22. String name = ParamUtil.get(actionRequest, "name", StringPool.BLANK);
  23.  
  24. if (_log.isInfoEnabled()) {
  25. _log.info("Hello " + name);
  26. }
  27.  
  28. String greetingMessage = "Hello " + name + "! Welcome to OSGi";
  29.  
  30. actionRequest.setAttribute("GREETER_MESSAGE", greetingMessage);
  31.  
  32. SessionMessages.add(actionRequest, "greetingMessage", greetingMessage);
  33. }
  34.  
  35. private static final Log _log = LogFactoryUtil.getLog(
  36. GreeterActionCommand.class);
  37.  
  38. }

===================

Filter

javax.portlet.filter.ActionFilter

javax.portlet.filter.EventFilter

javax.portlet.filter.RenderFilter

javax.portlet.filter.ResourceFilter

集成点:"javax.portlet.name" : a FQPN

例子:

Liferay7 BPM门户开发之36: 使用Portlet filters过滤器做切面AOP

===================

Social

com.liferay.portlet.social.model.SocialActivityInterpreter
集成点:"javax.portlet.name" : a FQPN
用途: 
例子:

com.liferay.portlet.social.model.SocialRequestInterpreter
集成点:"javax.portlet.name" : a FQPN
用途: 
例子:

===================

AssetRendererFactory

com.liferay.portlet.asset.model.AssetRendererFactory
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

AtomCollectionAdapter

com.liferay.portal.kernel.atom.AtomCollectionAdapter<?>
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

ConfigurationAction

com.liferay.portal.kernel.portlet.ConfigurationAction
集成点:"javax.portlet.name" : a FQPN
用途: 配置动作扩展
例子:https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/implementing-configuration-actions

===================

ControlPanelEntry

com.liferay.portlet.ControlPanelEntry
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

CustomAttributesDisplay

com.liferay.portlet.expando.model.CustomAttributesDisplay
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portlet.dynamicdatamapping.util.DDMDisplay
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.portlet.FriendlyURLMapper
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.search.Indexer
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.search.OpenSearch
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.security.permission.PermissionPropagator
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.pop.MessageListener
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.lar.PortletDataHandler
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.portlet.PortletLayoutListener
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

javax.portlet.PreferencesValidator
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.lar.StagedModelDataHandler
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.template.TemplateHandler
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.trash.TrashHandler
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.servlet.URLEncoder
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.notifications.UserNotificationHandler
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.webdav.WebDAVStorage
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.workflow.WorkflowHandler
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.xmlrpc.Method
集成点:"javax.portlet.name" : a FQPN
用途:
例子:

===================

com.liferay.portal.kernel.events.LifecycleAction
集成点:
用途:
例子:

===================

com.liferay.portal.kernel.search.IndexerPostProcessor
集成点: "indexer.class.name" : a indexer or entity class name
用途:
例子:

===================

com.liferay.portal.service.ServiceWrapper
集成点:
用途:
例子:

待续...

Liferay7 BPM门户开发之37: Liferay7下的OSGi Hook集成开发的更多相关文章

  1. Liferay7 BPM门户开发之34: liferay7对外服务类生成(RestService Get Url)

    在liferay7中开发不依赖Service Builder的对外服务类,非常简洁,只需要2点注解: 在类的前部定义: @ApplicationPath("/PathXXX") 方 ...

  2. Liferay7 BPM门户开发之22: Liferay7模型监听器(Model Listeners)

    Model Listeners实现ModelListener接口,用于持久化时的AOP处理 一些使用场景: Audit Listener: 在一个独立而分离的数据库,做信息更新的审计: Cache C ...

  3. Liferay7 BPM门户开发之25: Liferay7应用程序配置(APPLICATION CONFIGURATION)

    首先有几个概念需要明确.1.第一个概念是这里的应用程序配置不是写XML之类的配置文件,是类似字典的类型化配置这意味着应用程序配置不只是一个字符串键值对的列表.值还可以有类型,如整数列表,字符串列表,一 ...

  4. Liferay7 BPM门户开发之24: Liferay7应用程序安全

    整理中...... Resources, Roles, and PermissionsPortal Access Control List (PACL) Custom SSO Providers Au ...

  5. Liferay7 BPM门户开发之1:Liferay7开发环境准备

    liferay sdk下载 \IDE下载 \ Tomcat 安装细节不在此赘述 网上有很多. 只讲核心关键坑点 进入2016年,从Liferay6.2.5 ga6版本开始,到7.0 ga3,在ivy环 ...

  6. Liferay7 BPM门户开发之10: 通用流程实现从Servlet到Portlet(Part1)

    开发目的: 实现通用流程自动化处理(即实现不需要hardcode代码的bpm统一处理后台,仅需要写少量前端html form代码和拖拽设计BPM定义) 既可独立运行或可依托于Liferay或依托其它门 ...

  7. Liferay7 BPM门户开发之17: Portlet 生命周期

    Portlet 生命周期 init() =〉 render() =〉 processAction() =〉 processEvent() =〉 serveResource() =〉destroy() ...

  8. Liferay7 BPM门户开发之44: 集成Activiti展示流程列表

    处理依赖关系 集成Activiti之前,必须搞清楚其中的依赖关系,才能在Gradle里进行配置. 依赖关系: 例如,其中activiti-engine依赖于activiti-bpmn-converte ...

  9. Liferay7 BPM门户开发之12:acitiviti和liferay用户权限体系集成

    写到第12章才出现Liferay的内容,希望可以厚积薄发. 我们的目标是不使用不维护Activiti的用户组织架构,只维护Liferay的体系,这样的好处是非常明显的,即不用做组织架构的同步工作. 原 ...

随机推荐

  1. step by step 之餐饮管理系统七(点菜模块实现)

    好长时间没有更新这个系列了,一是因为这段时间比较忙,有很多事情,二来要学习新的东西,AngularJs,devExpress这两上框架,都是比较有名的框架,先上图: 上面就是用来点菜的界面,左边是已点 ...

  2. 【Thinking in Java】Java Callable的使用

    Callable<>和Runable类似,都是用于Java的并发执行. 唯一的区别是,Runable的run方法的返回是void,而Callable的call方法是有返回值的. call方 ...

  3. Python 4 —— 函数与模块

    函数和模块的使用 一.函数 一个例子说明一切. def hello(): print "hello world" def increment(num): num += 1 retu ...

  4. java-7311练习(上)

    java练习,仅供参考! 欢迎同学们交流讨论. JDK 1.8 API帮助文档 JDK 1.6 API中文文档 Java GUI -------------------------2016-10-23 ...

  5. Discuz!X2大附件上传插件-Xproer.HttpUploader6

    插件代码(github):https://github.com/1269085759/up6-discuz 插件代码(coding):https://coding.net/u/xproer/p/up6 ...

  6. JSP中<base href="<%=basePath%>">作用

    通常在JSP页面开通有如下代码: <% String path = request.getContextPath(); String basePath = request.getScheme() ...

  7. 开源的EtherCAT Master简介

    EtherCAT的主站开发是基于EtherCAT机器人控制系统的开发中非常重要的环节.目前常见开源的主站代码为的RT-LAB开发的SOEM (Simple OpenSource EtherCAT Ma ...

  8. 解剖SQLSERVER 第六篇 对OrcaMDF的系统测试里避免regressions(译)

    解剖SQLSERVER 第六篇  对OrcaMDF的系统测试里避免regressions (译) http://improve.dk/avoiding-regressions-in-orcamdf-b ...

  9. DataTable汇总

    一.排序 1 获取DataTable的默认视图 2 对视图设置排序表达式 3 用排序后的视图导出的新DataTable替换就DataTable (Asc升序可省略,多列排序用"," ...

  10. 设计模式之美:Observer(观察者)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Observer 模式结构样式代码. 别名 Dependency Publish-Subscribe 意图 定义对象间的一种一对 ...