无法在您的客户端中注册DynamicFeature。
见DynamicFeature documentation:
用于动态注册后匹配的 JAX-RS 元提供程序
部署时 JAX-RS 应用程序设置期间的提供程序。
JAX-RS 运行时使用动态特性来注册提供者
应应用于特定的资源类和方法,并且
覆盖任何基于注释的绑定定义
注册资源过滤器或拦截器实例。
实现这个接口的提供者可以用@Provider注解
注释以便在扫描时被 JAX-RS 运行时发现
对于资源和提供者。 仅支持此提供程序类型
服务器 API 的一部分。
JAX-RS Client API 可用于使用在 HTTP 协议之上公开的任何 Web 服务,并且不限于使用 JAX-RS 实现的服务。
请注意 JAX-RS 客户端 API不直接调用资源类。相反,它会向服务器生成 HTTP 请求。因此,您将无法从资源类中读取注释。
更新 1
我不确定这是否对您有用,但由于您想从您的客户端访问服务器资源类,因此值得一提的是 Jersey 提供了一个 proxy-based client API(org.glassfish.jersey.client.proxy 包) .
基本思想是您可以附加standard JAX-RS annotations to an interface,然后在服务器端通过资源类实现该接口,同时通过使用java.lang.reflect.Proxy调用正确的低级客户端 API 方法。
这个例子摘自Jersey documentation:
考虑一个在http://localhost:8080 公开资源的服务器。资源可以通过如下接口来描述:
@Path("myresource")
public interface MyResourceIfc {
@GET
@Produces("text/plain")
String get();
@POST
@Consumes("application/xml")
@Produces("application/xml")
MyBean postEcho(MyBean bean);
@GET
@Path("{id}")
@Produces("text/plain")
String getById(@PathParam("id") String id);
}
您可以使用this package 中定义的WebResourceFactory 类通过此接口访问服务器端资源。这是一个例子:
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080/");
MyResourceIfc resource = WebResourceFactory.newResource(MyResourceIfc.class, target);
String responseFromGet = resource.get();
MyBean responseFromPost = resource.postEcho(myBeanInstance);
String responseFromGetById = resource.getById("abc");
我不确定 RESTEasy 是否提供了类似的东西。
更新 2
RESTEasy 还提供了proxy framework。见documentation:
RESTEasy 有一个客户端代理框架,允许您使用 JAX-RS 注释来调用远程 HTTP 资源。它的工作方式是编写一个 Java 接口并在方法和接口上使用 JAX-RS 注释。例如:
public interface SimpleClient {
@GET
@Path("basic")
@Produces("text/plain")
String getBasic();
@PUT
@Path("basic")
@Consumes("text/plain")
void putBasic(String body);
@GET
@Path("queryParam")
@Produces("text/plain")
String getQueryParam(@QueryParam("param") String param);
@GET
@Path("matrixParam")
@Produces("text/plain")
String getMatrixParam(@MatrixParam("param") String param);
@GET
@Path("uriParam/{param}")
@Produces("text/plain")
int getUriParam(@PathParam("param") int param);
}
RESTEasy 有一个基于 Apache HttpClient 的简单 API。您生成一个代理,然后您可以调用代理上的方法。调用的方法会根据您如何注释方法并发布到服务器而转换为 HTTP 请求。以下是您的设置方法:
Client client = ClientFactory.newClient();
WebTarget target = client.target("http://example.com/base/uri");
ResteasyWebTarget rtarget = (ResteasyWebTarget) target;
SimpleClient simple = rtarget.proxy(SimpleClient.class);
simple.putBasic("hello world");
您也可以直接使用 RESTEasy 客户端扩展接口:
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target("http://example.com/base/uri");
SimpleClient simple = target.proxy(SimpleClient.class);
simple.putBasic("hello world");
[...]
该框架还支持 JAX-RS 定位器模式,但在客户端。因此,如果您有一个仅使用 @Path 注释的方法,则该代理方法将返回该方法返回的接口的新代理。
[...]
通常可以在客户端和服务器之间共享一个接口。在这种情况下,您只需让您的 JAX-RS 服务实现一个带注释的接口,然后重用相同的接口来创建客户端代理以在客户端调用。
更新 3
由于您已经在使用RESTEasy Proxy Framework 并且假设您的服务器资源实现了您用来创建客户端代理的相同接口,以下解决方案应该可以工作。
来自 Spring AOP 的 ProxyFactory 已经包含了 RESTEasy 客户端。该解决方案基本上创建了一个 proxy of the proxy 来拦截正在调用的方法。
以下类存储Method 实例:
public class MethodWrapper {
private Method method;
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
}
下面的代码很神奇:
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target("http://example.com/api");
ExampleResource resource = target.proxy(ExampleResource.class);
MethodWrapper wrapper = new MethodWrapper();
ProxyFactory proxyFactory = new ProxyFactory(resource);
proxyFactory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
wrapper.setMethod(invocation.getMethod());
return invocation.proceed();
}
});
ExampleResource resourceProxy = (ExampleResource) proxyFactory.getProxy();
Response response = resourceProxy.doSomething("Hello World!");
Method method = wrapper.getMethod();
ExpectedHttpStatus expectedHttpStatus = method.getAnnotation(ExpectedHttpStatus.class);
int status = response.getStatus();
int expectedStatus = annotation.status();
有关更多信息,请查看文档: