URL для загрузки ресурсов из пути к классу в Java

Вы можете попытаться передать значение региона в качестве параметра для вашего строкового ресурса

<string name="my_endpoint">https://%1$s-endpoint.mysite.com</string>

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

String endpoint = getString(R.string.my_endpoint, customer.region)

у вас есть только одна строка в вашем файле strings.xml , но здесь есть слабое место, если конечная точка для каждого региона не имеет этого ключа.

194
задан Pacerier 24 August 2014 в 21:11
поделиться

4 ответа

Введение и базовая реализация

Во-первых, вам понадобится как минимум URLStreamHandler. Это фактически откроет соединение с заданным URL-адресом. Обратите внимание, что это просто называется Handler ; это позволяет указать java -Djava.protocol.handler.pkgs = org.my.protocols , и он будет автоматически выбран с использованием "простого" имени пакета в качестве поддерживаемого протокола (в данном случае " classpath ").

Использование

new URL("classpath:org/my/package/resource.extension").openConnection();

Код

package org.my.protocols.classpath;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

/** A {@link URLStreamHandler} that handles resources on the classpath. */
public class Handler extends URLStreamHandler {
    /** The classloader to find resources from. */
    private final ClassLoader classLoader;

    public Handler() {
        this.classLoader = getClass().getClassLoader();
    }

    public Handler(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    protected URLConnection openConnection(URL u) throws IOException {
        final URL resourceUrl = classLoader.getResource(u.getPath());
        return resourceUrl.openConnection();
    }
}

Проблемы с запуском

Если вы похожи на меня, вы не хотите полагаться на свойство, установленное при запуске, чтобы добраться куда-нибудь (в моем В этом случае я предпочитаю оставлять свои опции открытыми, как Java WebStart - вот почему мне все это нужно).

Обходные пути / улучшения

Ручная спецификация обработчика кода

Если вы управляете кодом, вы можете выполнить

new URL(null, "classpath:some/package/resource.extension", new org.my.protocols.classpath.Handler(ClassLoader.getSystemClassLoader()))

, и это будет использовать ваш обработчик для открытия соединения.

Но опять же, это менее чем удовлетворительно , поскольку для этого вам не нужен URL - вы хотите это сделать, потому что некоторая библиотека, которую вы не можете (или не хотите) контролировать, хочет URL ...

Регистрация обработчика JVM

Окончательный вариант - зарегистрировать URLStreamHandlerFactory , который будет обрабатывать все URL-адреса в jvm:

package my.org.url;

import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import java.util.HashMap;
import java.util.Map;

class ConfigurableStreamHandlerFactory implements URLStreamHandlerFactory {
    private final Map<String, URLStreamHandler> protocolHandlers;

    public ConfigurableStreamHandlerFactory(String protocol, URLStreamHandler urlHandler) {
        protocolHandlers = new HashMap<String, URLStreamHandler>();
        addHandler(protocol, urlHandler);
    }

    public void addHandler(String protocol, URLStreamHandler urlHandler) {
        protocolHandlers.put(protocol, urlHandler);
    }

    public URLStreamHandler createURLStreamHandler(String protocol) {
        return protocolHandlers.get(protocol);
    }
}

Чтобы зарегистрировать обработчик, вызовите URL.setURLStreamHandlerFactory () с настроенной фабрикой. Затем введите новый URL ("путь к классам: org / my / package / resource.extension") , как в первом примере, и вперед.

Проблема регистрации обработчика JVM

Обратите внимание, что этот метод может быть вызван только один раз для каждой JVM, и обратите внимание, что Tomcat будет использовать этот метод для регистрации обработчика JNDI (AFAIK). Попробуйте Jetty (буду); в худшем случае вы можете сначала использовать этот метод, а затем он должен обойти вас!

Лицензия

Я передаю это в общественное достояние и прошу, если вы хотите изменить, запустите где-нибудь проект OSS и прокомментируйте здесь с подробностями. Лучшей реализацией было бы иметь URLStreamHandlerFactory , который использует ThreadLocal для хранения URLStreamHandler s для каждого Thread.currentThread (). GetContextClassLoader () [) . Я даже дам вам свои модификации и тестовые классы.

343
ответ дан 23 November 2019 в 05:23
поделиться

Расширение к Ответ Дилумса :

Без изменения кода вам, вероятно, потребуется реализовать собственные реализации интерфейсов, связанных с URL, как рекомендует Дилум. Чтобы упростить вам задачу, я могу порекомендовать посмотреть исходники Ресурсы Spring Framework . Хотя код не имеет формы обработчика потока, он был разработан для того, чтобы делать именно то, что вы хотите делать, и находится под лицензией ASL 2.0, что делает его достаточно дружественным для повторного использования в вашем коде с должным уважением.

2
ответ дан 23 November 2019 в 05:23
поделиться

Я не знаю, есть ли он уже, но вы можете легко сделать это сами.

Этот пример различных протоколов выглядит для меня как образец фасада. У вас есть общий интерфейс, когда есть разные реализации для каждого случая.

Вы можете использовать тот же принцип, создать класс ResourceLoader, который берет строку из вашего файла свойств и проверяет наш собственный протокол

myprotocol:a.xml
myprotocol:file:///tmp.txt
myprotocol:http://127.0.0.1:8080/a.properties
myprotocol:jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class

, удаляя myprotocol: с начала строки, а затем принимает решение, каким способом загрузить ресурс, и просто предоставляет вам ресурс.

2
ответ дан 23 November 2019 в 05:23
поделиться

(Аналогично ответу Аздера , но немного другой такт.)

Я не верю, что существует предопределенный обработчик протокола для содержимого из пути к классам. (Так называемый classpath: протокол.)

Однако Java позволяет добавлять собственные протоколы. Это достигается путем предоставления конкретных реализаций java.net.URLStreamHandler и java.net.URLConnection .

В этой статье описывается, как можно реализовать настраиваемый обработчик потока: http://java.sun.com/developer/onlineTraining/protocolhandlers/ .

6
ответ дан 23 November 2019 в 05:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: