使用受保护的类进行类型转换

时间:2018-10-05 16:15:06

标签: java reflection vert.x

由于要更改某些功能,因此我试图覆盖某些类的vertx Web项目。所以棘手的部分到了。

  @Override
  public void reroute(HttpMethod method, String path) {
    int split = path.indexOf('?');

    if (split == -1) {
      split = path.indexOf('#');
    }

    if (split != -1) {
      log.warn("Non path segment is not considered: " + path.substring(split));
      // reroute is path based so we trim out the non url path parts
      path = path.substring(0, split);
    }

    /*((HttpServerRequestWrapper) request).setMethod(method);
    ((HttpServerRequestWrapper) request).setPath(path);*/
    ((HttpServerRequestWrapper) request).setMethod(method);
    ((HttpServerRequestWrapper) request).setPath(path);
    request.params().clear();
    // we need to reset the normalized path
    normalisedPath = null;
    // we also need to reset any previous status
    statusCode = -1;
    // we need to reset any response headers
    response().headers().clear();
    // special header case cookies are parsed and cached
    if (cookies != null) {
      cookies.clear();
    }
    // reset the end handlers
    if (headersEndHandlers != null) {
      headersEndHandlers.clear();
    }
    if (bodyEndHandlers != null) {
      bodyEndHandlers.clear();
    }

    failure = null;
    restart();
  }

这段代码抛出一个编译错误:

'HttpServerRequestWrapper cannot be accessed from outside package'

我知道我们可以使用反射来创建无法访问的类的对象。在这种情况下可以使用反射吗?我该如何解决这个问题。

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

如何获取Class对象,然后在您的特定(未铸造)对象上调用方法?

我假设request是类型HttpServerRequestWrapper的类属性。然后,这就是我的建议:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

...

private final Method setMethod;
private final Method setPath;

public MyConstructor() {
    Method tmp1 = null, tmp2 = null;
    try {
        final Class<?> clazz = Class.forName("io.vertx.ext.web.impl.HttpServerRequestWrapper");
        tmp1 = clazz.getMethod("setMethod", HttpMethod.class);
        tmp1.setAccessible(true);
        tmp2 = clazz.getMethod("setPath", String.class);
        tmp2.setAccessible(true);
    } catch (ClassNotFoundException e) {
        // do something
    } catch (NoSuchMethodException e) {
        // do something
    } catch (SecurityException e) {
        // do something
    }
    this.setMethod = tmp1;
    this.setPath = tmp2;
}
...

@Override
public void reroute(HttpMethod method, String path) {
    ...
    try {
        this.setMethod.invoke(request, method);
        this.setPath.invoke(request, path);
    } catch (IllegalAccessException e) {
        // do something
    } catch (IllegalArgumentException e) {
        // do something
    } catch (InvocationTargetException e) {
        // do something
    }
    ...
}

编辑:我根据@GotoFinal的建议更新了此答案。

答案 1 :(得分:1)

在Java 8中和/或没有模块的情况下,可以将与此类相同的类放在与原始类相同的程序包中,以访问所有程序包默认类。

否则,您需要像在其他响应中一样使用反射,但是我要补充一点,最好缓存ClassMethod实例,就像使用Class.forName和{{1 }}每次都会降低代码速度。

答案 2 :(得分:0)

看起来HttpServerRequestWrapper实现了HttpServerRequest。因此,您可以在代码中将“ HttpServerRequestWrapper”更改为“ HttpServerRequest”。但是请记住,这样做只能调用接口中指定的方法。

您可以在https://vertx.io/docs/apidocs/io/vertx/rxjava/core/http/HttpServerRequest.html中看到这些方法。