https://javatutorial.net/override-out-of-the-box-ootb-modules-in-liferay-dxp

该博客涵盖有关在 Liferay DXP 中创建片段以及如何执行所需的覆盖的详细信息。

如何在 Liferay DXP 中替代现成的(OOTB)模块 - 图1

Liferay DXP 是最受欢迎的开放源代码之一,具有许多现成的(OOTB)模块,有时根据我们的特定要求,我们需要覆盖它们。 通常,使用 OSGi 片段是执行此类覆盖的方法。

该博客包括

什么是片段?

如何在 Liferay 7 中创建片段

片段在 Liferay 7 DXP 中的用途是:

  • 覆盖 Liferay OOTB 模块的 JSP
  • 覆盖语言属性
  • 用 Servlet 过滤器覆盖 HTTP 请求
  • 覆盖 Liferay Struts 动作
  • 替代 Liferay 模态监听器

什么是片段?

片段是 OSGi 模块的一种,类似于 mvcportlet,服务,激活器,面板应用程序等。可以说片段是主机模块的扩展。

对于 Liferay 7 之前的所有版本,都使用 Hook 覆盖 Liferay Portlet。 但是对于 Liferay 7,我们必须使用片段作为 Hook。 请注意,片段是扩展的主机模块,并且在部署时,片段模块定义将合并在主机模块中(仅当片段模块不与主机模块产生任何冲突时)。 如果发生任何类型的冲突,则直到其解决之前,片段都不会包含在主机模块中。 片段没有加载自己的类或捆绑程序激活器。

片段 jar 有自己的 OSGi 清单文件,该文件包含有关 OSGi 的信息。 请在下面找到MANIFEST.MF的重要信息:

  1. Manifest-Version: 1.0
  2. Bundle-ManifestVersion: 2
  3. Bundle-Name: Liferay Fragment
  4. Bundle-SymbolicName: azilen.login.fragment.module
  5. Bundle-Version: 1.0.0
  6. Bundle-RequiredExecutionEnvironment: JavaSE-1.6
  7. Fragment-Host: com.liferay.login.web;bundle-version=1.0.5
  8. Import-Package: org.apache.commons.logging;version=”1.0.4
  9. Export-Package: com.azilen.training;version=”1.0.0

请在下面找到其关键属性的详细信息。

Fragment-Host:主机模块的捆绑符号名称

Bundle-Version:捆绑软件的初始版本

Bundle-Version:人类可读的片段模块名称

Bundle-SymbolicName:唯一标识 OSGi 容器中的片段。

Import-Package:片段中使用的外部软件包

Export-Package:对其他模块可见的片段包

Liferay 7 使用片段来执行诸如以下操作

  1. 覆盖 Liferay OOTB 模块的 JSP
  2. 覆盖语言属性
  3. 用 Servlet 过滤器覆盖 HTTP 请求
  4. 覆盖 Liferay Struts 动作
  5. 替代 Liferay 模态监听器
  6. 覆盖 Liferay 动作命令

如何在 Liferay 7 中创建片段

要将 Liferay 片段创建为模块,请使用以下命令

  1. blade create -t fragment [-h hostBundleName] [-H hostBundleVersion] projectName

请注意,我们必须使用-t参数将刀片模块的类型指定为片段。 而-h参数将需要主机捆绑包符号名称和-H参数将需要将被覆盖的主机模块版本。 最后一个projectName是人类友好的片段模块名称。

如何覆盖 Liferay OOTB 模块的 JSP

让我们来看一个用例:我想覆盖 Liferay 登录模块,并且要根据自己的需求自定义外观。 因此,要创建的blade命令如下:

  1. blade create -t fragment -h com.liferay.login.web -H 1.0.5 login-fragment-module

