1

在 Java 中,我们至少可以通过两种方式注册自定义协议处理程序:

  1. 通过设置系统属性'java.protocol.handler.pkgs'
  2. 使用 URL.setURLStreamHandlerFactory

更多详情请查看http://accu.org/index.php/journals/1434

我不能选择第一个选项,因为我必须向服务器(tomcat)类路径添加很多 jar 文件,以使处理程序实现对引导类加载器可见。此外,还需要一些初始化,这必须在应用程序上下文中完成。

第二个选项的问题是Factory只能注册一次(检查java.net.URL#setURLStreamHandlerFactory),不幸的是它是由Tomcat完成的。

我能做的是创建一个装饰器工厂,它将通过我的协议处理程序扩展现有的。比使用 relfection 将静态字段 URL#factory 设置为 null 并使用 URL#setURLStreamHandlerFactory 以标准方式注册(再次?)我的“decoratorFactory”。我只是想知道在这里使用反射是否是个好主意......?治安怎么样?

我想做这样的事情:

try {
        Field factoryField = URL.class.getDeclaredField("factory");
        factoryField.setAccessible(true);
        //  get current factory
        Object currentFactory = factoryField.get(null);
        //  define a decorator factory
        MyFactoryDecorator mfd = new MyFactoryDecorator(currentFactory);
        //  set the factory to null and register MyFactoryDecorator using URL#setURLStreamHandlerFactory.
        factoryField.set(null, null);
        URL.setURLStreamHandlerFactory(mfd);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
4

1 回答 1

0

我想知道这是否可行,但是如果您创建一个实际上不包含实现的新 URLStreamHandlerFactory 怎么办?它只是坐在那里,然后在运行时通过应用上下文查找调用它时实例化真正的实现。然后理论上你可以在开始时通过系统属性实例化这个新的代理处理程序,但也可以在实际调用时使用你想要的那个。

更新:

实际上,我认为您上面的链接提到了这种策略:

另一种方法是使用工厂注册,但提供一个工厂类,它本身支持使用不同名称注册多个不同的流处理程序。

这种方法支持使用 java.net.URL 类的代码,但它确实需要对每个协议进行注册调用,因此需要对应用程序进行更改,然后才能使用新的 URL。然而,该方法通过多个类加载器解决了上面讨论的问题,因为工厂是由用户代码类加载器而不是由 URL 类的类加载器加载的。

我对您所做的一切以及注册的工作方式并不十分熟悉,因此这可能会或多或少复杂,具体取决于您在做什么。如果您甚至是否需要额外的注册,Idk,但听起来它可能会解决 .jar/app 上下文问题。

于 2015-09-03T21:49:06.003 回答