RestTemplate调用远程方法,服务端要求接受参数类型:applicationx-www-form-urlencoded(RestTemplate 表单请求)

it2026-04-15  1

前提条件是带有参数的请求。

根据分析源代码发现解决方式有两种:

第一种:将其新建类继承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; }

 

最新回复(0)