如何通过 Java 程序中的 java.net.URL 类监控打开的 URL?
Posted
技术标签:
【中文标题】如何通过 Java 程序中的 java.net.URL 类监控打开的 URL?【英文标题】:How can I monitor the opened URLs via java.net.URL class in a Java program? 【发布时间】:2010-02-05 16:45:10 【问题描述】:我正在开发一个大型(很多类)java 项目,我有它的源代码,但大多数类是通过 ClassLoaders 动态创建或下载的。 无论如何,我希望能够“覆盖” java.net.URL 类,这样我就可以追踪打开 url 的调用。我不能使用嗅探器,因为内容是 SSL 加密的。 我试图扩展 java.net.URL 但它不起作用,因为它是最终类。 我还打开了 java.net.URL 的源代码并对其进行了修改,并且可以成功构建它,现在如何使默认的 java 类加载器加载我修改后的 java.net.URL 副本而不是原来的? 欢迎任何建议!提前致谢。
【问题讨论】:
【参考方案1】:一种选择是使用 AspectJ 并将您的扩展代码编织到 URL 类中,而不是扩展它。这样您就不必修改任何原始资源,您仍然可以“扩展”最终类。当然,不利的一面是,您向项目添加了另一个依赖项。
如果您还没有使用过 AOP,您可以在我的博客中找到关于 AOP 的简短介绍:http://whatiscomingtomyhead.wordpress.com/2010/02/06/aspect-oriented-programming-an-introduction/
【讨论】:
感谢您的快速答复。这是我第一次使用 ***.com(当然是为了问,哈哈)。我以前从未使用过 AspectJ,但它听起来很完美,添加另一个依赖项没有问题。我试图弄清楚它是如何工作的,但无法真正理解它的语法。我发现了这个: Pointcut("execution(* new(..))") 看起来我们正在挂钩函数调用,对吧?不过,我不知道如何拦截对 java.net.URL 构造函数的调用。您能否为第一次使用 AspectJ 用户提供一些代码?再次感谢。 您好,Marcio,我编辑了我的答案并添加了一个指向我的博客的链接,您可以在其中找到 AOP 的简短介绍演示文稿(还有 1 个代码示例!)。您还可以在网上找到很多关于 AOP 的资料。构造函数切入点可以这样定义: call(URL.new(..)) 我希望这可以帮助您解决问题。问候尼尔斯!【参考方案2】:正如您所发现的,您无法扩展 URL。您也许能够让 JVM 加载您的自定义版本的类,但恕我直言,这听起来像是一场噩梦。
谢天谢地,您可以实现自定义 URLStreamHandlerFactory 并通过 URL.setURLStreamHandlerFactory() 注册它。这将允许您在 URL 打开流时进行包装和监控,就像您希望的那样。
编辑
但是,如果您的应用已经注册了一个,您将无法使用这种方法; URLStreamHandlerFactories 是 1/app。许多类型的应用程序容器都使用一种(例如 Tomcat),因此如果您使用其中一种,那么您就是 SOL。
【讨论】:
另一个问题是实现 URLStreamHandlerFactory 并非易事,因为您必须重新实现 VM 特定逻辑才能为不同协议找到合适的处理程序实现。【参考方案3】:您是否考虑过使用 AspectJ?您可以在 URL 构造函数上设置切入点,从而在任何新的 URL 实例创建时收到通知。
【讨论】:
【参考方案4】:如果您在标准 API 中修改了类,则必须在引导类路径之前添加您的类(jar 或目录),否则 VM 内部类将优先于添加到正常类路径中的任何类。对于 Sun 的 VM,您可以使用参数 -Xbootclasspath/p: 添加优先级高于内部实现的新类。
另一个选项,不修改 URL 实现可能是实现 ProxySelector。打开 URLConnection 将导致 URL 实现查询 ProxySelector.select(URI uri) 以获取给定地址的合适代理。如果您实际上正在使用代理,这甚至会起作用。您可以在注册自己的实现之前使用 ProxySelector.getDefault() 获取系统 ProxySelector,并在跟踪传递给 select 方法的 URI 后将 select 调用委托给原始实现。
【讨论】:
参数 -Xbootclasspath/p: 应该可以解决问题,但我想我会按照其他人的建议先尝试使用 AspectJ。最好不要弄乱默认实现,对吗?谢谢以上是关于如何通过 Java 程序中的 java.net.URL 类监控打开的 URL?的主要内容,如果未能解决你的问题,请参考以下文章