当前位置:网站首页>alibaba jarslink
alibaba jarslink
2022-06-27 11:26:00 【飘然渡沧海】
alibaba jarslink框架教程
demo的github地址:https://github.com/superRabbitMan/jarslink-demo
什么是jarslink
JarsLink (原名Titan)是一个基于JAVA的模块化开发框架,它提供在运行时动态加载模块(一个JAR包)、卸载模块和模块间调用的API。
为什么使用jarslink
隔离性
- 类隔离:框架为每个模块的Class使用单独的ClassLoader来加载,每个模块可以依赖同一种框架的不同的版本。
- 实例隔离:框架为每个模块创建了一个独立的Spring上下文,来加载模块中的BEAN,实例化失败不会影响其他模块。
- 资源隔离:后续会支持模块之间的资源隔离,每个模块使用独立的CPU和内存资源。
动态性
- 动态发布:模块能在运行时动态加载到系统中,实现不需要重启和发布系统新增功能。支持突破双亲委派机制,在运行时加载父加载器已经加载过的类,实现模块升级依赖包不需要系统发布。
- 动态卸载:模块能在运行时被动态卸载干净,实现快速下线不需要功能。
易用性
- 提供了通用灵活的API让系统和模块进行交互。
下载
\1. 官网:https://github.com/alibaba/jarslink
\2. 其它途径:https://oss.sonatype.org/#nexus-search;quick~jarslink
引入项目
至于如何创建一个Maven项目这里不多介绍,自己百度即可
#主要POM,这里请使用1.6以上的版本,因为接下来介绍有个功能1.6极其以上版本才支持
<dependency>
<groupId>com.alipay.jarslink</groupId>
<artifactId>jarslink-api</artifactId>
<version>1.6.1.20180301</version>
</dependency>
#依赖POM
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.5.RELEASE</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>17.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
引入模块jar包
模块jar文件引入是不用buildpath导入项目的,你可以放在CDEF盘任意位置都可以,因为这个模块jar文件是不随项目启动的,我们使用jarslink框架去引用它。
为了方便调用,我放在项目的resources文件下:

