java 如何使用 Spring MVC 设计通用的响应构建器/RESTful Web 服务?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14484657/
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
How do I design a generic Response builder / RESTful Web Service using Spring MVC?
提问by Eli Polonsky
Trying to build a RESTful web service using Spring MVC.
尝试使用 Spring MVC 构建 RESTful Web 服务。
The controller should return specific Java types, but the response body must be a generic envelope. How can this be done?
控制器应返回特定的 Java 类型,但响应主体必须是通用信封。如何才能做到这一点?
The following sections of code are what I have so far:
以下代码部分是我到目前为止所拥有的:
Controller method:
控制器方法:
@Controller
@RequestMapping(value = "/mycontroller")
public class MyController {
public ServiceDetails getServiceDetails() {
return new ServiceDetails("MyService");
}
}
Response envelope:
回复信封:
public class Response<T> {
private String message;
private T responseBody;
}
ServiceDetails
code:
ServiceDetails
代码:
public class ServiceDetails {
private String serviceName;
public ServiceDetails(String serviceName) {
this.serviceName = serviceName;
}
}
Intended final response to clients should appear as:
对客户的预期最终响应应显示为:
{
"message" : "Operation OK"
"responseBody" : {
"serviceName" : "MyService"
}
}
回答by ben75
What you can do is having a MyRestController
just wrapping the result in a Response
like this:
您可以做的是MyRestController
将结果包装成Response
这样:
@Controller
@RequestMapping(value = "/mycontroller")
public class MyRestController {
@Autowired
private MyController myController;
@RequestMapping(value = "/details")
public @ResponseBody Response<ServiceDetails> getServiceDetails() {
return new Response(myController.getServiceDetails(),"Operation OK");
}
}
This solution keep your original MyController
independant from your REST code. It seems you need to include Hymanson in your classpath so that Spring will auto-magically serialize to JSON (see thisfor details)
此解决方案使您的原始MyController
代码独立于您的 REST 代码。似乎您需要在类路径中包含 Hymanson,以便 Spring 自动神奇地序列化为 JSON(有关详细信息,请参阅此内容)
EDIT
编辑
It seems you need something more generic... so here is a suggestion.
看来您需要更通用的东西……所以这里有一个建议。
@Controller
@RequestMapping(value = "/mycontroller")
public class MyGenericRestController {
@Autowired
private MyController myController;
//this will match all "/myController/*"
@RequestMapping(value = "/{operation}")
public @ResponseBody Response getGenericOperation(String @PathVariable operation) {
Method operationToInvoke = findMethodWithRequestMapping(operation);
Object responseBody = null;
try{
responseBody = operationToInvoke.invoke(myController);
}catch(Exception e){
e.printStackTrace();
return new Response(null,"operation failed");
}
return new Response(responseBody ,"Operation OK");
}
private Method findMethodWithRequestMapping(String operation){
//TODO
//This method will use reflection to find a method annotated
//@RequestMapping(value=<operation>)
//in myController
return ...
}
}
And keep your original "myController" almost as it was:
并保持原来的“myController”几乎原样:
@Controller
public class MyController {
//this method is not expected to be called directly by spring MVC
@RequestMapping(value = "/details")
public ServiceDetails getServiceDetails() {
return new ServiceDetails("MyService");
}
}
Major issue with this : the @RequestMapping in MyController
need probably to be replaced by some custom annotation (and adapt findMethodWithRequestMapping
to perform introspection on this custom annotation).
主要问题是:MyController
需要的@RequestMapping可能被一些自定义注释替换(并适应findMethodWithRequestMapping
对此自定义注释执行自省)。
回答by reidarok
By default, Spring MVC uses org.springframework.http.converter.json.MappingHymansonHttpMessageConverter to serialize/deserialize JSON through Hymanson.
默认情况下,Spring MVC 使用 org.springframework.http.converter.json.MappingHymansonHttpMessageConverter 通过 Hymanson 序列化/反序列化 JSON。
I'm not sure if it's a great idea, but one way of solving your problem is to extend this class, and override the writeInternal method:
我不确定这是否是个好主意,但解决问题的一种方法是扩展此类,并覆盖 writeInternal 方法:
public class CustomMappingHymansonHttpMessageConverter extends MappingHymansonHttpMessageConverter {
@Override
protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
super.writeInternal(new Response(object, "Operation OK"), outputMessage);
}
}
If you're using XML configuration, you could enable the custom converter like this:
如果您使用 XML 配置,您可以像这样启用自定义转换器:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="path.to.CustomMappingHymansonHttpMessageConverter">
</mvc:message-converters>
</mvc:annotation-driven>