现在它将创建一个片段的骨架结构,您可以在bnd.bnd文件中看到主机模块(登录模块)的符号名称和版本。 可能会有一个查询,说明如何查找主机模块的符号名称和版本。 为了获得这些详细信息,我们必须使用编写的命令连接 gogo shell

  1. telnet localhost 11311

然后运行lb命令,它将列出服务器中部署的所有模块。 您可以找到带有其状态和版本的主机模块。

  1. 219|Active | 10 | Liferay Login Web (1.0.5)

现在我们的片段结构已经准备就绪,我们都可以重写主机模块 jsp。 由于我们需要覆盖login.jsp,因此请从

Liferay-src/modules/apps/foundation/login/loginweb/src/main/resources/METAINF/resources/login.jsp

并将其粘贴到login-fragmentmodule/src/main/resources/META-INF/resources/中。

现在根据需要修改login.jsp并部署login-fragment-module,成功部署后,您应该在 OOTB 登录模块中进行更改

如何覆盖 Liferay DXP 的语言属性

Liferay 支持多种语言。 因此,我们具有 OOTB 模块的语言属性。 假设我们要更改某些标签,错误消息,成功消息等的属性值。我们可以灵活地覆盖这些属性值,并且可以根据我们的要求进行更改。

让我们来看一个用例:我们要更改登录 Portlet 身份验证失败消息。 该消息的属性是:authentication-failed。 我们想用我们的自定义消息覆盖这些属性。

  1. blade create -t mvcportlet -p com.azilen.fragment.language -c CustomLanguageComponent languagefragment-module

请注意,此处创建的是-t mvcportlet而不是-t fragment,因为此处将使用 Resource bundle 类覆盖语言属性。

  1. CustomLanguageComponent.Java
  2. @Component(
  3. property = { "language.id=en_US" },
  4. service = ResourceBundle.class
  5. )
  6. public class CustomLanguageComponent extends ResourceBundle {
  7. ResourceBundle bundle = ResourceBundle.getBundle("content.Language",UTF8Control.INSTANCE);
  8. @Override
  9. protected Object handleGetObject(String key) {
  10. System.out.println("getting key"+key);
  11. return bundle.getObject(key);
  12. }
  13. @Override
  14. public Enumeration<String> getKeys() {
  15. return bundle.getKeys();
  16. }
  17. }

可以看出,我们正在创建扩展了ResourceBundle的自定义类CustomLanguageComponent,并在@Component注解中指定了属性{"language.id=en_US"}。 我们指出要覆盖Language_en.properties文件。

现在,在/language-fragmentmodule/src/main/resources/content下创建Language_en.properties,并使用我们的自定义消息添加身份验证失败的属性。

  1. authentication-failed=Authentication failed. Please try again (customized).

现在部署language-fragment-module,并且在登录模块中登录过程失败时,您将获得自定义消息。

如何使用 Servlet 过滤器覆盖

有时,我们需要拦截 http 请求,并需要在该请求上编写逻辑。 因此,我们可以使用BaseFilter实现它。

在这里,我们将拦截每个请求,仅在processFilter方法中打印日志。

  1. blade create -t mvcportlet -p com.azilen.custom.filter -c CustomFilterPortlet custom filterfragment-module
  2. CustomFilterPortlet.java
  3. @Component(
  4. immediate = true,
  5. property = {
  6. "dispatcher=REQUEST", "dispatcher=FORWARD",
  7. "servlet-context-name=",
  8. "servlet-filter-name=Custom Filter",
  9. "url-pattern=/*"
  10. },
  11. service = Filter.class
  12. )
  13. public class CustomFilterPortlet extends BaseFilter {
  14. private static final Log _log = LogFactoryUtil.getLog(CustomFilterPortlet.class);
  15. @Override
  16. protected void processFilter(HttpServletRequest request, HttpServletResponse response,
  17. FilterChain filterChain)throws Exception {
  18. log.info(“Intercept request successfully !!!”);
  19. filterChain.doFilter(request, response);
  20. }
  21. }

