2014-08-28 110 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