使用 RestTemplate 与对象作为数据和 application/x-www-form-urlencoded 内容类型? [英] Use RestTemplate with object as data and application/x-www-form-urlencoded content type?
问题描述
我需要通过内容类型为 application/x-www-form-urlencoded的
RestTemplate
发布一个对象(例如不是 MultiValueMap
)代码>.当我尝试这样做时......
I need to post an object (e.g. not a MultiValueMap
) via a RestTemplate
with the content type application/x-www-form-urlencoded
. When I try to do so ...
HttpHeaders headers = new HttpHeaders();
HttpEntity request;
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED)
// data is some generic type
request = new HttpEntity<>(data, headers);
// clazz is the Class<T> being returned
restTemplate.exchange(url, method, request, clazz)
...我收到以下错误:
... I get the following error:
org.springframework.web.client.RestClientException:无法写入请求:没有找到适合请求类型 [com.whatever.MyRequestPayload] 和内容类型 [application/x-www-form-urlencoded] 的 HttpMessageConverter
org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [com.whatever.MyRequestPayload] and content type [application/x-www-form-urlencoded]
这是我在 restTemplate.getMessageConverters()
中看到的:
Here is what I see within restTemplate.getMessageConverters()
:
为什么我不想提供 MultiValueMap
? 两个原因:
Why don't I want to provide a MultiValueMap
? Two reasons:
- 这是用于向多个端点发送请求的通用代码,因此专门为
x-www-form-urlencoded
添加重载只会使事情复杂化 - 似乎我不应该 - 我只是不知道需要使用哪个 HttpMessageConverter 来支持将对象转换为
x-www-form-urlencoded
字符串立>
- this is general purpose code which is used to send requests to multiple endpoints, so adding an overload specifically for
x-www-form-urlencoded
will only complicate things - it doesn't seem like I should have to -- I just don't know which HttpMessageConverter needs to be used to support converting objects to a
x-www-form-urlencoded
string
推荐答案
我最终不得不编写一个自定义 HTTP 消息转换器,它接受任何对象并将其作为 www-form-urlencoded 内容写出到请求正文:>
用法
I ended up having to write a custom HTTP message converter which takes any object and writes it out as www-form-urlencoded content to the request body:
RestTemplate template = new RestTemplate(...);
template.getMessageConverters().add(new ObjectToUrlEncodedConverter(mapper));
ObjectToUrlEncodedConverter
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.List;
public class ObjectToUrlEncodedConverter implements HttpMessageConverter
{
private static final String Encoding = "UTF-8";
private final ObjectMapper mapper;
public ObjectToUrlEncodedConverter(ObjectMapper mapper)
{
this.mapper = mapper;
}
@Override
public boolean canRead(Class clazz, MediaType mediaType)
{
return false;
}
@Override
public boolean canWrite(Class clazz, MediaType mediaType)
{
return getSupportedMediaTypes().contains(mediaType);
}
@Override
public List<MediaType> getSupportedMediaTypes()
{
return Collections.singletonList(MediaType.APPLICATION_FORM_URLENCODED);
}
@Override
public Object read(Class clazz, HttpInputMessage inputMessage) throws HttpMessageNotReadableException
{
throw new NotImplementedException();
}
@Override
public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage) throws HttpMessageNotWritableException
{
if (o != null)
{
String body = mapper
.convertValue(o, UrlEncodedWriter.class)
.toString();
try
{
outputMessage.getBody().write(body.getBytes(Encoding));
}
catch (IOException e)
{
// if UTF-8 is not supporter then I give up
}
}
}
private static class UrlEncodedWriter
{
private final StringBuilder out = new StringBuilder();
@JsonAnySetter
public void write(String name, Object property) throws UnsupportedEncodingException
{
if (out.length() > 0)
{
out.append("&");
}
out
.append(URLEncoder.encode(name, Encoding))
.append("=");
if (property != null)
{
out.append(URLEncoder.encode(property.toString(), Encoding));
}
}
@Override
public String toString()
{
return out.toString();
}
}
}
这篇关于使用 RestTemplate 与对象作为数据和 application/x-www-form-urlencoded 内容类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!