Spring 4.x / 3.x(Web MVC)REST API和JSON2 Post请求,如何一劳永逸?

在深入细节之前,我知道在Stackoverflow上有很多对话和相关的问题。 所有这些都以不同的方式帮助我,所以我想我把所有的发现放在一起作为一个有组织的常见问题总结我的发现。

相关的概念

当然,你知道这些,但我只是写他们作为一个快速审查。 随时编辑,以防万一我失去了一些东西。

HTTP POST请求:

当您愿意将对象发送到Web服务或您的服务器端应用程序时,会使用发布请求。

连载:

是从您的Web浏览器到您的服务器端应用程序的对象的过程。 可以使用jQuery Ajax调用或Curl post请求。

序列化协议:

这些日子里最stream行的是JSON和XML。 由于XML标签的性质,XML由于序列化的XML对象的规模相对较大而变得越来越stream行。 在这个FAQ中,主要关注的是JSON2序列化。

弹簧:

Spring框架及其强大的注释使得以有效的方式公开Web服务成为可能。 Spring中有很多不同的库。 这里我们关注的是Spring web MVC 。

curl与JQuery:

这些是您可以用来在您的客户端进行发布请求的工具。 即使您打算使用JQuery ajax调用,我build议您使用Curl进行debugging,因为它在发出请求后提供了详细的响应。

@RequestBody与@ RequestParam / @ PathVariable与@ModelAttribute:

如果您的Web服务不依赖于Java EE模型,则必须使用@RequestBody。 如果使用模型并将JSON对象添加到模型中,则可以通过@ModelAttribute访问该对象。 只有在您的请求是GET请求或GET和POST请求组合的情况下,您将需要使用@ RequestParam / @ PathVariable。

@RequestBody vs @ResposeBody:

正如你从名字中看到的那样简单,如果在服务器端方法处理请求之后发送客户端的响应,则只需要@ResponseBody。

RequestMappingHandlerAdapter vs AnnotationMethodHandlerAdapter:

RequestMappingHandlerAdapter是Spring框架的新的映射处理程序,它自Spring 3.1以来取代了AnnotationMethodHandlerAdapter。 如果您现有的configuration仍然在AnnotationMethodHandlerAdapter中,您可能会发现这个post很有用。 在我的文章中提供的configuration将给你一个关于如何设置RequestMappingHandlerAdapter的想法。

build立

您将需要设置一个消息转换器。 这就是你的序列化的JSON消息正文在服务器端转换成本地java对象的方式。

基本configuration从这里 。 转换器是基本configuration示例中的MarshallingHttpMessageConverter和CastorMarshaller,我用MappingJackson2HttpMessageConverter和MappingJacksonHttpMessageConverterreplace了它们。

在哪里放置configuration

我的项目设置的方式,我有两个configuration文件:

  • 应用程序上下文XML:一个是sessionFactory bean,dataSource bean等位于其中的应用程序上下文XML文件。
  • MVC调度程序Servlet XML:这是你有你的视图parsing器bean和导入你的应用程序上下文XML的地方。

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> 

你可以有多个消息转换器。 在这里,我创build了一个普通的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 

相关的post和​​问题

如果不是所有提供以下post和问题的人都能得到这个FAQ(如果我遇到有用的相关post/问题,这个列表将会扩展):

  1. 什么是正确的 JSON内容types?
  2. Spring 3.0使用jackson消息转换器进行JSON响应
  3. 如何使用terminal/命令行的Curl POST JSON数据来testingSpring REST?
  4. 发布JSON到REST API
  5. https://github.com/geowarin/spring-mvc-examples
  6. 如何使用curl将JSON发布到PHP
  7. Spring REST | MappingJacksonHttpMessageConverter产生无效的JSON
  8. https://github.com/eugenp/REST
  9. Spring Web MVC – validation个别请求参数
  10. 如何使用terminal/命令行的Curl POST JSON数据来testingSpring REST?
  11. 你如何从Java Servlet中返回一个JSON对象
  12. REST API返回JSON的MIMEtypes是什么?

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 

不同的错误情况:

在这里,我会探讨一下你在curl调用之后可能遇到的不同错误,以及可能出错的地方。

情景一:

 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。

根本原因:

  • 你可能在你的要求有一个错字(相信我可能会发生)!
  • 可能是因为你的弹簧configuration不对。 如果是这种情况,需要进一步深入了解实际出现的问题,但在开始更复杂的调查之前,我已经提供了一些初始操作。

操作:

在你确定所有事情都做得完全正确之后,你的configuration和你的URL都没有问题: – 运行一个maven clean。 – 取消部署您的networking应用程序或直接删除它。 – 重新部署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 

这背后的唯一原因是,您的请求格式不正确的事实。 如果您签出详细的curl响应,您应该能够看到“客户发送的请求在语法上不正确。”

根本原因:

您的JSON格式不正确,或者您缺lessJAVA对象的必需参数。

操作:

确保以正确的格式和正确数量的参数提供JSON对象。 可以为空的属性不是强制性的,但是你必须为所有的NotNullable属性提供数据。 记住Spring是使用Javareflection把你的JSON文件转换成Java对象是非常重要的,这是什么意思? 这意味着variables和方法名称是CasE SensItiVe。 如果您的JSON文件正在发送variables“userName”,那么您的Java对象中的匹配variables也必须命名为“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 

根本原因:

Json媒体types不受Web服务支持。 这可能是由于您的注释没有指定媒体types,或者您没有在Curl post命令中指定媒体types。

操作:

检查您的消息转换器设置是否正确,并确保Web服务注释符合上述示例。 如果这些都很好,请确保在Curl post请求中指定了内容types。

您的Web服务不支持json媒体types。

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指南春季结帐的进一步细节。

相关的post和​​问题

如果不是所有提供以下post和问题的人都能得到这个FAQ(如果我遇到有用的相关post/问题,这个列表将会扩展):

  1. 什么是正确的 JSON内容types?
  2. Spring 3.0使用jackson消息转换器进行JSON响应
  3. 如何使用terminal/命令行的Curl POST JSON数据来testingSpring REST?
  4. 发布JSON到REST API
  5. https://github.com/geowarin/spring-mvc-examples
  6. 如何使用curl将JSON发布到PHP
  7. Spring REST | MappingJacksonHttpMessageConverter产生无效的JSON
  8. https://github.com/eugenp/REST
  9. Spring Web MVC – validation个别请求参数
  10. 如何使用terminal/命令行的Curl POST JSON数据来testingSpring REST?
  11. 你如何从Java Servlet中返回一个JSON对象
  12. REST API返回JSON的MIMEtypes是什么?

应该很好的注意到,如果一个bean的类没有@JsonIgnore情况下有两个或两个以上的setter,那么就不能处理一个bean类。 Spring / Jackson抛出HttpMediaTypeNotSupportedException和http状态415 Unsupported Media Type。

例如:

 @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在返回types时不要有问题。

刚刚用Spring 3.2.2和Jackson 2.2进行testing。 它作为参数( @RequestBody )和/或作为返回types( @ResponseBody )正常工作。

更新2:

如果@JsonGetter@JsonSetter被指定, @JsonIgnore似乎不是必需的。