有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java生成的Swagger REST客户端无法正确处理查询参数的+字符

我有一个Spring REST控制器方法:

@ApiOperation("My method")
@RequestMapping(method = RequestMethod.POST, value = "/myMethod")
public void myMethod(@RequestParam("myParam") String myParam) {
...
}

REST客户机是使用swagger codegen CLI生成的,其语言为Java和libraryresttemplate

public void myMethod(String myParam) throws RestClientException {
    ...
    return apiClient.invokeAPI(path, HttpMethod.POST, queryParams, postBody, headerParams, formParams, accept, contentType, authNames, returnType);
}

ApiClient#invokeAPI的源代码(也生成了)是:

public <T> T invokeAPI(String path, HttpMethod method, MultiValueMap<String, String> queryParams, Object body, HttpHeaders headerParams, MultiValueMap<String, Object> formParams, List<MediaType> accept, MediaType contentType, String[] authNames, ParameterizedTypeReference<T> returnType) throws RestClientException {
    updateParamsForAuth(authNames, queryParams, headerParams);

    final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path);
    if (queryParams != null) {
        builder.queryParams(queryParams);
    }

    final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri());
    if(accept != null) {
        requestBuilder.accept(accept.toArray(new MediaType[accept.size()]));
    }
    if(contentType != null) {
        requestBuilder.contentType(contentType);
    }

    addHeadersToRequest(headerParams, requestBuilder);
    addHeadersToRequest(defaultHeaders, requestBuilder);

    RequestEntity<Object> requestEntity = requestBuilder.body(selectBody(body, formParams, contentType));

    ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
    ...
}

现在,当我调用myMethod传递一个包含+登录myParam的字符串时,我在服务器上收到一个空格字符,而不是+。这似乎是一个编码问题,因为URL查询参数中保留了加号以替换空格字符。这是来自swagger codegen还是Spring类的bug,还是根本没有bug?我该怎么解决

编辑:

招摇过市定义如下(由Spring REST controller生成):

{
  "swagger": "2.0",
  ...
  "paths": {
    "/myMethod": {
      "get": {
        "operationId": "myMethod",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "myParam",
            "in": "query",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
           ...
        }
      }
    }
 ...
}

编辑:

路径变量的编码似乎也存在类似的问题。当我将"bla:bla/bla"传递给路径变量时,特殊字符:/将不会被编码,而是按原样发送,这会导致服务器端出错,因为找不到映射


共 (1) 个答案

  1. # 1 楼答案

    A+通常表示url参数中的空格。这是一个标准。您的url将在下面的代码行中生成

    final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri());
    

    而且+不是编码的,因为它是一个有效值,随后将在接收端转换为空间。现在,当您尝试使用%2B时,上面的代码行会看到您有一个未编码的%字符,并将其转换为%252B

    当你在Spring上收到它时,它会为你把它转换回%2B。解决这个问题的一种方法是自己发送编码值。所以你会改变

     final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri());
    

    final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build(true).toUri());
    

    然后调用API方法

    client.myMethod("tarun%2blalwani")
    

    现在spring将收到tarun+lalwani,如下所示

    + in spring