Spring RequestMapping用于生成和使用JSON的控制器

使用多个Spring控制器来使用和生成application/json ,我的代码充满了长注释,如:

  @RequestMapping(value = "/foo", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) 

有没有办法生成一个“复合/inheritance/聚合”注释与consumesproduces 默认值,这样我可以改为写下这样的东西:

  @JSONRequestMapping(value = "/foo", method = RequestMethod.POST) 

我们如何定义上面的@JSONRequestMapping ? 注意传入的valuemethod就像在@RequestMapping中一样,如果默认值不合适,也可以传入consumesproduces

我需要控制我要回来的东西。 我想要produces /使用注释方法,以便获得适当的Content-Type标头。

从Spring 4.2.x开始,您可以使用@RequestMapping作为元注释来创建自定义映射注释。 所以:

有没有办法生成一个“复合/inheritance/聚合”注释与消耗和产生的默认值,这样我可以改为写下这样的东西:

 @JSONRequestMapping(value = "/foo", method = RequestMethod.POST) 

是的,有这样的方式。 您可以创建如下的元注释:

 @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @RequestMapping(consumes = "application/json", produces = "application/json") public @interface JsonRequestMapping { @AliasFor(annotation = RequestMapping.class, attribute = "value") String[] value() default {}; @AliasFor(annotation = RequestMapping.class, attribute = "method") RequestMethod[] method() default {}; @AliasFor(annotation = RequestMapping.class, attribute = "params") String[] params() default {}; @AliasFor(annotation = RequestMapping.class, attribute = "headers") String[] headers() default {}; @AliasFor(annotation = RequestMapping.class, attribute = "consumes") String[] consumes() default {}; @AliasFor(annotation = RequestMapping.class, attribute = "produces") String[] produces() default {}; } 

然后您可以使用默认设置,甚至可以根据需要覆盖它们:

 @JsonRequestMapping(method = POST) public String defaultSettings() { return "Default settings"; } @JsonRequestMapping(value = "/override", method = PUT, produces = "text/plain") public String overrideSome(@RequestBody String json) { return json; } 

您可以在spring的javadoc和github wiki中阅读有关AliasFor更多信息。

您的问题的简单答案是Java中没有Annotation-Inheritance 。 但是,有一种方法可以以我认为有助于解决问题的方式使用Spring注释。

类型级别和方法级别都支持@RequestMapping 。

当您在类型级别放置@RequestMapping ,对于该类中的每个方法,大多数属性都是“inheritance的”。 这在Spring参考文档中提到 。 查看api文档 ,了解在将@RequestMapping添加到类型时如何处理每个属性的详细信息。 我已经为下面的每个属性总结了这个:

  • name :Type级别的值与方法级别的值连接,使用’#’作为分隔符。
  • value :类型级别的值由方法inheritance。
  • path :类型级别的值由方法inheritance。
  • method :类型级别的值由方法inheritance。
  • params :类型级别的值由方法inheritance。
  • headers :Type级别的值由方法inheritance。
  • consumes :类型级别的值被方法覆盖。
  • produces :类型级别的值被方法覆盖。

这是一个简短的示例控制器,展示了如何使用它:

 package com.example; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping(path = "/", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.GET, RequestMethod.POST}) public class JsonProducingEndpoint { private FooService fooService; @RequestMapping(path = "/foo", method = RequestMethod.POST) public String postAFoo(@RequestBody ThisIsAFoo theFoo) { fooService.saveTheFoo(theFoo); return "http://myservice.com/foo/1"; } @RequestMapping(path = "/foo/{id}", method = RequestMethod.GET) public ThisIsAFoo getAFoo(@PathVariable String id) { ThisIsAFoo foo = fooService.getAFoo(id); return foo; } @RequestMapping(path = "/foo/{id}", produces = MediaType.APPLICATION_XML_VALUE, method = RequestMethod.GET) public ThisIsAFooXML getAFooXml(@PathVariable String id) { ThisIsAFooXML foo = fooService.getAFoo(id); return foo; } } 

您可以使用@RestController而不是@Controller注释。

您根本不需要配置使用或生成属性。 Spring将根据以下因素自动提供JSON。

  • 请求的接受标头是application / json
  • @ResponseBody注释方法
  • 类路径的jackson图书馆

您还应该遵循Wim的建议并使用@RestController注释定义控制器。 这将使您免于使用@ResponseBody注释每个请求方法

这种方法的另一个好处是,如果客户端需要XML而不是JSON,他们就会得到它。 他们只需要在接受标头中指定xml。

Spring中有2个注释: @RequestBody@ResponseBody 。 这些注释消耗,分别产生JSON。 这里有更多信息。