1 Star 14 Fork 5

蒋固金 / JModuleLink

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

第一部分 简介

JModuleLink是一个基于JAVA的模块化开发框架,它提供在运行时动态加载模块(一个或一组JAR包)、卸载模块的API,使开发者更加关注业务本身。

1.1 需求背景

现在在公司主要从事支付平台的开发工作,随着业务的增长,对接的银行支付通道越来越多,用户也不满足在一个通道下面开通单个商户,存在一个银行通道按照不同商户进行支付的需求,在传统实现当中,每次涉及到银行通道或者商户号的变更都需要重启服务器,体验较差。单个通道出现异常会影响其他通道的正常使用,用户对商户号的修改需要依赖开发人员对系统进行配置,增大后期维护成本。在同一个支付通道的多商户的背景下,部门银行提供的开发包无法兼容,需要对其进行隔离,于是在系统中使用了自定义的ClassLoader突破默认的双亲委托,自定义加载所需三方包以解决 冲突的问题,偶然的机会看到了阿里开源的jarslink,所以借鉴了其部分实现方式,编写了JModuleLink

传统开发模式问题:

  • 应用拆分的多或少都有问题。多则维护成本高,每次发布一堆应用。少则拆分成本高,无用功能很难下线。
  • 故障不隔离。当一个系统由多人同时参与开发时,修改A功能,可能会影响B功能,引发故障。
  • 多分支开发引发冲突。多分支开发完之后合并会产生冲突。
  • 牵一发动全身。一处核心代码的改动,或一个基础Jar的升级需要回归整个系统。
  • 升级和迁移成本高。中间件升级每个应用都有升级成本。

1.2 模块化开发的好处

  • 可插拔,一个应用由多个模块组成,应用里的模块可拆和合,模块可快速在多个系统中迁移和部署。
  • 模块化开发,模块之间互相隔离,实现故障隔离。
  • 一个模块一个分支,不会引发代码冲突。
  • 在模块中增加或修改功能,只会影响当前模块,不会影响整个应用。
  • 动态部署,在运行时把模块部署到应用中,快速修复故障,提高发布效率。
  • 多版本部署,可以在运行时同时部署某个模块的新旧版本,进行AB TEST。
  • 减少资源消耗,通过部署模块的方式减少应用数量和机器数量。

1.3 特性

1.3.1 隔离性

  • 类隔离:框架为每个模块的Class使用单独的ClassLoader来加载,每个模块可以依赖同一种框架的不同的版本。
  • 实例隔离:框架为每个模块创建了一个独立的Spring上下文,来加载模块中的BEAN,实例化失败不会影响其他模块(Spring环境)。

1.3.2 动态性

  • 动态发布:模块能在运行时动态加载到系统中,实现不需要重启和发布系统新增功能。支持突破双亲委派机制,在运行时加载父加载器已经加载过的类,实现模块升级依赖包不需要系统发布。
  • 动态卸载:模块能在运行时被动态卸载干净,实现快速下线不需要功能。

1.3.3 易用性

  • 提供了通用灵活的API让系统和模块进行交互。

第二部分 快速开始

使用JModuleLink可以直接下载源代码编译或者下载已经编译的jar文件,如果您是使用maven来构建项目,也可以直接在pom.xml中添加JModuleLink的坐标:

Maven central

<!-- http://mvnrepository.com/artifact/com.jianggujin/JModuleLink -->
<dependency>
    <groupId>com.jianggujin</groupId>
    <artifactId>JModuleLink</artifactId>
    <version>最新版本</version>
</dependency>

最新的版本可以从Maven仓库或者码云获取。

2.1 编写模块

对于模块而言,简单的来说就是Action的合集,所以我们需要掌握如何开发Action,编写一个Action我们只需要创建一个普通的类,然后让其实现JAction接口即可。

package com.jianggujin.modulelink.test.module;

import com.jianggujin.modulelink.JAction;
import com.jianggujin.modulelink.exception.JModuleLinkException;

/**
 * 自定义Action
 * 
 * @author jianggujin
 *
 */
