简体   繁体   English

带有 URL 编码数据的 Spring RestTemplate POST 请求

[英]Spring RestTemplate POST Request with URL encoded data

I'm new to Spring and trying to do a rest request with RestTemplate.我是 Spring 的新手,正在尝试使用 RestTemplate 进行休息请求。 The Java code should do the same as below curl command: Java 代码应执行与以下 curl 命令相同的操作:

curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: xyz" "https://someserver.com/api/v3/projects/1/labels"

But the server rejects the RestTemplate with a 400 Bad Request但是服务器以400 Bad Request拒绝 RestTemplate

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("PRIVATE-TOKEN", "xyz");
HttpEntity<String> entity = new HttpEntity<String>("name=feature&color=#5843AD", headers);
ResponseEntity<LabelCreationResponse> response = restTemplate.exchange("https://someserver.com/api/v3/projects/1/labels", HttpMethod.POST, entity, LabelCreationResponse.class);

Can somebody tell me what I'm doing wrong?有人可以告诉我我做错了什么吗?

I think the problem is that when you try to send data to server didn't set the content type header which should be one of the two: "application/json" or "application/x-www-form-urlencoded".我认为问题在于,当您尝试将数据发送到服务器时,没有设置应该是以下两者之一的内容类型标头:“application/json”或“application/x-www-form-urlencoded”。 In your case is: "application/x-www-form-urlencoded" based on your sample params (name and color).在您的情况下是:“application/x-www-form-urlencoded”基于您的示例参数(名称和颜色)。 This header means "what type of data my client sends to server".此标头的意思是“我的客户端向服务器发送的数据类型”。

RestTemplate restTemplate = new RestTemplate();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.add("PRIVATE-TOKEN", "xyz");

MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("name","feature");
map.add("color","#5843AD");

HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);

ResponseEntity<LabelCreationResponse> response =
    restTemplate.exchange("https://foo/api/v3/projects/1/labels",
                          HttpMethod.POST,
                          entity,
                          LabelCreationResponse.class);

You need to set the Content-Type to application/json.您需要将 Content-Type 设置为 application/json。 Content-Type has to be set in the request. Content-Type 必须在请求中设置。 Below is the modified code to set the Content-Type下面是设置内容类型的修改代码

final String uri = "https://someserver.com/api/v3/projects/1/labels";
String input = "US";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.add("PRIVATE-TOKEN", "xyz");
HttpEntity<String> request = new HttpEntity<String>(input, headers);
ResponseEntity<LabelCreationResponse> response = restTemplate.postForObject(uri, request,  LabelCreationResponse.class);

Here, HttpEntity is constructed with your input ie "US" and with headers.在这里,HttpEntity 是用您的输入(即“US”)和标头构建的。 Let me know if this works, if not then please share the exception.让我知道这是否有效,如果无效,请分享异常。 Cheers!干杯!

It may be a Header issue check if the header is a Valid header, are u referring to "BasicAuth" header?如果标头是有效标头,则可能是标头问题检查,您指的是“BasicAuth”标头吗?

HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED.toString());
headers.add("Accept", MediaType.APPLICATION_JSON.toString()); //Optional in case server sends back JSON data
    
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<String, String>();
requestBody.add("name", "feature");
requestBody.add("color", "#5843AD");
    
HttpEntity formEntity = new HttpEntity<MultiValueMap<String, String>>(requestBody, headers);
    
ResponseEntity<LabelCreationResponse> response = 
   restTemplate.exchange("https://example.com/api/request", HttpMethod.POST, formEntity, LabelCreationResponse.class);

my issue, the MessageConverters contains other converters may converts then entity to json (like FastJsonHttpMessageConverter).我的问题是, MessageConverters包含其他转换器可能会将实体转换为 json(如 FastJsonHttpMessageConverter)。 So i added the FormHttpMessageConverter to ahead and it works well.所以我将 FormHttpMessageConverter 添加到前面并且效果很好。

<T> JuheResult<T> postForm(final String url, final MultiValueMap<String, Object> body) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
    return exchange(url, HttpMethod.POST, requestEntity);
}

<T> JuheResult<T> exchange(final String url, final HttpMethod method, final HttpEntity<?> requestEntity) {
    ResponseEntity<JuheResult<T>> response = restTemplate.exchange(url, method, requestEntity,
            new JuheResultTypeReference<>());
    logger.debug("调用结果 {}", response.getBody());
    return response.getBody();
}

public JuheSupplierServiceImpl(RestTemplateBuilder restTemplateBuilder) {
    Duration connectTimeout = Duration.ofSeconds(5);
    Duration readTimeout = Duration.ofSeconds(5);

    restTemplate = restTemplateBuilder.setConnectTimeout(connectTimeout).setReadTimeout(readTimeout)
            .additionalInterceptors(interceptor()).build();
    restTemplate.getMessageConverters().add(0, new FormHttpMessageConverter());
}

fastjson prevent resttemplate converting other mediaTypes other than json fastjson 防止resttemplate转换json以外的其他mediaType

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM