Giới thiệu và thực hiện cơ bản
Trước tiên, bạn sẽ cần ít nhất một URLStreamHandler. Điều này thực sự sẽ mở kết nối đến một URL nhất định. Lưu ý rằng điều này được gọi đơn giản Handler
; điều này cho phép bạn chỉ định java -Djava.protocol.handler.pkgs=org.my.protocols
và nó sẽ tự động được chọn, sử dụng tên gói "đơn giản" làm giao thức được hỗ trợ (trong trường hợp này là "classpath").
Sử dụng
new URL("classpath:org/my/package/resource.extension").openConnection();
Mã
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();
}
}
Vấn đề ra mắt
Nếu bạn là bất cứ ai như tôi, bạn không muốn dựa vào một thuộc tính được thiết lập trong lần khởi chạy để đưa bạn đến một nơi nào đó (trong trường hợp của tôi, tôi muốn giữ các tùy chọn của mình mở như Java WebStart - đó là lý do tại sao
tôi cần tất cả điều này ).
Giải pháp thay thế / cải tiến
Hướng dẫn sử dụng mã đặc tả
Nếu bạn kiểm soát mã, bạn có thể làm
new URL(null, "classpath:some/package/resource.extension", new org.my.protocols.classpath.Handler(ClassLoader.getSystemClassLoader()))
và điều này sẽ sử dụng trình xử lý của bạn để mở kết nối.
Nhưng một lần nữa, điều này không thỏa đáng, vì bạn không cần URL để làm điều này - bạn muốn làm điều này bởi vì một số lib bạn không thể (hoặc không muốn) kiểm soát muốn url ...
Đăng ký xử lý JVM
Tùy chọn cuối cùng là đăng ký một URLStreamHandlerFactory
cái sẽ xử lý tất cả các url trên 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);
}
}
Để đăng ký xử lý, hãy gọi URL.setURLStreamHandlerFactory()
với nhà máy được cấu hình của bạn. Sau đó, làm new URL("classpath:org/my/package/resource.extension")
như ví dụ đầu tiên và đi bạn đi.
Vấn đề đăng ký xử lý JVM
Lưu ý rằng phương thức này chỉ có thể được gọi một lần cho mỗi JVM và lưu ý rằng Tomcat sẽ sử dụng phương thức này để đăng ký trình xử lý JNDI (AFAIK). Hãy thử cầu tàu (tôi sẽ được); tệ nhất, bạn có thể sử dụng phương pháp này trước và sau đó nó phải hoạt động xung quanh bạn!
Giấy phép
Tôi phát hành nó cho miền công cộng và hỏi rằng nếu bạn muốn sửa đổi rằng bạn bắt đầu một dự án OSS ở đâu đó và bình luận ở đây với các chi tiết. Việc thực hiện tốt hơn sẽ là có một URLStreamHandlerFactory
sử dụng ThreadLocal
s để lưu trữ URLStreamHandler
s cho mỗi Thread.currentThread().getContextClassLoader()
. Tôi thậm chí sẽ cung cấp cho bạn các sửa đổi và các lớp kiểm tra của tôi.
com.github.fommil.common-utils
gói mà tôi dự định sẽ cập nhật và phát hành sớm thông qua Sonatype.