บทนำและการนำไปปฏิบัติขั้นพื้นฐาน
ก่อนอื่นคุณต้องมี 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 - ซึ่งเป็นเหตุผลที่
ฉันต้องการทั้งหมดนี้ )
วิธีการแก้ปัญหา / การเพิ่มประสิทธิภาพ
ข้อมูลจำเพาะ Handler รหัสคู่มือ
หากคุณควบคุมรหัสคุณสามารถทำได้
new URL(null, "classpath:some/package/resource.extension", new org.my.protocols.classpath.Handler(ClassLoader.getSystemClassLoader()))
และสิ่งนี้จะใช้ตัวจัดการของคุณเพื่อเปิดการเชื่อมต่อ
แต่อีกครั้งสิ่งนี้น่าพอใจน้อยกว่าเพราะคุณไม่จำเป็นต้องใช้ URL ในการทำเช่นนี้ - คุณต้องการทำเช่นนี้เพราะ lib บางอย่างที่คุณไม่สามารถควบคุม (หรือไม่ต้องการ) ต้องการ URL ...
การลงทะเบียน JVM Handler
ตัวเลือกที่ดีที่สุดคือการลงทะเบียน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()
จากโรงงานที่ตั้งค่าไว้ของคุณ จากนั้นทำnew URL("classpath:org/my/package/resource.extension")
ตัวอย่างแรกและไปให้พ้น
ปัญหาการลงทะเบียน JVM Handler
โปรดทราบว่าวิธีนี้อาจเรียกได้เพียงครั้งเดียวต่อ JVM และโปรดทราบว่า Tomcat จะใช้วิธีนี้ในการลงทะเบียน JNDI handler (AFAIK) ลองท่าเทียบเรือ (ฉันจะ) ที่เลวร้ายที่สุดคุณสามารถใช้วิธีการก่อนแล้วจึงต้องแก้ไขคุณ!
การอนุญาต
ฉันเผยแพร่สิ่งนี้เป็นสาธารณสมบัติและถามว่าถ้าคุณต้องการแก้ไขว่าคุณเริ่มโครงการ OSS ที่ไหนสักแห่งและแสดงความคิดเห็นที่นี่พร้อมรายละเอียด การดำเนินที่ดีกว่าจะมีURLStreamHandlerFactory
ที่ใช้ThreadLocal
เพื่อการจัดเก็บสำหรับแต่ละURLStreamHandler
Thread.currentThread().getContextClassLoader()
ฉันจะให้การดัดแปลงและการทดสอบแก่คุณ
com.github.fommil.common-utils
แพ็คเกจที่ฉันวางแผนจะอัปเดตและวางจำหน่ายในไม่ช้าผ่าน Sonatype