Spring 4.x / 3.x(Web MVC)REST API和JSON2发布请求,如何获得一次所有? [英] Spring 4.x/3.x (Web MVC) REST API and JSON2 Post requests, how to get it right once for all?

查看:226
本文介绍了Spring 4.x / 3.x(Web MVC)REST API和JSON2发布请求,如何获得一次所有?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在详细讨论之前,我知道Stackoverflow上有很多对话和相关问题。所有这些都帮助我在不同的方式,所以我想我把我的研究结果,作为一个有组织的FAQ,总结我的发现。



相关概念



当然,你知道这些,但我只是将它们写成快速回顾。



HTTP POST请求:



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



序列化:



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



序列化协议:



这些天是JSON和XML。由于XML标记的本质,序列化的xml对象的大小相对较大,XML正变得不那么受欢迎。在此常见问题解答中,主要重点是 JSON2 序列化。



Spring:



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



Curl vs JQuery:



可以使用在您的客户端发出请求。即使您计划使用JQuery ajax调用,我建议您使用Curl进行调试,因为它在发出请求后提供了详细的响应。



@RequestBody vs @ RequestParam / @ PathVariable vs @ModelAttribute:



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



@RequestBody vs @ResposeBody:



从名称可以看出,



RequestMappingHandlerAdapter vs AnnotationMethodHandlerAdapter:


如果您在服务器端方法处理请求后发送响应,则只需要@ResponseBody。

RequestMappingHandlerAdapter是Spring框架的新映射处理程序,自Spring 3.1以来取代了AnnotationMethodHandlerAdapter。如果你现有的配置仍然在AnnotationMethodHandlerAdapter你可能会发现这篇文章有用。



设置



您将需要设置一个消息转换器。这是您的序列化JSON消息体在您的服务器端转换为本地Java对象的方式。



基本配置从这里。转换器是MarshallingHttpMessageConverter和CastorMarshaller在基本配置示例中,我已经替换为MappingJackson2HttpMessageConverter和MappingJacksonHttpMessageConverter 。



在哪里放置配置



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




  • 应用程序上下文XML:
    一个是应用程序上下文XML文件,您的sessionFactory bean,dataSource bean等位于其中。

  • MVC Dispatcher Servlet XML:
    这是您拥有视图解析器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 =requireSessionvalue =false/>

< / bean>
< bean id =jsonConverterclass =org.springframework.http.converter.json.MappingJackson2HttpMessageConverter>
< property name =supportedMediaTypesvalue =application / json/>
< / bean>

您可以有多个消息转换器。这里,我创建了一个正常的JSON以及一个JSON 2消息转换器。 XML文件中的Ref和普通bean格式已被使用(个人而言,我更喜欢ref标签作为它的neater)。



REST API



这是一个展示REST API的示例控制器。



控制器



这是您的用于HTTP帖子请求的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()+}被添加;
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 -HContent-Type:application / json-X POST -d'{id:100,username :JohnBlog,name:John,lastName:Blog,email:JohnBlog@user.com} http:// localhost:8080 / [YOURWEBAPP] / api / user /添加



相关帖子和问题



如果不是所有提供了以下帖子和问题的人都不能使用常见问题(如果我遇到有用的相关帖子/问题,此列表将会扩展):


  1. 什么是 -response-using-jackson-message-converter?rq = 1> Spring 3.0使用jackson消息转换器进行JSON响应

  2. 如何使用Curl从终端/命令行发送JSON数据到测试Spring REST?

  3. 将JSON发布到REST API

  4. https://github.com/ geowarin / spring-mvc-examples

  5. 如何使用curl将JSON发布到PHP

  6. Spring REST | MappingJacksonHttpMessageConverter产生无效的JSON

  7. https://github.com/ eugenp / REST

  8. Spring Web MVC - 验证个别请求参数

  9. >
  10. 如何从Java Servlet返回JSON对象

  11. 如果REST API正在返回JSON,那么什么MIME类型?


解决方案

CURL后调用



  curl -i -HContent-Type:application / json-X POST -d'{id:100,username:JohnBlog,name:John,lastName:Blog :JohnBlog@user.com}'http:// localhost:8080 / [YOURWEBAPP] / api / user / add 



不同的错误情况:



在这里,我将探讨在您进行curl调用后可能遇到的错误,以及可能出错的错误。



方案一:



  HTTP / 1.1 404未找到
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。



根本原因:


  • 您可能在您的请求中有错字(相信我可能会发生)!

  • 这可能是你的spring配置是不对的。如果是这种情况,它需要进一步挖掘出实际上出了问题,但我提供了一些您需要做的一些初始动作,才能开始更复杂的调查。



操作:

