背景:
随着中间件技术的发展和信息化应用系统研究的逐渐深入,很多中间件技术被应用到轨道应用系统领域。针对中间件在实时监控系统中的应用进行了研究,综合考虑CORBA与SOAP Web Services这两种主流分布式体系结构的优缺点,提出了一种CORBA与Web Services的集成方法。在此基础之上,设计并实现了一种中间件,解决异构安监平台与主动维保应用系统之间信息共享的问题。本中间件极大的方便了分布式实时监控系统中的信息共享,大大的提高了维保中心的的运营效率。
SOAP简单的理解,就是这样的一个开放协议SOAP=RPC+HTTP+XML:采用HTTP作为底层通讯协议;RPC作为一致性的调用途径,XML作为数据传送的格式,允许服务提供者和服务客户经过防火墙在INTERNET进行通讯交互。SOAP使用 HTTP传送 XML,尽管HTTP 不是有效率的通讯协议,而且 XML 还需要额外的文件解析(parse),两者使得交易的速度大大低于其它方案。但是XML 是一个开放、健全、有语义的讯息机制,而 HTTP 是一个广泛又能避免许多关于防火墙的问题,从而使SOAP得到了广泛的应用。但是如果效率对你来说很重要,那么您应该多考虑其它的方式,而不要选择使用 SOAP。
SOAP不会取代CORBA,两者的概念有所区别。CORBA是分布式应用的服务标准。CORBA为分布式应用程序建立服务,服务对象来执行客户端调用的服务,而SOAP是基于XML和HTTP的分布式对象的通信协议。实际上,利用SOAP的互操作性和CORBA强大的执行能力,两者可以很好的结合在一起应用。
安监平台把复杂的数据处理放在一个独立的服务进程模块daqnss中,C++语言具有强大的实时处理功能。安监平台系统根据实际要求定义接口IDL文件,定义访问设备属性、单点实时访问、报警信息结构体等接口,接口统一使用IDL工具生成异构语言使用的代理源文件(常用的语言包括C++/Java)。这样保证WebService与安监平台之间通过Corba技术实现桥接。WebService基于SOAP协议作为生产者角色,为上层主动维保平台和设备管理平台提供了一系列服务功能。
开发环境:
1、 操作系统
WINDOWS 7
2、系统
处理器:Intel(R) Core(TM) i5-2401M CPU @ 2.30GH 2.30GH
安装内存:3.00GB (2.88 GB可用)
系统类型:32位操作系统
3、工具环境
A、myeclipse-8.6
B、j2sdk1.4.2_16(jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008.exe)
C、VC++6.0 sp6
D、orbacus4.1.2
实现原理:
上层应用系统与安监平台之间基于SOAP协议通过中间件进行通讯。上层应用系统在用户界面层动态显示时,需要向安监信息系统请求设备的实时状态信息,安监信息系统响应该需要设备状态信息。对象定义规则主要以对象结构格式形成分层结构,主要包含设备资产编码、信息点号和当前实时数值等内容。
安监平台负责ISCS、车载(隧道、桥梁、触网、轨道)、车辆和信号各个专业数据集成,从原始数据的采集、加工、处理等操作,最后形成报警信息和工程数据。上层应用与安监平台通过SOAP WebService方式进行信息访问,这就导致SOAP WebService需要通过Corba接口访问实时数据库中的数据。
一、创建CORBA服务端
1)、定义接口
// **********************************************************************
//
// Copyright (c) 2012
// 公司
// 2012.04.28
// liuxuezong,上海
//
// All Rights Reserved
//
// **********************************************************************
#ifndef daqns_idl
#define daqns_idl
//
// version 0.01
//
module daqns
{
// 设备属性
struct DeviceProperty
{
long RtuNo; //设备号
long PointNo; //点号
float Value; //值
octet Type; // 类型
string Description; // 描述
};
typedef sequence<DeviceProperty> DevicePropertySeq;
interface DaqService
{
long GetAIValue(inlong nRtuNo, inlong nPointNo, outfloat Value);
long GetDIValue(inlong nRtuNo, inlong nPointNo, out octet Value);
long GetPIValue(inlong nRtuNo, inlong nPointNo, out unsignedlong Value);
DevicePropertySeq GetDeviceProperty(in string DeviceCode);
};
};
#endif
//
// EOF DaqService.idl
//
2)、daqnss服务进程模块
A、设备库管理
头文件定义
// **********************************************************************
//
// Copyright (c) 2012
// 公司
// 2012.06.11
// liuxuezong, 上海
//
// All Rights Reserved
//
// **********************************************************************
// Version: 1.0.0
#ifndef ___DEVICEMIB_H__
#define ___DEVICEMIB_H__
#include <iostream>
#include <list>
#include <numeric>
#include <algorithm>
using namespace std;
typedef struct tagDEVICEPROPERTY
{
unsigned int RtuNo;
unsigned int PointNo;
unsigned char Type;
char Description[48];
} DEVICEPROPERTY, *LPDEVICEPROPERTY, *PDEVICEPROPERTY;
typedef list<DEVICEPROPERTY> ListDevProp;
typedef struct tagDEVICEMIB
{
char DeviceCode[24];
ListDevProp listDev;
} DEVICEMIB, *LPDEVICEMIB, *PDEVICEMIB;
typedef list<DEVICEMIB> ListDevMib;
class CDeviceMib
{
public:
CDeviceMib();
~CDeviceMib();
public:
void Insert(constchar *DeviceCode, DEVICEPROPERTY DevProp);
int GetDeviceProperty(constchar *DeviceCode, ListDevProp &DevProp);
protected:
ListDevMib m_lstDevMib;
};
#endif
实现部分:
#include <assert.h>
#include "devicemib.h"
CDeviceMib::CDeviceMib()
{
}
CDeviceMib::~CDeviceMib()
{
}
void CDeviceMib::Insert(constchar *DeviceCode, DEVICEPROPERTY DevProp)
{
assert(DeviceCode != NULL);
list<DEVICEMIB>::iterator iter;
for (iter = m_lstDevMib.begin(); iter != m_lstDevMib.end(); iter++)
{
if (strcmp(DeviceCode, iter->DeviceCode) == 0)
{
iter->listDev.push_back(DevProp);
return;
}
}
DEVICEMIB devmib;
strcpy(devmib.DeviceCode, DeviceCode);
devmib.listDev.push_back(DevProp);
m_lstDevMib.push_back(devmib);
}
int CDeviceMib::GetDeviceProperty(constchar *DeviceCode, ListDevProp &DevProp)
{
assert(DeviceCode != NULL);
int nCount = 0;
list<DEVICEMIB>::iterator iter;
for (iter = m_lstDevMib.begin(); iter != m_lstDevMib.end(); iter++)
{
if (strcmp(DeviceCode, iter->DeviceCode) == 0)
{
DevProp = iter->listDev;
nCount = DevProp.size();
break;
}
}
return nCount;
}
设备管理库的作用主要是通过HASH算法,把相同设备资产编码组织在同一个链表下。设备管理库分为两条链路:一条是不同的设备编码之间织成线性链表关系,另一条是相同的设备编码之间组织成线性链表关系。设备编码分类,设备属性汇聚,用以方法加快设备属性的检索速度。
B、数据库接口
int InitDevicePorperty()
{
UCHAR szDSN[SQL_MAX_DSN_LENGTH] ="daqnss"; // Data Source Name buffer
UCHAR szUID[] = "sa";
UCHAR *szPasswd = (unsignedchar*)"rtsip";
//第一步:定义句柄
HENV hEnv = NULL;
HDBC hDBC = NULL;
HSTMT hStmt = NULL;
SQLRETURN ret;
//第二步:初始化环境
ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
ret = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
if (ret == SQL_SUCCESS)
{
printf("环境分配成功!\n");
}
//第三步:建立连接
ret = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDBC);
ret = SQLConnect(hDBC, szDSN, SQL_NTS, szUID, SQL_NTS, szPasswd, SQL_NTS);
if (!SQL_SUCCEEDED(ret))
{
printf("数据库连接失败!\n");
return -1;
}
//第四步:初始化语句句柄 //第五步:处理结果集
ret = SQLAllocHandle(SQL_HANDLE_STMT, hDBC, &hStmt);//申请资源
//得到当前设备资产编码
char cmdbuf[256];
sprintf(cmdbuf, "SELECT DeviceCode,RtuNo,PointNo,Type,DESCRIPTION " \
"FROM RTSIP.TB1205_DEVICEPROPERTY where order by DeviceCode, RtuNo, PointNo");
UCHAR *szSqlStr = (SQLCHAR *)cmdbuf;// SQL string
ret = SQLExecDirect(hStmt, szSqlStr, SQL_NTS);
SQLCHAR DeviceCode[24], Description[48];
SQLINTEGER RtuNo, PointNo, Type;
SQLINTEGER ind[5];
char seps[] =" ";
char szDeviceCode[24] ="";
char szResult[64] ="";
ret = SQLBindCol(hStmt, 1, SQL_CHAR, &DeviceCode, 24, &ind[0]);
ret = SQLBindCol(hStmt, 2, SQL_INTEGER, &RtuNo, 0, &ind[1]);
ret = SQLBindCol(hStmt, 3, SQL_INTEGER, &PointNo, 0, &ind[2]);
ret = SQLBindCol(hStmt, 4, SQL_INTEGER, &Type, 0, &ind[3]);
ret = SQLBindCol(hStmt, 5, SQL_CHAR, &Description, 48, &ind[4]);
while ((ret = SQLFetch(hStmt)) != SQL_NO_DATA_FOUND)
{
if (ret == SQL_ERROR)
{
break;
}
memset(DeviceCode, 0, sizeof(DeviceCode));
memset(Description, 0, sizeof(Description));
SQLGetData(hStmt, 1, SQL_CHAR, &DeviceCode, 24, &ind[0]);
SQLGetData(hStmt, 2, SQL_INTEGER, &RtuNo, 0, &ind[1]);
SQLGetData(hStmt, 3, SQL_INTEGER, &PointNo, 0, &ind[2]);
SQLGetData(hStmt, 4, SQL_INTEGER, &Type, 0, &ind[3]);
SQLGetData(hStmt, 5, SQL_CHAR, &Description, 48, &ind[4]);
DEVICEPROPERTY DevProp;
memset(&DevProp, 0, sizeof(DEVICEPROPERTY));
memset(szDeviceCode, 0, sizeof(szDeviceCode));
trim(szDeviceCode, (char *)DeviceCode, seps);
DevProp.RtuNo = RtuNo;
DevProp.PointNo= PointNo;
DevProp.Type = Type;
memset(szResult, 0, sizeof(szResult));
trim(szResult, (char *)Description, seps);
strncpy(DevProp.Description, szResult, 48);
lstDevMib.Insert(szDeviceCode, DevProp);
}
//第六步:中止处理
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
SQLDisconnect(hDBC);
SQLFreeHandle(SQL_HANDLE_DBC, hDBC);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
return 0;
}
C、CORBA实现接口
class DaqService_impl :public virtual POA_daqns::DaqService
{
public:
//取值操作 RET VAL: -1参数错误; 否则返回flag值(1 有效 0 无效)
virtual CORBA::Long GetAIValue(CORBA::Long nRtuNo,
CORBA::Long nPointNo,
CORBA::Float_out Value)
throw(CORBA::SystemException);
virtual CORBA::Long GetDIValue(CORBA::Long nRtuNo,
CORBA::Long nPointNo,
CORBA::Octet_out Value)
throw(CORBA::SystemException);
virtual CORBA::Long GetPIValue(CORBA::Long nRtuNo,
CORBA::Long nPointNo,
CORBA::ULong_out Value)
throw(CORBA::SystemException);
virtual ::daqns::DevicePropertySeq* GetDeviceProperty(constchar* DeviceCode)
throw(CORBA::SystemException);
};
CORBA::Long DaqService_impl::GetAIValue(CORBA::Long nRtuNo,
CORBA::Long nPointNo,
CORBA::Float_out Value)
throw(CORBA::SystemException)
{
CDacDataWrapper *pDataWrapper = CDacDataWrapper::Instance();
int nRet = pDataWrapper->GetAIValue(nRtuNo, nPointNo, (float32)Value);
return nRet;
}
CORBA::Long DaqService_impl::GetDIValue(CORBA::Long nRtuNo,
CORBA::Long nPointNo,
CORBA::Octet_out Value)
throw(CORBA::SystemException)
{
CDacDataWrapper *pDataWrapper = CDacDataWrapper::Instance();
int nRet = pDataWrapper->GetDIValue(nRtuNo, nPointNo, (uint8)Value);
return nRet;
}
CORBA::Long DaqService_impl::GetPIValue(CORBA::Long nRtuNo,
CORBA::Long nPointNo,
CORBA::ULong_out Value)
throw(CORBA::SystemException)
{
uint32 uValue = 0;
CDacDataWrapper *pDataWrapper = CDacDataWrapper::Instance();
int nRet = pDataWrapper->GetPIValue(nRtuNo, nPointNo, (uint32)uValue);
Value = (CORBA::ULong)uValue;
return nRet;
}
::daqns::DevicePropertySeq* DaqService_impl::GetDeviceProperty(constchar* DeviceCode)
throw(CORBA::SystemException)
{
::daqns::DevicePropertySeq_var DevPropSeq =new ::daqns::DevicePropertySeq();
CDacDataWrapper *pDataWrapper = CDacDataWrapper::Instance();
ListDevProp lstDevProp;
int nCount = lstDevMib.GetDeviceProperty(DeviceCode, lstDevProp);
DevPropSeq->length(nCount);
int i = 0;
list<DEVICEPROPERTY>::iterator iter;
for (iter = lstDevProp.begin(); iter != lstDevProp.end(); i++, iter++)
{
DEVICEPROPERTY DevProp = (DEVICEPROPERTY)(*iter);
::daqns::DeviceProperty daqnsDevProp;
daqnsDevProp.RtuNo = DevProp.RtuNo;
daqnsDevProp.PointNo = DevProp.PointNo;
float32 fValue = 0.0f;
int nRet = pDataWrapper->GetAIValue(DevProp.RtuNo, DevProp.PointNo, fValue);
daqnsDevProp.Value = fValue;
daqnsDevProp.Type = DevProp.Type;
daqnsDevProp.Description = CORBA::string_dup(DevProp.Description);
DevPropSeq[i] = daqnsDevProp;
}
return DevPropSeq._retn();
}
D、CORBA名称服务
安监平台使用中间件的名称服务,Corba的对象命名服务就是给对象实例提供一个名称,以便用户通过这些名称来获取对象的实例。对象命名服务是ORB上的对象找到其它对象的基本机制。名字是用来识别一个对象的可人工辨认的值,命名服务将这些名字映射到对象标记,名字-对象关联叫做名字联编。命名语言环境是一个名字空间,对象名字在这里是独一无二的。每个对象都有一个独一无二的参考标识符。可以有选择地将一个或多个名字与一个对象标记关联起来。相对于其命名语言环境始终定义一个名字。利用命名服务可以创建命名分层结构,客户可以搜寻不同的命名语言环境树,查找所要的对象。来自不同域的名字语言环境可以一起使用,为对象创建联合命名服务。CORBA命名分层结构不需要一个“统一”的根目录。一般情况下,用户可以规定对象的命名原则,表示对象所在的主机,功能等一系列的信息。
int DataProc()
{
CORBA::ORB_var orb;
DaqService_impl* impl = NULL;
try
{
// Initialize the ORB
orb = CORBA::ORB_init(daqArgc, daqArgv);
// Get a reference to the root POA
CORBA::Object_var rootPOAObj = orb->resolve_initial_references("RootPOA");
// Narrow it to the correct type
PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(rootPOAObj.in());
// Create POA policies
CORBA::PolicyList policies;
policies.length(1);
policies[0] = rootPOA->create_thread_policy(PortableServer::SINGLE_THREAD_MODEL);
// Get the POA manager object
PortableServer::POAManager_var manager = rootPOA->the_POAManager();
// Create a new POA with specified policies
PortableServer::POA_var daqPOA = rootPOA->create_POA("daqPOA", manager, policies);
// Free policies
CORBA::ULong len = policies.length();
for (CORBA::ULong i = 0;i < len; i++)
policies[i]->destroy();
// Get a reference to the Naming Service root_context
CORBA::Object_var rootContextObj = orb->resolve_initial_references("NameService");
// Narrow to the correct type
CosNaming::NamingContext_var nc = CosNaming::NamingContext::_narrow(rootContextObj.in());
// CosNaming::NamingContext_var nc = CosNaming::NamingContext::_narrow(rootContextObj);
// Create a reference to the servant
impl = new DaqService_impl();
// Activate object
PortableServer::ObjectId_var myObjID = daqPOA->activate_object(impl);
// Get a CORBA reference with the POA through the servant
CORBA::Object_var o = daqPOA->servant_to_reference(impl);
// The reference is converted to a character string
CORBA::String_var s = orb->object_to_string(o);
cout << "The IOR of the daq object is: " << s.in() << endl;
CosNaming::Name name;
name.length(1);
name[0].id = (constchar *)"daqSevice";
name[0].kind = (constchar *)"";
// Bind the Object into the name service
nc->rebind(name, o);
// Activate the POA
manager->activate();
cout << "The server is ready. Awaiting for incoming requests..." << endl;
// Strat the ORB
orb->run();
}
catch (const CORBA::Exception& e)
{
bStartFlag = FALSE;
cerr << " exception " << e._name() << endl;
return 1;
}
// Decrement reference count
if (impl)
{
impl->_remove_ref();
}
// End CORBA
if (!CORBA::is_nil(orb))
{
try
{
orb->destroy();
cout << "Ending CORBA..." << endl;
}
catch (const CORBA::Exception& e)
{
cout << "orb->destroy() failed:" << e._name() << endl;
return 1;
}
}
return 0;
}
二、创建WebService服务端
下图是创建Web Project生成的整体文件结构图:
1)、创建文件MyDeviceProperty.java,所属包为bean:
package bean;
import java.io.Serializable;
@SuppressWarnings("serial")
publicclass MyDevicePropertyimplements Serializable {
privateintType;
privateintRtuNo;
privateintPointNo;
privatefloatValue;
private StringDescription;
publicvoid setType(int Type) {
this.Type = Type;
}
publicint getType() {
returnType;
}
publicvoid setRtuNo(int RtuNo) {
this.RtuNo = RtuNo;
}
publicint getRtuNo() {
returnRtuNo;
}
publicvoid setPointNo(int PointNo) {
this.PointNo = PointNo;
}
publicint getPointNo() {
returnPointNo;
}
publicvoid setValue(float Value) {
this.Value = Value;
}
publicfloat getValue() {
returnValue;
}
publicvoid setDescription(String Description) {
this.Description = Description;
}
public String getDescription() {
returnDescription;
}
}
2)、创建文件IRtsipService.java,所属包为soap:
package soap;
import java.util.List;
import bean.MyDeviceProperty;
//Generated by MyEclipse
publicinterface IRtsipService {
publicfloat GetAIValue(int nRtuNo, int nPointNo);
publicbyte GetDIValue(int nRtuNo, int nPointNo);
publicint GetPIValue(int nRtuNo, int nPointNo);
public List<MyDeviceProperty> GetDeviceProperty(String strDevCode);
}
3)、创建文件RtsipServiceImpl.java,所属包为soap:
package soap;
import java.util.List;
import java.io.UnsupportedEncodingException;
import bean.MyDeviceProperty;
import daqns.DaqNamingSevice;
//Generated by MyEclipse
publicclass RtsipServiceImplimplements IRtsipService {
static DaqNamingSevicedaqnsrv;
public RtsipServiceImpl()
{
daqnsrv =new DaqNamingSevice();
}
publicfloat GetAIValue(int nRtuNo, int nPointNo)
{
returndaqnsrv.GetAIValue(nRtuNo, nPointNo);
}
publicbyte GetDIValue(int nRtuNo, int nPointNo)
{
returndaqnsrv.GetDIValue(nRtuNo, nPointNo);
}
publicint GetPIValue(int nRtuNo, int nPointNo)
{
returndaqnsrv.GetPIValue(nRtuNo, nPointNo);
}
public List<MyDeviceProperty> GetDeviceProperty(String strDevCode)
{
try
{
returndaqnsrv.GetDeviceProperty(strDevCode);
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
returnnull;
}
}
4)、创建文件DaqNamingSevice.java,所属包为daqns:
package daqns;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
importjava.util.Properties;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import bean.MyDeviceProperty;
publicclass DaqNamingSevice
{
privatestatic StringlpArgs[];
privatestatic DaqServicemanager;
privatestaticbooleanbInitFlag = false;
publicint Initialize()
{
try
{
org.omg.CORBA.Object managerObj;
//创建并初始化ORB
String nameservice ="corbaloc::localhost:10003/NameService";
//生成一个ORB,并初始化,这个和Server端一样
// Properties props = new Properties();
// props.put("org.omg.CORBA.ORBInitialPort", "10003");
// props.put("org.omg.CORBA.ORBInitialHost", "10.35.95.100");
// ORB orb = ORB.init(lpArgs, props);
ORB orb = ORB.init(lpArgs,null);
//得到一个NameComponent类型的对象
// get the root naming context
org.omg.CORBA.ObjectobjRef = orb.resolve_initial_references("NameService");
// Use NamingContextExt instead of NamingContext,
// part of theInteroperable naming Service.
// NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
NamingContextExt ncRef = NamingContextExtHelper.narrow(orb
.string_to_object("corbaloc::localhost:10003/NameService"));
//nc的id域为FirstTimeSevice,kind域为空字符串
NameComponent name =new NameComponent("daqSevice","");
NameComponent path[] = { name };
//从命名服务上下文中获得特定的命名服务对象
managerObj = ncRef.resolve(path);
// Narrow the previous object to obtain the correct type
manager = DaqServiceHelper.narrow(managerObj);
bInitFlag =true;
System.out.println("RTSIP的SOAP WebService与 CORBA初始化成功!");
}
catch (Exception e)
{
System.out.println("ERROR : " + e);
}
return 0;
}
public DaqNamingSevice()
{
Initialize();
}
publicvoid unInitialize()
{
}
/**
* @param msg
* @throws UnsupportedEncodingException
* 编码转换,以显示中文
*/
publicstaticvoid showMessage(String msg)throws UnsupportedEncodingException {
byte[] bytes = msg.getBytes("ISO-8859-1");
String rlt = new String(bytes,"GBK");
System.out.println(rlt);
}
publicstatic String decodeText(String src)throws UnsupportedEncodingException {
byte[] bytes = src.getBytes("ISO-8859-1");
String rlt = new String(bytes,"GBK");
return rlt;
}
publicfloat GetAIValue(int nRtuNo, int nPointNo)
{
float fValue = 0.0f;
try
{
org.omg.CORBA.FloatHolder fhValue =new org.omg.CORBA.FloatHolder(0.0f);
intnResult =manager.GetAIValue(nRtuNo, nPointNo, fhValue);
fValue = fhValue.value;
}
catch (Exception e)
{
e.printStackTrace();
Initialize();
}
return fValue;
}
publicbyte GetDIValue(int nRtuNo, int nPointNo)
{
byte bValue = 0;
try
{
org.omg.CORBA.ByteHolder bhValue =new org.omg.CORBA.ByteHolder();
intnResult =manager.GetDIValue(nRtuNo, nPointNo, bhValue);
bValue = bhValue.value;
}
catch (Exception e)
{
e.printStackTrace();
Initialize();
}
return bValue;
}
publicint GetPIValue(int nRtuNo, int nPointNo)
{
int nValue = 0;
try
{
org.omg.CORBA.IntHolder nhValue =new org.omg.CORBA.IntHolder(0);
intnResult =manager.GetPIValue(nRtuNo, nPointNo, nhValue);
nValue = nhValue.value;
}
catch (Exception e)
{
e.printStackTrace();
Initialize();
}
return nValue;
}
public List<MyDeviceProperty> GetDeviceProperty(String strDevCode)
throws UnsupportedEncodingException
{
List<MyDeviceProperty> list =new ArrayList<MyDeviceProperty>();
DeviceProperty[] DevPropSeq =manager.GetDeviceProperty(strDevCode);
int nCount = DevPropSeq.length;
for (int i = 0; i < nCount; i++)
{
MyDeviceProperty devProp =new MyDeviceProperty();
devProp.setRtuNo(DevPropSeq[i].RtuNo);
devProp.setPointNo(DevPropSeq[i].PointNo);
devProp.setValue(DevPropSeq[i].Value);
devProp.setType(DevPropSeq[i].Type);
devProp.setDescription(decodeText(DevPropSeq[i].Description));
list.add(devProp);
}
return list;
}
}
三、创建WebService客户端
WebService访问服务端,有好几种方法,本文通过提供的端口来创建客户端。下图是创建Java Applation生成的整体文件结构图:
1)、创建与服务器一致的文件MyDeviceProperty.java,所属包为bean:
package bean;
import java.io.Serializable;
@SuppressWarnings("serial")
publicclass MyDevicePropertyimplements Serializable {
privateintType;
privateintRtuNo;
privateintPointNo;
privatefloatValue;
private StringDescription;
publicvoid setType(int Type) {
this.Type = Type;
}
publicint getType() {
returnType;
}
publicvoid setRtuNo(int RtuNo) {
this.RtuNo = RtuNo;
}
publicint getRtuNo() {
returnRtuNo;
}
publicvoid setPointNo(int PointNo) {
this.PointNo = PointNo;
}
publicint getPointNo() {
returnPointNo;
}
publicvoid setValue(float Value) {
this.Value = Value;
}
publicfloat getValue() {
returnValue;
}
publicvoid setDescription(String Description) {
this.Description = Description;
}
public String getDescription() {
returnDescription;
}
}
2)、创建与服务器一致的文件IRtsipService.java,所属包为soap:
package soap;
import java.util.List;
import bean.MyDeviceProperty;
//Generated by MyEclipse
publicinterface IRtsipService {
publicfloat GetAIValue(int nRtuNo, int nPointNo);
publicbyte GetDIValue(int nRtuNo, int nPointNo);
publicint GetPIValue(int nRtuNo, int nPointNo);
public List<MyDeviceProperty> GetDeviceProperty(String strDevCode);
}
3)、创建与服务器一致的文件IRtsipService.java,所属包为soap:
package soap;
import java.util.List;
import java.net.MalformedURLException;
import org.codehaus.xfire.XFire;
import org.codehaus.xfire.XFireFactory;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.binding.ObjectServiceFactory;
import bean.MyDeviceProperty;
import soap.IRtsipService;
/**
* 通过Web服务端提供的接口来创建客户端
* @see客户端必须提供一个与服务端完全一致的接口,包名也要一致
* @see在本例中,需要在客户端(即该项目)中提供IRtsipService接口.
* @see并且此时需要在项目中引入XFire 1.2 Core Libraries和XFire 1.2 HTTP Client Libraries
*/
publicclass rtsip {
/**
* @param args
* @throws Exception
* @throws MalformedURLException
*/
publicstaticvoid main(String[] args)throws MalformedURLException, Exception {
//访问的地址
String serviceURL = ("http://localhost:8080/rtsip/services/RtsipService");
//首先使用XFire的ObjectServiceFactory从IRtsipService接口创建一个服务模型serviceModel
// serviceModel包含服务的说明,换句话说,就是服务的元数据
Service serviceModel =new ObjectServiceFactory().create(
IRtsipService.class);
// 为XFire获得一个代理工厂对象
XFire xfire = XFireFactory.newInstance().getXFire();
XFireProxyFactory serviceFactory =new XFireProxyFactory(xfire);
try
{
// 通过proxyFactory,使用服务模型serviceModel和服务端点URL(用来获得WSDL)
//得到一个服务的本地代理,这个代理就是实际的客户端
IRtsipService service = (IRtsipService)serviceFactory.create(
serviceModel, serviceURL);
float f = service.GetAIValue(2, 1);
System.out.println("rtuno=2,pointno=1:"+f);
List<MyDeviceProperty> list = service.GetDeviceProperty("201206110001");
System.out.println("设备资产编码:201206110001");
// 遍历list
for (MyDeviceProperty devProp : list)
{
System.out.println("RtuNo:"+devProp.getRtuNo());
System.out.println("PointNo:"+devProp.getPointNo());
System.out.println("Value:"+devProp.getValue());
System.out.println("Type:"+devProp.getType());
System.out.println("Description:"+devProp.getDescription());
}
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
}
}
四、测试
首先,按顺序启动下列几个服务程序
1、启动Java服务程序
icrosoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。
:\Windows\system32>tnameserv
初始的命名范围:
OR:000000000000002b49444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f
e746578744578743a312e30000000000001000000000000009a000102000000000e3139322e3130
02e36342e363000038400000045afabcb0000000020000f42400000000100000000000000020000
008526f6f74504f41000000000d544e616d65536572766963650000000000000008000000010000
0011400000000000002000000010000002000000000000100010000000205010001000100200001
109000000010001010000000026000000020002
ransientNameServer:将初始对象引用端口设置为:900
准备就绪。
2、启动Corba名称服务程序
Microsoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。
C:\Windows\system32>cd D:\orbacus-4.1.2\bin
C:\Windows\system32>d:
D:\orbacus-4.1.2\bin>mynameserv
3、启动daqnss命名服务程序
Microsoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。
C:\Windows\system32>cd E:\
C:\Windows\system32>e:
E:\daqnss
The IOR of the daq object is: IOR:01cccccc1300000049444c3a446171536572766963653a
312e3000cc01000000000000007c000000010102cc160000004c502d36303931332e636173636f2e
7369676e616c00a0ef2c000000abacab3131333337393037333832005f526f6f74504f4100646171
504f410000cafebabe4fbed8b60000000001000000010000002000000001cccccc01000100020000
002000010001000105000101000100000009010100
The server is ready. Awaiting for incoming requests...
1)、testjavartsip输出结果:
rtuno=2,pointno=1:287.93298
设备资产编码:201206110001
RtuNo:2
PointNo:1
Value:287.93298
Type:1
Description:A相电流
RtuNo:2
PointNo:2
Value:161.97089
Type:1
Description:B相电流