动态加载jar,实现自定义业务
Posted malaya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态加载jar,实现自定义业务相关的知识,希望对你有一定的参考价值。
在实际业务中,我们经常会遇到需要按不同用户实现不同业务逻辑,如果按照最简单粗暴的做法,当然是使用if else ...来实现。
不过作为一个社会人,这样怎么能体现出我们的战斗力呢,下面我们来实现一个牛叉的方法。
具体思路:
将不同的业务逻辑按用户放到不同的jar包,然后系统通过读取jar包,来实现各自业务;
以后即使用户的逻辑发生变化,也只要把jar包上传到服务器,就可以动态实现,不影响生产环境了。
1.接口
public interface InterfaceAction { public String getId(); public abstract String action(); }
2.新建项目
action.ext.bj
pom.xml 依赖于base包
<dependency> <groupId>com.qn</groupId> <artifactId>action.base</artifactId> <version>0.0.1-SNAPSHOT</version>
</dependency>
实现接口
public class ExtBj implements InterfaceAction { /** * @see action.base.code.InterfaceAction#getId() */ @Override public String getId() { return "bj"; } /** * @see action.base.code.InterfaceAction#action() */ @Override public String action() { return "This is bj...."; } }
按照此项目新建个action.ext.nt
实现完接口后,导出jar包,存放到一个目录下;
3.完成自定义MyClassLoader
public class MyClassLoader { private ClassLoader loader; private Map<String, InterfaceAction> actionMap = new HashMap<>(); /** * Getter method for property <tt>actionMap</tt>. * * @return property value of actionMap */ public Map<String, InterfaceAction> getActionMap() { return actionMap; } /** * Setter method for property <tt>actionMap</tt>. * * @param actionMap value to be assigned to property actionMap */ public void setActionMap(Map<String, InterfaceAction> actionMap) { this.actionMap = actionMap; } public void load(String jarFileName) { JarFile jarFile = null; try { File file = new File(jarFileName); URL url = new URL("file:" + jarFileName); loader = new URLClassLoader(new URL[] { url }); file.lastModified(); jarFile = new JarFile(file); Enumeration<JarEntry> enumFiles = jarFile.entries(); JarEntry entry; //遍历Jar包中的每一个文件 while (enumFiles.hasMoreElements()) { entry = enumFiles.nextElement(); String classFullName = entry.getName(); //仅处理.class文件 if (classFullName.indexOf("META-INF") < 0 && classFullName.indexOf(".class") > 0) { String className = classFullName.substring(0, classFullName.length() - 6) .replaceAll("/", "."); //使用当前类加载器加载jar包中的类 System.out.println("加载类start:" + className); Class<?> clazz = loader.loadClass(className); System.out.println("加载类end:" + clazz); boolean flag = isInterface(clazz, InterfaceAction.class); if (flag) { InterfaceAction ia = ((Class<InterfaceAction>) clazz).newInstance(); actionMap.put(ia.getId(), ia); System.out.println(actionMap); } } } } catch (Exception e) { e.printStackTrace(); } } /** * 是否实现该接口 * @param c * @param szInterface * @return */ private boolean isInterface(Class c, Class szInterface) { Class[] face = c.getInterfaces(); for (int i = 0, j = face.length; i < j; i++) { if (face[i].equals(szInterface)) { return true; } } return false; } }
4.接下来就是test了
public static void main(String[] args) { MyClassLoader ml = new MyClassLoader(); ml.load("D:\\temp\\action.ext.bj.jar"); ml.load("D:\\temp\\action.ext.nt.jar"); String s = ml.getActionMap().get("nt").action(); System.out.println(s); }
加载类start:action.ext.bj.ExtBj 加载类end:class action.ext.bj.ExtBj {[email protected]} 加载类start:action.ext.nt.ExtNt 加载类end:class action.ext.nt.ExtNt {[email protected], [email protected]} This is nt.....
韦爵爷说过:大功告成。。。
以上是关于动态加载jar,实现自定义业务的主要内容,如果未能解决你的问题,请参考以下文章
如何在模块化的 java 11 应用程序中动态加载 Libreoffice jar,而不从自定义类加载器中获取 ClassCastException
Springboot 使用@RefreshScope 注解,实现配置文件的动态加载