由于项目采用restful的接口风格,自然会用到delete和put请求,但实现delete、put请求还是踩到了坑。
前端采用Jquery的Ajax接口:
$.ajax({
type: "delete",
url: encodeURI('xxx/yyy'),
data: {var1: xxx, var2: xxx, ...}
async: true,
processData: false,
success: function (data) {
callback(data);
},
error: function (e) {
callback({status: {code: 'error', message: e}});
}
});
后端Spring的controller的代码:
@RequestMapping(value = "xxx/yyy", method = RequestMethod.DELETE)
public JSONObject deleteEntity(@RequestParam("var1")Long var1,
@RequestParam("var2")String var2
@RequestParam("var3")Float var3) {
...
}
请求后报400错误。
于是从前端代码排除,将procesData
选项设置为true
或false
都没效果;
再将contentType
设为text/html
或application/json
,还是没效果。
网上的一些资料说将前端的ajax请求的type
设置为post
,data
加上_method: 'delete'
参数:
$.ajax({
type: "post",
url: encodeURI('xxx/yyy'),
data: {var1: xxx, var2: xxx, ..., _method: 'delete'}
success: function (data) {
callback(data);
},
error: function (e) {
callback({status: {code: 'error', message: e}});
}
});
Spring后端代码RequestMapping
加上produces = "text/html"
:
@RequestMapping(value = "xxx/yyy", produces = "text/html", method = RequestMethod.DELETE)
public JSONObject deleteEntity(@RequestParam("var1")Long var1,
@RequestParam("var2")String var2
@RequestParam("var3")Float var3) {
...
}
果然,请求接收成功!
不过请求最终还是没有成功返回,抛出500服务器异常:
2017-08-07 16:57:12 WARN ExceptionHandlerExceptionResolver 391 doResolveHandlerMethodException - Failed to invoke @ExceptionHandler method: public com.alibaba.fastjson.JSONObject com.polyzg.polyzgoaserver.controller.ExceptionController.unkownException(java.lang.Exception) org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:259) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:174) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:113) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:384) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:59) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:136) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:74) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1222) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1034) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:984) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:469) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:392) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:395) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:254) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:177) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar:8.5.16]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_45]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar:8.5.16]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_45]
异常为HttpMediaTypeNotAcceptableException
,因此可断定是请求返回的数据responseBody
的MIME类型不相符。
再仔细看Controller的deleteEntity
方法:
@RequestMapping(value = "xxx/yyy", produces = "text/html", method = RequestMethod.DELETE)
public JSONObject deleteEntity(@RequestParam("var1")Long var1,
@RequestParam("var2")String var2
@RequestParam("var3")Float var3) {
...
}
RequestMapping
的参数produces = "text/html"
, 说明要返回的是text/html
格式的页面,而函数实际返回的是JSONObject
。
将produces = "text/html"
改为produces = "application/json"
,delete请求成功并正确返回json数据!
另外测试了必须将ajax请求的processData
参数设置为true
才行,若设置为false
则抛出406异常。
因此,最终最佳的处理方法是:
前端代码:
$.ajax({
type: "post",
url: encodeURI('xxx/yyy'),
data: {var1: xxx, var2: xxx, ..., _method: 'delete'},
async: true,
processData: true,
success: function (data) {
callback(data);
},
error: function (e) {
callback({status: {code: 'error', message: e}});
}
});
后端代码:
@RequestMapping(value = "xxx/yyy", produces = "application/json", method = RequestMethod.DELETE)
public JSONObject deleteEntity(@RequestParam("var1")Long var1,
@RequestParam("var2")String var2
@RequestParam("var3")Float var3) {
...
}
对于PUT请求,类似的实现方法,就不再赘述。