我正在尝试使用Spring构建一个非常基本的REST API。
我的网址端点是:
GET /notes
GET /notes/{noteId}
POST /notes
PUT /notes/{noteId}
DELETE /notes/{noteId}
除了我想要运行以更新项目的PUT
请求之外,所有这些端点都可以正常工作。
问题是没有通过PUT
接收数据,因为它适用于POST
。
这是我的控制者;我通过添加与update
方法相同但使用POST
的方法对其进行了测试,但效果很好。我不知道为什么?
package notes;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/notes")
public class NotesController {
...
@RequestMapping(value="/{noteId}", method=RequestMethod.PUT)
public Response update(@PathVariable Integer noteId, Note note) {
return new Response("Note Updated", note);
}
@RequestMapping(value="/{noteId}", method=RequestMethod.POST)
public Response updateWithPost(@PathVariable Integer noteId, Note note) {
return new Response("Note Updated", note);
}
...
}
使用邮递员,我已对POST
http://127.0.0.1:8080/notes/5进行了测试,回复是:
{
"message": "Note Updated",
"note": {
"id": null,
"title": "Hello World detail content",
"text": "Hello World",
"createdAt": "72, Mar 2015",
"updatedAt": "72, Mar 2015"
}
}
但对于具有完全相同数据的PUT
http://127.0.0.1:8080/notes/5,响应为:
{
"message": "Note Updated",
"note": {
"id": null,
"title": "",
"text": "",
"createdAt": "72, Mar 2015",
"updatedAt": "72, Mar 2015"
}
}
更新请求
适用于PUT
和{ POST
请求我发送相同的测试数据:
title: Hello World
text: Hello World detail content
响应级
package notes;
public class Response {
private String message;
private Note note;
public Response(String text) {
setMessage(text);
}
public Response(String text, Note note) {
setMessage(text);
setNote(note);
}
//...getters/setters
}
注意课程
package notes;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Note {
private Integer id = null;
private String title = "";
private String text = "";
private Date createdAt = new Date();
private Date updatedAt = new Date();
public Note() {}
public Note(String title, String text) {
this.setTitle(title);
this.setText(text);
}
//...getters/setters
}
ApplicationConfig
package notes;
import org.springframework.context.annotation.*;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@EnableWebMvc
@Configuration
public class ApplicationConfig {
}
我不知道为什么这不起作用?
答案 0 :(得分:4)
这是Servlet Spec的限制以及Spring用于填充模型属性的内部工作方式。
首先,规范说
3.1.1参数可用时
以下是在将表单数据填充到表单之前必须满足的条件 参数集:
- 请求是HTTP或HTTPS请求。
- HTTP方法是POST。
- 内容类型为application / x-www-form-urlencoded。
- servlet已对请求对象上的任何
醇>getParameter
方法系列进行了初始调用。如果不符合条件 并且帖子表单数据不包含在参数集中 数据必须仍然可以通过请求对象对servlet可用 输入流。如果满足条件,则不再发布表单数据 可以直接从请求对象的输入中读取 流。
其次,你的处理程序方法的第二个参数,即类型Note
的参数,实际上是considered a model attribute,好像它是用@ModelAttribute
隐式注释的。因此,它由Spring的ModelAttributeMethodProcessor
处理。此HandlerMethodArgumentResolver
使用getParameter
(及其系列方法)填充已创建实例的字段。
由于这是PUT请求,因此无法通过getParameter
检索参数。但是,它们仍然可以通过请求体访问,但是Spring并不是为了模型属性而去那里。
您可以自己进行转换。但我建议您将请求内容更改为JSON或XML for PUT,并使用@RequestBody
带注释的参数。
There is a long standing request to add parameters for PUT requests.
答案 1 :(得分:0)
不知道这里是否属实(或者如果它现在甚至是相关的,还没有使用REST的东西一段时间),但我已经打了一个过去Jetty和Tomcat处理PUT
的问题 - 请求不同(应用程序本身就像你的代码一样使用Spring MVC),另一个期望参数在URL中,另一个想要它们在体内,喜欢POST。
显然,HTTP规范在这方面并不十分精确,因此不同的容器可以以不同的方式处理它。更多信息here。