2014-08-28 68 views
0

假设我有一个具有基于Hibernate的持久层的Spring 4 Web应用程序。我想创建一个支持我的模型的基本CRUD操作的RestController。创建读取记录的方法可以毫无困难地工作:将JSON映射到Spring REST控制器中的Hibernate模型

@RequestMapping(value = "/stuff/list", method = RequestMethod.GET) 
public List<Stuff> getStuff(){ 
    return stuffService.findAll(); 
} 

Jackson处理对象序列化,没问题。但是如果我想添加一个通过POST请求创建新记录的方法呢?有没有简单的方法来支持这种简单的方法?

@RequestMapping(value = "/stuff/new", method = RequestMethod.POST) 
public Integer getStuff(@RequestParam("stuff") Stuff stuff){ 
    return stuffService.save(stuff); 
} 

是这样的可能吗?或者我需要手动将发布的表单数据映射到新对象?

SOLUTION

这是我如何解决我的问题,有一对夫妇的步骤。首先,我的最终控制方法:

@RequestMapping(value = "/stuff/new", method = RequestMethod.POST) 
public Integer getStuff(@RequestBody Stuff stuff){ 
    return stuffService.save(stuff); 
} 

我已经有适用于所有应用程序的请求API过滤器,允许跨源资源共享,但需要修改,这允许请求指定内容类型:

public class SimpleCORSFilter implements Filter{ 

    @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 
      FilterChain filterChain) throws IOException, ServletException { 

     HttpServletResponse response = (HttpServletResponse) servletResponse; 
     response.setHeader("Access-Control-Allow-Origin", "*"); 
     response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 
     response.setHeader("Access-Control-Max-Age", "3600"); 
     response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type"); 
     filterChain.doFilter(servletRequest, servletResponse); 

    } 

    @Override public void init(FilterConfig filterConfig) throws ServletException { } 

    @Override public void destroy() { } 
} 

被注册在我的web.xml文件:当我提出一个要求,如下面的一个

<filter> 
    <filter-name>cors</filter-name> 
    <filter-class>com.company.app.util.SimpleCORSFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>cors</filter-name> 
    <url-pattern>/api/*</url-pattern> 
</filter-mapping> 

现在,它将正确映射我提交了JSON到我的模型并坚持一个新的实例:

var stuff = { 
    name: "Some stuff", 
    description: "This is some stuff." 
} 

$.ajax({ 
    url: url, 
    method: "post", 
    dataType: "json", 
    data: JSON.stringify(stuff), 
    contentType: "application/json" 
    }).done(function(data){ 
    console.log(data); 
    }).fail(function(x, status, e){ 
    console.log(e); 
    }); 
+0

内容是HTML表单POST还是JSON? – Affe 2014-08-28 17:28:53

+0

@Affe:JSON,通过浏览器AJAX请求或Spring'RestTemplate'发送。 – woemler 2014-08-28 17:30:33

回答

1

要告诉Spring,您希望它将解串器应用于内容而不是尝试使用标准HTML表单绑定,请使用@RequestBody

@RequestMapping(value = "/stuff/new", method = RequestMethod.POST) 
public Integer getStuff(@RequestBody Stuff stuff){ 
    return stuffService.save(stuff); 
} 

@RequestParam告诉它来寻找具有该名称的各个参数和应用标准的数据绑定,而不是帖子的全部内容反序列化为一个对象。

+0

我是否需要明确设置'consumes =“application/something”'?或者它会期望适当的JSON格式?是否需要额外的请求标头? – woemler 2014-08-28 17:51:03

+0

仅当您想要将具有不同标题的请求路由到不同位置或将其锁定时。对于简单的事情,开箱即用的'将会“正确无误”。 (请注意,如果您指定了消耗,具有有效内容但缺少标题的请求将被拒绝,您可能会也可能不想这样做。) – Affe 2014-08-28 18:13:04

+0

像我一样编写我的控制器方法会导致'415(不支持的介质类型)错误。另一个所以答案​​(http://stackoverflow.com/questions/11492325/post-json-fails-with-415-unsupported-media-type-spring-3-mvc)建议改变请求头,但这并没有帮助。 – woemler 2014-08-28 18:18:16

1

是的,绝对。杰克逊会自动做双向映射的实体,所以如果你想POST东西给服务器只是使用相同的JSON格式,你看到当你做GET