Почему ClassLoader возвращает путь с лишним вторым восклицательным знаком - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь получить ресурс в ClassLoader. Упрощенная версия кода выглядит примерно так:

String ePath = "rewrite/common/RenameFunctor.groovy"
String fPath = ThClType.class.getClassLoader().getResource(ePath);

ответ, который я получаю как fPath, равен jar:file:/Users/myName/warPath/warName.war!/WEB-INF/classes!/rewrite/common/RenameFunctor.groovy. Реальный путь к ресурсу нам нужен именно таким, кроме как без второго восклицательного знака. (В отличие от warName.war, classes - это обычный каталог.)

Кто-нибудь знает, что могло вызвать дополнительный восклицательный знак и / или что можно сделать, чтобы его исправить? Это как часть процесса обновления какого-то довольно старого кода, который я не писал, поэтому, если возможна эзотерическая настройка поведения ClassLoader, возможно, это было сделано в этом случае. если это возможно , возможно , тогда я не знаю, как это проверить, и буду признателен за любую информацию.

1 Ответ

0 голосов
/ 28 апреля 2018

Предупреждение: этот ответ является частью предположения и догадки о механике, он может быть не на 100% правильным, но я думаю, что он достаточно близок. Насколько я знаю, фактическая загрузка класса WAR будет варьироваться в зависимости от контейнера сервлета или сервера приложений, поэтому этот ответ может не подходить для всех из них.

Если вы посмотрите на

jar:file:/Users/myName/warPath/warName.war!/WEB-INF/classes!/rewrite/common/RenameFunctor.groovy

Вы можете разделить его на следующие части:

  1. file:/Users/myName/warPath/warName.war
  2. /WEB-INF/classes
  3. /rewrite/common/RenameFunctor.groovy

Фактический ресурс, который находится на пути к классам, является последним, /rewrite/common/RenameFunctor.groovy, остальные части - это координаты, используемые загрузчиком классов войны, чтобы найти часть пути к классам, которая содержит этот ресурс: сначала местоположение сам файл войны file:/Users/myName/warPath/warName.war, а затем путь в войне /WEB-INF/classes.

Эта теория основана на документации JarURLConnection, которая гласит:

URL-соединение с файлом Java ARchive (JAR) или записью в JAR файл.

Синтаксис URL-адреса JAR:

jar:<url>!/{entry}  

например:

jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class

URL-адреса Jar должны использоваться для ссылки на файл JAR или записи в JAR файл. Пример выше - это URL JAR, который ссылается на запись JAR. Если имя записи опущено, URL относится ко всему файлу JAR: jar:http://www.foo.com/bar/baz.jar!/

Таким образом, для простого jar первая часть URL идентифицирует сам файл jar, а вторая часть идентифицирует ресурс внутри jar.

Технически файлы war являются файлами jar, но, в отличие от файлов jar, сам файл war не является частью пути к классам. Вместо этого он содержит элементы, которые добавляются в путь к классам. Например, файлы jar в WEB-INF/lib и классы и другие файлы в WEB-INF/classes.

Разделенные ! части затем определяют шаги, предпринятые загрузчиком war-класса для поиска определенного ресурса, в данном случае /rewrite/common/RenameFunctor.groovy.

...