草庐IT

java - 获取对 Java 的默认 http(s) URLStreamHandler 的引用

coder 2024-03-27 原文

我有一个需要在我的项目之一中使用的库,不幸的是,它注册了自己的 URLStreamHandler 来处理 http-URL。有没有办法获取对 Java 默认 http- 和 https-URLStreamHandlers 的引用,这样我就可以在 URL 的构造函数中指定其中一个来打开标准的 http不使用被库覆盖的协议(protocol)连接?

最佳答案

找到了:

sun.net.www.protocol.http.Handler

有了它,我现在可以:

URL url = new URL(null, "http://...", new sun.net.www.protocol.http.Handler());
HttpURLConnection cxn = (HttpURLConnection) url.openConnection();

我得到一个普通的 Java HttpURLConnection 而不是库提供的那个。


更新:

我发现了另一种更通用的方法:删除库的 URLStreamHandlerFactory !

这有点棘手,因为从技术上讲,URL 类不允许您多次设置工厂或通过官方函数调用清除它,但是通过一些反射魔法,我们可以做到无论如何:

public static String unsetURLStreamHandlerFactory() {
    try {
        Field f = URL.class.getDeclaredField("factory");
        f.setAccessible(true);
        Object curFac = f.get(null);
        f.set(null, null);
        URL.setURLStreamHandlerFactory(null);
        return curFac.getClass().getName();
    } catch (Exception e) {
        return null;
    }
}

此方法获取静态字段 factoryURL -class,使其可访问,获取其当前值并将其更改为 null。之后,它调用 URL.setStreamHandlerFactory(null) (现在可以毫无错误地完成)使此设置成为“官方”,即让该功能有机会执行它可能想要执行的任何其他清理工作。然后返回之前注册的工厂的类名,仅供引用。如果出现任何问题,它会吞下异常(我知道,这是个坏主意...)并返回 null

供引用:这是relevant source-code for URL.java .

注意:这种方法可能比使用内部 sun 类(就可移植性而言)风险更大,因为它依赖于 URL 类的特定内部结构(即存在和 factory 字段的确切功能),但它的优点是我不需要遍历我的所有代码来查找所有 URL 构造函数并添加处理程序参数......此外,它可能破坏依赖于其注册处理程序的库的某些功能。幸运的是,这两个问题(可移植性和部分损坏的库功能)都与我的案例无关。


更新:#2

当我们使用反射时:这是获取对默认处理程序的引用的可能最安全的方法:

public static URLStreamHandler getURLStreamHandler(String protocol) {
    try {
        Method method = URL.class.getDeclaredMethod("getURLStreamHandler", String.class);
        method.setAccessible(true);
        return (URLStreamHandler) method.invoke(null, protocol);        
    } catch (Exception e) {
        return null;
    }
}

然后您可以将其简单地称为:

URLStreamHandler hander = getURLStreamHandler("http");

注意:此调用需要发生在图书馆注册其 URLStreamHandlerFactory 之前 ,否则您最终会引用到它们的处理程序。

为什么我认为这是最安全的方法?因为URL.getURLStreamHandler(...)不是完全私有(private)的方法,而只是包私有(private)的。因此,修改其调用签名可能会破坏同一包中的其他代码。此外,它的名称并没有真正为返回我们正在寻找的东西以外的任何东西留下太多空间。因此,我希望 URL 的不同/ future 实现不太可能(尽管仍然不是不可能)。 -class 将与此处所做的假设不兼容。

关于java - 获取对 Java 的默认 http(s) URLStreamHandler 的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18018628/

有关java - 获取对 Java 的默认 http(s) URLStreamHandler 的引用的更多相关文章

  1. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  2. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  3. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  4. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  5. ruby-on-rails - 在默认方法参数中使用 .reverse_merge 或 .merge - 2

    两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option

  6. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  7. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  8. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  9. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  10. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

随机推荐