确认一切正常完成后,您的配置和URL都没有错误:
- 运行maven干净。
- 取消部署您的Web应用程序或仅删除它。
- 重新部署Web应用程序
- 确保在您的maven / gradle中只使用一个版本的Spring



方案二:



  HTTP / 1.1 400错误请求
服务器:Apache-Coyote / 1.1
Content-Type:text / html; = utf-8
Content-Length:968
日期:Tue,04 Jun 2013 03:08:05 GMT
连接:close
pre>

这背后的唯一原因是你的请求格式不正确。如果您签出详细的curl响应,您应该可以看到客户端发送的请求在语法上不正确。



根本原因:

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



操作:

JSON对象以正确的格式和正确的参数数量。可空属性不是强制性的,但您必须为所有NotNullable属性提供数据。非常重要的是要记住Spring正在使用Java反射将你的JSON文件转换为Java对象,这是什么意思?它意味着变量和方法名称是CasE SensItiVe。如果您的JSON文件发送变量userName,则您的Java对象中的匹配变量也必须命名为userName。如果你有getters和setter,他们也必须遵循相同的规则。 getUserName和setUserName。



Senario三:



  HTTP / 1.1 415不支持的媒体类型
服务器:Apache-Coyote / 1.1
Content-Type:text / html; charset = utf-8
Content-Length:1051
Date :Wed,24 August 2011 08:50:17 GMT



根本原因:

您的Web服务不支持Json媒体类型。这可能是因为您的注释没有指定媒体类型,或者您没有在Curl post命令中指定媒体类型。



操作:

您的消息转换器设置正确,并确保Web服务注释与上面的示例匹配。如果这些都很好,请确保您在Curl发布请求中指定了内容类型。



您的网络服务不支持json媒体类型。



Senario N(!):



  HTTP / 1.1 200 OK 
服务器:Apache-Coyote / 1.1
Content-Type:application / json; charset = UTF-8
Transfer-Encoding:chunked
Date:Tue,04 Jun 2013 03: 06:16 GMT

Congrats用户实际上发送到您的服务器端REST API。



有关如何设置弹簧检查的详细信息,请参阅spring mvc指南。



相关帖子和问题



如果不是所有提供了以下帖子和问题的人都不能使用此常见问题(如果我遇到有用的相关帖子/问题,此列表将会展开):




  1. 什么是正确的 JSON内容类型?

  2. Spring 3.0使用jackson消息转换器进行JSON响应

  3. 如何POST

  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 - 验证个别请求参数


  10. 你如何从Java Servlet返回JSON对象

  11. 如果REST API正在返回JSON,那么什么MIME类型?


Before going into details, I know there has been lots of conversations and related questions on Stackoverflow. All of them kind of help me in different ways so I thought I put my findings all together as a single organized FAQ to summarize my findings.

Related Concepts

Surely you know about these but I just write them as a quick review. Feel free to edit in case I am missing something.

HTTP POST Request:

A post request is used when you are willing to send an object to a web service or a your server side application.

Serialization:

Is the process of getting the object from your web browser through to your server side application. A jQuery Ajax call or a Curl post request can be used.

Serialization protocols:

The most popular ones theses days are JSON and XML. XML is becoming less popular as serialized xml objects are relatively bigger in size due the the nature of XML tagging. In this FAQ the main focus is JSON2 serialization.

Spring:

Spring framework and its powerful annotation makes it possible to expose web service in an efficient way. There are a lot of different libraries in Spring. The one that is our focus here is Spring web MVC.

Curl vs JQuery:

These are the tools you can use to make a post request in your client side. Even if you are planning to use JQuery ajax call, I suggest you use Curl for debugging purposes as it provides you with a detailed response after making the post request.

@RequestBody vs @RequestParam/@PathVariable vs @ModelAttribute:

In cases where you have a web service that is not depending on your Java EE model, @RequestBody must be used. If you are using the model and your JSON object is added to the model, you can access the object through @ModelAttribute. Only for cases where your request is either a GET request or a GET and POST request combination you will need to use @RequestParam/@PathVariable.

@RequestBody vs @ResposeBody:

As you can see from the name it as simple as that, you only need the @ResponseBody if you are sending a response the the client after the server side method processed the request.

RequestMappingHandlerAdapter vs AnnotationMethodHandlerAdapter:

RequestMappingHandlerAdapter is the new mapping handler for Spring framework that replaced AnnotationMethodHandlerAdapter since Spring 3.1. If your existing configuration is still in AnnotationMethodHandlerAdapter you might find this post useful. The config provided in my post will give you an idea on how to set up the RequestMappingHandlerAdapter.

Setup

You will need to setup a message convertor. This is how your serialized JSON message body is converted into a local java object at your server side.

