不同的.Net版本客户端软件调用Java Web Service区别
Posted 程序你好
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不同的.Net版本客户端软件调用Java Web Service区别相关的知识,希望对你有一定的参考价值。
最近的系统中需要.Net开发的离线端软件通过Web Service技术和Java开发的在线系统进行数据交互。
在这个过程中碰到不少问题,写出来供大家参考。
Java这边在线系统基于easyUI,String Boot,mybatis技术,前后端完全分离的架构。
Java Web Service实现:
先来吐槽一下,其实如果使用Restful Json的方式与客户端交互,我们在线系统本身就支持,客户端也需要去处理soap版本的问题,实现起来更方便。可我说了不算。。。
1、Java端的代码很简单,引入包,加上webservice注解,写代码实现逻辑。
@WebService(targetNamespace = "http:/****/", endpointInterface = "******.TaskWebService")
@Component
public class TaskWebServiceImpl implements TaskWebService {
@Autowired
private SqlSessionTemplate session;
@Autowired
private QueryService queryService;
@Autowired
private EntityDao entityDao;
@Override
public List<TaskOrderInfo> getTaskOrders() {
TaskOrderReturn result = new TaskOrderReturn();
User user = User.getCurUser();
Org org = user.getOrg();
String orgLevel = org.getOrgLevel();
Map<String, Object> map = getMapByUser(user);
if (map.isEmpty()) {
return new ArrayList<TaskOrderInfo>();
}
......
}
2、.Net 4.0客户端调用
在.Net Framework 2.0和4.0里生成的proxy代理类是不同的。
先来看4.0:
public partial class TaskWebServiceClient : System.ServiceModel.ClientBase
代理类继承自WCF服务Client对象,这个类是在.Net 3.0中引入WCF框架的时候添加进来的。
System.ServiceModel.ClientBase:提供用于创建可以调用服务的Windows通信基础(WCF)客户端对象的基本实现。
主要用于调用WCF创建的各种Binding类型的服务,当然也包括BasicHttpBinding也就是Soap 1.1。
接下来使用此代理类调用web服务。
这里碰到一个问题,Soap版本的问题,因为自动生成的代理类只支持soap1.1,可我们Java web服务是基于高版本的soap协议, 结果调研失败。
Java服务端改回1.1版。
接着继续。
又发现一个坑,本来应该从.Net Client 传送到Web Service上的参数,服务器接收不到。
使用Soap工具跟踪,发现soap消息里根本就没有。
后来发现生成的代理类中,所有的值类型字段都增加了一个变量名+ Specified命名的布尔字段。
默认这些字段是False,这种情况下,在调用web服务时,这些字段的值不会加入到soap消息里。
修改代码,设置这些字段为True。
para.startTime = DateTime.Parse("2018-05-01");
para.startTimeSpecified = true;
para.endTime = DateTime.Parse("2018 -07-01");
para.endTimeSpecified = true;
服务器端设置了在http header中加入了,access token进行访问控制。
.Net 4.0中在http header中加入token代码:
using (var wsClient = new wsClient.UpDownWebServiceClient()) { using (OperationContextScope scope = new OperationContextScope(wsClient.InnerChannel)) { var httpRequestProperty = new HttpRequestMessageProperty(); httpRequestProperty.Headers["Authorization"] = accessTokenKey OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty; downloadParam para = new downloadParam(); para.pageNum = 1; para.pageNumSpecified = true; para.pageSize = 10; para.pageSizeSpecified = true; para.startTime = DateTime.Parse("2018-05-01"); para.startTimeSpecified = true; para.endTime = DateTime.Parse("2018 -07-01"); para.endTimeSpecified = true; var list = wsClient.download(para); } }
调用成功!
可发现一个奇怪的问题,有个别的Web Service API行为很奇怪。这个API是返回一组数据列表,客户端调用正常,soap消息监控正常,服务器端执行正常,
可是返回到.net客户端的对象一直是空。而使用Java客户端调用和返回都是正常的。
经过监视soap消息,发现消息中其实已经返回了对象数据。怀疑是在soap消息反序列化成.net对象时候出了问题。可这个问题一直没找到原因。
3、使用.net2.0调用服务
在2.0中代理类从 System.Web.Services.Protocols.SoapHttpClientProtocol 类继承而来。
使用access token
重载代理类的 GetWebRequest方法,在http header中加入access token
protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
var request = base.GetWebRequest(uri);
request.Headers.Add("Authorization", this.Authorization); // <----
return request;
}
如果需要在soap header加入内容:
从System.Web.Services.Protocols.SoapHeader类继承,定义自己的soapheader类:MySoapHeader
在代理类中增加属性:
private MySoapHeader mySoapHeaderValueField;
public MySoapHeader MySoapHeaderValue
{
get
{
return this.mySoapHeaderValueField;
}
set
{
this.mySoapHeaderValueField = value;
}
}
在 web方法上增加attribute声明:
/// <remarks/>
[System.Web.Services.Protocols.SoapHeaderAttribute("MySoapHeaderValue")]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="http://****/", ResponseNamespace="http://****/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("return", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public downloadReturn download([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] downloadParam arg0) {
object[] results = this.Invoke("download", new object[] {
arg0});
return ((downloadReturn)(results[0]));
}
调用成功,而且使用2.0调用web 服务并没有发现4.0版本发现的问题。
总结
说实话,本来应该是个很简单的问题,结果碰到一堆坑。建议大家使用Restful /Json方式进行服务器和客户端数据交互,尤其是在跨语言的情况行下,更方便,更简单,也不需要关心soap版本之类的东东。
以上是关于不同的.Net版本客户端软件调用Java Web Service区别的主要内容,如果未能解决你的问题,请参考以下文章
.net调用Oracle 报错:System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本问题