通过REST中的RestTemplate进行POST请求


126

我没有找到解决问题的示例,因此想向您寻求帮助。我不能简单地使用JSON中的RestTemplate对象发送POST请求

每当我得到:

org.springframework.web.client.HttpClientErrorException:415不支持的媒体类型

我以这种方式使用RestTemplate:

...
restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
list.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(list);
...
Payment payment= new Payment("Aa4bhs");
Payment res = restTemplate.postForObject("http://localhost:8080/aurest/rest/payment", payment, Payment.class);

我怎么了


1
该网址不再有效
@troyfolger

谢谢-这个环节的工作,因为这写的:spring.io/guides/gs/consuming-rest
troyfolger

为了解决上述特定的OP问题,您可能缺少具有适当内容类型的HTTP标头,请参见下面的morganw09dev答案。
troyfolger

这些问题主要与服务器API配置有关。您可以使用独立客户端(例如Postman)测试Server API,并在请求中复制相同的标头。至少在我看来,这是技巧。
莱纳斯(Linus)

1
@Johnny B,如果已回答,请注明答案
Vishal

Answers:


161

这项技术对我有用:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.put(url, entity);

我希望这有帮助


3
请说明哪一行应返回http请求的结果
gstackoverflow 2015年

对我来说,没有必要指定任何标题。我使用了带有单个参数的HttpEntity。
君士坦丁堡Cronemberger'May

24
方法.put()void
'18

4
使用postForEntity(url, entity, String.class)作品代替put(url, entity)
Janac Meena,

1
@ Kanu,requestJson是有效的JSON字符串还是其他?
德瓦(Deva)

95

尝试调试REST端点时遇到了这个问题。这是一个使用Spring的RestTemplate类发出我使用的POST请求的基本示例。我花了相当长的时间才能将来自不同地方的代码组合在一起,以得到一个有效的版本。

RestTemplate restTemplate = new RestTemplate();

String url = "endpoint url";
String requestJson = "{\"queriedQuestion\":\"Is there pain in your hand?\"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
String answer = restTemplate.postForObject(url, entity, String.class);
System.out.println(answer);

我的其余端点使用的特定JSON解析器在字段名称周围使用了必要的双引号,因此这就是为什么我在requestJson String中转义了双引号的原因。



Spring是否可以像使用RestTemplate的Restful API一样使用消息转换器将Java对象自动转换为json?
秋季

1
将媒体类型设置为APPLICATION_JSON是解决此问题的关键。
皮特·T

我使用HttpEntity <String>实体= new HttpEntity <String>(requestJson,headers);解决了我的问题 这条线
Ved Prakash

76

我一直在使用带有JSONObjects的rest模板,如下所示:

// create request body
JSONObject request = new JSONObject();
request.put("username", name);
request.put("password", password);

// set headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);

// send request and parse result
ResponseEntity<String> loginResponse = restTemplate
  .exchange(urlString, HttpMethod.POST, entity, String.class);
if (loginResponse.getStatusCode() == HttpStatus.OK) {
  JSONObject userJson = new JSONObject(loginResponse.getBody());
} else if (loginResponse.getStatusCode() == HttpStatus.UNAUTHORIZED) {
  // nono... bad credentials
}

谢谢-JSONObject toString方法对我很有用,它帮助我准确地获取了JSONString。
西蒙(Simon)

1
如何为此开发以上代码:curl -vvv -X POST“ localhost:8080 / SillyService_SRC / oauth / ... ”?
Pra_A

@MikaelLepistö我如何在服务器端从json检索这些参数?
KJEjava48

@ KJEjava48我不明白您的意思是...这是响应中的服务器端代码。如果您正在考虑如何解析json响应,则取决于您使用的框架。
MikaelLepistö17年

@MikaelLepistö我的意思是如何在另一端解析json响应,包括如何在java中接收响应?您只发布了一端(即服务器端)的代码。
KJEjava48 '17


9

如果您使用的是Spring 3.0,避免org.springframework.web.client.HttpClientErrorException:415 Unsupported Media Type异常的一种简便方法是在类路径中包含jackson jar文件,并使用mvc:annotation-drivenconfig元素。如此处指定

我想弄清楚为什么mvc-ajax应用程序在没有任何特殊配置的情况下就可以工作了MappingJacksonHttpMessageConverter。如果您阅读了上面我紧密链接的文章:

在幕后,Spring MVC委托给HttpMessageConverter来执行序列化。在这种情况下,Spring MVC会调用在Jackson JSON处理器上构建的MappingJacksonHttpMessageConverter。当您在类路径中使用Jackson时使用mvc:annotation驱动的配置元素时,将自动启用此实现。


7

“ 415不支持的媒体类型”错误告诉您服务器将不接受您的POST请求。您的请求绝对没问题,这是服务器配置错误。

MappingJacksonHttpMessageConverter会自动将request content-type标头设置为application/json,而我的猜测是您的服务器拒绝了它。不过,您还没有告诉我们有关您的服务器设置的任何信息,因此我不能就此提供任何建议。


7

我是用这种方式做的,而且有效。

HttpHeaders headers = createHttpHeaders(map);
public HttpHeaders createHttpHeaders(Map<String, String> map)
{   
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    for (Entry<String, String> entry : map.entrySet()) {
        headers.add(entry.getKey(),entry.getValue());
    }
    return headers;
}

//在此处传递标题

 String requestJson = "{ // Construct your JSON here }";
logger.info("Request JSON ="+requestJson);
HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
logger.info("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
logger.info("Response ="+response.getBody());

希望这可以帮助


4

我遇到了这个问题,并且在客户端上使用Spring的RestTemplate,在服务器上使用Spring Web。这两个API的错误报告都很差,因此很难使用它们进行开发。

经过许多小时的尝试,我发现问题是由于传递了POST正文的空引用而不是预期的List引起的。我认为RestTemplate不能从空对象确定内容类型,但是不会抱怨它。添加正确的标头后,在进入服务方法之前,我开始在Spring中获得另一个服务器端异常。

解决方法是从客户端传递一个空列表,而不是null。由于默认的内容类型用于非空对象,因此不需要标头。


3

这段代码对我有用。

RestTemplate restTemplate = new RestTemplate();
Payment payment = new Payment("Aa4bhs");
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("payment", payment);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(map, headerObject);

Payment res = restTemplate.postForObject(url, httpEntity, Payment.class);

我正在使用一种非常相似的方法,但它对我没有用。由于某种原因,我的“地图”等效项未转换为json或作为出站主体包含在内,即目标服务看不到任何有效载荷。
abdel

2

如果您不想处理回应

private RestTemplate restTemplate = new RestTemplate();
restTemplate.postForObject(serviceURL, request, Void.class);

如果您需要对流程的回应

String result = restTemplate.postForObject(url, entity, String.class);

0

对我来说,此设置发生错误:

AndroidAnnotations Spring Android RestTemplate Module 还有...

GsonHttpMessageConverter

Android批注与此转换为生成POST不带参数的请求时存在一些问题。简单的参数new Object()为我解决了。


0

为什么要比您更努力地工作?postForEntity接受一个简单的Map对象作为输入。在Spring中为给定的REST端点编写测试时,以下对我而言工作正常。我相信这是在Spring中提出JSON POST请求的最简单的方法:

@Test
public void shouldLoginSuccessfully() {
  // 'restTemplate' below has been @Autowired prior to this
  Map map = new HashMap<String, String>();
  map.put("username", "bob123");
  map.put("password", "myP@ssw0rd");
  ResponseEntity<Void> resp = restTemplate.postForEntity(
      "http://localhost:8000/login",
      map,
      Void.class);
  assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
}

0

如果您不想自己映射JSON,则可以按照以下步骤进行操作:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter()));
ResponseEntity<String> result = restTemplate.postForEntity(uri, yourObject, String.class);

0

我在春季启动中尝试了以下操作:

ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() {};
public Map<String, Object> processResponse(String urlendpoint)
{
    try{
    
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        //reqobj
        JSONObject request = new JSONObject();
        request.put("username", name);
        //Or Hashmap 
        Map<String, Object> reqbody =  new HashMap<>();
        reqbody.put("username",username);
        Gson gson = new Gson();//mvn plugin to convert map to String
        HttpEntity<String> entity = new HttpEntity<>( gson.toJson(reqbody), headers);
        ResponseEntity<Map<String, Object>> response = resttemplate.exchange(urlendpoint, HttpMethod.POST, entity, typeRef);//example of post req with json as request payload
        if(Integer.parseInt(response.getStatusCode().toString()) == HttpURLConnection.HTTP_OK)
        {
            Map<String, Object>  responsedetails = response.getBody();
            System.out.println(responsedetails);//whole json response as map object
            return responsedetails;
        }
    } catch (Exception e) {
        // TODO: handle exception
        System.err.println(e);
    }
    return null;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.