Spring中的内容类型问题 [英] Issue with content type in Spring
问题描述
我收到的POST有问题.我有以下端点:
I have an issue with a POST that I am receiving. I have the following endpoint:
@RequestMapping(value = "/payment", method = POST)
public void saveOrder(@RequestBody PaymentDto paymentDto) throws RequiredFieldException, IOException, MessagingException {
//do something
}
现在,当有人通过该URL向我发送POST时,我得到以下响应:
Now, when someone send me POST on this URL, I get the following in response:
{"errorMessage":"Unsupported Media Type",
"errorId":"906f5dc8-0b79-4f91-9eaa-a252e8d5ac76",
"errorDetails":
{"message":"Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported",
"exception":"org.springframework.web.HttpMediaTypeNotSupportedException",
"errors":null
}}
我该如何解决?发送时无法更改内容类型标头.它是由我无法控制的服务器发送的.
How can I fix that? I cannot change content type header when I send it. It is send from server that I don't control.
推荐答案
到目前为止,对我来说最好的替代方法是编写一个转换器.
So far the best alternativity for me was write a converter.
我选择这种方式的要点是:
My points to choose this way are:
- 我只需要处理我的API中的一个端点(和一个对象),这与我可以控制它们的其他端点不同;
- 我无法控制调用我的端点的第三方服务;
- 第三方服务仅以一种方式通过媒体类型为
application/x-www-form-urlencoded
的POST调用我的服务.
- I need to deal with only one endpoint (and only one object) in my API which are different for others endpoints that I have control over them;
- I have not control about the thirdy party service that call my endpoint;
- The thirdy party service call in only one way my services, via POST with media type as
application/x-www-form-urlencoded
.
第一:编写一个对象
package xx.xx.xx;
import java.io.Serializable;
public class MyObject implements Serializable {
private static final long serialVersionUID = -7474838713815803531L;
private String name;
private String id;
...
getters
setters
...
}
第二:创建一个转换器以映射模型
Second: create a converter to mapping the model
package xx.xx.xx;
import java.io.IOException;
import java.util.Map;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import com.fasterxml.jackson.databind.ObjectMapper;
import xx.xx.xx.MyObject;
public class MyObjectConverter extends AbstractHttpMessageConverter<MyObject> {
private static final FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
private static final ObjectMapper mapper = new ObjectMapper();
@Override
protected boolean supports(Class<?> clazz) {
return (MyObject.class == clazz);
}
@Override
protected MyObject readInternal(Class<? extends MyObject> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
Map<String, String> vals = formHttpMessageConverter.read(null, inputMessage).toSingleValueMap();
return mapper.convertValue(vals, MyObject.class);
}
@Override
protected void writeInternal(MyObject myObject, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
}
}
第三:告诉Spring使用此转换器
Third: tell to spring use this converter
package xx.xx.xx;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class HppResponseConverterDTOConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(converter());
}
private MyObjectConverter converter() {
MyObjectConverter converter = new MyObjectConverter();
MediaType mediaType = new MediaType("application", "x-www-form-urlencoded", Charset.forName("UTF-8"));
converter.setSupportedMediaTypes(Arrays.asList(mediaType));
return converter;
}
}
奖金:此配置/实现处理属性内的下划线字符,换句话说:您可以使用@JsonProperty
批注,因为上面的此实现使用ObjectMapper
并且对象Mapper(我认为)与spring用于序列化的相同普通的POST与Content-type: application/json
.
Bonus: this configuration/implementation deal with underscore character inside attributes, in other words: you can use @JsonProperty
annotation because this implementation above use ObjectMapper
and object Mapper (I think) is the same that spring use to serialize normal POST's with Content-type: application/json
.
第四,最后:使用此实现:
Fourth and final: using this implementation:
package xx.xx.xx;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/my-object-controller")
public class MyObjectController {
@PostMapping(value = "/something", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void doSomething(@RequestBody MyObject myObject) {
doSomethingWithMyObject(myObject);
}
}
我希望它会有所帮助:)
I hope it helps :)
编辑:我正在使用Spring Boot 2
EDIT: I'm using spring boot 2
这篇关于Spring中的内容类型问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!