不同的.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版本之类的东东。

请关注公众号:程序你好

原文发布于微信公众号 - 程序你好(codinghello)

原文发表时间:2018-08-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏运维一切

laravel自定义错误页面 原

app\Exceptions\handler.php 在render的时候就携带了这个异常

1203
来自专栏恰童鞋骚年

设计模式的征途—19.命令(Command)模式

在生活中,我们装修新房的最后几道工序之一是安装插座和开关,通过开关可以控制一些电器的打开和关闭,例如电灯或换气扇。在购买开关时,用户并不知道它将来到底用于控制什...

682
来自专栏有趣的django

Django rest framework源码分析(4)----版本

版本  新建一个工程Myproject和一个app名为api (1)api/models.py from django.db import models c...

3756
来自专栏博客园

.NET Core 使用RabbitMQ

  RabbitMQ是一个开源的,基于AMQP(Advanced Message Queuing Protocol)协议的完整,可复用的企业级消息队列(Mess...

1503
来自专栏java相关

Mac OS使用brew安装memcached

1101
来自专栏智能大石头

NewLife.Redis基础教程

X组件缓存架构以ICache接口为核心,包括MemoryCache、Redis和DbCache实现,支持FX和netstandard2.0! 后续例程与使用说明...

1143
来自专栏NetCore

Linq to Sql 更新数据时容易忽略的问题

越来越多的朋友喜欢用Linq to Sql来进行开发项目了,一般我们都会遇到CRUD等操作,不可否认,在查询方面Linq真的带来很大的便利,性能方面也表现不错,...

2068
来自专栏我有一个梦想

设计模式学习笔记-命令模式

1. 概述   将一个请求封装为一个对象(即我们创建的Command对象),从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的...

20210
来自专栏walterlv - 吕毅的博客

使用 Task.Wait()?立刻死锁(deadlock)

发布于 2017-10-27 15:54 更新于 2018-04...

1021
来自专栏一个爱瞎折腾的程序猿

在asp.net core2.1中添加中间件以扩展Swashbuckle.AspNetCore3.0支持简单的文档访问权限控制

在此之前的接口项目中,若使用了 Swashbuckle.AspNetCore,都是控制其只在开发环境使用,不会就这样将其发布到生产环境(安全第一) 。 那么,...

1711

扫码关注云+社区

领取腾讯云代金券