Spring 4.x / 3.x(Web MVC)REST API和JSON2 Post请求,如何正确使用它?
在深入细节之前,我知道在Stackoverflow上有很多对话和相关的问题。 他们都以不同的方式帮助我,所以我认为我把所有研究结果放在一起作为一个有组织的FAQ来总结我的发现。
相关概念
当然你知道这些,但我只是写他们作为一个快速审查。 随时编辑,以防万一我失去了一些东西。
HTTP POST请求:
当您愿意将对象发送到Web服务或您的服务器端应用程序时,会使用发布请求。
连载:
是将对象从Web浏览器传递到服务器端应用程序的过程。 可以使用jQuery Ajax调用或Curl post请求。
序列化协议:
这些日子中最受欢迎的是JSON和XML。 XML由于XML标签的性质而变得不太流行,因为序列化的XML对象的大小相对较大。 在这个FAQ中,主要焦点是JSON2序列化。
弹簧:
Spring框架及其强大的注释使得以有效的方式公开Web服务成为可能。 Spring中有很多不同的库。 这里我们关注的是Spring web MVC。
卷曲与JQuery:
这些是您可以用来在您的客户端进行发布请求的工具。 即使您计划使用JQuery ajax调用,我建议您使用Curl进行调试,因为它在发出请求后提供了详细的响应。
@RequestBody vs @ RequestParam / @ PathVariable vs @ModelAttribute:
如果您的Web服务不依赖于您的Java EE模型,则必须使用@RequestBody。 如果您使用模型并将JSON对象添加到模型中,则可以通过@ModelAttribute访问该对象。 只有在您的请求是GET请求或GET和POST请求组合的情况下,您将需要使用@ RequestParam / @ PathVariable。
@RequestBody vs @ResposeBody:
正如您从名字中看到的那样简单,如果您在服务器端方法处理请求后发送客户端的响应,则只需要@ResponseBody。
RequestMappingHandlerAdapter vs AnnotationMethodHandlerAdapter:
RequestMappingHandlerAdapter是自Spring 3.1以来取代AnnotationMethodHandlerAdapter的Spring框架的新映射处理程序。 如果您现有的配置仍然在AnnotationMethodHandlerAdapter中,您可能会觉得这篇文章很有用。 我的文章中提供的配置将为您提供有关如何设置RequestMappingHandlerAdapter的想法。
建立
您将需要设置消息转换器。 这就是您的序列化JSON消息体在您的服务器端转换为本地java对象的方式。
基本配置从这里。 转换器是基本配置示例中的MarshallingHttpMessageConverter和CastorMarshaller,我用MappingJackson2HttpMessageConverter和MappingJacksonHttpMessageConverter替换了它们。
何处放置配置
我的项目设置的方式,我有两个配置文件:
hadlerAdapter bean必须位于MVC Dispatcher XML文件的后面。
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
<ref bean="jsonConverter"/>
</list>
</property>
<property name="requireSession" value="false"/>
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
</bean>
你可以有多个消息转换器。 在这里,我创建了一个普通的JSON以及一个JSON 2消息转换器。 已经使用XML文件中的Ref和正常bean格式(我个人比较喜欢ref标签)。
REST API
这是一个暴露REST API的示例控制器。
控制器
这是您的HTTP POST请求的REST API公开的地方。
@Component
@Controller
@RequestMapping("/api/user")
public class UserController {
@RequestMapping(value = "/add", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String insertUser(@RequestBody final User user) {
System.out.println(user.toString());
userService.insertUser(user);
String userAdded = "User-> {" + user.toString() + "} is added";
System.out.println(userAdded);
return userAdded;
}
}
Java对象
@JsonAutoDetect
public class User {
private int id;
private String username;
private String name;
private String lastName;
private String email;
public int getId() {
return externalId;
}
public void setId(final int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(final String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return this.getName() + " | " + this.getLastName() + " | " + this.getEmail()
+ " | " + this.getUsername() + " | " + this.getId() + " | ";
}
}
CURL邮政电话
curl -i -H "Content-Type: application/json" -X POST -d '{"id":100,"username":"JohnBlog","name":"John","lastName":"Blog","email":"JohnBlog@user.com"}' http://localhost:8080/[YOURWEBAPP]/api/user/add
相关的帖子和问题
如果不是所有提供以下帖子和问题的人都可以访问此FAQ(如果我遇到有用的相关帖子/问题,此列表将会扩展):
CURL邮政电话
curl -i -H "Content-Type: application/json" -X POST -d '{"id":100,"username":"JohnBlog","name":"John","lastName":"Blog","email":"JohnBlog@user.com"}' http://localhost:8080/[YOURWEBAPP]/api/user/add
不同的错误情景:
在这里,我会探索在进行卷曲调用之后可能遇到的不同错误,以及可能发生错误的错误。
情景一:
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 949
Date: Tue, 04 Jun 2013 02:59:35 GMT
这意味着您提供的URL中不存在REST API。
根本原因:在你确定所有事情都完全正确完成之后,你的配置和你的URL都没有错: - 运行一个maven clean。 - 取消部署您的Web应用程序或直接删除它。 - 重新部署Web应用程序 - 确保在Maven / Gradle中只使用一个版本的Spring
情景二:
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 968
Date: Tue, 04 Jun 2013 03:08:05 GMT
Connection: close
背后的唯一原因是,您的请求格式不正确。 如果您签出详细的卷曲响应,您应该能够看到“客户发送的请求在语法上不正确。”。
根本原因:您的JSON格式不正确,或者您缺少JAVA对象的必需参数。
操作:确保以正确的格式和正确数量的参数提供JSON对象。 可为空的属性不是强制性的,但您必须为所有NotNullable属性提供数据。 记住Spring使用Java反射将JSON文件转换为Java对象非常重要,这意味着什么? 这意味着变量和方法名称是CasE SensItiVe。 如果您的JSON文件正在发送变量“userName”,那么您的Java对象中的匹配变量也必须命名为“userName”。 如果你有吸气者和安装者,他们也必须遵循相同的规则。 getUserName和setUserName匹配我们前面的示例。
塞纳里奥三:
HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 1051
Date: Wed, 24 Aug 2011 08:50:17 GMT
根本原因: 您的Web服务不支持Json媒体类型。 这可能是由于您的注释未指定媒体类型,或者您未在Curl post命令中指定媒体类型。
操作:检查您的消息转换器是否设置正确,并确保Web服务注释符合上述示例。 如果这些都很好,请确保您在Curl发布请求中指定了内容类型。
您的Web服务不支持json媒体类型。
Senario N(!):
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 04 Jun 2013 03:06:16 GMT
恭喜用户实际发送到您的服务器端REST API。
有关如何设置弹簧mvc指南的更多详细信息。
相关的帖子和问题
如果不是所有提供以下帖子和问题的人都可以访问此FAQ(如果我遇到有用的相关帖子/问题,此列表将会扩展):
应该很好地注意到,如果一个Bean的类有两个或更多的setter,而没有@JsonIgnore
,那么就不能处理一个bean类。 Spring / Jackson抛出HttpMediaTypeNotSupportedException
和http状态415不支持的媒体类型。
示例:
@JsonGetter
public String getStatus() {
return this.status;
}
@JsonSetter
public void setStatus(String status) {
this.status = status;
}
@JsonIgnore
public void setStatus(StatusEnum status) {
if (status == null) {
throw new NullPointerException();
}
this.status = status.toString();
}
更新:在这种情况下,我们还必须指定@JsonGetter
和@JsonSetter
在返回类型时不会有问题。
刚刚用Spring 3.2.2和Jackson 2.2进行了测试。 它可以很好地作为参数( @RequestBody
)和/或作为返回类型( @ResponseBody
)。
更新2:
如果指定@JsonGetter
和@JsonSetter
, @JsonIgnore
似乎不是必需的。
上一篇: Spring 4.x/3.x (Web MVC) REST API and JSON2 Post requests, how to get it right once for all?