引子
事件描述
开发环境:Mac, dea,Spring boot 1.5.3.RELEASE
在开发微信小程序客服消息的时候,需要针对context为1的内容回复一张图片。
因为,微信小程序相关的配置都是写在Common模板下的,所以就把图片放在Common模块下的resource中。

IDEA中,使用以下代码都能拿到图片对象。
1
| InputStream is = ClassLoader.getSystemResourceAsStream("qrcode_for_gh_ac1de8498046_258.jpg");
|
1
| InputStream is = WxMaServiceConfiguration.class.getResourceAsStream("/qrcode_for_gh_ac1de8498046_258.jpg");
|
当项目部署到服务器上的tomcat的时候,以上两个方法就都找不到图片对象了。
1 2 3 4 5 6 7
| -webroot -WEB-INF -classes -application.properties ...... -lib -xxx-common-1.0.0-SNAPSHOT.jar(jarz中包含了图片)
|
为什么开发环境可以加载,部署到服务器上就加载不了了呢?
分析
ClassLoader.getSystemResourceAsStream
java.lang.ClassLoader
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| public abstract class ClassLoader {
public static InputStream getSystemResourceAsStream(String name) { URL url = getSystemResource(name); try { return url != null ? url.openStream() : null; } catch (IOException e) { return null; } }
public static URL getSystemResource(String name) { ClassLoader system = getSystemClassLoader(); if (system == null) { return getBootstrapResource(name); } return system.getResource(name); }
@CallerSensitive public static ClassLoader getSystemClassLoader() { initSystemClassLoader(); if (scl == null) { return null; } SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkClassLoaderPermission(scl, Reflection.getCallerClass()); } return scl; }
private static synchronized void initSystemClassLoader() { if (!sclSet) { if (scl != null) throw new IllegalStateException("recursive invocation"); sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); if (l != null) { Throwable oops = null; scl = l.getClassLoader(); try { scl = AccessController.doPrivileged( new SystemClassLoaderAction(scl)); } catch (PrivilegedActionException pae) { oops = pae.getCause(); if (oops instanceof InvocationTargetException) { oops = oops.getCause(); } } if (oops != null) { if (oops instanceof Error) { throw (Error) oops; } else { throw new Error(oops); } } } sclSet = true; } } private static URL getBootstrapResource(String name) { URLClassPath ucp = getBootstrapClassPath(); Resource res = ucp.getResource(name); return res != null ? res.getURL() : null; }
static URLClassPath getBootstrapClassPath() { return sun.misc.Launcher.getBootstrapClassPath(); } ...... }
|
sun.misc.Launcher
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| public class Launcher { private static URLStreamHandlerFactory factory = new Launcher.Factory(); private static Launcher launcher = new Launcher(); private static String bootClassPath = System.getProperty("sun.boot.class.path"); private ClassLoader loader;
......
public Launcher() { Launcher.ExtClassLoader var1; try { var1 = Launcher.ExtClassLoader.getExtClassLoader(); } catch (IOException var10) { throw new InternalError("Could not create extension class loader", var10); }
try { this.loader = Launcher.AppClassLoader.getAppClassLoader(var1); } catch (IOException var9) { throw new InternalError("Could not create application class loader", var9); }
Thread.currentThread().setContextClassLoader(this.loader); ......
}
public static URLClassPath getBootstrapClassPath() { return Launcher.BootClassPathHolder.bcp; }
......
private static class BootClassPathHolder { static final URLClassPath bcp; private BootClassPathHolder() {}
static { URL[] var0; if (Launcher.bootClassPath != null) { var0 = (URL[])AccessController.doPrivileged(new PrivilegedAction<URL[]>() { public URL[] run() { File[] var1 = Launcher.getClassPath(Launcher.bootClassPath); int var2 = var1.length; HashSet var3 = new HashSet();
for(int var4 = 0; var4 < var2; ++var4) { File var5 = var1[var4]; if (!var5.isDirectory()) { var5 = var5.getParentFile(); }
if (var5 != null && var3.add(var5)) { MetaIndex.registerDirectory(var5); } }
return Launcher.pathToURLs(var1); } }); } else { var0 = new URL[0]; }
bcp = new URLClassPath(var0, Launcher.factory, (AccessControlContext)null); bcp.initLookupCache((ClassLoader)null); } }
static class AppClassLoader extends URLClassLoader { public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException { final String var1 = System.getProperty("java.class.path"); final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1); return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() { public Launcher.AppClassLoader run() { URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2); return new Launcher.AppClassLoader(var1x, var0); } }); } ...... } }
|
从上面代码可以知道,java.lang.ClassLoader#getSystemClassLoader
获取是 sun.misc.Launcher.AppClassLoader
。
java.lang.ClassLoader#getBootstrapResource
方法,返回的是 sun.misc.URLClassPath
对象。这个对象是在rt.jar包中的。
https://blog.csdn.net/briblue/article/details/54973413 详细看下 这里的classloader内容。
XXX.class.getResourceAsStream
WebappClassLoader 可以加载 jar中的资源文件
WebappClassLoader
context:
delegate: false
repositories:
/WEB-INF/classes/
———-> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@2145b572
1 2 3
| ClassLoader.getSystemClassLoader().getClass() class sun.misc.Launcher$AppClassLoader
|
原文链接: https://adeng-wc.github.io/2019/05/22/Resource/
版权声明: 转载请注明出处.