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://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:

@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
集成点:
用途:
例子:

待续...

时间: 2024-10-23 02:24:51

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

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

在liferay7中开发不依赖Service Builder的对外服务类,非常简洁,只需要2点注解: 在类的前部定义: @ApplicationPath("/PathXXX") 方法前定义: @GET @Path("/ActionXXX") @Produces("text/plain") 例子:得到注册用户 import com.liferay.portal.kernel.model.User; import com.liferay.portal

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

Portlet 生命周期 init() =〉 render() =〉 processAction() =〉 processEvent() =〉 serveResource() =〉destroy() init() 在Liferay容器部署portlet时,启动portlet实例化 init有两个写法: public void init() throws PortletException public void init(PortletConfig config) throws PortletEx

Liferay7 BPM门户开发之42: Liferay核心JSP定制扩展

Liferay最大的好处是不仅接口强大,利于扩展,就连JSP定制扩展都提供了3种方式. 修改核心jsp代码,有3种修改方式:1.暴力修改直接修改(位于portal-web/docroot/html),编译部署,会带来风险,而且不能同步更新. 2.全量扩展修改热部署jsp文件(替代原有jsp),这是v7.0下的OSGi方式,实现方式非常优雅. 3.CustomJspBag Hook方式实现CustomJspBag接口,做jsp片段式的修改,同样是增量热部署,也是v7.0下的OSGi方式(需要增加依

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

优秀的平台必然松耦合.易扩展  -- 王昕 第一步:修改liferay-hook.xml <?xml version="1.0"?> <!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.2.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_2_0.dtd"> <hook> <portal-properties>

Liferay7 BPM门户开发之8: Activiti实用问题集合

1.如何实现审核的上级获取(任务逐级审批) 这个是必备功能,通过Spring的注入+Activiti表达式可以很容易解决. 可参考: http://blog.csdn.net/sunxing007/article/details/8491552 http://linhongyu.blog.51cto.com/6373370/1656596 2.如何设置流程发起人,并动态在其他任务中使用 通过变量,在启动的时候设置. activiti里设置流程发起人的功能很绕. activiti 指定发起人,并作

Liferay7 BPM门户开发之19: 理解Service Builder体系

Service Builder是Liferay为业务开发而设计的模型驱动(model-driven)平台工具,提供一系列的实体类.数据持久化.服务相关的代码自动生成服务.支持Hibernate and Spring集成,缓存处理,动态查询等特性.令人惊讶的是,Liferay所有的持久化代码.Servie接口代码都是由Service Builder自动生成的,可见其自动化程度之高. 注意:Liferay的数据持久化开发不是必需用Service Builder,你可以直接用JDBC.JPA等任何技术

Liferay7 BPM门户开发之6: Activiti数据库换为mysql

第一步: 在mysql中创建数据库名字叫 'activiti' 执行D:\activiti-5.21.0\database\create下的脚本 第二步: 打开=> apache-tomcat/webapps/activiti-explorer/WEB-INF/classes/ db.properties 修改配置文件 db.properties db=activiti jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localho

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

集成Activiti之前,必须搞清楚其中的依赖关系,才能在Gradle里进行配置. 依赖关系: 例如,其中activiti-engine依赖于activiti-bpmn-converter,而activiti-bpmn-converter又依赖于activiti-bpmn-model 那么这以下的引用都是要设置的,缺一不可,否则portlet会无法注入进OSGi容器 org.activiti:activiti-engine:jar:5.xx.0+- org.activiti:activiti-b

Liferay7 BPM门户开发之3: Activiti开发环境搭建

下载地址: http://activiti.org/download.html 源码: https://github.com/Activiti/Activiti 环境准备(检查项): JDK 1.7 + JAVA_HOME :java -version 下载 Eclipse Indigo + 拷贝activiti-explorer.war 到 Tomcat/webapps目录 运行Tomcat/bin目录startup.bat or startup.sh 不修改Tomcat http端口情况下访