public class CustomAction implements JAction {

    @Override
    public Object execute(JModuleContext context) throws JModuleLinkException {
        // TODO
        return null;
    }

    @Override
    public String getActionName() {
        return "customAction";
    }

    @Override
    public boolean isDefault(String moduleName) {
        return false;
    }
}

JAction中包含三个方法:

修饰符与类型 方法 描述
Object execute(JModuleContext context) 真正的业务逻辑处理方法
String getActionName() Action的名称,在同一个模块中,该值唯一
boolean isDefault(String moduleName) 该方法用于判断Action在模块中
是否为默认的Action
用于找不到指定Action的时候
的默认处理(可控制是否使用)

最后只需要将编写好的模块打包即可。建议一个模块就是一个FAT JAR,当然了,这并不是强制的,JModuleLink也支持一个模块有多个资源或jar。除了上面的写法之外,JModuleLink提供了一个JAction的抽象实现JAbstractAction,多数情况下,我们只需要重写execute方法即可,默认的Action名称为当前类名首字母小写。

package com.jianggujin.modulelink.test.module;

import com.jianggujin.modulelink.exception.JModuleLinkException;
import com.jianggujin.modulelink.support.JAbstractAction;

/**
 * 自定义Action
 * 
 * @author jianggujin
 *
 */
public class CustomAction extends JAbstractAction {

    @Override
    public Object execute(JModuleContext context) throws JModuleLinkException {
        // TODO
        return null;
    }
}

2.2 模块管理器

模块的加载运行需要JModuleLink的核心支持,首先我们需要初始化JModuleManager,使用该类可以完成模块的加载、卸载、查找等操作,建议使用单例模式初始化该类的对象,使用全局唯一的模块管理器管理模块。

JModuleManager moduleManager = new JDefaultModuleManager();

除此之外,还可以使用更加简单的方式来获得JModuleManager的实例对象:

JModuleManager moduleManager = JDefaultModuleManager.getInstance();

该种方式获得的JModuleManager对象为单例对象,且只有第一次调用该方法的时候才会真正初始化。

2.3 加载模块

我们可以使用JModuleConfig 来定义一个模块信息。配置说明如下:

名称 说明
moduleName 模块名,建议用英文命名,全局唯一
description 模块描述
moduleUrls 模块的资源地址,比如jar文件的位置
exclusionActions 需要排除的action,值为全限定类名
scanPackages 需要扫描的包,不为空时会启动扫描包下面的Action、监听器、拦截器。
如果使用Spring配置且模块环境为Spring,该值为空时,尝试使用XML加载,否则使用注解。
在SpringBoot模块环境下该值无效
reload 重新加载,如果该值为true,加载模块时会先卸载已加载模块然后重新加载
exclusionModuleListeners 需要排除的模块事件监听器
exclusionInterceptors 需要排除的拦截器

使用示例:

JModuleConfig moduleConfig = new JModuleConfig(moduleName);
moduleConfig.setDescription(moduleDesc);
moduleConfig.addModuleUrl(moduleUrl);
moduleConfig.addScanPackage(scanPackage);
moduleManager.load(moduleConfig);

这样就完成了一个模块的加载。

2.4 使用模块

模块正常加载后,我们就可以通过模块管理器查找已经加载的模块并执行指定的Action。使用方式如下:

public Object service(String moduleName, String actionName) {
    JModule module = moduleManager.getModule(moduleName);
    if (actionName == null) {
        return module.doDefaultAction(null);
    }
    return module.doAction(actionName, null);
}

Action的参数按照实际情况传递

2.5 卸载模块

当一个模块不再使用的时候,我们可以动态的将其卸载,JModuleManager提供了相应的卸载方法:

   /**
    * 卸载一个模块
    */
   void unload(String moduleName);

卸载模块的时候必须调用JModuleManagerunload方法实现,虽然该接口提供了查找JModule的方法,并且JModule存在destroy()方法,但是我们依然不建议直接调用模块的的销毁方法,避免管理器模块状态不一致出现错误。

