简体   繁体   English

使用Spring WebMVC REST控制器基于Accept标头的不同响应实体主体

[英]Different response entity body based on accept header with Spring WebMVC REST controller

I have a controller with a method signature like this 我有一个带有方法签名的控制器

@RequestMapping(value = "/{project:[A-Z0-9_+\\.\\(\\)=\\-]+}", method = RequestMethod.GET)
public ResponseEntity<Object> lookupProject(@PathVariable String project,
        @RequestParam(value = "fields", required = false) String fields,
        @RequestParam(value = "asList", required = false, defaultValue = "false") boolean asList);

I am returning for JSON a Collection<Object> or Map<String, Object> . 我为JSON返回Collection<Object>Map<String, Object> This isn't suitable for XML. 这不适用于XML。 I'd rather return a Project object. 我宁愿返回一个Project对象。

Is there a clean way to determine which content type will be produced? 有没有一种干净的方法来确定将生成哪种内容类型? The work-around would be another method which produces XML only and returns the Project object. 解决方法是仅生成XML并返回Project对象的另一种方法。 I'd rather like to avoid duplicate code. 我想避免重复的代码。

I am on Spring 3.1.3-RELEASE. 我在Spring 3.1.3-RELEASE上。

According to Spring documentation, your produces param will return content based on the Accept, ie 根据Spring文档,您的产生参数将基于Accept返回内容,即

@RequestMapping(value="/someUrl/", produces="application/*")
public Project someControllerMethod(...)

If the method takes in application/xml, the method will produce XML, if application/json, it will produce json, etc. 如果该方法接受application / xml,则该方法将生成XML,如果该application / json,则将生成json等。

You just need marshallers set up for the appropriate object types. 您只需要为适当的对象类型设置编组器即可。

Documentation here: 此处的文档:

http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html#produces () http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html#produces ()

Content type to be produced will depend on type acceptable by the client.One solution for this is already mentioned, using produces attribute.Another solution is using ContentNegotiatingViewResolver, which can resolve views based on accept header or other mechanism. 产生的内容类型将取决于客户端可接受的类型。已经提到的一种解决方案是使用Produces属性。另一种解决方案是使用ContentNegotiatingViewResolver,它可以基于accept标头或其他机制解析视图。

Refer the documentation http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.html 请参阅文档http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.html

Example: http://www.mkyong.com/spring-mvc/spring-3-mvc-contentnegotiatingviewresolver-example/ 示例: http//www.mkyong.com/spring-mvc/spring-3-mvc-contentnegotiatingviewresolver-example/

尽管我认为Dardo的解决方案是最好的,但是您可以使用XMLHttpMessageConverter检查对象类型,如果它是Project对象,则可以进行不同的转换。

In Spring Framework 4.1 you can use a ResponseBodyAdvice to modify the value returned from an @ResponseBody or ResponseEntity method just before it is written out. 在Spring Framework 4.1中,您可以使用ResponseBodyAdvice修改@ResponseBody或ResponseEntity方法返回的值,然后再将其写出。

See http://docs.spring.io/spring-framework/docs/4.1.0.RC2/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyAdvice.html . 参见http://docs.spring.io/spring-framework/docs/4.1.0.RC2/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyAdvice.html

I ended up in splitting in two methods. 我最终分为两种方法。

Public methods have been renamed to lookupAsType . 公共方法已重命名为lookupAsType Both delegate/return 既委托/返回

String[] fieldsArray = StringUtils.split(fields, ',');
return lookup(project, fieldsArray, asList, mediaType);

The new method lookup has the same code s before but contains not an if clause for the media types. 新方法lookup具有相同的代码,但不包含媒体类型的if子句。

if (mediaType.equals(MediaType.APPLICATION_JSON)) {
    body = projectValues;
} else if (mediaType.equals(MediaType.APPLICATION_XML)) {
    body = new Project(projectValues);
} else {
    throw new NotImplementedException("Project lookup is not implemented for media type '" + mediaType + "'");
}

The bad thing is that MediaType is not a enum but an ugly class. 不好的是,MediaType不是枚举,而是一个丑陋的类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM