由于业务需要,在webapps下有两个项目A和B,A项目要获取B项目中所有controller的注解。可是同样的代码在普通的main函数执行可以获取到,但是部署到tomcat中就获取不到,感觉和classloader有关系,但是又不大懂,有没有高人指导?
这是反射代码
public class Recursion { /** * 递归获取指定文件或者文件夹下的指定文件 * * @param path * @param filePaths * @param fileType */ public static void searchFiles(String path, List<String> filePaths, String fileType) { File file = new File(path); if (file.isFile()) { filePaths.add(path); return; } File[] files = file.listFiles(); if (files != null) { for (File itemFile : files) { if (itemFile.isFile() && itemFile.getName().endsWith(fileType)) { filePaths.add(itemFile.getAbsolutePath()); } else if (itemFile.isDirectory()) { searchFiles(itemFile.getAbsolutePath(), filePaths, fileType); } } } } /** * 返回包名和class文件路径的字典集合 * * @param path * @return */ public static ConcurrentHashMap<String, String> getClasses(String path) { List<String> filePaths = new ArrayList<>(); searchFiles(path, filePaths, ".class"); ConcurrentHashMap<String, String> classs = new ConcurrentHashMap<>(); for (String filePath : filePaths) { int classes = filePath.indexOf("classes"); String packageName = filePath.substring(classes + 8, filePath.length()); packageName = packageName.replaceAll("\\\\", "."); packageName = packageName.replaceAll(".class", ""); classs.put(packageName, filePath); } return classs; } }
public class ClassLoaderUtil extends ClassLoader { private byte[] results; public ClassLoaderUtil(String classPathName) { results = loadClassFile(classPathName); } /** * @param packageName 包名 */ public void getAnnotations(String packageName) { try { Class<?> clazz = this.loadClass(packageName); Object object = clazz.newInstance(); Annotation[] annotations = object.getClass().getAnnotations(); System.out.println(object.getClass().getName()); System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); for (Annotation annotation : annotations) { System.out.println(annotation.toString()); } System.out.println(""); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 把class文件转成字节码 * * @param classPath * @return */ private byte[] loadClassFile(String classPath) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { FileInputStream fi = new FileInputStream(classPath); BufferedInputStream bis = new BufferedInputStream(fi); byte[] data = new byte[1024 * 256]; int ch = 0; while ((ch = bis.read(data, 0, data.length)) != -1) { bos.write(data, 0, ch); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return bos.toByteArray(); } @Override protected Class<?> loadClass(String arg0, boolean arg1) { Class<?> clazz = findLoadedClass(arg0); if (clazz == null) { if (getParent() != null) { try { //这里我们要用父加载器加载如果加载不成功会抛异常 clazz = getParent().loadClass(arg0); } catch (Exception e) { } } if (clazz == null) { clazz = defineClass(arg0, results, 0, results.length); } } return clazz; } }
这是普通类测试代码
public class test { public static void main(String[] args) { String webBaseRealPath = "D:\\myself\\apache-tomcat-8.5.28\\webapps\\http\\WEB-INF\\classes\\com\\sac\\web\\controller"; ConcurrentHashMap<String, String> classes = Recursion.getClasses(webBaseRealPath); classes.forEach((k, v) -> { ClassLoaderUtil myClassLoader = new ClassLoaderUtil(v); myClassLoader.getAnnotations(k); }); } }
是可以获取到注解的
但是放在控制器下,为什么就不行呢?
@RequiresRoles({"dev"}) @ApiOperation(notes = "GET", httpMethod = "GET", value = "获取系统全部资源列表") @GetMapping(value = "resources/total") public ResponseEntity getAll(HttpServletRequest servletRequest) throws ClassNotFoundException { String webBaseRealPath = servletRequest.getServletContext().getRealPath(""); String webBusinessRelativePath = ConfigurationProvider.config.getWebCore().getPublishPath().getBussinessApiRelativePath(); String webBaseRelativePath = ConfigurationProvider.config.getWebCore().getPublishPath().getApiRelativePath(); String webBusinessRealPath = webBaseRealPath.replace(webBaseRelativePath, webBusinessRelativePath); //test webBaseRealPath = "D:\\myself\\apache-tomcat-8.5.28\\webapps\\http\\WEB-INF\\classes\\com\\sac\\web\\controller"; ConcurrentHashMap<String, String> classes = Recursion.getClasses(webBaseRealPath); classes.clear(); classes.put("com.sac.web.controller.BaseController", "D:\\myself\\apache-tomcat-8.5.28\\webapps\\http\\WEB-INF\\classes\\com\\sac\\web\\controller\\BaseController.class"); classes.forEach((k, v) -> { ClassLoaderUtil myClassLoader = new ClassLoaderUtil(v); myClassLoader.getAnnotations(k); }); //Class<?> aClass = Class.forName("com.sac.web.controller.OrganizationController"); resourceService.getAllSystemResources(webBaseRealPath); return null; }