1、读取jar包中的MANIFEST.MF文件的属性
// 取到JarFile
JarFile jarFile = new JarFile("jar的路径");
// 获取Manifest
Manifest mf = jarFile.getManifest();
// 获取到属性集合
Attributes attrs = mf.getMainAttributes();
// 读取实现类
String attr = attrs.getValue("需要读取的属性");
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* jar包加载器
* @author wst 2021年3月18日 下午4:18:30
*
*/
public class JarLoader {
// 资源
public static List<URLClassLoader> cachedJarFiles = new ArrayList<URLClassLoader>();
// 加载的类
public static Map<String, Class<?>> clazzMap = new HashMap<>(16);
public JarLoader() {
}
/**
* 扫描一个文件夹下面的所有jar,不包含子文件夹和子jar
* @author wst 2021年3月18日 下午4:18:46
* @param directoryPath
* @return
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws IOException
*/
public static Map<String, Class<?>> loadAllJarFromAbsolute(String directoryPath) throws
NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
clazzMap.clear();
File directory = new File(directoryPath);
// 判断是否为文件夹,如果是文件,直接用单个jar解析的方法去解析
if (!directory.isDirectory()) {
// 添加jar扫描路径
addUrl(directory);
return loadJarFromAbsolute(directoryPath);
}
// 如果是文件夹,则需要循环加载当前文件夹下面的所有jar
File[] jars = directory.listFiles();
if (jars != null && jars.length > 0) {
List<String> jarPath = new LinkedList<>();
for (File file : jars) {
String fPath = file.getPath();
// 只加载jar
if (fPath.endsWith(".jar")) {
addUrl(file);
jarPath.add(fPath);
}
}
if (jarPath.size() > 0) {
for (String path : jarPath) {
clazzMap.putAll(loadJarFromAbsolute(path));
}
}
}
return clazzMap;
}
/**
* 功能描述: 从绝对路径中加载jar包中的类
* 扫描指定jar包前需要将这个jar的地址加入了系统类加载器的扫描列表中
* 注意,这里只支持单个jar的加载,如果这个jar还引入了其他jar依赖,会加载失败
* 所以只能用来加载对其他jar包没有依赖的简单对象类信息
*
* @author wst 2021年3月18日 下午4:19:12
* @param path jar包路径加载地址
* @return
* @throws IOException
*/
public static Map<String, Class<?>> loadJarFromAbsolute(String path) throws IOException {
@SuppressWarnings("resource")
JarFile jar = new JarFile(path);
Enumeration<JarEntry> entryEnumeration = jar.entries();
while (entryEnumeration.hasMoreElements()) {
JarEntry entry = entryEnumeration.nextElement();
// 先获取类的名称,符合条件之后再做处理,避免处理不符合条件的类
String clazzName = entry.getName();
if (clazzName.endsWith(".class")) {
// 去掉文件名的后缀
clazzName = clazzName.substring(0, clazzName.length() - 6);
// 替换分隔符
clazzName = clazzName.replace("/", ".");
// 加载类,如果失败直接跳过
try {
Class<?> clazz = Class.forName(clazzName);
// 将类名称作为键,类Class对象作为值存入mao
// 因为类名存在重复的可能,所以这里的类名是带包名的
clazzMap.put(clazzName, clazz);
} catch (Throwable e) {
// 这里可能出现有些类是依赖不全的,直接跳过,不做处理,也没法做处理
}
}
}
return clazzMap;
}
/**
* 添加需要扫描的jar包
* @author wst 2021年3月18日 下午4:19:28
* @param jarPath
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws MalformedURLException
*/
public static void addUrl(File jarPath) throws NoSuchMethodException, InvocationTargetException,
IllegalAccessException, MalformedURLException {
URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
// 反射获取类加载器中的addURL方法,并将需要加载类的jar路径
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
if (!method.isAccessible()) {
method.setAccessible(true);
}
URL url = jarPath.toURI().toURL();
// 把当前jar的路径加入到类加载器需要扫描的路径
method.invoke(classLoader, url);
}
/**
* 关闭资源
* @author wst 2021年3月18日 下午4:19:35
*/
public static void close() {
for (URLClassLoader conn : cachedJarFiles) {
try {
conn.close(); // 关闭资源
} catch (IOException e) {
e.printStackTrace();
}
}
cachedJarFiles.clear(); // 清空资源
clazzMap.clear(); // 加载的类
}
}
public boolean connect(String uid, String ip, String port) {
Notification notification = new Notification();
try {
final IcJarFolder jar = icJarFolderService.get("id", "402897817843ea71017843ecd1820000");
// 加载jar包
Map<String, Class<?>> allJar = JarLoader.loadAllJarFromAbsolute(jar.getFolder());
// 找到需要实例的类
Class<?> IABCDevice = allJar.get(jar.getClassName());
// 实例类
Object instance = IABCDevice.newInstance();
// 找到实例类的方法
Method method = IABCDevice.getMethod("connect", String.class, String.class, String.class);
// String[] param = new String[] {uid, ip, port};
//执行方法
Object ada = method.invoke(instance, uid, ip, port);
logger.info("jar执行结果: {}", JSONObject.toJSONString(ada));
JarLoader.close();
notification.setTipMessage("jar执行完成");
notification.setSuccess(true);
} catch (Exception e) {
JarLoader.close();
e.printStackTrace();
notification.setTipMessage("jar执行出错");
notification.setSuccess(false);
}
return true;
}