我正在编写一个 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/

10-12 17:52
查看更多