最重要的对象
<!-- 模块加载引擎,负责加载模块--><bean name="moduleLoader" class="com.alipay.jarslink.api.impl.ModuleLoaderImpl"></bean>
<!-- 模块管理器,负责注册,卸载,查找模块以及执行Action --><bean name="moduleManager" class="com.alipay.jarslink.api.impl.ModuleManagerImpl"></bean>
配置jarslink.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--模块加载引擎-->
<bean id="moduleLoader" name="moduleLoader" class="com.alipay.jarslink.api.impl.ModuleLoaderImpl" />
<!--模块管理器-->
<bean id="moduleManager" name="moduleManager" class="com.alipay.jarslink.api.impl.ModuleManagerImpl" />
</beans>
配置模块信息
public static ModuleConfig buildModuleConfig() {
URL demoModule = Thread.currentThread().getContextClassLoader().getResource("jarslink-module-demo-1.0.0.jar");//加载模块jar包,可以在任意路径下
ModuleConfig moduleConfig = new ModuleConfig();
moduleConfig.setName("hello-world");//设置模块名称
moduleConfig.setEnabled(true);
moduleConfig.setVersion("1.0.0");//设置版本
moduleConfig.setProperties(ImmutableMap.of("svnPath", new Object()));
moduleConfig.setModuleUrl(ImmutableList.of(demoModule));
return moduleConfig;
}
第一个调用demo
package com.alibaba.test;
import com.alipay.jarslink.api.Action;
import com.alipay.jarslink.api.Module;
import com.alipay.jarslink.api.ModuleLoader;
import com.alipay.jarslink.api.ModuleManager;
import com.alipay.jarslink.api.impl.AbstractModuleRefreshScheduler;
import com.alipay.jarslink.api.impl.ModuleManagerImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Map;
import java.util.Set;
/** * Created by HASEE on 2018/4/22. */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath*:jarslink.xml"})
public class JarsLinkTest {
@Autowired
private ModuleLoader moduleLoader;
@Autowired
private ModuleManager moduleManager;
@Test
public void test1() {
// System.out.println("moduleLoader = " + moduleLoader);
// System.out.println("moduleManager = " + moduleManager);
Module module = moduleLoader.load(ModuleRefreshSchedulerImpl.buildModuleConfig());//加载模块,加载一个模块
moduleManager.register(module);//注册模块信息
/*获取指定的Action,执行方式一*/
Module mod = moduleManager.find("hello-world");
Map<String, Action> actions = mod.getActions();
// Set<String> keys = actions.keySet();
// for (String key : keys) {
// System.out.println(key + ", " + actions.get(key));
// }
Action xmlaction = actions.get("XMLACTION");
System.out.println(xmlaction.execute("hello world"));
/*获取指定的Action,执行方式二*/
//doAction参数:模块中action的名称,action中execute方法的参数
String result = module.doAction("XMLACTION", "hello world");
System.out.println(result);
}
}
总结
Jarslink的使用就这么简单,1)加载模块jar。2)注册模块。3)调用模块的Action
开发模块(新建一个maven项目)
模块和Action的关系,一个jar包就是一个模块,模块中有一个或多个Action类,我们调用的就是模块的Action获取功能。所有开发模块其实就是开发Action。
Action的开发也比较简单,只要实现com.alipay.jarslink.api.Action<R,T>类即可,Action有2个泛型类,R表示传入参数,T表示返回参数。
Action一共要实现两个方法,1)T execute(Rvar1);。2)String getActionName();。execute方法是Action提供的功能方法。getActionName方法是获取的名称,该名称必须唯一,如果不唯一那么将不知道要执行模块的那个Action。
package com.alibaba.action;
import com.alipay.jarslink.api.Action;
/** * Created by HASEE on 2018/4/22. */
public class HelloWorldAction implements Action<String, String> {
@Override
public String execute(String s) {
return s + ":hello world";
}
@Override
public String getActionName() {
return "hello-world-action";
}
}
配置xml文件
配置文件的存放目录请注意,resources/META-INF/spring/*.xml,加载模块的时候会到这个目录下去读取配置信息。

配置信息如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd" default-autowire="byName">
<context:annotation-config/>
<!--创建Action-->
<bean id="helloWorldAction" class="com.alibaba.action.HelloWorldAction"/>
<bean id="welComeAction" class="com.alibaba.action.WelComeAction" />
</beans>
编译文件然后到处Jar包,这样一个模块就开发完成了,这个模块包含了一个HelloworldAction的类。
将导出的jar包引入到第一个案例的resources文件夹下,就可以调用了。
第二个调用demo
配置自己开发的模块
public static ModuleConfig buildModuleConfig_Demo() {
URL demoModule = Thread.currentThread().getContextClassLoader().getResource("jarslink-demo-action-1.0-SNAPSHOT.jar");
ModuleConfig moduleConfig = new ModuleConfig();
moduleConfig.setName("demo-action");
moduleConfig.setEnabled(true);
moduleConfig.setVersion("1.0.0");
//配置自定义的properties信息
moduleConfig.setProperties(ImmutableMap.of("svnPath", new Object()));
moduleConfig.setModuleUrl(ImmutableList.of(demoModule));
return moduleConfig;
}
package com.alibaba.test;
import com.alipay.jarslink.api.Action;
import com.alipay.jarslink.api.Module;
import com.alipay.jarslink.api.ModuleLoader;
import com.alipay.jarslink.api.ModuleManager;
import com.alipay.jarslink.api.impl.AbstractModuleRefreshScheduler;
import com.alipay.jarslink.api.impl.ModuleManagerImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Map;
import java.util.Set;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath*:jarslink.xml"})
public class JarsLinkTest {
@Autowired
private ModuleLoader moduleLoader;
@Autowired
private ModuleManager moduleManager;
@Test
public void test2() {
//加载和注册模块
Module module = moduleLoader.load(ModuleRefreshSchedulerImpl.buildModuleConfig_Demo());//加载模块,加载一个模块
moduleManager.register(module);
String result = module.doAction("hello-world-action", "rabbit");
System.out.println("result = " + result);
}
}
总结
一个模块的Action开发就是这么简单,1)创建自己的Action。2)配置文件中配置bean信息。问题在于每次开发一个Action就要配置文件中加配置文件<beanid=”” name=”” class=”” />,一旦类多了,这样管理比较麻烦,还好在1.6版本中提供了扫描包的功能。
扫描包功能
Action的开发过程是一样的,只不过在xml文件中不需要使用配置信息,而是在调用的时候扫描指定的包即可,下面是关键的代码。
package com.alibaba.test;
import com.alipay.jarslink.api.Module;
import com.alipay.jarslink.api.ModuleConfig;
import com.alipay.jarslink.api.ModuleLoader;
import com.alipay.jarslink.api.ModuleManager;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.net.URL;
/** * Created by HASEE on 2018/4/23. */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath*:jarslink.xml"})
public class AnnoJarsLinkTest {
@Autowired
private ModuleLoader moduleLoader;
@Autowired
private ModuleManager moduleManager;
@Test
public void test1() {
URL demoModule = Thread.currentThread().getContextClassLoader().getResource("jarslink-demo-anno-action-1.0-SNAPSHOT.jar");
ModuleConfig moduleConfig = new ModuleConfig();
moduleConfig.setName("anno-action");
moduleConfig.setEnabled(true);
moduleConfig.setVersion("1.0.0");
moduleConfig.setProperties(ImmutableMap.of("svnPath", new Object()));
moduleConfig.setModuleUrl(ImmutableList.of(demoModule));
//扫描模块下的Action
moduleConfig.addScanPackage("com.alibaba.action");
Module module = moduleLoader.load(moduleConfig);
moduleManager.register(module);
System.out.println("string to long " + module.doAction("string-to-long", "500"));
}
}
最佳实践
HTTP请求转发
通过请求路径来确定请求的模块和action
private ModuleManager moduleManager;
@RequestMapping(value = "module/{moduleName}/{actionName}/process.json", method = {
RequestMethod.GET,RequestMethod.POST })
public Object process(HttpServletRequest request, HttpServletResponse response) {
Map<String, String> pathVariables = resolvePathVariables(request);
String moduleName = pathVariables.get("moduleName").toUpperCase()
String actionName = pathVariables.get("actionName").toUpperCase()
String actionRequest = XXX;
return moduleManager.doAction(moduleName,
actionName, actionRequest);
}
private Map<String, String> resolvePathVariables(HttpServletRequest request) {
return (Map<String, String>) request
.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
}
如何发布模块
有两个方案:
方案1 拉模式
- 1:在本地编译代码打包成JAR包。
- 2:把JAR上传到一个远程文件服务器,比如阿里云的OSS。
- 3:应用从远程服务器下载JAR,可以把配置信息存放在JAR里,比如版本号,JAR名。
方案2 推模式
- 1:在本地编译代码打包成JAR包。
- 2:把JAR直接SCP到服务器上的某个目录。
- 3:应用检查服务指定目录的JAR是否有更新,如果有更新就进行加载。
边栏推荐
- "Internet +" contest topic hot docking | I figure to understand 38 propositions of Baidu
- 【TcaplusDB知识库】TcaplusDB系统管理介绍
- Challenges of machine learning system in production
- ECMAScript 6(es6)
- 从零开始搭建物联网系统
- AUTOCAD——三种修剪方式
- Qstype implementation of self drawing interface project practice (I)
- 【TcaplusDB知识库】TcaplusDB系统用户组介绍
- Heap heap sort TOPK
- Interview shock 60: what will cause MySQL index invalidation?
猜你喜欢

