Implementasi Intro dan dasar
Pertama, Anda membutuhkan setidaknya URLStreamHandler. Ini sebenarnya akan membuka koneksi ke URL yang diberikan. Perhatikan bahwa ini hanya disebut Handler
; ini memungkinkan Anda untuk menentukan java -Djava.protocol.handler.pkgs=org.my.protocols
dan secara otomatis akan diambil, menggunakan nama paket "sederhana" sebagai protokol yang didukung (dalam hal ini "classpath").
Pemakaian
new URL("classpath:org/my/package/resource.extension").openConnection();
Kode
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();
}
}
Luncurkan masalah
Jika Anda seperti saya, Anda tidak ingin bergantung pada properti yang diatur dalam peluncuran untuk membawa Anda ke suatu tempat (dalam kasus saya, saya ingin menjaga opsi saya tetap terbuka seperti Java WebStart - itulah sebabnya
saya membutuhkan semua ini ).
Penanganan / Peningkatan
Spesifikasi Penangan kode manual
Jika Anda mengontrol kode, Anda dapat melakukannya
new URL(null, "classpath:some/package/resource.extension", new org.my.protocols.classpath.Handler(ClassLoader.getSystemClassLoader()))
dan ini akan menggunakan handler Anda untuk membuka koneksi.
Tapi sekali lagi, ini kurang memuaskan, karena Anda tidak perlu URL untuk melakukan ini - Anda ingin melakukan ini karena beberapa lib Anda tidak dapat (atau tidak ingin) mengendalikan keinginan url ...
Pendaftaran JVM Handler
Opsi terakhir adalah mendaftar URLStreamHandlerFactory
yang akan menangani semua url di 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);
}
}
Untuk mendaftarkan pawang, hubungi URL.setURLStreamHandlerFactory()
pabrik Anda yang sudah dikonfigurasi. Kemudian lakukan new URL("classpath:org/my/package/resource.extension")
seperti contoh pertama dan Anda pergi.
Masalah Pendaftaran Handler JVM
Perhatikan bahwa metode ini hanya dapat dipanggil sekali per JVM, dan perhatikan juga bahwa Tomcat akan menggunakan metode ini untuk mendaftarkan penangan JNDI (AFAIK). Coba Jetty (saya akan); paling buruk, Anda dapat menggunakan metode ini terlebih dahulu dan kemudian harus bekerja di sekitar Anda!
Lisensi
Saya merilis ini ke domain publik, dan meminta jika Anda ingin memodifikasi bahwa Anda memulai proyek OSS di suatu tempat dan berkomentar di sini dengan detailnya. Implementasi yang lebih baik adalah memiliki URLStreamHandlerFactory
yang menggunakan ThreadLocal
s untuk menyimpan URLStreamHandler
masing-masing Thread.currentThread().getContextClassLoader()
. Saya bahkan akan memberi Anda kelas modifikasi dan tes saya.
com.github.fommil.common-utils
paket saya yang saya berencana untuk perbarui dan rilis segera melalui Sonatype.