java - RESTEasy 和方括号中的 MultivaluedMap

标签 java jax-rs resteasy

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

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

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

@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]
  • 键2:[值2]
  • 键3:[值3]

有没有另一种解包/重新打包的方法,也许可以完全避免这整个问题?谢谢。

完整答案

@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();

最佳答案

这是因为 MultivaluedMap 接口(interface)。

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

它以 List 的形式返回值。
而不是 parameters.get(key) 试试 parameters.getFirst(key)

请注意,这将删除同一参数的其他值。在进行诸如 blahblah:8080?foo=bar1&foo=bar2 的 rest 调用时,可以为同一参数发送多个值。使用 getFirst() 调用,您将仅获得 bar1 值。如果您确定不会收到多个电话,您可以使用 getFirst(key) 方法

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

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

关于java - RESTEasy 和方括号中的 MultivaluedMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24833004/

相关文章:

java - 编写 QBE Restful 方法的最佳方法?

Java:如何指定一个目录,这样我就不需要指定它来引用它的 .jar 文件

java - 修复了 Rest 服务输入参数中的名称

java - Android:将视频作为 POST 请求上传到 Java 后端?

java - Swagger 和 web.xml

java - Java Resteasy 中的赛前过滤器

java - 多次调用 onFocusChange 导致 "hasFocus"变量不可用

java - 从 HashMap 中检索记录

java - 使用 -cp 或 -classpath 手动设置 CLASSPATH 无法按预期工作

java - Jersey 方法不允许 405