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
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 ThreadLocal
s Thread.currentThread().getContextClassLoader()
Her URLStreamHandler
s saklamak için kullandığı URLStreamHandlerFactory
sahip olacaktır. Hatta benim değişiklikler ve test dersleri vereceğim.
Neden Java bize bir isim dosya adından...
Nasıl iki genel türleri ile bir arabir...
Ve Java okuma görüntülemek için bir ar...
Nasıl Ubuntu 10.10 üzerinde Sun Java i...
Eclipse: Java, sınıf nerede kullanıldı...