在这里,CustomFilterPortlet扩展了BaseFilter并覆盖了processFilter方法,我们可以在其中编写逻辑,并且必须在@Component属性中将 url 模式指定为url-pattern=/*

如何覆盖 Liferay Struts 动作

在 Liferay 6.2 和其他早期版本中,所有 Liferay 操作都由struts-config.xml中定义的 struts 操作处理。 另一方面,在 Liferay 7 DXP 中,大多数操作都在ActionCommand中进行了转换。Liferay 7 仍然具有struts-config.xml中定义的一些支持动作。

如果要覆盖该特定操作,则可以使用StrutsAction.class覆盖它。 请注意,StrutsAction.class只能覆盖struts-config.xml文件中定义的 struts 动作。

在这里,我们将覆盖“条款和条件”操作,该操作在用户首次登录且必须接受条款和条件时执行。

  1. blade create -t mvcportlet -p com.azilen.custom.struts.action -c
  2. CustomTermsOfUseActionPortlet struts-action-fragment
  3. CustomTermsOfUseActionPortlet.Java
  4. @Component(
  5. immediate=true,
  6. property={
  7. "path=/portal/update_terms_of_use"
  8. },
  9. service = StrutsAction.class
  10. )
  11. public class CustomTermsOfUseActionPortlet extends BaseStrutsAction {
  12. private static final Log _log =
  13. LogFactoryUtil.getLog(CustomTermsOfUseActionPortlet.class);
  14. @Override
  15. public String execute(StrutsAction originalStrutsAction, HttpServletRequest request,
  16. HttpServletResponse response)throws Exception {
  17. log.info("Calling Custom Termsof Use Action");
  18. //you logic goes here
  19. return originalStrutsAction.execute(request, response);
  20. }
  21. }

在这里,CustomTermsOfUseActionPortlet扩展了BaseStrutsAction并覆盖了executes方法,我们可以在其中编写自定义逻辑。 我们需要在@Component的属性"path=/portal/update_terms_of_use"中指定要覆盖的 struts 操作路径。

如何覆盖 Liferay 模态监听器

有时,我们可能需要覆盖 Liferay 的 OOTB 实体,例如UserGroupDLFileEntry等,以执行onAfterUpdateonBeforeUpdate之类的操作。 我们可以使用BaseModelListener<T>类覆盖这些方法。

在这里,我们将覆盖 Liferay UseronAfterUpdate方法,该方法将在更新任何用户时执行。

  1. blade create -t mvcportlet -p com.azilen.modal.listener.portlet c CustomUserModalListerPortlet custom-model-listener-module
  2. @Component(
  3. immediate = true,
  4. service = ModelListener.class
  5. )
  6. public class CustomUserModalListerPortlet extends BaseModelListener<User> {
  7. @Override
  8. public void onAfterUpdate(User model) throws ModelListenerException {
  9. _log.info("user is updateing... !!!!");
  10. super.onAfterUpdate(model);
  11. }
  12. private static final Log _log =
  13. LogFactoryUtil.getLog(CustomUserModalListerPortlet.class);
  14. }

在这里CustomUserModalListerPortlet扩展了BaseModelListener&lt;User&gt;并覆盖了onAfterUpdate方法,在这里我们可以编写自定义逻辑。 我们需要在@Component中将服务属性值定义为ModelListener.class

自定义 Liferay DXP 开放源代码以开发高度可扩展的现代应用程序具有极大的可能性。 程序员发现 Lifera 7 非常有趣,因为它使编码成为基于创意和逻辑思考的过程。 结果, Liferay DXP 开发在开发人员和行业中都越来越受欢迎。

作者简介

Sandip Patel 是一名技术爱好者,并且是拥有 7 年以上经验的 Liferay & MongoDB 认证专家。 他正在与 Azilen Technologies 合作,并且喜欢随时了解最新的 Liferay 技术和创新。