尝试使用
Spring MVC构建RESTful Web服务.
控制器应返回特定的Java类型,但响应主体必须是通用信封.如何才能做到这一点?
以下代码部分是我到目前为止所拥有的:
控制器方法:
@Controller @RequestMapping(value = "/mycontroller") public class MyController { public ServiceDetails getServiceDetails() { return new ServiceDetails("MyService"); } }
回复信封:
public class Response<T> { private String message; private T responseBody; }
ServiceDetails代码:
public class ServiceDetails { private String serviceName; public ServiceDetails(String serviceName) { this.serviceName = serviceName; } }
对客户的最终回应应显示为:
{ "message" : "Operation OK" "responseBody" : { "serviceName" : "MyService" } }
解决方法
你可以做的是让一个MyRestController只是将结果包装在一个响应中,如下所示:
@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"); } }
此解决方案使您的原始MyController与REST代码保持独立.看来你需要在类路径中包含Jackson,以便Spring自动神奇地序列化为JSON(详见this)
编辑
看来你需要更通用的东西……所以这里有一个建议.
@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 ... } }
并保持原来的“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"); } }
主要问题是:MyController中的@RequestMapping可能需要被一些自定义注释替换(并调整findMethodWithRequestMapping以对此自定义注释执行内省).