在详细介绍之前,我知道 Stackoverflow 上已经有很多对话和相关问题。他们都以不同的方式帮助我,所以我想我将我的发现全部放在一起作为一个有组织的常见问题解答来总结我的发现。
相关概念
您当然知道这些,但我只是将它们写为快速回顾。如果我遗漏了什么,请随意编辑。
HTTP POST 请求:
当您愿意将对象发送到 Web 服务或服务器端应用程序时,将使用 post 请求。
序列化:
是将对象从 Web 浏览器获取到服务器端应用程序的过程。可以使用 jQuery Ajax 调用或 Curl post 请求。
序列化协议:
目前最流行的是 JSON 和 XML。由于 XML 标记的性质,序列化的 xml 对象的大小相对较大,因此 XML 变得越来越不流行。在此常见问题解答中,主要焦点是JSON2 https://stackoverflow.com/questions/3979649/json2-vs-jquery-json序列化。
Spring:
Spring框架及其强大的注释使得以有效的方式公开Web服务成为可能。 Spring 有很多不同的库。我们这里的重点是Spring Web MVC http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestbody.
Curl 与 JQuery:
这些是您可以用来在客户端发出发布请求的工具。即使您计划使用 JQuery ajax 调用,我建议您使用 Curl 进行调试,因为它会在发出 post 请求后为您提供详细的响应。
@RequestBody vs @RequestParam/@PathVariable vs @ModelAttribute:
如果您的 Web 服务不依赖于 Java EE 模型,则必须使用 @RequestBody。如果您正在使用模型并且您的 JSON 对象已添加到模型中,则可以通过 @ModelAttribute 访问该对象。仅当您的请求是 GET 请求或 GET 和 POST 请求组合的情况下,您才需要使用 @RequestParam/@PathVariable。
@RequestBody 与 @ResposeBody:
从名称中可以看出,它很简单,如果在服务器端方法处理请求后向客户端发送响应,则只需要@ResponseBody。
RequestMappingHandlerAdapter 与 AnnotationMethodHandlerAdapter:
RequestMappingHandlerAdapter 是 Spring 框架的新映射处理程序,自 Spring 3.1 以来取代了 AnnotationMethodHandlerAdapter。如果您现有的配置仍在 AnnotationMethodHandlerAdapter 中,您可能会发现这篇文章很有用。我的帖子中提供的配置将让您了解如何设置 RequestMappingHandlerAdapter。
Setup
您将需要设置一个消息转换器。这就是序列化 JSON 消息正文在服务器端转换为本地 java 对象的方式。
基本配置来自here https://stackoverflow.com/questions/3979649/json2-vs-jquery-json。转换器是 Marshalling HttpMessageConverter 和 CastorMarshaller基本配置示例 https://stackoverflow.com/questions/3979649/json2-vs-jquery-json,我已将它们替换为 MappingJackson2HttpMessageConverter 和 MappingJacksonHttpMessageConverter。
配置放在哪里
我的项目设置方式有两个配置文件:
- 应用程序上下文 XML:
其中之一是 sessionFactory bean、dataSource bean 等所在的应用程序上下文 XML 文件。
- MVC 调度程序 Servlet XML:
您可以在此处拥有视图解析器 bean 并导入应用程序上下文 XML。
hadlerAdapter bean 必须位于后面的 MVC 调度程序 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":"JohnB[email protected] /cdn-cgi/l/email-protection"}' http://localhost:8080/[YOURWEBAPP]/api/user/add
相关帖子和问题
如果不是所有提供以下帖子和问题的人,这个常见问题解答就不可能实现(如果我遇到有用的相关帖子/问题,此列表将会扩展):
- 是什么correctJSON 内容类型? https://stackoverflow.com/questions/477816/what-is-the-correct-json-content-type?rq=1
- Spring 3.0 使用 Jackson 消息转换器进行 JSON 响应 https://stackoverflow.com/questions/2259551/spring-3-0-making-json-response-using-jackson-message-converter?rq=1
- 如何使用 Curl 从终端/命令行发布 JSON 数据来测试 Spring REST? https://stackoverflow.com/questions/7172784/how-to-post-json-data-with-curl-from-terminal-commandline-to-test-spring-rest
- 将 JSON 发布到 REST API https://stackoverflow.com/questions/10323957/posting-json-to-rest-api
- https://github.com/geowarin/spring-mvc-examples https://github.com/geowarin/spring-mvc-examples
- 如何使用curl将JSON发布到PHP https://stackoverflow.com/questions/813487/how-to-post-json-to-php-with-curl
- 春季休息| MappingJacksonHttpMessageConverter 生成无效的 JSON https://stackoverflow.com/questions/5613566/spring-rest-mappingjacksonhttpmessageconverter-produces-invalid-json
- https://github.com/eugenp/REST https://github.com/eugenp/REST
- Spring Web MVC - 验证单个请求参数 https://stackoverflow.com/questions/6203740/spring-web-mvc-validate-individual-request-params?rq=1
- 如何使用 Curl 从终端/命令行发布 JSON 数据来测试 Spring REST? https://stackoverflow.com/questions/7172784/how-to-post-json-data-with-curl-from-terminal-commandline-to-test-spring-rest?rq=1
- 如何从 Java Servlet 返回 JSON 对象 https://stackoverflow.com/questions/2010990/how-do-you-return-a-json-object-from-a-java-servlet?lq=1
- 如果 REST API 返回 JSON,那么什么 MIME 类型? https://stackoverflow.com/questions/404470/what-mime-type-if-json-is-being-returned-by-a-rest-api