Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 471|回复: 0

关于通过webclient和JSON格式报文与服务器之间通讯的解决方法和遇到的难题

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-29 08:51:17 | 显示全部楼层 |阅读模式

    话说做这个很久了,不过我比较磨洋工。所以托了很久,今天才真正跑通了整个流程。

    一开始老师要我做的时候,我有点没明白意思,后来看了msdn后明白了不少。

    我要做的是用一句话来概括就是,通过JSON来与后台的J2EE通讯,操作数据。

    但就是这样一个简单的任务,我大概有认真做了一个礼拜吧。

     

    下面说说主要的实现方法:

    首先我们要提到webclient这个类,这是system自带的一个模仿web浏览器的类,用它来模仿POST访问(其实还能GET、PUT、DELETE)。

     

    具体的思路是:首先实体化一个webclient,打开端口下载或者上传JSON字符串,然后通过绑定实体类的方法来序列化或者反序列化JSON报文,最后做到我们需要的数据操作。

     

    具体代码如下:

     

     

    1、首先我们需要绑定实体类,之后用微软的自带类库来解析(也可以用JSON.NET这个开源的第三方类库,不过有些方法我还不懂)

    [DataContract]
            public class jsontext
            {
                [DataMember(Order = 0, IsRequired = true)]
                public int total { get; set; }
    
                [DataMember(Order = 1, IsRequired = true)]
                public weatherInfo[] rows { get; set; }
            }
    
            [DataContract]
            public class weatherInfo
            {
                [DataMember(Order = 0, IsRequired = true)]
                public int id { get; set; }
    
                [DataMember(Order = 1)]
                public double weatherType { get; set; }
    
                [DataMember(Order = 2)]
                public string weatherName { get; set; }
    
                [DataMember(Order = 3)]
                public double maxTemperature { get; set; }
    
                [DataMember(Order = 4)]
                public double minTemperature { get; set; }
    
                [DataMember(Order = 5)]
                public double rainFall { get; set; }
    
                [DataMember(Order = 6)]
                public double snowFall { get; set; }
            }
    
            [DataContract]
            public class weatherInsert
            {
                [DataMember(Order = 0, Name = "weatherInfo.iweatherType")]
                public double iweatherType { get; set; }
    
                [DataMember(Order = 1, Name = "weatherInfo.cweatherName")]
                public string cweatherName { get; set; }
    
                [DataMember(Order = 2, Name = "weatherInfo.imaxTemperature")]
                public double imaxTemperature { get; set; }
    
                [DataMember(Order = 3, Name = "weatherInfo.iminTemperature")]
                public double iminTemperature { get; set; }
    
                [DataMember(Order = 4, Name = "weatherInfo.irainFall")]
                public double irainFall { get; set; }
    
                [DataMember(Order = 5, Name = "weatherInfo.isnowFall")]
                public double isnowFall { get; set; }
               
            }

     

     

    2、然后实例一个webclinet

    WebClient webclient = new WebClient();            
                if (!webclient.IsBusy)
                {
                    webclient.Encoding = System.Text.Encoding.UTF8;//防止乱码
                    json = webclient.DownloadString(address);
                }

     

    3、序列化和反序列化,这里我就写在一起了

    public static class iotmonSerial
            {
                //反序列化
                public static T parse<T>(string jsonstring)
                {
                    using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonstring)))
                    {
                        return (T)new DataContractJsonSerializer(typeof(T)).ReadObject(ms);
                    }
                }
    
                //序列化
                public static string stringify(object jsonObject)
                {
                    using (var ms = new MemoryStream())
                    {
                        new DataContractJsonSerializer(jsonObject.GetType()).WriteObject(ms, jsonObject);
                        return Encoding.UTF8.GetString(ms.ToArray());
                    }
                }
            }

     

    4、通过调用前面的方法以及实体类,真正的解析了JSON,当然现在只是下载了数据,之后我会说如何上传。

    var ppp = iotmonSerial.parse<jsontext>(json);
                foreach (var item in ppp.rows)
                {
                    myTextBlock.Text += item.id + "\t" + item.weatherType + "\t" + item.weatherName + "\n";
                }

     

    5、然后我们来说说怎么上传数据吧~(太艰辛了)

    Uri address = new Uri("http://localhost:8080/iotMon/WeatherInfo/listWeatherInfoPaged.action");
    WebClient webClient = new WebClient();
    webClient.UploadStringAsync(address, "POST", testString);

    看上去很简单吧,但是这才是最坑人的地方,因为弄完之后,我发现死活传不上去。我比对了很多次JSP页面上发送的字符串,都是一模一样的。

    这是我苦恼了很久的问题,最后和老师调试了好久,终于找到了问题所在。

    首先得定义发过去字符串的标头,详见http://msdn.microsoft.com/zh-cn/library/system.net.webclient(v=vs.95).aspx(最后有提到)

    但是坑爹的MSDN也没有说解决方案,最后还是感谢强大的百度和谷歌!

     

    标头是如下(不同的服务器可能不一样,需要调整,第一个是保证编码是UTF-8的,我们的项目UTF-8的):

    webClient.Encoding = System.Text.Encoding.UTF8;
    webClient.Headers.Add(HttpRequestHeader.Accept, "json");
    webClient.Headers.Add(HttpRequestHeader.ContentType,"application/x-www-form-urlencoded; charset=UTF-8");
    webClient.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");

    然后这么折腾之后我发现还是不行,最后通过浏览器看上传过去的数据,发现了问题所在!

    url发送过去的东西,会有一个url编码的转换,JSON报文里面最多的“{”和“[”都被转换成了“%7B”和“%5B”,所以我们需要Microsoft.JScript.GlobalObject.encodeURIComponent来将已经做好的需要上传的报文转换格式。(需要说明的是,我们的J2EE后台写的比较奇怪,所以上传和下载下来的格式是不一样的,这一点我一开始没发现,走了不少弯路。)

     

    到这里,就可以实现上传和下载了!真是不容易那(大変)!

     

    下面是一些需要到的库文件:

    System.Runtime.Serialization;    解析JSON报文
    System.Runtime.Serialization.Json;
    System.ServiceModel;        绑定实体类需要
    System.ServiceModel.Web;
    System.IO;
    System.Xml;
    System.Net;             解析JSON报文
    System.Net.Http;
    System.Net.Http.Formatting;
    System.Web.Script.Serialization;
    System.Json;

     

     最后一点忘记补充了,上传上去的时候需要通过URL编码,这个视具体项目要不要转码。

    最新问题,当服务器为linux系统时,需要加上webClient.Headers.Add(HttpRequestHeader.AcceptLanguage, "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");,不然无法上传。

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-23 06:03 , Processed in 0.066952 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表