Java 用于生成和使用 JSON 的控制器的 Spring RequestMapping
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35123835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring RequestMapping for controllers that produce and consume JSON
提问by Roshan Mathews
With multiple Spring controllers that consume and produce application/json
, my code is littered with long annotations like:
使用多个 Spring 控制器来消费和生产application/json
,我的代码中散落着长注释,例如:
@RequestMapping(value = "/foo", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
Is there a way to produce a "composite/inherited/aggregated" annotation with defaultvalues for consumes
and produces
, such that I could instead write something like:
有没有办法用and 的默认值生成“复合/继承/聚合”注释,这样我就可以写一些类似的东西:consumes
produces
@JSONRequestMapping(value = "/foo", method = RequestMethod.POST)
How do we define something like @JSONRequestMapping
above? Notice the value
and method
passed in just like in @RequestMapping
, also good to be able to pass in consumes
or produces
if the default isn't suitable.
我们如何定义类似@JSONRequestMapping
上面的内容?注意value
和method
就像 in 一样传入@RequestMapping
,也可以传入consumes
或者produces
默认值不合适。
I need to control what I'm returning. I want the produces
/consumes
annotation-methods so that I get the appropriate Content-Type
headers.
我需要控制我要返回的内容。我想要produces
/ consumes
annotation-methods 以便获得适当的Content-Type
标题。
采纳答案by Ali Dehghani
As of Spring 4.2.x, you can create custom mapping annotations, using @RequestMapping
as a meta-annotation. So:
从 Spring 4.2.x 开始,您可以创建自定义映射注释,@RequestMapping
用作元注释。所以:
Is there a way to produce a "composite/inherited/aggregated" annotation with default values for consumes and produces, such that I could instead write something like:
@JSONRequestMapping(value = "/foo", method = RequestMethod.POST)
有没有办法用消费和生产的默认值生成“复合/继承/聚合”注释,这样我就可以写一些类似的东西:
@JSONRequestMapping(value = "/foo", method = RequestMethod.POST)
Yes, there is such a way. You can create a meta annotation like following:
是的,有这样的方法。您可以创建一个元注释,如下所示:
@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 {};
}
Then you can use the default settings or even override them as you want:
然后您可以使用默认设置,甚至可以根据需要覆盖它们:
@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;
}
You can read more about AliasFor
in spring's javadocand github wiki.
您可以AliasFor
在 spring 的javadoc和github wiki 中阅读更多相关信息。
回答by alexandrum
回答by Wim Deblauwe
You can use the @RestController
instead of @Controller
annotation.
您可以使用@RestController
而不是@Controller
注释。
回答by FGreg
The simple answer to your question is that there is no Annotation-Inheritance in Java. However, there is a way to use the Spring annotations in a way that I think will help solve your problem.
您的问题的简单答案是Java 中没有Annotation-Inheritance。但是,有一种方法可以以我认为有助于解决您的问题的方式使用 Spring 注释。
@RequestMappingis supported at both the type level and at the method level.
@RequestMapping在类型级别和方法级别都受支持。
When you put @RequestMapping
at the type level, most of the attributes are 'inherited' for each method in that class. This is mentionedin the Spring reference documentation. Look at the api docsfor details on how each attribute is handled when adding @RequestMapping
to a type. I've summarized this for each attribute below:
当您放在@RequestMapping
类型级别时,该类中的每个方法的大多数属性都是“继承的”。Spring 参考文档中提到了这一点。有关在添加到类型时如何处理每个属性的详细信息,请查看api 文档@RequestMapping
。我为下面的每个属性总结了这一点:
name
: Value at Type level is concatenated with value at method level using '#' as a separator.value
: Value at Type level is inherited by method.path
: Value at Type level is inherited by method.method
: Value at Type level is inherited by method.params
: Value at Type level is inherited by method.headers
: Value at Type level is inherited by method.consumes
: Value at Type level is overridden by method.produces
: Value at Type level is overridden by method.
name
: 类型级别的值使用“#”作为分隔符与方法级别的值连接。value
: 类型级别的值由方法继承。path
: 类型级别的值由方法继承。method
: 类型级别的值由方法继承。params
: 类型级别的值由方法继承。headers
: 类型级别的值由方法继承。consumes
:类型级别的值被方法覆盖。produces
:类型级别的值被方法覆盖。
Here is a brief example Controller that showcases how you could use this:
这是一个简短的示例控制器,展示了如何使用它:
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;
}
}
回答by hyness
You shouldn't need to configure the consumes or produces attribute at all. Spring will automatically serve JSON based on the following factors.
您根本不需要配置消耗或生产属性。Spring 将根据以下因素自动提供 JSON。
- The accepts header of the request is application/json
- @ResponseBodyannotated method
- Hymanson library on classpath
- 请求的接受头是application/json
- @ResponseBody注释方法
- 类路径上的 Hymanson 库
You should also follow Wim's suggestion and define your controller with the @RestControllerannotation. This will save you from annotating each request method with @ResponseBody
您还应该遵循 Wim 的建议并使用@RestController注释定义您的控制器。这将使您免于使用@ResponseBody注释每个请求方法
Another benefit of this approach would be if a client wants XML instead of JSON, they would get it. They would just need to specify xml in the accepts header.
这种方法的另一个好处是,如果客户想要 XML 而不是 JSON,他们会得到它。他们只需要在接受标头中指定 xml。