前提条件是带有参数的请求。
根据分析源代码发现解决方式有两种:
第一种:将其新建类继承MappingJackson2HttpMessageConverter.class 将所需的媒体类型添加进去,并将其设置到对应的RestTemplate对象中。样例部分代码:
public class MyMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
public MyMappingJackson2HttpMessageConverter(){
List<MediaType> mediaTypes = new ArrayList<>(); mediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED); //加入text/html类型的支持 setSupportedMediaTypes(mediaTypes);
} }
RestTemplate template = new RestTemplate();
template.getMessageConverters().add(new MyMappingJackson2HttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
第二种:根据追踪源码,发现有消息体FormHttpMessageConverter.class该类专门处理表单形式的请求,前提条件则是需要参数类型也必须是MultiValueMap。
参考源码思路:
public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
super.doWithRequest(httpRequest);
Object requestBody = this.requestEntity.getBody();
if (requestBody == null) {
HttpHeaders httpHeaders = httpRequest.getHeaders();
HttpHeaders requestHeaders = this.requestEntity.getHeaders();
if (!requestHeaders.isEmpty()) {
requestHeaders.forEach((key, values) -> httpHeaders.put(key, new LinkedList<>(values)));
}
if (httpHeaders.getContentLength() < 0) {
httpHeaders.setContentLength(0L);
}
}
else {
Class<?> requestBodyClass = requestBody.getClass();
Type requestBodyType = (this.requestEntity instanceof RequestEntity ?
((RequestEntity<?>)this.requestEntity).getType() : requestBodyClass);
HttpHeaders httpHeaders = httpRequest.getHeaders();
HttpHeaders requestHeaders = this.requestEntity.getHeaders();
MediaType requestContentType = requestHeaders.getContentType();
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
if (messageConverter instanceof GenericHttpMessageConverter) {//对应第一种解决方案
GenericHttpMessageConverter<Object> genericConverter =
(GenericHttpMessageConverter<Object>) messageConverter;
if (genericConverter.canWrite(requestBodyType, requestBodyClass, requestContentType)) {
if (!requestHeaders.isEmpty()) {
requestHeaders.forEach((key, values) -> httpHeaders.put(key, new LinkedList<>(values)));
}
if (logger.isDebugEnabled()) {
if (requestContentType != null) {
logger.debug("Writing [" + requestBody + "] as \"" + requestContentType +
"\" using [" + messageConverter + "]");
}
else {
logger.debug("Writing [" + requestBody + "] using [" + messageConverter + "]");
}
}
genericConverter.write(requestBody, requestBodyType, requestContentType, httpRequest);
return;
}
}
else if (messageConverter.canWrite(requestBodyClass, requestContentType)) {//对应第二种解决方案
if (!requestHeaders.isEmpty()) {
requestHeaders.forEach((key, values) -> httpHeaders.put(key, new LinkedList<>(values)));
}
if (logger.isDebugEnabled()) {
if (requestContentType != null) {
logger.debug("Writing [" + requestBody + "] as \"" + requestContentType +
"\" using [" + messageConverter + "]");
}
else {
logger.debug("Writing [" + requestBody + "] using [" + messageConverter + "]");
}
}
((HttpMessageConverter<Object>) messageConverter).write(
requestBody, requestContentType, httpRequest);
return;
}
}
String message = "Could not write request: no suitable HttpMessageConverter found for request type [" +
requestBodyClass.getName() + "]";
if (requestContentType != null) {
message += " and content type [" + requestContentType + "]";
}
throw new RestClientException(message);
}
}
}
第二种情况继续更追:
@Override
public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
if (!MultiValueMap.class.isAssignableFrom(clazz)) {//要求参数类型也必须MultiValueMap
return false;
}
if (mediaType == null || MediaType.ALL.equals(mediaType)) {
return true;
}
for (MediaType supportedMediaType : getSupportedMediaTypes()) {
if (supportedMediaType.isCompatibleWith(mediaType)) {
return true;
}
}
return false;
}