具体示例请参考:https://gitee.com/jianggujin/JModuleLink-demo

第三部分 扩展阅读

3.1 事件监听

JModuleLink中,我们可以对模块的开始加载、加载完成、激活、取消激活、卸载事件进行监听,以便于我们在代码中做一些额外的处理,监听模块的事件,我们需要实现JModuleListener接口,模块加载过程中,会先尝试从模块中加载实现了该接口的监听类,然后才会加载相关的Action,以便于监听器可以完整的获得事件回调。如果只需要监听模块的部分事件,JModuleLink中还提供了一个JModuleListenerAdapter,我们只需要重写需要处理的回调方法即可。

3.2 Spring模块

JModuleLink支持Spring模块,默认提供的加载器会针对Spring环境的模块进行特殊处理,我们可以使用XML或注解的形式创建Spring环境的上下文,当然,上下文的创建是加载器根据模块配置进行选择的。JModuleLinkSpring模块提供专用的配置类JSpringModuleConfig,该配置中除了拥有JModuleConfig的所有属性之外,还拥有一些扩展属性,扩展属性如下:

名称 说明
xmlPatterns XML配置,默认加载的配置文件:classpath*:META-INF/spring/*.xmlclasspath*:*META-INF/spring/*.xml,自定义配置文件后,默认配置无效
exclusions 需要排除的配置文件

需要注意的是,在模块配置中,如果配置了scanPackages,则模块加载器会初始化AnnotationConfigApplicationContext作为上下文,此时xmlPatternsexclusions配置无效,否则使用ClassPathXmlApplicationContext初始化上下文,加载器会扫描上下文中注入的Action监听器,需要排除的Action监听器的配置是正常生效的,排除的Action只能作为普通Bean使用而不能被模块执行。

想要加载器将模块作为Spring环境加载需要满足以下条件:

  • 配置类使用JSpringModuleConfigJSpringBootModuleConfig
  • 模块类路径中可以加载到org.springframework.context.support.ClassPathXmlApplicationContext对象,这里需要分清楚的是,JModuleLink的运行环境不一定是Spring环境也可以正常加载作为Spring环境的模块,主要在模块类路径下或JModuleLink运行的类路径下扫描到Spring相关类即可

如果加载器检测模块环境以及配置不满足Spring的加载条件,则会将其作为普通模块加载处理。

3.3 SpringBoot模块

Spring环境的模块类似,JModuleLinke也专门提供了对SpringBoot环境模块的特殊处理,使用SpringBoot才需要使用JModuleSpringBootConfig作为配置类,该配置中除了拥有JModuleConfig的所有属性之外,还拥有一些扩展属性,扩展属性如下:

名称 说明
sources SpringBoot source

SpringBoot环境下,scanPackages配置无效,将会将扫描与初始化完全交给SpringBoot处理,与Spring环境类似,想要加载器将模块作为SpringBoot环境加载需要满足以下条件:

  • 配置类使用JSpringBootModuleConfig
  • 模块类路径中可以加载到org.springframework.boot.SpringApplication对象

如果加载器检测模块环境以及配置不满足SpringBoot的加载条件,则会将其作为普通模块加载处理。

3.4 Web环境

JModuleLink的初衷是实现可插拔、多模块的热部署,对于Web环境暂时没有做过多的支持,后期可能会增加直接初始化Web环境模块的增强处理,目前针对Web环境做了简单的适配,提供了JGenericHttpActionJHttpAction两个用于Web环境的Action,这两个实现的关系和HttpServletGenericServlet非常相似,可以按照Servlet的开发方式开发Action。在执行Action的时候我们只需要使用JHttpHolderHttpServletRequestHttpServletResponse进行包装并作为入参传递,就可以使其正常工作。

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2018 蒋固金 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

动态模块,实现模块热部署 展开 收起
Java
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/jianggujin/JModuleLink.git
git@gitee.com:jianggujin/JModuleLink.git
jianggujin
JModuleLink
JModuleLink
master

搜索帮助