URL.setURLStreamHandlerFactory - PullRequest
       10

URL.setURLStreamHandlerFactory

7 голосов
/ 20 января 2012

Я занимаюсь разработкой веб-приложения с использованием исполняемого файла jar со встроенным Jetty.
Мой файл содержит зависимый файл jar. (Jar in jar)
Я ссылаюсь на JarRsrcLoader и RsrcURLStreamHandlerFactory, разработанные Eclipse..
JarRsrcLoader использует URL#setURLStreamHandlerFactory(RsrcURLStreamHandlerFactory) для разрешения rsrc протокола.
Тем самым он может разрешить путь к классу для jar.
Но становится невозможным решить обычный протокол как побочные эффекты.
например file:xxxx или jar:xxxx.
RsrcURLStreamHandlerFactory имеет метод setURLStreamHandlerFactory.
Может быть, я думаю, что должен установить агрегат по умолчанию для этого метода.
Я не знаю, что установить этот метод,

Ответы [ 2 ]

11 голосов
/ 13 февраля 2012

В среде выполнения Java зарегистрирован только один экземпляр реализации URLStreamHandlerFactory, поэтому эта реализация должна знать обо всех поддерживаемых протоколах.

Поведение Oracle / Sun по умолчанию не реализовано таким образом, но напрямуюв классе java.net.URL.Таким образом, вы не можете просто внедрить реализацию по умолчанию в виде связанной фабрики в RsrcURLStreamHandlerFactory.Первая часть ответа.

Метод java.net.URL getURLStreamHandler загружает реализацию для протокола X в соответствии с политикой именования его имени класса, по умолчанию sun.net.www.protocol.X.Handler

Если вы посмотрите на jre/lib/rt.jar, вы найдете:

sun/net/www/protocol/ftp/Handler.class
sun/net/www/protocol/gopher/Handler.class
sun/net/www/protocol/mailto/Handler.class
sun/net/www/protocol/netdoc/Handler.class
sun/net/www/protocol/http/Handler.class
sun/net/www/protocol/jar/Handler.class
sun/net/www/protocol/file/Handler.class

Список базовых пакетов, используемых для выбора протокола URLStreamHandler, происходит из java.protocol.handler.pkgs системного свойства Java.Я предлагаю вам прочитать полный исходный код java/net/URL.java из JDK src.zip, чтобы понять детали.

  • Так что правильный способ сделать это (что бы ни делал IBM / Eclipse)это оставить механизм по умолчанию на месте и установить, например, -Djava.protocol.handler.pkgs="com.company.product.protocol" в командной строке (если у вас есть разрешение / аккредитация для этого).С реализацией URLStreamHandler с именем com.company.product.protocol.rsrc.Handler, которая использует JarRsrcLoader, вы выполняете работу.

  • Альтернативный вариант - записать реализацию URLStreamHandlerFactory как цепочечную фабрику вRsrcURLStreamHandlerFactory на основе URL.getURLStreamHandler исходного кода.Например, вы можете прочитать этот старый код JBoss .Он опирается на URL внутренний кеш обработчиков, предварительно загружая другие известные (или используемые ) протоколы перед регистрацией фабрики.На мой взгляд, просто безобразно.

Предупреждение : RsrcURLStreamHandler заменил исходный код из 180 строк URLStreamHandler.parseURL на свой собственный 10-строки "версия" без вызова super.parseURL.Конечно, это не соответствует спецификации конкатенации URL!Будьте осторожны, вы можете столкнуться с ошибкой в ​​зависимости от способа использования таких URL.

1 голос
/ 13 февраля 2018

Начиная с Java 9, вы можете использовать SPI для предоставления обработчиков:

URL (String, String, int, String) конструктор JavaDoc, описывающий алгоритм поиска:

  1. Если приложение ранее настроило экземпляр URLStreamHandlerFactory в качестве фабрики обработчика потока, то метод createURLStreamHandler этого экземпляра вызывается со строкой протокола в качестве аргумента для создания обработчика протокола потока.

  2. Если URLStreamHandlerFactory еще не настроен или если фабричный метод createURLStreamHandler возвращает значение null, то механизм ServiceLoader используется для поиска URLStreamHandlerProvider реализаций с использованием системызагрузчик классов. Порядок расположения поставщиков зависит от конкретной реализации, и реализация может свободно кэшировать обнаруженных поставщиков.ServiceConfigurationError, Error или RuntimeException, выброшенные из createURLStreamHandler, если они обнаружены, будут переданы вызывающему потоку.Метод createURLStreamHandler каждого провайдера, если он создан, вызывается со строкой протокола до тех пор, пока провайдер не вернет ненулевое значение или все провайдеры не будут исчерпаны.

  3. Если на предыдущем шаге не удается найтиВ обработчике протокола конструктор считывает значение системного свойства: java.protocol.handler.pkgs
  4. Если на предыдущем шаге не удается найти обработчик протокола, тогда конструктор пытается загрузить встроенный обработчик протокола.Если этот класс не существует или если класс существует, но не является подклассом URLStreamHandler, то генерируется исключение MalformedURLException.

Гарантированные обработчики протоколов для следующих протоколов гарантированно существуют в пути поиска: http, https, file и jar

...