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

Java 带有URL编码数据的Spring RestTemplate POST请求,java,spring,spring-web,Java,Spring,Spring Web,我是Spring新手,正在尝试使用RestTemplate执行rest请求。Java代码应执行与以下curl命令相同的操作: curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: xyz" "https://someserver.com/api/v3/projects/1/labels" 但服务器拒绝RestTemplate,并发出400错误请求 RestTemplate restTemplate = new

我是Spring新手,正在尝试使用RestTemplate执行rest请求。Java代码应执行与以下curl命令相同的操作:

curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: xyz" "https://someserver.com/api/v3/projects/1/labels"
但服务器拒绝RestTemplate,并发出
400错误请求

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);
RestTemplate RestTemplate=new RestTemplate();
HttpHeaders=新的HttpHeaders();
添加(“专用令牌”、“xyz”);
HttpEntity=新的HttpEntity(“名称=功能和颜色=#5843AD”,标题);
ResponseEntity response=restTemplate.exchange(“https://someserver.com/api/v3/projects/1/labels,HttpMethod.POST,entity,LabelCreationResponse.class);

有人能告诉我我做错了什么吗?

您需要将内容类型设置为application/json。必须在请求中设置内容类型。下面是设置内容类型的修改代码

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);
最终字符串uri=”https://someserver.com/api/v3/projects/1/labels";
字符串输入=“US”;
HttpHeaders=新的HttpHeaders();
headers.setContentType(MediaType.APPLICATION\u FORM\u URLENCODED);
添加(“专用令牌”、“xyz”);
HttpEntity请求=新的HttpEntity(输入,标题);
ResponseEntity response=restemplate.postForObject(uri、请求、LabelCreationResponse.class);
在这里,HttpEntity是用您的输入即“US”和头构建的。 让我知道这是否有效,如果无效,请分享例外。
干杯

如果报头是有效的报头,则可能是报头问题检查,u是否指“BasicAuth”报头

HttpHeaders=newhttpheaders();
headers.add(“Content-Type”,MediaType.APPLICATION_FORM_URLENCODED.toString());
headers.add(“Accept”,MediaType.APPLICATION_JSON.toString())//如果服务器发回JSON数据,则为可选
MultiValueMap requestBody=新链接的MultiValueMap();
添加(“名称”、“特征”);
添加(“颜色”,“#5843AD”);
HttpEntity formEntity=新的HttpEntity(请求主体、标题);
响应性响应=
restTemplate.exchange(“https://example.com/api/request,HttpMethod.POST,formEntity,LabelCreationResponse.class);

我认为问题在于,当您尝试向服务器发送数据时,没有设置内容类型标题,该标题应为两个标题之一:“application/json”或“application/x-www-form-urlencoded”。在您的例子中,是基于示例参数(名称和颜色)的“application/x-www-form-urlencoded”。此标题表示“我的客户端发送到服务器的数据类型”

RestTemplate RestTemplate=new RestTemplate();
HttpHeaders=新的HttpHeaders();
headers.setContentType(MediaType.APPLICATION\u FORM\u URLENCODED);
添加(“专用令牌”、“xyz”);
MultiValueMap=新链接的MultiValueMap();
地图。添加(“名称”、“特征”);
地图。添加(“颜色”,“#5843AD”);
HttpEntity=新的HttpEntity(映射、标题);
反应性反应=
restTemplate.exchange(“https://foo/api/v3/projects/1/labels",
HttpMethod.POST,
实体,
LabelCreationResponse.class);

我的问题是,
消息转换器
包含其他转换器,可以将实体转换为json(如FastJsonHttpMessageConverter)。因此,我将FormHttpMessageConverter添加到ahead中,它运行良好

<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());
}
JuheResult postForm(最终字符串url,最终多值映射体){
HttpHeaders=新的HttpHeaders();
headers.setContentType(MediaType.APPLICATION\u FORM\u URLENCODED);
HttpEntity requestEntity=新的HttpEntity(主体、标题);
返回交换(url、HttpMethod.POST、requestEntity);
}
JuheResult交换(最终字符串url、最终HttpMethod方法、最终HttpEntity requestEntity){
ResponseEntity response=restemplate.exchange(url、方法、requestEntity、,
新的JuheResultTypeReference());
logger.debug(“调用结果 {},response.getBody());
返回response.getBody();
}
公共JuheSupplierServiceImpl(RestTemplateBuilder RestTemplateBuilder){
持续时间连接超时=持续时间秒(5);
持续时间readTimeout=持续时间秒(5);
restTemplate=restTemplateBuilder.setConnectTimeout(connectTimeout).setReadTimeout(readTimeout)
.additionalInterceptors(interceptor()).build();
restTemplate.getMessageConverters().add(0,新FormHttpMessageConverter());
}


fastjson阻止resttemplate转换json以外的其他媒体类型不起作用,但我找到了原因。HttpHeader类始终将字符串设置为JSON对象。我必须将内容类型设置为APPLICATION\u FORM\u URLENCODED。无论如何,谢谢你的帮助。史:谢谢你的回答。请您重新表述您的答案,解释为什么您添加的消息转换器有帮助?我在lagecy proj中使用fastjson,然后fastjson有一些
错误
打破了spring的默认配置'/***可以序列化/反序列化所有类型。*/public FastJsonHttpMessageConverter(){super(MediaType.ALL);}'仅添加contentType无效。事实上,人们建议将contentType添加到messageCoverter等中;列表形式=新建ArrayList();UrlEncodedFormEntity实体=新的UrlEncodedFormEntity(表单,Consts.UTF_8);httpPost.setEntity(实体);addHeader(“内容类型”,“应用程序/x-www-form-urlencoded”);CloseableHttpResponse-tokenResponse=userWebTokenHTTPclient.execute(httpPost);
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);
<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());
}