Basic Configuration from here. The convertors were MarshallingHttpMessageConverter and CastorMarshaller in the basic configuration sample, I have replaced them with MappingJackson2HttpMessageConverter and MappingJacksonHttpMessageConverter.

Where to put the configuration

The way my project is set up, I have two config files:

  • Application Context XML: One it the application context XML file where your sessionFactory bean, dataSource bean, etc. are located.
  • MVC Dispatcher Servlet XML: This is where you have your view resolver bean and import your application context XML.

hadlerAdapter bean has to be located in the later that is the MVC Dispatcher XML file.

<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>

You can have multiple message convertors. here, I have created a normal JSON as well as a JSON 2 message convertor. Both Ref and normal bean format in the XML file have been used (personally I prefer the ref tag as its neater).

REST API

Here is a sample controller that is exposing the REST API.

The controller

This is where your REST API for a HTTP post request is exposed.

@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;
    }
}

The Java Object

@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 Post call

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

Related posts and questions

This FAQ was not possible if it wasn't for all the people who provided the following posts and questions (this list will expand if I come across useful related posts/questions):

  1. What is the correct JSON content type?
  2. Spring 3.0 making JSON response using jackson message converter
  3. How to POST JSON data with Curl from Terminal/Commandline to Test Spring REST?
  4. Posting JSON to REST API
  5. https://github.com/geowarin/spring-mvc-examples
  6. How to post JSON to PHP with curl
  7. Spring REST | MappingJacksonHttpMessageConverter produces invalid JSON
  8. https://github.com/eugenp/REST
  9. Spring Web MVC - validate individual request params
  10. How to POST JSON data with Curl from Terminal/Commandline to Test Spring REST?
  11. How do you return a JSON object from a Java Servlet
  12. What MIME type if JSON is being returned by a REST API?

解决方案

CURL Post call

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

Different Error Scenarios:

Here I explore different errors you might come across after you have made a curl call and what might have possibly gone wrong.

Scenario One:

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

This implies that the REST API does not exist in the URL you have provide.

Root cause:
  • You might have a typo in your request (believe me this can happen)!
  • It could be that your spring configuration is not right. If this is the case it needs further digging into what has actually gone wrong but I have provided some initial actions you need to do before start your more sophisticated investigation.
Actions:

After you have made sure that everything is done perfectly right and nothing is wrong with your Configuration nor you URL: - Run a maven clean. - Undeploy your web app or simply delete it. - Redeploy the web app - Make sure to use only one version of Spring in your maven/gradle

Scenario Two:

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

The only reason behind this is that fact that your request is not formatted correctly. If you checkout the detailed curl response you should be able to see "The request sent by the client was syntactically incorrect.".

Root cause:

Either your JSON format is not right or you are missing a mandatory parameter for the JAVA object.

Actions:

Make sure you provide the JSON object in correct format and with the right number of parameters. Nullable properties are not mandatory but you do have to provide data for all NotNullable properties. It is VERY important to remember that Spring is using Java reflection to turn yours JSON file into Java objects, what does this mean? it means that variable and method names are CasE SensItiVe. If your JSON file is sending the variable "userName", than your matching variable in your Java object MUST also be named "userName". If you have getters and setters, they also have to follow the same rule. getUserName and setUserName to match our previous example.

Senario Three:

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

Root cause:

The Json media type is not supported by your web service. This could be due to your annotation not specifying the media type or you not specifying the media type in Curl post command.

Actions:

Check your message convertor is set up correctly and make sure the web service annotation matches the example above. If these were fine, make sure you specify the content-type in your Curl post request.

The json media type is not supported by your web service.

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 

Congrats the user is actually send to your server side REST API.

For further details on how to set up your spring checkout the spring mvc guide.

Related posts and questions

This FAQ was not possible if it wasn't for all the people who provided the following posts and questions (this list will expand if I come across useful related posts/questions):

  1. What is the correct JSON content type?
  2. Spring 3.0 making JSON response using jackson message converter
  3. How to POST JSON data with Curl from Terminal/Commandline to Test Spring REST?
  4. Posting JSON to REST API
  5. https://github.com/geowarin/spring-mvc-examples
  6. How to post JSON to PHP with curl
  7. Spring REST | MappingJacksonHttpMessageConverter produces invalid JSON
  8. https://github.com/eugenp/REST
  9. Spring Web MVC - validate individual request params
  10. How to POST JSON data with Curl from Terminal/Commandline to Test Spring REST?
  11. How do you return a JSON object from a Java Servlet
  12. What MIME type if JSON is being returned by a REST API?

这篇关于Spring 4.x / 3.x(Web MVC)REST API和JSON2发布请求,如何获得一次所有?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