SORU
14 Mayıs 2009, PERŞEMBE


URL Java sınıf kaynakları yüklemek için

Java, kaynakları ama farklı URL protokolleri ile aynı API kullanarak her türlü yükleyebilirsiniz

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

Bu güzel kaynağa ihtiyacı olduğunu uygulamasından kaynak gerçek yükleme decouples, ve bir URL bir Dize olduğundan, kaynak yükleme de çok kolayca ayarlanabilir.

Yük kaynakları mevcut classloader kullanarak bir protokol var mı? Bu Jar protokolü ile aynı kaynaktan geliyor bilmeme gerek yok.

Elbette Class.getResourceAsStream("a.xml"), kullanarak bunu yapabilirim, ama o beni varolan kodu için farklı bir API ve bu nedenle değişiklikleri kullanmak gerekir. Kaynak için bir URL zaten, sadece mülkiyet bir dosya güncelleme belirtin ben her yerde bunu kullanmak mümkün olmak istiyorum.

CEVAP
20 Kasım 2009, Cuma


Giriş ve temel Uygulama

İlk olarak, en az bir URLStreamHandler ihtiyacın olacak. Bu aslında belirli bir URL için bağlantı açar. Dikkat edin bu sadece denir Handler; bu belirlemenizi sağlar java -Djava.protocol.handler.pkgs=org.my.protocols ve otomatik olarak alıp kullanarak "basit" paket adı olarak desteklenen protokolü (bu durumda "sınıf").

Kullanımı

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

Kod

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();
    }
}

Sorunları başlatın

Eğer bir şey bana, seni istemiyorum güvenebileceğim bir özellik olmaktan kümesi başlatmak için bir yere (benim durumumda, ben sevmeye devam seçeneklerimi açık gibi Java webstart uygulamalarında bu yüzdenBentüm bu gerekir).

Geçici Çözümler/Geliştirmeler

Manuel kod şartname İşleyicisi

Eğer kodu kontrol edersen yapabilirsin

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

ve bu amirin bağlantı açmak için kullanacak.

Fakat yine de, bu daha az tatmin edici olarak ihtiyacın yok bir URL yapmak - tek istediğin bu çünkü bazı lib edemezsin (veya istemiyorum) denetim istiyor... URL

JVM İşleyici kaydı

Son seçenek jvm genelinde tüm adresler idare edecek URLStreamHandlerFactory kayıt için:

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);
    }
}

İşleyicisi kaydetmek için yapılandırılmış fabrika URL.setURLStreamHandlerFactory() Ara. Sonra new URL("classpath:org/my/package/resource.extension") ilk örnek gibi.

JVM İşleyicisi Kayıt Sorunu

Bu yöntem, yalnızca bir kez başına JVM çağrılabilir, ve Tomcat bu yöntem JNDI işleyicisi (AFAIK) kaydetmek için kullanacağı iyi not unutmayın. İskele (olacağım) deneyin, en kötü yöntemi kullanabilirsiniz ve daha sonra geçici bir çözüm bulmak için vardır!

Lisans

Ben kamu malı için bu sürüm, ve eğer OSS proje başlangıç için bunu değiştirmek isterseniz isteyin ve buraya yorum ayrıntıları. Daha iyi bir uygulama ThreadLocals Thread.currentThread().getContextClassLoader()Her URLStreamHandler s saklamak için kullandığı URLStreamHandlerFactory sahip olacaktır. Hatta benim değişiklikler ve test dersleri vereceğim.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Incredible Tutorials

    Incredible T

    27 EKİM 2006
  • L33TNoonProductions

    L33TNoonProd

    24 EYLÜL 2010
  • manadude21

    manadude21

    11 Mart 2008