当前位置:网站首页>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是否有更新,如果有更新就进行加载。
边栏推荐
- 【TcaplusDB知识库】TcaplusDB单据受理-创建游戏区介绍
- [tcapulusdb knowledge base] tcapulusdb business data backup introduction
- [tcapulusdb knowledge base] Introduction to tcapulusdb analytical text export
- [worthy of collection] centos7 installation MySQL complete operation command
- 【TcaplusDB知识库】TcaplusDB OMS业务人员权限介绍
- The wonderful use of 0 length array in C language
- ECMAScript 6(es6)
- [tcaplusdb knowledge base] Introduction to tcaplusdb tcaplusadmin tool
- 最大路径和问题(摘樱桃问题)
- Precautions for use of IO interface interrupt of Jerry [chapter]
猜你喜欢

巅峰小店APP仿站开发玩法模式讲解源码分享

【TcaplusDB知识库】TcaplusDB单据受理-建表审批介绍

15+城市道路要素分割应用,用这一个分割模型就够了!

Youboxun attended the openharmony technology day to create a new generation of secure payment terminals

【TcaplusDB知识库】TcaplusDB单据受理-创建游戏区介绍

进程间通信详解
![[tcapulusdb knowledge base] Introduction to tcapulusdb general documents](/img/04/b1194ca3340b23a4fb2091d1b2a44d.png)
[tcapulusdb knowledge base] Introduction to tcapulusdb general documents

C语言0长度数组的妙用

Code for structural design of proe/creo household appliances - electric frying pan

杰理之DAC输出方式设置【篇】
随机推荐
【TcaplusDB知识库】TcaplusDB OMS业务人员权限介绍
21:第三章:开发通行证服务:4:进一步完善【发送短信,接口】;(在【发送短信,接口】中,调用阿里云短信服务和redis服务;一种设计思想:BaseController;)
Oracle-多表查询
【TcaplusDB知识库】TcaplusDB业务数据备份介绍
Nvme2.0 protocol - new features
最大路径和问题(摘樱桃问题)
Jerry's seamless looping [chapter]
Naacl 2022 | TAMT: search the transportable Bert subnet through downstream task independent mask training
R语言glm函数构建二分类logistic回归模型(family参数为binomial)、使用AIC函数比较两个模型的AIC值的差异(简单模型和复杂模型)
0基础了解电商系统如何对接支付渠道
R language uses the polR function of mass package to construct the ordered multi classification logistic regression model, and uses the vglm function of VGAM package to test the parallelism hypothesis
QStyle类用法总结(三)
[tcapulusdb knowledge base] tcapulusdb doc acceptance - transaction execution introduction
Jerry's serial port communication serial port receiving IO needs to set digital function [chapter]
Informatics Olympiad all in one 1332: [example 2-1] weekend dance
21: Chapter 3: develop pass service: 4: further improve [send SMS, interface]; (in [send SMS, interface], call Alibaba cloud SMS service and redis service; a design idea: basecontroller;)
Proe/Creo家电产品结构设计规范-电煎锅
VPT模型视频讲解
istio相关资料
Microsoft cloud technology overview