Liferay7 BPM门户开发之37: Liferay7下的OSGi Hook集成开发
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:
AUI()
.use('aui-base','aui-delayed-task', 'liferay-poller',
function(A) { Liferay.namespace('BladePoller'); Liferay.BladePoller.Manager = {
init: function() { var instance = this; instance._portletId = A.one("#pollerPortletId").val(); instance._bladePollerContainer = A.one('#bladePollerContainer'); console.log("Init: portletId:"+instance._portletId+
", containerId:"+instance._bladePollerContainer); instance._updateTask = new A.debounce(instance._updateMessage,30000,
instance); instance._updateTask.delay(0); Liferay.Poller.addListener(instance._portletId,instance._onPollerUpdate, instance); Liferay.on(
'sessionExpired',
function(event) {
Liferay.Poller.removeListener(instance._portletId);
instance._bladePollerContainer.hide();
}
); }, send: function(options, id) { console.log("Options:" + options + ", id:" + id); var instance = this; Liferay.Poller.submitRequest(instance._portletId, options, id); instance._updateTask();
}, _updateMessage: function() {
console.log("Update Message");
var instance = this;
instance.send( {
status : 'OK'
});
}, _onPollerUpdate : function(response, chunkId) { console.log("updating..."); var instance = this; instance._bladePollerContainer.text(response.content.message); instance._bladePollerContainer.show(); instance.send(
{
status : 'OK'
}
); } }; A.augment(Liferay.BladePoller.Manager, A.Attribute, true); Liferay.publish(
'pollerPortletReady',
{
defaultFn: A.bind('init', Liferay.BladePoller.Manager),
fireOnce: true
}
); A.on(
'domready',
function() {
Liferay.fire('pollerPortletReady');
}
); } );
jsp:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %> <%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %><%@
taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %><%@
taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %><%@
taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %> <liferay-theme:defineObjects /> <portlet:defineObjects />
<p>
<b><liferay-ui:message
key="blade_portlet_BladePollProcessorPortlet.title" /></b>
</p> <input id="pollerPortletId" type="hidden" value="<%= portletDisplay.getId() %>" /> <p id="bladePollerContainer"></p>
Java:
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import javax.portlet.Portlet;
import org.osgi.service.component.annotations.Component; @Component(
immediate = true,
property = {
"com.liferay.portlet.css-class-wrapper=portlet-pollprocessor-blade",
"com.liferay.portlet.display-category=category.sample",
"com.liferay.portlet.header-portlet-javascript=/js/main.js",
"com.liferay.portlet.poller-processor-class=blade.portlet.BladePollProcessor",
"com.liferay.portlet.private-request-attributes=false",
"com.liferay.portlet.private-session-attributes=false",
"com.liferay.portlet.remoteable=true",
"com.liferay.portlet.render-weight=50",
"javax.portlet.display-name=BLADE PollProcessor",
"javax.portlet.expiration-cache=0",
"javax.portlet.init-param.template-path=/",
"javax.portlet.init-param.view-template=/view.jsp",
"javax.portlet.portlet.info.keywords=blade,pollprocessor",
"javax.portlet.portlet.info.short-title=BLADE PollProcessor",
"javax.portlet.portlet.info.title=BLADE PollProcessor",
"javax.portlet.resource-bundle=content.Language",
"javax.portlet.security-role-ref=power-user,user"
},
service = Portlet.class
)
public class BladePollProcessorPortlet extends MVCPortlet {
} import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.poller.BasePollerProcessor;
import com.liferay.portal.kernel.poller.DefaultPollerResponse;
import com.liferay.portal.kernel.poller.PollerProcessor;
import com.liferay.portal.kernel.poller.PollerRequest;
import com.liferay.portal.kernel.poller.PollerResponse;
import java.util.Date;
import org.osgi.service.component.annotations.Component; @Component(
immediate = true,
property = {"javax.portlet.name=blade_portlet_BladePollProcessorPortlet"},
service = PollerProcessor.class
)
public class BladePollProcessor extends BasePollerProcessor { @Override
protected PollerResponse doReceive(PollerRequest pollerRequest)
throws Exception { if (_log.isDebugEnabled()) {
_log.debug("Recevied the poller request" + pollerRequest);
} JSONObject responseJSON = JSONFactoryUtil.createJSONObject();
PollerResponse pollerResponse = new DefaultPollerResponse();
responseJSON.put(
"message", "Hello from BLADE Poller, time now is:" + new Date());
pollerResponse.setParameter("content", responseJSON); return pollerResponse;
} @Override
protected void doSend(PollerRequest pollerRequest) throws Exception {
String status = getString(pollerRequest, "status"); if (_log.isInfoEnabled()) {
_log.info("Poller status:" + status);
}
} private final Log _log = LogFactoryUtil.getLog(BladePollProcessor.class); }
===================
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都不是官方推荐方式
例子:
@Component(
immediate = true, property = {"path=/login/login"},
service = StrutsPortletAction.class
)
public class BladePortletAction extends BaseStrutsPortletAction { @Override
public void processAction(
StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, ActionRequest actionRequest,
ActionResponse actionResponse)
throws Exception { if (_log.isDebugEnabled()) {
_log.debug("BladePortletAction - procesAction");
} ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
WebKeys.THEME_DISPLAY); User loggedinUser = themeDisplay.getUser(); if ((loggedinUser != null) && _log.isInfoEnabled()) {
_log.info(
"Logging in with user:[" + loggedinUser.getFirstName() + " " +
loggedinUser.getLastName() + "]"); _log.info(
"Logged in user: Current Greetings[" +
loggedinUser.getGreeting() + "]");
} originalStrutsPortletAction.processAction(
originalStrutsPortletAction, portletConfig, actionRequest,
actionResponse);
} @Override
public String render(
StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, RenderRequest renderRequest,
RenderResponse renderResponse)
throws Exception { if (_log.isDebugEnabled()) {
_log.debug("BladePortletAction - render");
} ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
WebKeys.THEME_DISPLAY); User loggedinUser = themeDisplay.getUser(); if (loggedinUser != null) {
loggedinUser.setLastName("BLADE"); loggedinUser.setGreeting(
"Hello," + loggedinUser.getFirstName() + " from BLADE!"); _userLocalService.updateUser(loggedinUser);
} return originalStrutsPortletAction.render(
originalStrutsPortletAction, portletConfig, renderRequest,
renderResponse);
} @Override
public void serveResource(
StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, ResourceRequest resourceRequest,
ResourceResponse resourceResponse)
throws Exception { if (_log.isDebugEnabled()) {
_log.debug("BladePortletAction - serveResource");
} originalStrutsPortletAction.serveResource(
originalStrutsPortletAction, portletConfig, resourceRequest,
resourceResponse);
} @Reference(unbind = "-")
public void setUserService(UserLocalService userService) {
_userLocalService = userService;
} private static final Log _log = LogFactoryUtil.getLog(
BladePortletAction.class); private UserLocalService _userLocalService; }
===================
ResourceBundle
java.util.ResourceBundle
集成点:"javax.portlet.name" : a FQPN
用途: 用于国际化字符串
例子:https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/localizing-your-application
demo:
import com.liferay.portal.kernel.language.UTF8Control;
import java.util.Enumeration;
import java.util.ResourceBundle;
import org.osgi.service.component.annotations.Component; @Component(
immediate = true, property = {"language.id=en_US"},
service = ResourceBundle.class
)
public class CustomResourceBundle extends ResourceBundle { @Override
public Enumeration<String> getKeys() {
return _resourceBundle.getKeys();
} @Override
protected Object handleGetObject(String key) {
return _resourceBundle.getObject(key);
} private final ResourceBundle _resourceBundle = ResourceBundle.getBundle(
"content.Language", UTF8Control.INSTANCE); }
===================
ActionCommand
com.liferay.util.bridges.mvc.ActionCommand
集成点:"action.command.name" : an MVCPortlet action command name
集成点:"javax.portlet.name" : a FQPN
用途: Action周期处理
例子:https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/mvc-action-command
demo:
@Component(
immediate = true,
property = {
"javax.portlet.name=com_liferay_blade_samples_portlet_actioncommand_GreeterPortlet",
"mvc.command.name=greet"
},
service = MVCActionCommand.class
)
public class GreeterActionCommand implements MVCActionCommand { @Override
public boolean processAction(
ActionRequest actionRequest, ActionResponse actionResponse)
throws PortletException { _handleActionCommand(actionRequest); return true;
} private void _handleActionCommand(ActionRequest actionRequest) {
String name = ParamUtil.get(actionRequest, "name", StringPool.BLANK); if (_log.isInfoEnabled()) {
_log.info("Hello " + name);
} String greetingMessage = "Hello " + name + "! Welcome to OSGi"; actionRequest.setAttribute("GREETER_MESSAGE", greetingMessage); SessionMessages.add(actionRequest, "greetingMessage", greetingMessage);
} private static final Log _log = LogFactoryUtil.getLog(
GreeterActionCommand.class); }
===================
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集成开发的更多相关文章
- Liferay7 BPM门户开发之34: liferay7对外服务类生成(RestService Get Url)
在liferay7中开发不依赖Service Builder的对外服务类,非常简洁,只需要2点注解: 在类的前部定义: @ApplicationPath("/PathXXX") 方 ...
- Liferay7 BPM门户开发之22: Liferay7模型监听器(Model Listeners)
Model Listeners实现ModelListener接口,用于持久化时的AOP处理 一些使用场景: Audit Listener: 在一个独立而分离的数据库,做信息更新的审计: Cache C ...
- Liferay7 BPM门户开发之25: Liferay7应用程序配置(APPLICATION CONFIGURATION)
首先有几个概念需要明确.1.第一个概念是这里的应用程序配置不是写XML之类的配置文件,是类似字典的类型化配置这意味着应用程序配置不只是一个字符串键值对的列表.值还可以有类型,如整数列表,字符串列表,一 ...
- Liferay7 BPM门户开发之24: Liferay7应用程序安全
整理中...... Resources, Roles, and PermissionsPortal Access Control List (PACL) Custom SSO Providers Au ...
- Liferay7 BPM门户开发之1:Liferay7开发环境准备
liferay sdk下载 \IDE下载 \ Tomcat 安装细节不在此赘述 网上有很多. 只讲核心关键坑点 进入2016年,从Liferay6.2.5 ga6版本开始,到7.0 ga3,在ivy环 ...
- Liferay7 BPM门户开发之10: 通用流程实现从Servlet到Portlet(Part1)
开发目的: 实现通用流程自动化处理(即实现不需要hardcode代码的bpm统一处理后台,仅需要写少量前端html form代码和拖拽设计BPM定义) 既可独立运行或可依托于Liferay或依托其它门 ...
- Liferay7 BPM门户开发之17: Portlet 生命周期
Portlet 生命周期 init() =〉 render() =〉 processAction() =〉 processEvent() =〉 serveResource() =〉destroy() ...
- Liferay7 BPM门户开发之44: 集成Activiti展示流程列表
处理依赖关系 集成Activiti之前,必须搞清楚其中的依赖关系,才能在Gradle里进行配置. 依赖关系: 例如,其中activiti-engine依赖于activiti-bpmn-converte ...
- Liferay7 BPM门户开发之12:acitiviti和liferay用户权限体系集成
写到第12章才出现Liferay的内容,希望可以厚积薄发. 我们的目标是不使用不维护Activiti的用户组织架构,只维护Liferay的体系,这样的好处是非常明显的,即不用做组织架构的同步工作. 原 ...
随机推荐
- 自动挂载文件/etc/fstab功能详解
今天看了这篇文章,对于自动挂载中的一些小细节和参数有了更深的理解,所以这次把它摘下来,留做查询 一./etc/fstab文件的作用 1.我们把磁盘手动挂载之后如果不把它写入/etc/fstab这个文件 ...
- 从up6-down2升级到down3
概述: 添加存储过程down_f_process.sql,down_f_del.sql 更新DnFile.updateProcess,DnFile.Delete 更新down.js 更新down.fo ...
- 【转】Python中的赋值、浅拷贝、深拷贝介绍
这篇文章主要介绍了Python中的赋值.浅拷贝.深拷贝介绍,Python中也分为简单赋值.浅拷贝.深拷贝这几种"拷贝"方式,需要的朋友可以参考下 和很多语言一样,Python中 ...
- Django 中 如何使用 settings.py 中的常量
在用django 框架开发 python web 程序的时候 , 在模板页面经常会用到 settings.py 中设置的常量,比如MEDIA_URL, 我尝试过在模板页面用类似如下的方式 程序代码 { ...
- cognos制作报表流程
第一章 创建报表 制作ReportStudio报表,步骤如下图所示: 第二章 添加查询 1.点击中间栏的查询资源管理器,然后点击查询,就可以新建查询.步骤如下图所示: 2.点击查询出现的页面: 3.在 ...
- Sql server中访问Excel---select from Excel
本文介绍在MSSMS中通过SQL语句查询Excel的方法. 访问Excel主要是通过Office提供的ACE数据源来完成这个操作,使用opendatasource来实现访问Excel.即在MSSMS中 ...
- 编译系统中的 NFA/DFA算法理解
1.问题概述 NFA 和 DFA浅析---要深入了解正则表达式,必须首先理解有穷自动机. 有穷自动机(Finite Automate)是用来模拟实物系统的数学模型,它包括如下五个部分: 有穷状态集St ...
- JAVA读取TXT文件、新建TXT文件、写入TXT文件
1.创建TXT文件 按照正常的逻辑写就好 先定义一个文件给定一个路径——>判断这个路径上这个文件存不存在——>若不存在则建立,try/catch根据程序提示自动生成就好 2.读取TXT文件 ...
- [1002]prime
输入一个数,判断其是否为素数: 本题有多组测试样例. 输入规则如下: 第一行为一个整数,样例组数T: 第二至第t+1行每行都有一个整数a(a >= 2),表示需要处理的数: 如果是素数则输出“y ...
- 大型B2B网站开发手记 1
本手记记录所有该B2B网站开发中遇到的问题和解决方法,一方面给大家一些思路,一方面提升自己,记录整个过程 1. 测试环境部署问题 部署环境是server2012 R2,部署上去发现WCF报错如下 sv ...