我正在编写一个 REST 端点,它需要同时支持 application/x-www-form-urlencoded 和 application/json 作为请求正文。我做了以下配置,
@RequestMapping(method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE }, consumes = {
MediaType.APPLICATION_FORM_URLENCODED_VALUE, MediaType.APPLICATION_JSON_VALUE }, path = Constants.ACCESS_TOKEN_V1_ENDPOINT)
public OAuth2Authorization createAccessTokenPost(
@RequestBody(required = false) MultiValueMap<String, String> paramMap) { ..
虽然它单独支持 application/x-www-form-urlencoded 或 application/json (当我从消耗 = {} 注释掉一种内容类型时),但它不能同时支持两者。有任何想法吗 ?
最佳答案
根据我的发现,spring 不支持同时使用“application/x-www-form-urlencoded
”、“application/json
”和“application/xml
”的内容类型。
我认为 的原因:Spring 通过解析 JSON 和 XML 类型并将它们注入(inject)到标有 @RequestBody
spring 注释的 java pojo 中来处理它们。但是,必须将 x-www-form-urlencoded
注入(inject)到标有 MultiValueMap<>
的 @RequestBody
对象中。将不会同时支持用 @RequestBody
标记的两种不同的 java 类型,因为 spring 可能不知道在哪里注入(inject)有效负载。
一个有效的解决方案 :
“application/x-www-form-urlencoded
”可以在 API 中得到支持。也就是说,它可以使用@RequestBody 注释注入(inject)到 spring 的 MultiValueMap<>
中。
为了在同一方法上支持 JSON 和 XML,我们可以利用 servlet 规范和构建在它们之上的 spring 类将有效负载提取为流。
示例代码 :
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.MultiValueMap;
// usual REST service class
@Autowired
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
@Autowired
private Jaxb2RootElementHttpMessageConverter jaxb2RootElementHttpMessageConverter;
public ResponseEntity<Object> authorizationRequestPost(HttpServletResponse response, HttpServletRequest request,@RequestBody(required = false) MultiValueMap<String, String> parameters) {
// this MultiValueMap<String,String> will contain key value pairs of "application/x-www-form-urlencoded" parameters.
// payload object to be populated
Authorization authorization = null;
HttpInputMessage inputMessage = new ServletServerHttpRequest(request) {
@Override
public InputStream getBody() throws IOException {
return request.getInputStream();
}
};
if (request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {
authorization = (Authorization) mappingJackson2HttpMessageConverter.read(Authorization.class, inputMessage);
}
else if (request.getContentType().equals(MediaType.APPLICATION_XML_VALUE)) {
authorization = (Authorization)jaxb2RootElementHttpMessageConverter.read(Authorization.class, inputMessage);
}
else{
// extract values from MultiValueMap<String,String> and populate Authorization
}
// remaining method instructions
}
需要注意的是 可以使用此方法支持任何自定义数据类型/标记/格式。 Spring 的
org.springframework.http.converter.HttpMessageConverter<>
可以扩展编写解析逻辑。另一种可能的方法 可能是 AOP 风格的解决方案,它会执行相同的逻辑:通过从
HttpServlet
输入流中提取有效负载并注入(inject)有效负载对象来解析有效负载。第三种方法 将编写一个过滤器来执行逻辑。
关于spring - Spring 的 rest Controller 同时支持 application/json 和 application/x-www-form-urlencoded,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47924463/