RESTEasy和方括号中的多值映射

时间:2014-07-18 20:09:19

标签: java jax-rs resteasy

我正在使用JAX-RS构建中继服务器。我需要能够从GET请求中提取任何查询参数,然后将它们重新包装到另一个请求中,以传递给另一个服务器。我不熟悉MultivaluedMap,但我只知道发生了什么。 UriInfogetQueryParameters方法返回MultivaluedMap<String, String>。令我意外的是,每个参数的值都是List值,即使它们声称是String值(通过我读取JavaDoc的方式)。

换句话说,如果我有一个foo=bar的键值对,则在URL查询字符串中,当我提取参数时,它会显示为foo=[bar]。当我尝试重新包装参数并将其发送到另一台服务器时,这完全抛出了一个循环(实际上是500服务器错误)。

是否有另一种方法来处理从Request中解包查询字符串,然后将其重新打包为另一个请求?我包含了一些代码来说明我的问题:

@GET
@Path("parameters")
public Response showParameters(@Context UriInfo uriInfo) {

    MultivaluedMap<String, String> parameters = uriInfo.getQueryParameters();

    StringBuffer sb = new StringBuffer();

    sb.append("<h4>Parameters:</h4>");
    if (parameters != null) {
        sb.append("<ul>");
        Iterator it = parameters.keySet().iterator();
        while (it.hasNext()) {
            String key = (String)it.next();
            sb.append("<li>")
                .append(key)
                .append(": ")
                .append(parameters.get(key))
                .append("</li>");
        }
        sb.append("</ul>");
    }
    else {
        sb.append("<p>None</p>");   
    }

    return Response.ok(sb.toString()).build();
}

因此,总而言之,如果请求具有查询参数,从上面的代码中打印出来的内容是这样的:

参数:

  • key1:[value1]
  • key2:[value2]
  • key3:[value3]

还有其他方法可以解压缩/重新包装,也许可以完全避免这个问题吗?感谢。

完整答案

@Jack值得赞扬,因为我指的是正确的方向,我正在标记his answer是正确的,但这就是我的工作。

    Client client = ClientBuilder.newClient();

    // Assume instance variable providing URI (without query string).
    WebTarget target = client.target(theRequestUri);

    // Instance variable uriInfo.
    MultivaluedMap<String, String> parameters = uriInfo.getQueryParameters();

    if (parameters != null && parameters.size() > 0) {
        Iterator it = parameters.keySet().iterator();
        String key = null;
        StringTokenizer st = null;

        while (it.hasNext()) {
            key = (String)it.next();

            // RESTEasy API is quirky, here. It wraps the values in square 
            // brackets; moreover, each value is separated by a comma and  
            // padded by a space as well. ([one, two, three, etc])

            st = new StringTokenizer(parameters.get(key).toString(), "[,]");
            while (st.hasMoreTokens()) {
                target = target.queryParam(key, st.nextToken().trim());
            }
        }
    }

    // Instance method: getContentType.
    Response response = target.request().accept(getContentType()).get();

1 个答案:

答案 0 :(得分:3)

它因为MultivaluedMap接口。

public interface MultivaluedMap<K, V> extends Map<K, List<V>> {

它返回值List
而不是parameters.get(key)尝试parameters.getFirst(key)

请注意,这将删除同一参数的其他值。在进行休息调用(例如blahblah:8080?foo=bar1&foo=bar2)时,可以为同一参数发送多个值。通过getFirst()电话,您只会获得bar1值。如果您确定无法接听多个电话,则可以使用getFirst(key)方法

--- 更新 --- 根据您的评论,您似乎需要遍历多值映射并在WebTarget实例上调用queryParam。我知道你正在寻找一个图书馆/直接的方式来做到这一点。我没有尝试RESTEasy。但我认为代码应该足够简单。

multiValuesMap?.each { key, values->
 webTargetInstance = webTargetInstance.queryParam(key, values as Object[])
}