首页

实现获取扫描指定包路径下的jar文件或class文件JarPojoHandler类示例代码

标签:java,代码,例子,getClazzInstances,jar类加载器,class文件     发布时间:2017-03-11   

通过JarPojoHandler类实现了扫描指定路径下如何获取所有的JAR包或class文件,可以对特定class对象文件筛选过滤等,具体代码如下所示

import java.io.File;@b@import java.io.FileFilter;@b@import java.io.IOException;@b@import java.net.JarURLConnection;@b@import java.net.URL;@b@import java.net.URLClassLoader;@b@import java.net.URLDecoder;@b@import java.util.ArrayList;@b@import java.util.Enumeration;@b@import java.util.HashMap;@b@import java.util.LinkedHashSet;@b@import java.util.List;@b@import java.util.Map;@b@import java.util.Set;@b@import java.util.jar.JarEntry;@b@import java.util.jar.JarFile;@b@@b@/**@b@ * 扫描指定包(包括jar)下的class文件 <br> @b@ */@b@public class JarPojoHandler {@b@	private static Map<String, List<Class<?>>> pojoClasses = new HashMap<String, List<Class<?>>>();@b@@b@	/**@b@	 * 获得指定路径下的所有 JAR包@b@	 * @param strPath@b@	 * @return@b@	 */@b@	public static List<File> getDirFiles(String strPath) {@b@		List<File> list = new ArrayList<File>();@b@		File f = new File(strPath);@b@		if (f.isDirectory()) {@b@			File[] fList = f.listFiles();@b@			for (int j = 0; j < fList.length; j++) {@b@				if (fList[j].isDirectory()) {@b@					getDirFiles(strPath + fList[j].getName() + "\\");@b@				} else {@b@					int u = fList[j].getName().indexOf(".");@b@					if (u != -1) {@b@						if (fList[j].getName().substring(u + 1, fList[j].getName().length()).equals("jar")) {@b@							list.add(fList[j]);@b@						}@b@					}@b@				}@b@			}@b@		}@b@		return list;@b@	}@b@@b@	/**@b@	 * 加载数据持久化对象@b@	 * @param file@b@	 * @param packages@b@	 * @param current@b@	 * @return@b@	 */@b@	public static List<Class<?>> getClazzInstances(File file, String packages,@b@			String current) {@b@		try {@b@			if (file == null) return null;@b@			URLClassLoader loader = new URLClassLoader(new URL[] { new URL(@b@					"file:" + file.getAbsolutePath()) }, Thread.currentThread()@b@					.getContextClassLoader());@b@			List<Class<?>> classinstances = new ArrayList<Class<?>>();@b@			JarFile jarFile = new JarFile(file);@b@			Enumeration<?> enum1 = jarFile.entries();@b@			List<Class<?>> clzlist = JarPojoHandler.pojoClasses.get(current);@b@			if(clzlist == null ) {@b@				clzlist = new ArrayList<Class<?>>();@b@				pojoClasses.put(current, clzlist);@b@			}@b@			while (enum1.hasMoreElements()) {@b@				JarEntry entry = (JarEntry) enum1.nextElement();@b@				if (entry.isDirectory()) continue;@b@				String jar = entry.getName();@b@				if (jar.endsWith(".class")) {@b@					String clzname = jar.substring(0, jar.lastIndexOf(".class")).replace('/', '.');@b@					String clzpackage = clzname.substring(0, clzname.lastIndexOf("."));@b@					String currentpackage = packages + "." + current + ".bean";@b@					if (clzpackage.equals(currentpackage)) {@b@						Class<?> clz = loader.loadClass(clzname);@b@						classinstances.add(clz);@b@					}@b@					if (clzname.startsWith(packages)) {@b@						Class<?> clz = loader.loadClass(clzname);@b@						clzlist.add(clz);@b@					}@b@				}@b@			}@b@			if(jarFile != null) jarFile.close();@b@			return classinstances;@b@		} catch (Exception e) {@b@			e.printStackTrace();@b@		}@b@		return null;@b@	}@b@@b@	public static Set<Class<?>> getClasses(String pack) {@b@		// 第一个class类的集合@b@		Set<Class<?>> classes = new LinkedHashSet<Class<?>>();@b@		// 是否循环迭代@b@		boolean recursive = true;@b@		// 获取包的名字 并进行替换@b@		String packageName = pack;@b@		String packageDirName = packageName.replace('.', '/');@b@		// 定义一个枚举的集合 并进行循环来处理这个目录下的things@b@		Enumeration<URL> dirs;@b@		try {@b@			dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);@b@			// 循环迭代下去@b@			while (dirs.hasMoreElements()) {@b@				// 获取下一个元素@b@				URL url = dirs.nextElement();@b@				// 得到协议的名称@b@				String protocol = url.getProtocol();@b@				// 如果是以文件的形式保存在服务器上@b@				if ("file".equals(protocol)) {@b@					// file类型的扫描@b@					// 获取包的物理路径@b@					String filePath = URLDecoder.decode(url.getFile(), "UTF-8");@b@					// 以文件的方式扫描整个包下的文件 并添加到集合中@b@					findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);@b@				} else if ("jar".equals(protocol)) {@b@					// 如果是jar包文件@b@					// 定义一个JarFile@b@					// jar类型的扫描@b@					JarFile jar;@b@					try {@b@						// 获取jar@b@						jar = ((JarURLConnection) url.openConnection()).getJarFile();@b@						// 从此jar包 得到一个枚举类@b@						Enumeration<JarEntry> entries = jar.entries();@b@						// 同样的进行循环迭代@b@						while (entries.hasMoreElements()) {@b@							// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件@b@							JarEntry entry = entries.nextElement();@b@							String name = entry.getName();@b@							// 如果是以/开头的@b@							if (name.charAt(0) == '/') {@b@								// 获取后面的字符串@b@								name = name.substring(1);@b@							}@b@							// 如果前半部分和定义的包名相同@b@							if (name.startsWith(packageDirName)) {@b@								int idx = name.lastIndexOf('/');@b@								// 如果以"/"结尾 是一个包@b@								if (idx != -1) {@b@									// 获取包名 把"/"替换成"."@b@									packageName = name.substring(0, idx).replace('/', '.');@b@								}@b@								// 如果可以迭代下去 并且是一个包@b@								if ((idx != -1) || recursive) {@b@									// 如果是一个.class文件 而且不是目录@b@									if (name.endsWith(".class") && !entry.isDirectory()) {@b@										// 去掉后面的".class" 获取真正的类名@b@										String className = name.substring(packageName.length() + 1, name.length() - 6);@b@										try {@b@											// 添加到classes@b@											classes.add(Class.forName(packageName + '.' + className));@b@										} catch (ClassNotFoundException e) {@b@											// .error("添加用户自定义视图类错误 找不到此类的.class文件");@b@											e.printStackTrace();@b@										}@b@									}@b@								}@b@							}@b@						}@b@					} catch (IOException e) {@b@						// log.error("在扫描用户定义视图时从jar包获取文件出错");@b@						e.printStackTrace();@b@					}@b@				}@b@			}@b@		} catch (IOException e) {@b@			e.printStackTrace();@b@		}@b@		return classes;@b@	}@b@@b@	public static void findAndAddClassesInPackageByFile(String packageName,@b@			String packagePath, final boolean recursive, Set<Class<?>> classes) {@b@		// 获取此包的目录 建立一个File@b@		File dir = new File(packagePath);@b@		// 如果不存在或者 也不是目录就直接返回@b@		if (!dir.exists() || !dir.isDirectory()) {@b@			// log.warn("用户定义包名 " + packageName + " 下没有任何文件");@b@			return;@b@		}@b@		// 如果存在 就获取包下的所有文件 包括目录@b@		File[] dirfiles = dir.listFiles(new FileFilter() {@b@			// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)@b@			public boolean accept(File file) {@b@				return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));@b@			}@b@		});@b@		// 循环所有文件@b@		for (File file : dirfiles) {@b@			// 如果是目录 则继续扫描@b@			if (file.isDirectory()) {@b@				findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes);@b@			} else {@b@				// 如果是java类文件 去掉后面的.class 只留下类名@b@				String className = file.getName().substring(0, file.getName().length() - 6);@b@				try {@b@					// 添加到集合中去@b@					// classes.add(Class.forName(packageName + '.' +  className));@b@					// 经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净@b@					classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className));@b@				} catch (ClassNotFoundException e) {@b@					// log.error("添加用户自定义视图类错误 找不到此类的.class文件");@b@					e.printStackTrace();@b@				}@b@			}@b@		}@b@	}@b@@b@	public static Map<String, List<Class<?>>> getPojoClasses() {@b@		return pojoClasses;@b@	}@b@	@b@	public static void realese() {@b@		pojoClasses.clear();@b@	}@b@@b@}