先给出rest service中的这个方法:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUWYxYmZhR2MiNjY3QGMjFGZlNTOzUWZjJGO2YzM1MWMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
View Code
代码不复杂,post一段String过来(xml/json/html格式均可),自动映射成Order对象的实例model,然后根据请求HttpHeader中的Content-Type,如果是xml(application/xml),则返回model对应的xml,如果是json(application/json),则返回model对应的json,其它则返回页面
c#的调用代码:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUWYxYmZhR2MiNjY3QGMjFGZlNTOzUWZjJGO2YzM1MWMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
这二种常用的调用方式,居然全跪了,返回的结果是一堆java异常:
java.lang.NullPointerException
at org.apache.struts2.convention.ConventionUnknownHandler.handleUnknownActionMethod(ConventionUnknownHandler.java:423)
at com.opensymphony.xwork2.DefaultUnknownHandlerManager.handleUnknownMethod(DefaultUnknownHandlerManager.java:96)
...
无奈百度了一圈,发现还有另一种方法,利用TcpClient调用
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUWYxYmZhR2MiNjY3QGMjFGZlNTOzUWZjJGO2YzM1MWMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
总算调用成功了,但是由于java端是用SendRedirect在客户端重定向的,所以该方法得到的返回结果如下:
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location: http://localhost:8080/struts2-rest-ex/rest/orders/230.xml
Content-Length: 0
Date: Mon, 27 Oct 2014 03:18:56 GMT
Connection: close
是一堆http头的原文,只能曲线救国,将其中的Location:后的部分(即重定向的url),取出来再次get请求。
这样的解决方案显然有点笨拙,继续深挖:
org.apache.struts2.rest.RestActionMapper这个类的getMapping()方法,看下源码:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUWYxYmZhR2MiNjY3QGMjFGZlNTOzUWZjJGO2YzM1MWMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
注意91-96行,这里有一个判断:
再来细看下:isExpectContinue
这段代码的意思是如果请求Http头里有Except信息,且等于100-continue,则返回true。如果返回true,刚才那段判断,会返回putContinueMethodName这个变量所指的方法:
但是Controller里只有create方法,并没有createContinue方法,所以找不到方法,当然报错。
而c#中如果以post方法请求url时,不论是HttpWebRequest还是WebClient,默认都会添加expect = 100-continue的头信息,因此c#调用时会报错,而firefox的RestClient插件、java调用、ajax调用,因为没有拼except信息,不会出错。
如果客户端向服务端post数据,考虑到post的数据可能很大,搞不好能把服务器玩坏(或者超时),所以,有一个贴心的约定,客户端先发一个except头信息给服务器,问下:我要post数据了,可能很大,你想想要不要收,采用什么措施收?如果服务器很聪明,可能会对这种情况做出特殊响应,就比如刚才的java代码,遇到这种头信息,不是调用create方法,而是createContinue方法。
这本是一个不错的约定,但是偏偏本文中的Controller方法,又没有提供createContinue方法,所以辜负了客户端的美意,好心当成驴肝肺了。
终极解决方案:
方案A:HttpWebRequest请求时,把默认的except行为去掉
这样,最终发出去的头信息,就不会有except行
方案B: Controller中把createContinue方法补上
直接调用create方法,安抚下双方,不让调用出错即可。