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

时间:2018-03-06 09:18:20

标签: java spring spring-web

我是Spring的新手,并尝试使用RestTemplate进行休息请求。 Java代码应该与下面的curl命令相同:

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

但服务器拒绝使用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);

有人可以告诉我我做错了吗?

4 个答案:

答案 0 :(得分:15)

我认为问题在于,当您尝试向服务器发送数据时,没有设置内容类型标题,该标题应该是两个中的一个:&#34; application / json&#34;或&#34; application / x-www-form-urlencoded&#34; 。在你的情况下是:&#34; application / x-www-form-urlencoded&#34;根据您的样本参数(名称和颜色)。此标头表示&#34;客户端向服务器发送的数据类型&#34;。

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<String, String>();
map.add("name","feature");
map.add("color","#5843AD");

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

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

答案 1 :(得分:2)

您需要将Content-Type设置为application / json。必须在请求中设置Content-Type。以下是用于设置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);

这里,HttpEntity是用您的输入构建的,即“US”和标题。 如果有效,请告诉我,如果没有,请分享例外情况。 干杯!

答案 2 :(得分:0)

如果标题是有效标题,可能是标题问题检查,是否指的是&#34; BasicAuth&#34;头?

HttpHeader 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);

答案 3 :(得分:0)

我的问题,MessageConverters 包含其他转换器可能会将实体转换为 json(如 FastJsonHttpMessageConverter)。所以我在前面添加了 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 防止 resttemplate 转换 json 以外的其他媒体类型