c#调用JAVA的Webservice处理XML数据及批量轮询的实现方法
前段时间做一个调用外单位WEBSERVICE的项目,项目完成的功能其实很简单,就是我们单位有很多车友会员,我们想对他们提供车辆违章信息告之服务!我们这边交警部门给我们开放了WS的接口,我们就是想通过这个WS,来轮询会员的违章信息!
其中那个Webservice使用JAVA的Xfire开发的,当时想像得很简单,因为WS(Webservice)可以跨平台调用,因此非常适合不同系统之间数据交换!网上也有很多调用的代码!但我在实际使用中还是遇到了一些问题!首先是我们要调用的那个WS数据管理非常严格,为了数据的安全,他们在中间加入防火墙,访问是通过VPN来进行的,并且他们对访问端口进行映射,我刚开始通过.net来添加WEB 服务,可以访问到方法名称,但在程序调用时报404错误!咨询了一下开发商,说是他们通过JAVA开发的程序调用没有问题!对于从未接触过JAVA的我来说安装JDK、TOMCAT、MyEclipse,折腾的不亦乐呼!从网上又找了些视频教程看了几天,好在JAVA和C#有点象,据说C#就是微软借鉴了JAVA很多优点!搞出这么一个C#的新语言!使用JAVA调用了一下,确实可以调用成功!至今我也没搞明白,.net为什么调用不成功,我只知道那两个地址的端口不一样,问题也就卡在这块了,但JAVA能调用成功,却不能理解,咨询了一下开发商那边一个很厉害的资深JAVA工程师(没想到居然还是个MM),说是因为两个平台底层的访问原理不同,后来通过我们上一级技术部门的帮助,给了一个解决方案:
通过本地使用JAVA来调用WS打包成一个代理方法并发布到本地TOMCAT,再通过.net使用request的方法返回结果!基本思路就是这样!
实现步骤:
(一)TOMCAT:http://localhost:8080/readvioinfo.jsp 通过在输入不同的参数返回不同的结果!如:http://localhost:8080/readvioinfo.jsp?hphm=京AW342&hpzl=02
(二)在.net中的代码实现:
实现的方法代码:
public string getXmlStr(string hphmcode)
{
string Url = "http://localhost:8080/readvioinfo.jsp";
string hphm = hphmcode;
string hpzl = "02";
//Encoding encoding = Encoding.GetEncoding("utf-8");
Encoding encoding = Encoding.GetEncoding("GB2312");
string postData = "hphm=" + hphm + "&hpzl=" + hpzl;
byte[] data = encoding.GetBytes(postData);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
//发送数据
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(data, 0, data.Length);
requestStream.Close();
//接收返回值
HttpWebResponse res = (HttpWebResponse)request.GetResponse();
StreamReader sReader = new StreamReader(res.GetResponseStream(), System.Text.Encoding.UTF8);
string strBack = sReader.ReadToEnd();
//Response.Write(strBack);
sReader.Close();
res.Close();
return strBack;
}
(三)对返回XML格式数据的处理:
JAVA WS返回的结果是XML格式的字符串:如下
<?xml version="1.0" encoding="utf-8"?>
<root>
<code>1</code>
<count>2</count>
<vioInfo>
<wfdz>建设路700米处</wfdz>
<wfsj>2010-01-15</wfsj>
<clbj>未处理</clbj>
<jkbj>未交款</jkbj>
<wfnr>机动车行驶超过规定时速30%以上不足50%的</wfnr>
</vioInfo>
<vioInfo>
<wfdz>华南路强生中学北300米处</wfdz>
<wfsj>2009-09-08</wfsj>
<clbj>未处理</clbj>
<jkbj>未交款</jkbj>
<wfnr>机动车行驶超过规定时速30%以上不足50%的</wfnr>
</vioInfo>
</root>
在.net可以方便的对XML数据进行读取和处理!个人感觉比JAVA要方便啊,JAVA要通过SAX和DOM4J(反正我没研究过)!我是将返回结果放到一个富文本框rtb_result里。
实现代码如下:
string strXML = this.rtb_result.Text.Trim();
XmlDocument doc = new XmlDocument();
doc.LoadXml(strXML);
XmlElement root = doc.DocumentElement;
XmlNodeList mynodelist = doc.SelectNodes("//root/vioInfo"); //查询全部vioInfo节点
if (mynodelist.Count !=0)
{
//循环遍历节点,查询是否存在该节点
for (int i = 0; i < mynodelist.Count; i++)
{
this.rtb_result.Text="违章地点:"+mynodelist[i].ChildNodes[0].InnerText + "\n";
this.rtb_result.Text+="违章时间:"+mynodelist[i].ChildNodes[1].InnerText + "\n";
this.rtb_result.Text +="处理情况:"+ mynodelist[i].ChildNodes[2].InnerText + "\n";
this.rtb_result.Text +="交款情况:"+ mynodelist[i].ChildNodes[3].InnerText + "\n";
this.rtb_result.Text +="违章内容:"+ mynodelist[i].ChildNodes[4].InnerText + "\n";
}
}
else
{
this.rtb_result.Text = "无返回的结果集!";
}
上面的代码完成将返回的XML数据读取我们需要的节点内容并返回到富文本框上显示出来
(四)怎么实现批量轮询的功能,这也是我们最终要得到的功能!我的设想是让用户通过导入一个记录包括车牌号码、手机号码、车辆类型等会员信息的EXCEL文件,将会员信息导入到数据控件中,再通过逐条读取信息与信息做为上面步骤的查询参数,每次读取将返回的信息追加到窗体的富文本框中,整个循环完成后也就完成了本次会员的违章信息轮询!在读取EXCEL文档我采用了ADO.NET,将EXCEL做为一个数据源来加载的,加载完成后,采用datareader控制来逐条读数据,这样速度比较快!完成的代码如下:
private void btn_getdata_Click(object sender, EventArgs e)
{
this.openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Excel files(*.xls)|*.xls";
if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
{
loadXsl2Reader();
}
}
public void loadXsl2Reader()
{
int lookNum = 0;
FileInfo fileInfo = new FileInfo(openFileDialog1.FileName);
string filePath = fileInfo.FullName;
string connExcel = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties=Excel 8.0";
try
{
OleDbConnection oleDbConnection = new OleDbConnection(connExcel);
oleDbConnection.Open();
//获取excel表
DataTable dataTable = oleDbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
//获取sheet名,其中[0][1]...[N]: 按名称排列的表单元素
string tableName = dataTable.Rows[0][2].ToString().Trim();
tableName = "[" + tableName.Replace("'", "") + "]";
//利用SQL语句从Excel文件里获取数据并填充到datareader中
string query = "SELECT 车牌号码,right(车架号,4) as 验证码,手机号码 FROM " + tableName;
OleDbCommand usrCMD = oleDbConnection.CreateCommand();
usrCMD.CommandText = query;
OleDbDataReader usrd= usrCMD.ExecuteReader();
this.rtb_result.Text = "车牌号码 手机号 违章地址 违章时间 处理情况 交款情况 违章内容\n";
//string rtbresult="";
while (usrd.Read())
{
string para_cphm = usrd["车牌号码"].ToString().Trim();
string para_code = usrd["验证码"].ToString().Trim();
string para_mbphone = usrd["手机号码"].ToString().Trim();
string strXML = GetResultXML(para_cphm, para_code).Trim();
XmlDocument doc = new XmlDocument();
doc.LoadXml(strXML);
XmlElement root = doc.DocumentElement;
XmlNodeList mynodelist = doc.SelectNodes("//root/vioInfo"); //查询全部vioInfo节点
if (mynodelist.Count != 0)
{
//MessageBox.Show("共有" + mynodelist.Count + "条违章记录!");
//循环遍历节点,查询是否存在该节点
//this.rtb_result.Text = "";
for (int i = 0; i < mynodelist.Count; i++)
{
lookNum += 1;
this.label3.Text = "正在匹配ing......:已匹配" + lookNum.ToString() + "条记录!";
this.rtb_result.Text += para_cphm+" ";
this.rtb_result.Text += para_mbphone + " ";
this.rtb_result.Text += mynodelist[i].ChildNodes[0].InnerText+" ";
this.rtb_result.Text += Convert.ToDateTime(mynodelist[i].ChildNodes[1].InnerText).ToString("yyyyMMdd-HH:mm")+" ";
/*上句为什么要这么写是为了将DATETIME显示为一个20100801-21:25格式的字符串,方便EXCEL导入文本时不会出现字段错误*/
this.rtb_result.Text += mynodelist[i].ChildNodes[2].InnerText +" ";
this.rtb_result.Text += mynodelist[i].ChildNodes[3].InnerText + " ";
this.rtb_result.Text += mynodelist[i].ChildNodes[4].InnerText + "\n";
//RichTextBox中的文本自动下滚到最后,使窗体在执行数据轮询时显示滚动数据
this.rtb_result.Select(this.rtb_result.TextLength, 0);
this.rtb_result.Focus();
this.rtb_result.ScrollToCaret();
}
}
}
usrd.Close();
oleDbConnection.Close();
MessageBox.Show("轮询结束!共有" + lookNum.ToString() + "条违章记录!请点击保存将查询结果保存为文本文件");
this.label3.Text = "共查询到:"+lookNum.ToString()+"条记录!";
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
(五)导出到文本文件:
private void button5_Click(object sender, EventArgs e)
{
if (this.rtb_result.Text != "")
{
this.saveFileDialog1.Filter = "txt files(*.txt)|*.txt";
this.saveFileDialog1.FilterIndex = 2;
this.saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
string filepath = "";
string resultStr = this.rtb_result.Text.Replace("\n", "\r\n"); ;
filepath = saveFileDialog1.FileName;
StreamWriter sTmp = new StreamWriter(filepath);
sTmp.WriteLine(resultStr);
sTmp.Flush();
sTmp.Close();
MessageBox.Show("文件已成功导出到" + filepath);
}
}
else
{
MessageBox.Show("没有记录!");
}
}
导出的文本文件可以通过EXCEL导入进来再编辑、修改、过滤、筛选等操作就比较自由了!当然也把代码修改一下直接导出EXCEL也是很方便的!上述的功能还很简单,只是完成了基本功能的实现,程序还是要通过后期的使用不断完善!