在做项目经常需要用到配置文件,读取文件的路径问题也是我们经常遇到的。一般路径问题分为2种:classpath路径和web路径。
一.Class路径
概念:ClassLoader类加载器,负责加载类的对象。查找classpath离不开ClassLoader的帮助。
ClassLoader提供getResource(String name)方法,查找具有给定名称的资源。
getResource
public URL getResource(String name)查找具有给定名称的资源。资源是可以通过类代码以与代码基无关的方式访问的一些数据(图像、声音、文本等)。
资源名称是以 '/' 分隔的标识资源的路径名称。
此方法首先搜索资源的父类加载器;如果父类加载器为 null,则搜索的路径就是虚拟机的内置类加载器的路径。如果搜索失败,则此方法将调用 findResource(String) 来查找资源。
参数:
name - 资源名称
返回:
读取资源的 URL 对象;如果找不到该资源,或者调用者没有足够的权限获取该资源,则返回 null。
从以下版本开始:
1.1
查找类路径的配置文件总共有多种方法实现,都是在获得
ClassLoader实例的情况下实现的 ,以为PathExample对象为例:
(1) PathExample.class.getResource("")
(2) PathExample.class.getResource("/")
(1)和(2)是调用同一个方法,都是从当前类的Class对象中获取资源地址
getResource
public URL getResource(String name)查找带有给定名称的资源。查找与给定类相关的资源的规则是通过定义类的 classloader 实现的。此方法委托给此对象的类加载器。如果此对象通过引导类加载器加载,则此方法将委托给 ClassLoader.getSystemResource(java.lang.String)。
在委托前,使用下面的算法从给定的资源名构造一个绝对资源名:
如果 name 以 '/' ('\u002f') 开始,则绝对资源名是 '/' 后面的 name 的一部分。
否则,绝对名具有以下形式:
modified_package_name/name
其中 modified_package_name 是此对象的包名,该名用 '/' 取代了 '.' ('\u002e')。
参数:
name - 所需资源的名称
返回:
一个 URL 对象;如果找不到带有该名称的资源,则返回 null
从以下版本开始:
JDK1.1
也就是这个方法是先查找是否有类的过定义类的classloader实现,如果有就从自定义的classloader中查找资源,如果没有就从
ClassLoader.getSystemResource(java.lang.String)也就是从默认的系统类加载器中查找.
(1)表示的当前的包路径,如果配置文件在当前包内,可以直接传入配置文件名字,如:text.xml
(2)表示前的classpath的根路径, 如果配置文件在根目录,则传入参数 /text.xml
如果资源文件在包里面可以通过传入包路径来获得资源地址,如在包a/b/c/test.xml文件,
应传入参数 /a/b/c/test.xml(3) PathExample.class.getClassLoader().getResource("")
此方法获取claspaths根路径
getClassLoader
public ClassLoader getClassLoader()返回该类的类加载器。有些实现可能使用 null 来表示引导类加载器。如果该类由引导类加载器加载,则此方法在这类实现中将返回 null。
如果存在安全管理器,并且调用者的类加载器不是 null,也不同于或是请求其类加载器的类的类加载器的祖先,则此方法通过 RuntimePermission("getClassLoader") 权限调用此安全管理器的 checkPermission 方法,以确保可以访问该类的类加载器。
如果此对象表示一个基本类型或 void,则返回 null。
返回:
加载此对象所表示的类或接口的类加载器。
抛出:
SecurityException - 如果存在安全管理器,并且 checkPermission 方法拒绝对该类类加载器的访问。
另请参见:
ClassLoader, SecurityManager.checkPermission(java.security.Permission), RuntimePermission
从文档中可看出,可能会有NULL的情况,不推荐此方法。
(4)ClassLoader.getSystemClassLoader().getResource("")
(5)ClassLoader.getSystemResource("")
(5)的实现其实还是通过(4)来现实的,都是从系统默认的ClassLoader获取当前的classpath根目录
(6)Thread.currentThread().getContextClassLoader().getResource("")
从当前线程中获取classloader对象
getContextClassLoader
public ClassLoader getContextClassLoader()返回该线程的上下文 ClassLoader。上下文 ClassLoader 由线程创建者提供,供运行于该线程中的代码在加载类和资源时使用。如果未设定,则默认为父线程的 ClassLoader 上下文。原始线程的上下文 ClassLoader 通常设定为用于加载应用程序的类加载器。
首先,如果有安全管理器,并且调用者的类加载器不是 null,也不同于其上下文类加载器正在被请求的线程上下文类加载器的祖先,则通过 RuntimePermission("getClassLoader") 权限调用该安全管理器的 checkPermission 方法,查看是否可以获取上下文 ClassLoader。
返回:
该线程的上下文 ClassLoader
从以下版本开始:
1.2
另请参见:
setContextClassLoader(java.lang.ClassLoader), SecurityManager.checkPermission(java.security.Permission), RuntimePermission
以上六种方法,其实都可以解决问题,并在某些方面不是最好的方式,如果不考虑特殊情况的话,推荐使用的(1)、(2)或(6)。
以下是mybatis源码中用来读配置文件的工具类,很不错,各种classloader都考虑了,很好用,贴出来参考下:
package com.talkweb.spe.config;
import java.io.InputStream;
import java.net.URL;
/**
* A class to wrap access to multiple class loaders making them work as one
*/
public class ClassLoaderWrapper {
ClassLoader defaultClassLoader;
ClassLoader systemClassLoader;
ClassLoaderWrapper() {
try {
systemClassLoader = ClassLoader.getSystemClassLoader();
} catch (SecurityException ignored) {
// AccessControlException on Google App Engine
}
}
/**
* Get a resource as a URL using the current class path
*
* @param resource - the resource to locate
* @return the resource or null
*/
public URL getResourceAsURL(String resource) {
return getResourceAsURL(resource, getClassLoaders(null));
}
/**
* Get a resource from the classpath, starting with a specific class loader
*
* @param resource - the resource to find
* @param classLoader - the first classloader to try
* @return the stream or null
*/
public URL getResourceAsURL(String resource, ClassLoader classLoader) {
return getResourceAsURL(resource, getClassLoaders(classLoader));
}
/**
* Get a resource from the classpath
*
* @param resource - the resource to find
* @return the stream or null
*/
public InputStream getResourceAsStream(String resource) {
return getResourceAsStream(resource, getClassLoaders(null));
}
/**
* Get a resource from the classpath, starting with a specific class loader
*
* @param resource - the resource to find
* @param classLoader - the first class loader to try
* @return the stream or null
*/
public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
return getResourceAsStream(resource, getClassLoaders(classLoader));
}
/**
* Find a class on the classpath (or die trying)
*
* @param name - the class to look for
* @return - the class
* @throws ClassNotFoundException Duh.
*/
public Class<?> classForName(String name) throws ClassNotFoundException {
return classForName(name, getClassLoaders(null));
}
/**
* Find a class on the classpath, starting with a specific classloader (or die trying)
*
* @param name - the class to look for
* @param classLoader - the first classloader to try
* @return - the class
* @throws ClassNotFoundException Duh.
*/
public Class<?> classForName(String name, ClassLoader classLoader) throws ClassNotFoundException {
return classForName(name, getClassLoaders(classLoader));
}
/**
* Try to get a resource from a group of classloaders
*
* @param resource - the resource to get
* @param classLoader - the classloaders to examine
* @return the resource or null
*/
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
for (ClassLoader cl : classLoader) {
if (null != cl) {
// try to find the resource as passed
InputStream returnValue = cl.getResourceAsStream(resource);
// now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource
if (null == returnValue) returnValue = cl.getResourceAsStream("/" + resource);
if (null != returnValue) return returnValue;
}
}
return null;
}
/**
* Get a resource as a URL using the current class path
*
* @param resource - the resource to locate
* @param classLoader - the class loaders to examine
* @return the resource or null
*/
URL getResourceAsURL(String resource, ClassLoader[] classLoader) {
URL url;
for (ClassLoader cl : classLoader) {
if (null != cl) {
// look for the resource as passed in...
url = cl.getResource(resource);
// ...but some class loaders want this leading "/", so we'll add it
// and try again if we didn't find the resource
if (null == url) url = cl.getResource("/" + resource);
// "It's always in the last place I look for it!"
// ... because only an idiot would keep looking for it after finding it, so stop looking already.
if (null != url) return url;
}
}
// didn't find it anywhere.
return null;
}
/**
* Attempt to load a class from a group of classloaders
*
* @param name - the class to load
* @param classLoader - the group of classloaders to examine
* @return the class
* @throws ClassNotFoundException - Remember the wisdom of Judge Smails: Well, the world needs ditch diggers, too.
*/
Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {
for (ClassLoader cl : classLoader) {
if (null != cl) {
try {
Class<?> c = Class.forName(name, true, cl);
if (null != c) return c;
} catch (ClassNotFoundException e) {
// we'll ignore this until all classloaders fail to locate the class
}
}
}
throw new ClassNotFoundException("Cannot find class: " + name);
}
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
return new ClassLoader[]{
classLoader,
defaultClassLoader,
Thread.currentThread().getContextClassLoader(),
getClass().getClassLoader(),
systemClassLoader};
}
}
package com.talkweb.spe.config;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.Properties;
/**
* A class to simplify access to resources through the classloader.
*/
public class Resources {
private static ClassLoaderWrapper classLoaderWrapper = new ClassLoaderWrapper();
/**
* Charset to use when calling getResourceAsReader.
* null means use the system default.
*/
private static Charset charset;
Resources() {
}
/**
* Returns the default classloader (may be null).
*
* @return The default classloader
*/
public static ClassLoader getDefaultClassLoader() {
return classLoaderWrapper.defaultClassLoader;
}
/**
* Sets the default classloader
*
* @param defaultClassLoader - the new default ClassLoader
*/
public static void setDefaultClassLoader(ClassLoader defaultClassLoader) {
classLoaderWrapper.defaultClassLoader = defaultClassLoader;
}
/**
* Returns the URL of the resource on the classpath
*
* @param resource The resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static URL getResourceURL(String resource) throws IOException {
return classLoaderWrapper.getResourceAsURL(resource);
}
/**
* Returns the URL of the resource on the classpath
*
* @param loader The classloader used to fetch the resource
* @param resource The resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static URL getResourceURL(ClassLoader loader, String resource) throws IOException {
URL url = classLoaderWrapper.getResourceAsURL(resource, loader);
if (url == null) throw new IOException("Could not find resource " + resource);
return url;
}
/**
* Returns a resource on the classpath as a Stream object
*
* @param resource The resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static InputStream getResourceAsStream(String resource) throws IOException {
return getResourceAsStream(null, resource);
}
/**
* Returns a resource on the classpath as a Stream object
*
* @param loader The classloader used to fetch the resource
* @param resource The resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
if (in == null) throw new IOException("Could not find resource " + resource);
return in;
}
/**
* Returns a resource on the classpath as a Properties object
*
* @param resource The resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static Properties getResourceAsProperties(String resource) throws IOException {
Properties props = new Properties();
InputStream in = getResourceAsStream(resource);
props.load(in);
in.close();
return props;
}
/**
* Returns a resource on the classpath as a Properties object
*
* @param loader The classloader used to fetch the resource
* @param resource The resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static Properties getResourceAsProperties(ClassLoader loader, String resource) throws IOException {
Properties props = new Properties();
InputStream in = getResourceAsStream(loader, resource);
props.load(in);
in.close();
return props;
}
/**
* Returns a resource on the classpath as a Reader object
*
* @param resource The resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static Reader getResourceAsReader(String resource) throws IOException {
Reader reader;
if (charset == null) {
reader = new InputStreamReader(getResourceAsStream(resource));
} else {
reader = new InputStreamReader(getResourceAsStream(resource), charset);
}
return reader;
}
/**
* Returns a resource on the classpath as a Reader object
*
* @param loader The classloader used to fetch the resource
* @param resource The resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static Reader getResourceAsReader(ClassLoader loader, String resource) throws IOException {
Reader reader;
if (charset == null) {
reader = new InputStreamReader(getResourceAsStream(loader, resource));
} else {
reader = new InputStreamReader(getResourceAsStream(loader, resource), charset);
}
return reader;
}
/**
* Returns a resource on the classpath as a File object
*
* @param resource The resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static File getResourceAsFile(String resource) throws IOException {
return new File(getResourceURL(resource).getFile());
}
/**
* Returns a resource on the classpath as a File object
*
* @param loader - the classloader used to fetch the resource
* @param resource - the resource to find
* @return The resource
* @throws java.io.IOException If the resource cannot be found or read
*/
public static File getResourceAsFile(ClassLoader loader, String resource) throws IOException {
return new File(getResourceURL(loader, resource).getFile());
}
/**
* Gets a URL as an input stream
*
* @param urlString - the URL to get
* @return An input stream with the data from the URL
* @throws java.io.IOException If the resource cannot be found or read
*/
public static InputStream getUrlAsStream(String urlString) throws IOException {
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
return conn.getInputStream();
}
/**
* Gets a URL as a Reader
*
* @param urlString - the URL to get
* @return A Reader with the data from the URL
* @throws java.io.IOException If the resource cannot be found or read
*/
public static Reader getUrlAsReader(String urlString) throws IOException {
Reader reader;
if (charset == null) {
reader = new InputStreamReader(getUrlAsStream(urlString));
} else {
reader = new InputStreamReader(getUrlAsStream(urlString), charset);
}
return reader;
}
/**
* Gets a URL as a Properties object
*
* @param urlString - the URL to get
* @return A Properties object with the data from the URL
* @throws java.io.IOException If the resource cannot be found or read
*/
public static Properties getUrlAsProperties(String urlString) throws IOException {
Properties props = new Properties();
InputStream in = getUrlAsStream(urlString);
props.load(in);
in.close();
return props;
}
/**
* Loads a class
*
* @param className - the class to fetch
* @return The loaded class
* @throws ClassNotFoundException If the class cannot be found (duh!)
*/
public static Class<?> classForName(String className) throws ClassNotFoundException {
return classLoaderWrapper.classForName(className);
}
public static Charset getCharset() {
return charset;
}
public static void setCharset(Charset charset) {
Resources.charset = charset;
}
}
读取资源文件,直接使用Resources即可,简单好用!
二.web路径
getServletContext().getRealPath("/")
获取web项目的根路径 就能大解决问题了
以后如有发现问题再补充,关于classloader的地方还有些不理解,以后再补充。