Unity shader learning (II) the first shader

matlab习题 —— 创建 50 行 50 列全零矩阵、全 1 矩阵、单位矩阵、对角矩阵,输出矩阵第135号元素。

Unity Shader学习(一)认识unity shader基本结构

One copy ten, CVPR oral is accused of plagiarizing a lot

星际争霸的虫王IA退役2年搞AI,自叹不如了
![[tcapulusdb knowledge base] tcapulusdb doc acceptance - transaction execution introduction](/img/d9/f6735906a130834c4b3e28de2b2617.png)
[tcapulusdb knowledge base] tcapulusdb doc acceptance - transaction execution introduction

Interview shock 60: what will cause MySQL index invalidation?

"24 of the 29 students in the class successfully went to graduate school" rushed to the hot search! Where are the remaining five?

【TcaplusDB知识库】TcaplusDB常规单据介绍

微软云 (Microsoft Cloud) 技术概述
随机推荐
Jerry's constant feeding of dogs will cause frequent switch interruptions leading to timer [chapter]
[tcapulusdb knowledge base] Introduction to tcapulusdb tcapsvrmgr tool (I)
深入理解 happens-before 原则
AUTOCAD——三种修剪方式
C语言0长度数组的妙用
Institute of Microbiology, Chinese Academy of Sciences recruited 20 young PI, with a resettlement fee of 2million yuan and a start-up fund of 10million yuan (long-term effective)
QStyle类用法总结(二)
Redis distributed lock 15 ask, what have you mastered?
飞桨产业级开源模型库:加速企业AI任务开发与应用
【TcaplusDB知识库】TcaplusDB常规单据介绍
The wonderful use of 0 length array in C language
Jerry's seamless looping [chapter]
Xuri 3sdb, installing the original ROS
matlab习题 —— 创建 50 行 50 列全零矩阵、全 1 矩阵、单位矩阵、对角矩阵,输出矩阵第135号元素。
R语言使用MASS包的polr函数构建有序多分类logistic回归模型、使用VGAM包的vglm函数对有序多分类logistic回归模型进行平行性假设作检验
R language dplyr package arrange function sorts dataframe data, sorts dataframe data through multiple data columns, specifies the first field to be sorted in descending order, and does not specify the
最大路径和问题(摘樱桃问题)
deep learning statistical arbitrage
Leetcode 177 The nth highest salary (June 26, 2022)
Salesforce 容器化 ISV 场景下的软件供应链安全落地实践