Пакет jar или военный пакет SpringBoot не может получить решение файла ресурсов

задняя часть .NET Linux Tomcat

описание проблемы

В процессе разработки мы часто сталкиваемся с ситуациями, когда нам нужно получить файлы ресурсов в коде, и я недавно столкнулся с проблемой при переносе исходного нативного проекта Tomcat в проект SpringBoot, то есть при локальном запуске получить локальный файл xml файл ресурсов можно получить, но когда проект упакован как военный пакет, а затем развернут на Tomcat для запуска, возникает проблема, и сообщается об ошибке, что файл ресурсов не может быть найден. Затем после поиска и проверки было определено, что прошел следующий кодClassLoaderПри получении пути произошла ошибка.

ExcelXmlModelFactory.class.getClassLoader().getResource("template/").getPath()

Мой путь к хранилищу файлов ресурсов выглядит следующим образом

Путь журнала, напечатанный в локальном файле,

/Users/hupengfei/git/lap/lap-service/out/production/resources/template

Но каталог, напечатанный, когда SpringBoot упакован как военный пакет и развернут на Tomcat,

/home/app/lap/app/lap-service-1.0.0-SNAPSHOT.war!/WEB-INF/classes!/template/

Видно, что к несжатым файлам нельзя получить прямой доступ в Linux, поэтому файлы не будут найдены.

Решение

пройти черезClassLoaderизgetResourceAsStream()способ получить его поток, вы можете получить

Чтобы прочитать файлы в банке, мы можем использовать только поток для чтения, а не файл.

Два способа получить ресурсы

Обычно в процессе разработки возникает проблема чтения конфигурационных файлов, обычно есть два способа чтения. одинClass.getResource(String path), одинClassLoader.getResource(String path), хотя оба могут читать файлы, но вpathНачинка немного другая.

Class.getResource

  • путь начинается с/Начало: он получается из корня классов класса
  • ПУТЬ не/Начало: по умолчанию для получения ресурсов из пакета, где находится этот класс

Вот пример

public class Test {
    public static void main(String[] args) {
    	 System.out.println(Test.class.getResource("/"));
        System.out.println(Test.class.getResource(""));
    }
}

Вывод выглядит следующим образом

file:/Users/hupengfei/git/Test/out/production/classes/
file:/Users/hupengfei/git/Test/out/production/classes/Practice/Day13/

то если вresourceВ разделе есть три файла ресурсов

Так как же получить эти три файла, ведь структура каталогов в папке класса следующая

-- classes
	-- Convience
	-- Practice
	-- Test

Итак, если вы хотите получить файл ресурсов под тестом, вы можете получить его следующим образом.

System.out.println(Test.class.getResource("../../Test/1.xml"));
System.out.println(Test.class.getResource("/Test/1.xml"));

ClassLoader.getResource

ClassLoader.getResourceПуть не может начинаться с/В начале путь по умолчанию читается из корневого каталога

Примеры следующие

System.out.println(Test.class.getClassLoader().getResource(""));
System.out.println(Test.class.getClassLoader().getResource("/"));

распечатать следующим образом

file:/Users/hupengfei/git/Test/out/production/classes/
null

Из приведенного выше примера мы видим, что

Test.class.getClassLoader().getResource("")=Test.class.getResource("/")

Разница между двумя файлами ресурсов приобретения

На самом деле проверитьClass.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);
    }

Последнее, что он звонил, былоClassLoader.getResourceэтот метод, то почемуpathотличие, потому что его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;
    }

Видно, что здесь надето/

исходящий

Справочная статья