将JSON发布到REST API
我正在创建一个将接受JSON请求的REST API。
我正在使用CURL测试它:
curl -i -POST -H 'Accept: application/json' -d '{"id":1,"pan":11111}' http://localhost:8080/PurchaseAPIServer/api/purchase
但是得到以下错误:
HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 1051
Date: Wed, 25 Apr 2012 21:36:14 GMT
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method ().
调试时,它甚至不会进入我在控制器中的创建操作。
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import com.app.model.Purchase;
import com.app.service.IPurchaseService;
@Controller
public class PurchaseController {
@Autowired
private IPurchaseService purchaseService;
@RequestMapping(value = "purchase", method = RequestMethod.GET)
@ResponseBody
public final List<Purchase> getAll() {
return purchaseService.getAll();
}
@RequestMapping(value = "purchase", method = RequestMethod.POST)
@ResponseStatus( HttpStatus.CREATED )
public void create(@RequestBody final Purchase entity) {
purchaseService.addPurchase(entity);
}
}
UPDATE
我将Jackson配置文件添加到AppConfig.java中:
@Configuration
@ComponentScan(basePackages = "com.app")
public class AppConfig {
@Bean
public AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter()
{
final AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter = new AnnotationMethodHandlerAdapter();
final MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
HttpMessageConverter<?>[] httpMessageConverter = { mappingJacksonHttpMessageConverter };
String[] supportedHttpMethods = { "POST", "GET", "HEAD" };
annotationMethodHandlerAdapter.setMessageConverters(httpMessageConverter);
annotationMethodHandlerAdapter.setSupportedMethods(supportedHttpMethods);
return annotationMethodHandlerAdapter;
}
}
我的GET正在正常工作:
curl -i -H "Content-Type:application/json" -H "Accept:application/json" http://localhost:8080/PurchaseAPIServer/api/purchase
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 26 Apr 2012 21:19:55 GMT
[{"id":1,"pan":111}]
但是当尝试POST时,我得到以下内容:
curl -i -X POST -H "Content-Type:application/json" -H "Accept:application/json" http://localhost:8080/PurchaseAPIServer/api/purchaseMe -d "{"id":2,"pan":122}"
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 971
Date: Thu, 26 Apr 2012 21:29:56 GMT
Connection: close
The request sent by the client was syntactically incorrect ().
我的模特:
@Entity
@XmlRootElement
public class Purchase implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6603477834338392140L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Long pan;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPan() {
return pan;
}
public void setPan(Long pan) {
this.pan = pan;
}
}
任何想法,我要去错了吗?
谢谢
正如sdouglass所建议的那样,Spring MVC会自动检测Jackson并设置一个MappingJacksonHttpMessageConverter来处理JSON的转换。 但我确实需要明确地配置转换器以使其正常工作,正如他也指出的那样。
我添加了以下内容,并且我的CURL GET请求正在工作..Hooray。
AppConfig.java
@Configuration
@ComponentScan(basePackages = "com.app")
public class AppConfig {
@Bean
public AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter()
{
final AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter = new AnnotationMethodHandlerAdapter();
final MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
HttpMessageConverter<?>[] httpMessageConverter = { mappingJacksonHttpMessageConverter };
String[] supportedHttpMethods = { "POST", "GET", "HEAD" };
annotationMethodHandlerAdapter.setMessageConverters(httpMessageConverter);
annotationMethodHandlerAdapter.setSupportedMethods(supportedHttpMethods);
return annotationMethodHandlerAdapter;
}
}
curl -i -H "Content-Type:application/json" -H "Accept:application/json" http://localhost:8080/PurchaseAPIServer/api/purchase
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 26 Apr 2012 21:19:55 GMT
[{"id":1,"pan":111}]
但是下面的CURL POST仍然不起作用(从不触及控制器操作并且没有给出控制台调试信息。
curl -i -X POST -H "Content-Type:application/json" http://localhost:8080/PurchaseAPIServer/api/purchaseMe -d "{"id":2,"pan":122}"
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 971
Date: Thu, 26 Apr 2012 21:29:56 GMT
Connection: close
The request sent by the client was syntactically incorrect ().
所以我添加了Logback来开始一些详细的调试。
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/home/thomas/springApps/purchaseapi.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.hibernate" level="DEBUG" />
<logger name="org.springframework" level="TRACE" />
<logger name="org.springframework.transaction" level="INFO" />
<logger name="org.springframework.security" level="INFO" /> <!-- to debug security related issues (DEBUG) -->
<logger name="org.springframework.web.servlet.mvc" level="TRACE" /> <!-- some serialization issues are at trace level here: org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod -->
<!-- our service -->
<logger name="com.app" level="DEBUG" />
<!-- <logger name="com.app" level="INFO" /> --><!-- to follow if setup is being executed -->
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</configuration>
向org.springframework.web.servlet.mvc添加TRACE级别的调试给了我这个问题的答案。
2012-04-28 14:17:44,579 DEBUG [http-bio-8080-exec-3] o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor [AbstractMessageConverterMethodArgumentResolver.java:117] Reading [com.app.model.Purchase] as "application/json" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter@74a14fed]
2012-04-28 14:17:44,604 TRACE [http-bio-8080-exec-3] o.s.w.s.m.m.a.ServletInvocableHandlerMethod [InvocableHandlerMethod.java:159] Error resolving argument [0] [type=com.app.model.Purchase]
HandlerMethod details:
Controller [com.app.controller.PurchaseController]
Method [public void com.app.controller.PurchaseController.create(com.app.model.Purchase)]
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unexpected character ('p' (code 112)): was expecting double-quote to start field name
我将我的CURL POST改为以下这一切:
curl -i -X POST -H "Content-Type:application/json" http://localhost:8080/PurchaseAPIServer/api/purchase -d '{"pan":11111}'
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Sat, 28 Apr 2012 13:19:40 GMT
希望有人认为这有用。
如果我正确地记得Spring文档说Spring MVC会自动检测类路径上的Jackson,并设置MappingJacksonHttpMessageConverter来处理JSON的转换,但我认为我遇到了必须手动/明确地配置转换器才能获得的情况事情要工作。 你可能想尝试添加到你的MVC配置XML:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
</list>
</property>
</bean>
更新 :这是正确格式化JSON发布,请参阅https://stackoverflow.com/a/10363876/433789
它的2014年,我想添加一些更新,这个问题帮助我解决了同样的问题。
代码更新以替换Spring 3.2中不推荐使用的AnnotationMethodHandlerAdapter
@Configuration public class AppConfig {@Bean public RequestMappingHandlerAdapter annotationMethodHandlerAdapter() { final RequestMappingHandlerAdapter annotationMethodHandlerAdapter = new RequestMappingHandlerAdapter(); final MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJackson2HttpMessageConverter(); List<HttpMessageConverter<?>> httpMessageConverter = new ArrayList<HttpMessageConverter<?>>(); httpMessageConverter.add(mappingJacksonHttpMessageConverter); String[] supportedHttpMethods = { "POST", "GET", "HEAD" }; annotationMethodHandlerAdapter.setMessageConverters(httpMessageConverter); annotationMethodHandlerAdapter.setSupportedMethods(supportedHttpMethods); return annotationMethodHandlerAdapter; } }
HTTP / 1.1 415不支持的媒体类型错误
花了很多小时试图弄清楚为什么即使在添加了正确的JSON配置之后,我仍然发现了415错误,我终于意识到问题不在于服务器端,而在于客户端。 为了让Spring接受你的JSON,你必须确保你发送“Content-Type:application / json”和“Accept:application / json”作为你的http头文件的一部分。 对我来说,这是一个android应用程序HttpUrlConnection,我必须将其设置为:
public static String doPost(final String urlString,final String requestBodyString) throws IOException {
final URL url = new URL(urlString);
final HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setChunkedStreamingMode(0);
urlConnection.connect();
final PrintWriter out = new PrintWriter(urlConnection.getOutputStream());
out.print(requestBodyString);
out.close();
final InputStream in = new BufferedInputStream(urlConnection.getInputStream());
final String response = readIt(in);
in.close(); //important to close the stream
return response;
} finally {
urlConnection.disconnect();
}
}
链接地址: http://www.djcxy.com/p/8511.html
下一篇: JSON2 vs. jquery