существуетJava
, чтобы прочитать файл по относительному пути, часто используется следующий метод:
xxx.class.getResource();
xxx.class.getClassLoader().getResource();
существуетSpring
, мы также можем пройтиSpring
который предоставилResource
Сделай что-нибудь:
ClassPathResource
FileSystemResource
ServletContextResource
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
Вот краткое резюме их различий:
ClassLoader##getResource()
Этот метод является главным действующим лицом на сегодняшний день.
мы все знаемClassLoader
используется для загрузки.class
документ иClassLoader
это следоватьJava
Механизм родительского делегирования при загрузке класса.
Так,ClassLoader
как ты это нашел.class
Что с файлом? ответURLClassPath
Java
Поставляется с 3ClassLoader
соответственноBootStrap ClassLoader
,EtxClassLoader
,AppClassLoader
,
эти 3ClassLoader
НаследованиеURLClassLoader
,иURLClassLoader
содержитURLClassPath
записывать каждыйClassLoader
соответствующая загрузка.class
Путь к файлу, когда вам нужно загрузить ресурсы, просто начните сURLClassPath
Найдите соответствующий путь.
Вот тестовый код:
System.out.println("BootStrap ClassLoader ");
Stream.of(System.getProperty("sun.boot.class.path").split(";")).forEach(System.out::println);
System.out.println("ExtClassLoader:");
Stream.of(System.getProperty("java.ext.dirs").split(";")).forEach(System.out::println);
System.out.println("AppClassLoader:");
Stream.of(System.getProperty("java.class.path").split(";")).forEach(System.out::println);
Результат выглядит следующим образом:
BootStrap ClassLoader
H:\java\jdk1.8\jre\lib\resources.jar
H:\java\jdk1.8\jre\lib\rt.jar
H:\java\jdk1.8\jre\lib\sunrsasign.jar
H:\java\jdk1.8\jre\lib\jsse.jar
H:\java\jdk1.8\jre\lib\jce.jar
H:\java\jdk1.8\jre\lib\charsets.jar
H:\java\jdk1.8\jre\lib\jfr.jar
H:\java\jdk1.8\jre\classes
ExtClassLoader:
H:\java\jdk1.8\jre\lib\ext
C:\Windows\Sun\Java\lib\ext
AppClassLoader:
H:\java\jdk1.8\jre\lib\charsets.jar
H:\java\jdk1.8\jre\lib\deploy.jar
H:\java\jdk1.8\jre\lib\ext\access-bridge-64.jar
H:\java\jdk1.8\jre\lib\ext\cldrdata.jar
H:\java\jdk1.8\jre\lib\ext\dnsns.jar
H:\java\jdk1.8\jre\lib\ext\jaccess.jar
H:\java\jdk1.8\jre\lib\ext\jfxrt.jar
H:\java\jdk1.8\jre\lib\ext\localedata.jar
H:\java\jdk1.8\jre\lib\ext\nashorn.jar
H:\java\jdk1.8\jre\lib\ext\sunec.jar
H:\java\jdk1.8\jre\lib\ext\sunjce_provider.jar
H:\java\jdk1.8\jre\lib\ext\sunmscapi.jar
H:\java\jdk1.8\jre\lib\ext\sunpkcs11.jar
H:\java\jdk1.8\jre\lib\ext\zipfs.jar
H:\java\jdk1.8\jre\lib\javaws.jar
H:\java\jdk1.8\jre\lib\jce.jar
H:\java\jdk1.8\jre\lib\jfr.jar
H:\java\jdk1.8\jre\lib\jfxswt.jar
H:\java\jdk1.8\jre\lib\jsse.jar
H:\java\jdk1.8\jre\lib\management-agent.jar
H:\java\jdk1.8\jre\lib\plugin.jar
H:\java\jdk1.8\jre\lib\resources.jar
H:\java\jdk1.8\jre\lib\rt.jar
F:\spring-test\target\classes
AppClassLoader
отвечает за часто используемыеJDK jar
и от чего зависит проектjar
СумкаВышеуказанные параметры можно получить через sun.misc.Launcher.class
Через выходные параметры мы можем ясно видеть, что каждый
ClassLoader
Ответственная зона
Сказав это, это иClassLoader#getResource()
Что это значит?
Это большое дело, я только что задал вопрос ранее,ClassLoader
как читать.class
Что с файлом?
ответURLClassPath#getResource()
метод: каждыйUrlClassLoader
на всем протяженииURLClassPath
Чтобы сохранить соответствующую область загрузки, когда вам нужно найти.class
файл, проходURLClassPath#getResource()
Найди это.
Посмотрим еще разClassLoader#getResource()
//双亲委派查找
public URL getResource(String name) {
URL url;
if (parent != null) {
url = parent.getResource(name);
} else {
url = getBootstrapResource(name);
}
if (url == null) {
url = findResource(name);
}
return url;
}
//由于BootStrap ClassLoader是C++写的,Java拿不到其引用。
//因此这里单独写了一个方法获取BootStrapResource()
private static URL getBootstrapResource(String name) {
URLClassPath ucp = getBootstrapClassPath();
Resource res = ucp.getResource(name);
return res != null ? res.getURL() : null;
}
URLClassLoader#findResource()
public URL findResource(final String name) {
URL url = AccessController.doPrivileged(
new PrivilegedAction<URL>() {
public URL run() {
return ucp.findResource(name, true);
}
}, acc);
return url != null ? ucp.checkURL(url) : null;
}
Нам нужно только обратить внимание на это предложениеucp.findResource(name, true);
, вот поиск.class
файловый метод, поэтому мы можем сделать выводClassLoader#getResource()
процесс:
- Во-первых,
AppClassLoader
делегироватьExtClassLoader
Узнать, есть ли соответствующий ресурс -
ExtClassLoader
делегироватьBootStrap ClassLoader
Найдите, есть ли соответствующий ресурс -
BootStrap ClassLoader
пройти черезURLClasspath
Найдите область, загруженную самостоятельно, и вернитесь, когда найдете ее. -
BootStrap ClassLoader
Соответствующий ресурс не найден.ExtClassLoader
пройти черезURLClasspath
Найдите область, загруженную самостоятельно, и вернитесь, когда найдете ее. -
ExtClassLoader
Соответствующий ресурс не найден.AppClassLoader
пройти черезURLClasspath
Найдите область, загруженную самостоятельно, и вернитесь, когда найдете ее. -
AppClassLoader
Не найдено, выдает исключение.
Этот процесс, как раз и загрузка.class
Файловый процесс тот же.
Здесь мы можем найти это поClassLoader#getResource()
может получитьJDK
ресурсы, зависит отJAR
пакеты ресурсов и т. д.
Поэтому мы можем даже написать:
//читатьjava.lang.String.class
байт-код
InputStream inputStream =Test.class.getClassLoader().getResourceAsStream("java/lang/String.class");
try(BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream)){
byte[] bytes=new byte[1024];
while (bufferedInputStream.read(bytes)>0){
System.out.println(new String(bytes, StandardCharsets.UTF_8));
}
}
ПонялClassLoader#getResource()
, На самом деле эта статья почти такая же, потому что нижние слои методов, которые будут использоваться позже, всеClassLoader#getResource()
class##getResource()
class##getResource()
дноClassLoader#getResource()
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);
}
Но есть небольшая разницаclass#getResource()
один дополнительныйresolveName()
метод:
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;
}
этоresolveName()
Примерно определить, является ли путь относительным или абсолютным путем, если это относительный путь, имя ресурса будет добавлено к корневому пути текущего проекта:
Test.class.getResource("spring-config.xml");
становится после разрешения
com/dengchengchao/test/spring-config.xml
Такие ресурсы можно найти только в текущем проекте.
Test.class.getResource("test.txt"); //相对路径
Test.class.getResource("/"); //根路径
Уведомление:
ClassLoader#getResource()
не может быть/
начало
Spring # ClassPathResource()
существуетSpring
в, даResource
был расширен так, чтоResource
Может адаптироваться к большему количеству сценариев применения,
ноClssPathResource()
дно все ещеClassLoader##getResource()
,следовательноClassLoader##getResource()
свойства д,ClassPathResource
также поддерживает.
protected URL resolveURL() {
if (this.clazz != null) {
return this.clazz.getResource(this.path);
} else {
return this.classLoader != null ? this.classLoader.getResource(this.path) : ClassLoader.getSystemResource(this.path);
}
}
ClassPathResource
для чтенияclasses
файл каталога
Вообще говоря, дляSpringBoot
Проект, структура упакованной проекта выглядит следующим образом:
xxx.jar
|--- BOOT-INF
|--------|--classes
|--------|----|--com
|--------|----|-- application.properties
|--------|----|--logback.xml
| -------|-- lib
|--- META-INF
|--- org
можно увидеть,ClassPathResource()
Начальный путьclasses
, обычно мы читаемapplication.properties
это использоватьClasspathResource()
приобретенный
В процессе обычного использования следует обратить внимание на три момента:
-
Разница между classpath и classpath*:
Класс: возвращать только первый файл, который выглядит ClassPath *: вернет все файлы нахождения
-
существует
Spring
, вам нужно прямо выразить использованиеClassPathResource()
Если вы хотите найти его, вы можете добавить его напрямуюclasspath:
голова -
использовать
classpath
от/
а не к/
разницы нет в начале
Spring # ServletContextResource
ServletContextResource
направлен наServlet
делать, мы знаем,Servlet
Регулированиеwebapp
Каталог выглядит следующим образом:
иServletContextResource
путьxxx
Каталог запускается. ЭтоServletContextResource
получитьform.html
и другие ресурсы.
Также сравните вышеClassPathResource
мы можем узнать:
"classpath:com"
Эквивалентно:
ServletContextResource("WEB-INF/classes/com")
Spring # FileSystemResource
FileSystemResource
Нечего сказать, просто ресурсы системного каталога, такие как
ApplicationContext ctx =
new FileSystemXmlApplicationContext("D://test.xml");
Маркировка головы как этоfile:
Например:
ApplicationContext ctx =
new FileSystemXmlApplicationContext("flie:D://test.xml");
Если вы считаете, что текст хороший, добро пожаловать в общедоступную учетную запись WeChat: Yiyou Java, время от времени публикуйте несколько статей о продвинутых Java, каждый день, спасибо за внимание.