All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.core.lang.ClassLoaderUtil Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * Copyright (C) 2008 feilong
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.feilong.core.lang;

import static com.feilong.core.bean.ConvertUtil.toList;
import static com.feilong.core.util.MapUtil.newLinkedHashMap;

import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.feilong.core.Validate;
import com.feilong.core.net.URLUtil;
import com.feilong.tools.slf4j.Slf4jUtil;

/**
 * {@link java.lang.ClassLoader ClassLoader}工具类.
 * 
 * 

关于查找资源:

* *
* *
    *
  • {@link #getResource(String)}
  • *
  • {@link #getResourceInAllClassLoader(String, Class)}
  • *
* *
* *

关于 {@link java.lang.Class#getResourceAsStream(String) Class#getResourceAsStream(String)} VS * {@link java.lang.ClassLoader#getResourceAsStream(String) ClassLoader#getResourceAsStream(String)}

* *
* *

* 基本上,两个都可以用于从 classpath 里面进行资源读取,classpath包含classpath中的路径和classpath中的jar *

* *

* 假设配置文件在 src/main/resources下面,比如 messages/feilong-core-message_en_US.properties, *

* *
    *
  1. {@link java.lang.Class#getResourceAsStream(String) Class#getResourceAsStream(String)} 需要这么写 * "/messages/feilong-core-message_en_US.properties",
    * 路径可以写成相对路径或者绝对路径; 以 / 开头,则这样的路径是指定绝对路径, 如果不以 / 开头, 则路径是相对与这个class所在的包的
  2. *
  3. {@link java.lang.ClassLoader#getResourceAsStream(String) ClassLoader#getResourceAsStream(String)} 需要这么写 * "messages/feilong-core-message_en_US.properties",
    * {@link ClassLoader} JVM会使用BootstrapLoader去加载资源文件.
    * 所以路径还是这种相对于工程的根目录即"messages/feilong-core-message_en_US.properties" 不需要"/"
  4. *
  5. 如果你的项目使用了spring,建议条件允许的话,使用 org.springframework.core.io.ClassPathResource,这个类是基于{@link ClassLoader}的,同时会 * org.springframework.util.StringUtils#cleanPath(String),并且如果发现首字符是/斜杆, 会去掉,这样使用起来很方便
  6. *
* *
* * @author feilong * @see java.lang.ClassLoader * @see java.net.URLClassLoader * @see "org.springframework.core.io.ClassPathResource#ClassPathResource(String, ClassLoader)" * @since 1.0.0 */ public final class ClassLoaderUtil{ /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(ClassLoaderUtil.class); /** Don't let anyone instantiate this class. */ private ClassLoaderUtil(){ //AssertionError不是必须的. 但它可以避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化. //see 《Effective Java》 2nd throw new AssertionError("No " + getClass().getName() + " instances for you!"); } //--------------------------------------------------------------- /** * 获得给定名称 resourceName 的资源. * *

示例:

* *
* *

* 比如,在 src/test/resources 目录下面有 messages/feilong-core-test.properties 资源文件,编译之后,地址会出现在 * target/test-classes/messages/feilong-core-test.properties *

* *
     * ClassLoaderUtil.getResource("/messages/feilong-core-test.properties") 
     * 或者 ClassLoaderUtil.getResource("messages/feilong-core-test.properties")
     * 
* * 返回相同的结果 * *
     * file:/E:/Workspaces/feilong/feilong-core/target/test-classes/messages/feilong-core-test.properties
     * 
* *
* *

注意:

*
*
    *
  1. 如果 resourceName 是以斜杆 "/" 开头,那么会被截取,因为 {@link ClassLoader} 解析方式不需要开头的斜杆, 请参见 * org.springframework.core.io.ClassPathResource#ClassPathResource(String, ClassLoader)
  2. *
  3. "",表示classes 的根目录
  4. *
*
* *

不同环境结果不一样:

* *
* * * * * * * * * * * * * * * * * * * *
示例(maven)测试在web环境中,(即使打成jar的情形)
getResource("")file:/E:/Workspaces/feilong/feilong-platform/feilong-core/target/test-classes/file:/E:/Workspaces/feilong/feilong-platform/feilong-web-test/src/main/webapp/WEB-INF/classes/
getResource("com")file:/E:/Workspaces/feilong/feilong-platform/feilong-core/target/test-classes/comfile:/E:/Workspaces/feilong/feilong-platform/feilong-web-test/src/main/webapp/WEB-INF/classes/com/
*
* * @param resourceName * the resource name * @return 如果 resourceName 是null,抛出 {@link NullPointerException}
* 如果找不到该资源,或者调用者没有足够的权限获取该资源,则返回 null * @see "org.apache.commons.lang3.ClassPathUtils#toFullyQualifiedPath(Package, String)" * @see #getResource(ClassLoader, String) * @see #getClassLoaderByClass(Class) */ public static URL getResource(String resourceName){ return getResource(getClassLoaderByClass(ClassLoaderUtil.class), resourceName); } /** * 查找具有给定名称的资源,资源是可以通过类代码以与代码基无关的方式访问的一些数据(图像、声音、文本等). * *

注意:

*
*
    *
  1. 如果 resourceName 是以 斜杆 "/" 开头,那么会被截取, 因为 ClassLoader解析方式不需要 开头的斜杆, 请参见 * org.springframework.core.io.ClassPathResource#ClassPathResource(String, ClassLoader)
  2. *
  3. "",表示classes 的根目录
  4. *
*
* * @param classLoader * the class loader * @param resourceName * the resource name * @return 如果 classLoader 是null,抛出 {@link NullPointerException}
* 如果 resourceName 是null,抛出 {@link NullPointerException}
* 如果找不到该资源,或者调用者没有足够的权限获取该资源,则返回 null * @since 1.2.1 */ private static URL getResource(ClassLoader classLoader,String resourceName){ Validate.notNull(classLoader, "classLoader can't be null!"); Validate.notNull(resourceName, "resourceName can't be null!"); boolean startsWithSlash = resourceName.startsWith("/"); String usePath = startsWithSlash ? StringUtil.substring(resourceName, 1) : resourceName; URL result = classLoader.getResource(usePath); LOGGER.trace("search resource:[\"{}\"] in [{}],result:[{}]", resourceName, classLoader, result); return result; } //--------------------------------------------------------------- /** * 加载资源 resourceName为 InputStream. * *

注意:

*
*
    *
  1. 如果 resourceName 是以 斜杆 "/" 开头,那么会被截取, 因为 ClassLoader解析方式不需要 开头的斜杆, 请参见 * org.springframework.core.io.ClassPathResource#ClassPathResource(String, ClassLoader)
  2. *
  3. "",表示classes 的根目录
  4. *
*
* * @param resourceName * The name of the resource to load * @param callingClass * The Class object of the calling object * @return 如果 resourceName 是null,抛出 {@link NullPointerException}
* 如果查找不到资源,那么返回 null * @see #getResourceInAllClassLoader(String, Class) * @see "org.apache.velocity.util.ClassUtils#getResourceAsStream(Class, String)" */ public static InputStream getResourceAsStream(String resourceName,Class callingClass){ URL url = getResourceInAllClassLoader(resourceName, callingClass); return URLUtil.openStream(url); } /** * Load a given resource. * *

注意:

*
*
    *
  1. 如果 resourceName 是以 斜杆 "/" 开头,那么会被截取,因为 ClassLoader解析方式不需要开头的斜杆, 请参见 * org.springframework.core.io.ClassPathResource#ClassPathResource(String, ClassLoader)
  2. *
  3. "",表示classes 的根目录
  4. *
  5. *

    * This method will try to load the resource using the following methods (in order): *

    *
      *
    • From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()} *
    • From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()} *
    • From {@link Class#getClassLoader() callingClass.getClassLoader() } (如果 callingClass 不是null) *
    *
  6. *
*
* * @param resourceName * The name of the resource to load * @param callingClass * The Class object of the calling object * @return 如果 resourceName 是null,抛出 {@link NullPointerException}
* 如果 callingClass 是null,将会忽略此参数
* 如果在所有的{@link ClassLoader}里面都查不到资源,那么返回null * @since 1.6.2 */ public static URL getResourceInAllClassLoader(String resourceName,Class callingClass){ Validate.notNull(resourceName, "resourceName can't be null!"); List classLoaderList = getAllClassLoaderList(callingClass); for (ClassLoader classLoader : classLoaderList){ URL url = getResource(classLoader, resourceName); if (null == url){ LOGGER.trace(getLogInfo(resourceName, classLoader, false)); }else{ if (LOGGER.isTraceEnabled()){ LOGGER.trace(getLogInfo(resourceName, classLoader, true)); } return url; } } LOGGER.debug("not found:[{}] in all ClassLoader,return null", resourceName); return null; } //--------------------------------------------------------------- /** * 获得 all class loader list. * *

* This method will try to get ClassLoader list using the following methods (in order): *

*
    *
  • From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()} *
  • From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()} *
  • From {@link Class#getClassLoader() callingClass.getClassLoader() } (如果 callingClass 不是null) *
* * @param callingClass * the calling class * @return the all class loader * @since 1.6.2 */ private static List getAllClassLoaderList(Class callingClass){ List list = toList(// getClassLoaderByCurrentThread(), getClassLoaderByClass(ClassLoaderUtil.class)); if (null != callingClass){ list.add(getClassLoaderByClass(callingClass)); } return list; } /** * 通过 {@link Thread#getContextClassLoader()} 获得 {@link ClassLoader}. * * @return the class loader by current thread */ private static ClassLoader getClassLoaderByCurrentThread(){ ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (LOGGER.isTraceEnabled()){ LOGGER.trace("[Thread.currentThread()].getContextClassLoader:{}", formatClassLoader(classLoader)); } return classLoader; } /** * 通过类来获得 {@link ClassLoader}. * * @param callingClass * the calling class * @return 如果 callingClass 是null,抛出 {@link NullPointerException}
* @see java.lang.Class#getClassLoader() */ private static ClassLoader getClassLoaderByClass(Class callingClass){ Validate.notNull(callingClass, "callingClass can't be null!"); ClassLoader classLoader = callingClass.getClassLoader(); if (LOGGER.isTraceEnabled()){ LOGGER.trace("[{}].getClassLoader():{}", callingClass.getSimpleName(), formatClassLoader(classLoader)); } return classLoader; } //--------------------------------------------------------------- /** * 获得 log info. * * @param resourceName * the resource name * @param classLoader * the class loader * @param isFouned * the is founed * @return the log info * @since 1.6.2 */ private static String getLogInfo(String resourceName,ClassLoader classLoader,boolean isFouned){ String message = "{}found [{}],in ClassLoader:[{}]"; return Slf4jUtil.format(message, isFouned ? "" : "not ", resourceName, formatClassLoader(classLoader)); } /** * Format class loader. * * @param classLoader * the class loader * @return the string * @since 1.6.2 */ private static String formatClassLoader(ClassLoader classLoader){ Map map = newLinkedHashMap(2); map.put("classLoader[CanonicalName]", classLoader.getClass().getCanonicalName()); map.put("classLoader[Root Classpath]", "" + getResource(classLoader, "")); return map.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy