1 Star 0 Fork 5

steven_Jiang / JModuleLink

forked from 蒋固金 / 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.JModuleLinkException;

/**
 * 自定义Action
 * 
 * @author jianggujin
 *
 */
public class CustomAction implements JAction<Object, Object> {

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

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

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

JAction中包含三个方法:

修饰符与类型 方法 描述
<I, O> O execute(I in) 真正的业务逻辑处理方法,
I为入参数据类型,
O为返回数据类型
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.JModuleLinkException;
import com.jianggujin.modulelink.impl.JAbstractAction;

/**
 * 自定义Action
 * 
 * @author jianggujin
 *
 */
public class CustomAction extends JAbstractAction<Object, Object> {

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

2.2 初始化 JModuleManager

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

JModuleManager moduleManager = new JModuleManagerImpl();

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

JModuleManager moduleManager = JModuleManagerImpl.getInstance();

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

2.3 加载模块

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

名称 说明
name 模块名,建议用英文命名,全局唯一
desc 模块描述
version 模块版本
moduleUrls 模块的资源地址,比如jar文件的位置
actions 需要使用的action,值为全限定类名
exclusionActions 需要排除的action,值为全限定类名
scanPackages 需要扫描的包,不为空时会启动扫描。默认的实现会扫描包下面的JAction实现类;如果使用spring, 将自动扫描注解形式的bean ,并装配扫描到的JAction
active 是否激活,仅当模块有多个版本的时候有效
reload 重新加载,如果该值为true,加载模块时会先卸载已加载模块然后重新加载

使用示例:

JModuleConfig moduleConfig = new JModuleConfig("moduleName", "moduleVersion");
moduleConfig.setDesc(moduleDesc);
moduleConfig.addModuleUrl(new File(modulePath).toURI().toURL());
moduleConfig.addScanPackage(scanPackage);
moduleManager.load(moduleConfig);

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

2.4 使用模块

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

public Object service(String moduleName, String actionName) {
   if (moduleManager.has(moduleName)) {
      JModule module = moduleManager.find(moduleName);
      if (actionName == null) {
         if (module.hasDefaultAction()) {
            return module.doDefaultAction(null);
         }
      } else {
         if (module.hasAction(actionName)) {
            return module.doAction(actionName, null);
         }
      }
      throw new JModuleNotFoundException("Not found action.");
   }
   throw new JModuleNotFoundException("Not found module.");
}

建议直接使用JModule提供的doAction方法执行指定的Action,或者使用JModuleUtils 提供的doActionWithinModuleClassLoader 方法执行,否则可能会导致模块的类加载器无法正常使用。

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

2.5 AB测试

如果我们希望对一个模块的不同版本进行AB TEST,我们只需要加载指定模块的不同版本,然后使用模块管理器的activeVersion(String name, String version) 可以直接切换模块默认使用的版本。

2.6 模块卸载销毁

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

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

   /**
    * 卸载一个模块的指定版本
    */
   void unload(String name, String version);

需要注意的是如果仅仅是卸载模块的指定版本,且该版本为当前正在使用的版本,那么被卸载的模块中除去卸载版本后不能含有多个版本,否则无法卸载。

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

2.7 spring

JModuleLink除了默认的模块管理器实现,也针对spring提供了spring的模块管理器实现。使用spring的模块管理器,我们仅需要将JModuleManagerImpl 换成JSpringModuleManager ,一般情况下,我们会将该对象实例交给spring管理。

另外,与默认的通用实现不同的地方还有,在加载模块的时候,建议使用JSpringModuleConfig 作为模块信息的配置类。JSpringModuleConfigJModuleConfig 的基础上增加了3个配置项。配置说明如下:

名称 说明
properties 模块里的bean需要的配置信息,集成了spring properties
xmlPatterns 需要加载的 XML配置
exclusions 需要排除的配置文件

需要注意的是,如果配置中我们添加了扫描的包,在初始化spring模块的上下文的时候将使用注解的形式扫描,否则使用XML方式。

2.8 Web环境

考虑到有些时候可能会将JModuleLink用于Web环境。为了方便操作,提供了Web专用的模块管理器,子模块可以共享程序上下文属性(只读),使用Web环境,我们需要把管理器换成JWebModuleManager,在编写Action的时候,我们可以直接继承JServletActionJHttpServletAction,这两个实现本质上都是Servlet,这样我们就可以像编写普通Servlet代码一样编写模块的Action。管理器会在模块初始化和销毁的时候回调其对应的方法(与传统Servlet保持一致)。

需要特殊注意的是使用JWebModuleManager加载的模块为JWebModule,在原有模块的基础上提供了doServletActiondoDefaultAction方法,可以直接传递请求和响应对象。

Web环境中对应的配置类为JWebModuleConfig,在默认的JModuleConfig基础上新增了如下参数:

名称 说明
initParameters 上下文参数
servletInitParameters Servlet参数,键值为Action的名字
webRootPath Web根目录,会在该目录下按照标准war解压后的文件结构添加类路径

2.9 日志

因为JModuleLink的大部分常用功能不需要依赖任何三方包,所以提供了一种轻量的日志方式,默认会在控制台输出日志内容,我们可以按照实际集成的日志三方包,编写日志的实现类,然后调用JLogFactorysetImplementation 方法设置日志实现类,该类需要实现JLog 接口。

从1.0.2版本开始默认集成了JLogging,如果不引用该包,用法与原来相同。引用后日志将会使用Jlogging实现,原有代码无需修改。

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/steven_Jiang/JModuleLink.git
git@gitee.com:steven_Jiang/JModuleLink.git
steven_Jiang
JModuleLink
JModuleLink
master

搜索帮助