如何使用 RESTEasy 代理客户端发送查询参数映射
How to send a query params map using RESTEasy proxy client
我正在寻找一种方法来将包含参数名称和值的地图传递给 GET Web 目标。我期待 RESTEasy 将我的地图转换为 URL 查询参数列表;然而,RESTEasy 会抛出一个异常 Caused by: javax.ws.rs.ProcessingException: RESTEASY004565: A GET request cannot have a body.
。我如何告诉 RESTEasy 将此映射转换为 URL 查询参数?
这是代理界面:
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
public interface ExampleClient {
@GET
@Path("/example/{name}")
@Produces(MediaType.APPLICATION_JSON)
Object getObject(@PathParam("name") String name, MultivaluedMap<String, String> multiValueMap);
}
这是用法:
@Controller
public class ExampleController {
@Inject
ExampleClient exampleClient; // injected correctly by spring DI
// this runs inside a spring controller
public String action(String objectName) {
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
// in the real code I get the params and values from a DB
params.add("foo", "bar")
params.add("jar", "car")
//.. keep adding
exampleClient.getObject(objectName, params); // throws exception
}
}
在研究 RESTEasy 源代码数小时后,我发现无法通过接口注释来做到这一点。简而言之,RESTEasy 从 org.jboss.resteasy.client.jaxrs.internal.proxy.processors.ProcessorFactory
创建了一个叫做 'processor' 的东西来将注释映射到目标 URI。
但是,通过创建一个 ClientRequestFilter
来解决这个问题非常简单,它从请求正文中获取 Map(当然在执行请求之前),并将它们放在 URI 查询参数中。检查下面的代码:
过滤器:
@Provider
@Component // because I'm using spring boot
public class GetMessageBodyFilter implements ClientRequestFilter {
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
if (requestContext.getEntity() instanceof Map && requestContext.getMethod().equals(HttpMethod.GET)) {
UriBuilder uriBuilder = UriBuilder.fromUri(requestContext.getUri());
Map allParam = (Map)requestContext.getEntity();
for (Object key : allParam.keySet()) {
uriBuilder.queryParam(key.toString(), allParam.get(key));
}
requestContext.setUri(uriBuilder.build());
requestContext.setEntity(null);
}
}
}
PS:为了简单起见,我使用了Map
而不是MultivaluedMap
我正在寻找一种方法来将包含参数名称和值的地图传递给 GET Web 目标。我期待 RESTEasy 将我的地图转换为 URL 查询参数列表;然而,RESTEasy 会抛出一个异常 Caused by: javax.ws.rs.ProcessingException: RESTEASY004565: A GET request cannot have a body.
。我如何告诉 RESTEasy 将此映射转换为 URL 查询参数?
这是代理界面:
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
public interface ExampleClient {
@GET
@Path("/example/{name}")
@Produces(MediaType.APPLICATION_JSON)
Object getObject(@PathParam("name") String name, MultivaluedMap<String, String> multiValueMap);
}
这是用法:
@Controller
public class ExampleController {
@Inject
ExampleClient exampleClient; // injected correctly by spring DI
// this runs inside a spring controller
public String action(String objectName) {
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
// in the real code I get the params and values from a DB
params.add("foo", "bar")
params.add("jar", "car")
//.. keep adding
exampleClient.getObject(objectName, params); // throws exception
}
}
在研究 RESTEasy 源代码数小时后,我发现无法通过接口注释来做到这一点。简而言之,RESTEasy 从 org.jboss.resteasy.client.jaxrs.internal.proxy.processors.ProcessorFactory
创建了一个叫做 'processor' 的东西来将注释映射到目标 URI。
但是,通过创建一个 ClientRequestFilter
来解决这个问题非常简单,它从请求正文中获取 Map(当然在执行请求之前),并将它们放在 URI 查询参数中。检查下面的代码:
过滤器:
@Provider
@Component // because I'm using spring boot
public class GetMessageBodyFilter implements ClientRequestFilter {
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
if (requestContext.getEntity() instanceof Map && requestContext.getMethod().equals(HttpMethod.GET)) {
UriBuilder uriBuilder = UriBuilder.fromUri(requestContext.getUri());
Map allParam = (Map)requestContext.getEntity();
for (Object key : allParam.keySet()) {
uriBuilder.queryParam(key.toString(), allParam.get(key));
}
requestContext.setUri(uriBuilder.build());
requestContext.setEntity(null);
}
}
}
PS:为了简单起见,我使用了Map
而不是MultivaluedMap