Project获取资源需要一个启点,加载资源的动作是由ClassLoader来完成的。
Class对象和当前线程对象可以找到当前加载资源的ClassLoader,
通过ClassLoader的getResource(String name)方法及其它衍生出来的方法可以找到Application的启点及获取相关资源
private void display() { path=this.getClass().getResource("/loadresource").getPath(); System.out.println(path); path=this.getClass().getResource("/loadresource/bp.txt").getPath(); System.out.println(path); path=this.getClass().getResource("/").getPath(); System.out.println(path); URL url=this.getClass().getResource("loadresource/bp.txt"); System.out.println("Is Null:"+(url==null)); path=GetResouceTest.class.getClassLoader().getResource("").getPath(); System.out.println(path); path=GetResouceTest.class.getClassLoader().getResource("loadresource/bp.txt").getPath(); System.out.println(path); url=GetResouceTest.class.getClassLoader().getResource("/loadresource/bp.txt"); System.out.println("Is Null:"+(url==null)); path=Thread.currentThread().getContextClassLoader().getResource("").getPath(); System.out.println(path); path=Thread.currentThread().getContextClassLoader().getResource("loadresource/bp.txt").getPath(); System.out.println(path); url=Thread.currentThread().getContextClassLoader().getResource("loadresource/bp.txt"); System.out.println("Is Null:"+(url==null)); url=Thread.currentThread().getContextClassLoader().getResource("/loadresource/bp.txt"); System.out.println("Is Null:"+(url==null)); }
Output:
/E:/java/workspace/test/bin/loadresource /E:/java/workspace/test/bin/loadresource/bp.txt /E:/java/workspace/test/bin/ Is Null:true /E:/java/workspace/test/bin/ /E:/java/workspace/test/bin/loadresource/bp.txt Is Null:true /E:/java/workspace/test/bin/ /E:/java/workspace/test/bin/loadresource/bp.txt Is Null:false Is Null:true
Conclusion:
java.lang.Class<T>的URL getResource(String name)时可以使用参数:
(1)"/":代表项目根目录,也就是ClassPath的root
(2)以"/"开头的包路径
java.lang.ClassLoader的URL getResource(String name)时使用参数:
(1)"":代表项目根目录,也就是ClassPath的root
(2)不以"/"开头的包路径
源码解析:
java.lang.Class
/** * Finds a resource with a given name. The rules for searching resources * associated with a given class are implemented by the defining * {@linkplain ClassLoader class loader} of the class. This method * delegates to this object's class loader. If this object was loaded by * the bootstrap class loader, the method delegates to {@link * ClassLoader#getSystemResource}. * * <p> Before delegation, an absolute resource name is constructed from the * given resource name using this algorithm: * * <ul> * * <li> If the {@code name} begins with a {@code '/'} * (<tt>'\u002f'</tt>), then the absolute name of the resource is the * portion of the {@code name} following the {@code '/'}. * * <li> Otherwise, the absolute name is of the following form: * * <blockquote> * {@code modified_package_name/name} * </blockquote> * * <p> Where the {@code modified_package_name} is the package name of this * object with {@code '/'} substituted for {@code '.'} * (<tt>'\u002e'</tt>). * * </ul> * * @param name name of the desired resource * @return A {@link java.net.URL} object or {@code null} if no * resource with this name is found * @since JDK1.1 */ public java.net.URL getResource(String name) { name = resolveName(name); ClassLoader cl = getClassLoader0(); if (cl==null) { // A system class. return ClassLoader.getSystemResource(name); } return cl.getResource(name); }
/** * Add a package name prefix if the name is not absolute Remove leading "/" * if name is absolute */ private String resolveName(String name) { if (name == null) { return name; } if (!name.startsWith("/")) { Class<?> c = this; while (c.isArray()) { c = c.getComponentType(); } String baseName = c.getName(); int index = baseName.lastIndexOf('.'); if (index != -1) { name = baseName.substring(0, index).replace('.', '/') +"/"+name; } } else { name = name.substring(1); } return name; }
从源码看:
(1)java.lang.Class的getResource(String name)方法调用了ClassLoader的getResource(String name)方法;
(2)java.lang.Class的resolveName(String name)方法去掉了name中的第一个字符“/”,
java.lang.Classloader的getResource(String name)的参数name首字母没有“/”
Extension section:
如果路径中有空格及中文在某些场景会出来问题。
可以尝试在getResource(Sting name).toURL()来解决。