java访问华为网管软件iMaster NCE的北向接口

最近做的一个项目,需要读取华为一个叫iMaster NCE的网管软件的北向接口。这个iMaster NCE(以下简称NCE)用于管理项目的整个网络,尤其是光网络。业主要求我们访问该软件提供的对外接口,读取一些网络信息,比如网元、故障告警、性能等。

NCE的接口提供了多种协议的版本,给过来的资料是基于SOAP的WebService,据说目前最常用的http版本要收费。

基于SOAP的WebService,我以前用.NET的时候搞过。首先要在项目里访问WebService的WSDL,生成一个客户端(代理),然后本地通过此代理对接口进行访问。Java项目也是类似的套路。以下是d调用XML接口的开发步骤介绍,并附上一个读取NCE上告警信息数量的实例。

一、开发前准备

1、选择SOAP中间件

在开始开发之前,需要选择适当的SOAP中间件来实现WebService的客户端。

开源SOAP中间件主要包括:

Apache CXF

Apache AXIS

商业SOAP中间件主要包括:

IBM Websphere

BEA Weblogic

理论上可以自由选择任意符合SOAP规范的中间件以进行客户端的开发。华为选择Apache CXF作为服务端中间件,同时建议客户端也采用Apache CXF,以获得最大的兼容性。不过Apache CXF只支持使用JAVA作为编程语言。我们用的正是java,很自然就选用Apache CXF。

2、获取WSDL文件

接入XML接口,首先需要获取WSDL文件。获取WSDL的方式有两种,分别是使用发布文档中打包的WSDL文件,以及直接访问每一个XML接口所在服务地址来获取。可以通过北向XML接口服务地址获取WSDL,比如http://10.71.226.29:9997/ManagedElementRetrieval?wsdl

这种方式一次只能获取一种服务的WSDL。由于厂家直接给了所有WSDL,所以这一步就省了。

3、生成Stub代码

1)生成代码

获取到WSDL文件后,需要通过Apache CXF附带的wsdl2java工具将其转换成JAVA代码。wsdl2java可以到Apache CXF官网下载。需要注意的是,新的版本不支持JDK8,如果还是JDK8,最后的版本是apache-cxf-3.5.9。

生成语句示例:

apache-cxf不需安装,解压即用。

bash 复制代码
cd D:\soft\develop\wsdl\apache-cxf-3.5.9\bin

wsdl2java -client -xjc-npa -d q:\test2 Q:\wsdl\ManageResourceInventory\IIS\wsdl\TopoViewRetrieval\TopoViewRetrievalHttp.wsdl

生成了一堆代码:

2)创建Stub代码项目

将生成的代码搭建一个项目,比如叫mtop项目。则可以将它生成一个jar包,比如叫mtop.jar。

3)应用Stub代码

然后将它放到我们读取NCE的项目中:

4、后面加入新的接口

上面只是生成了一个wsdl的Stub代码。如果后面需要加入新的wsdl,则如法炮制,先用wsdl2java生成Stub代码,然后将整个代码文件拷贝到Stub项目,遇到同名的忽略,不要覆盖,相当于只拷贝了新增的文件。然后重新生成jar包。

二、示例

以下是一个读取NCE告警数量的示例。

1、基本工具

java 复制代码
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.landtool.jbh.entity.Otn;
import com.landtool.jbh.service.OtnService;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Component;
import org.tmforum.mtop.fmw.xsd.hdr.v1.CommunicationPatternType;
import org.tmforum.mtop.fmw.xsd.hdr.v1.CommunicationStyleType;
import org.tmforum.mtop.fmw.xsd.hdr.v1.Header;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.xml.ws.Holder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * otn的地址及账号信息,既定义于配置文件,也保存于数据库
 * 从代码可看出,优先级上,数据库 > 配置文件
 */
@Component
public class WebServiceUtil {
    // the type of communication pattern
    private static CommunicationPatternType patternType = CommunicationPatternType.SIMPLE_RESPONSE;
    // the type of communication style
    private static CommunicationStyleType styleType = CommunicationStyleType.RPC;

    // the Web Service URL
    private static String strURL = "http://10.0.2.18:9997/";
    public void setStrUrl(String value) {
        WebServiceUtil.strURL = value;
    }

    // userName
    private static String strUser = "BXuser";
    public void setStrUser(String value) {
        WebServiceUtil.strUser = value;
    }

    // password
    private static String strPassword = "Changeme_147";
    public void setStrPassword(String value) {
        WebServiceUtil.strPassword = value;
    }

    // MD
    private static String strMD = "Huawei/NCE";
    @Value("${data-oc.md}")
    public void setStrMD(String value) {
        WebServiceUtil.strMD = value;
    }
    public static String getStrMD() {
        return WebServiceUtil.strMD;
    }

    @Resource
    private OtnService otnService;

    @PostConstruct
    public void init() {
        Otn otn = new Otn();
        List<Otn> list = this.otnService.queryByPage(otn, PageRequest.of(0, 1000)).getContent();
        if (list.size() > 0) {
            otn = list.get(0);
            setStrPassword(otn.getPassword());
            setStrUser(otn.getAccount());
            setStrUrl(String.format("http://%s:%s/", otn.getIp(), otn.getPort()));
            setStrMD(otn.getNote());
        }
    }

    public static <T> T getWebService(String action, Class<T> clazz) {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(clazz);
        Map<String, Object> properties = factory.getProperties();
        if (properties == null) {
            properties = new HashMap<String, Object>();
            factory.setProperties(properties);
        }
        properties.put("set-jaxb-validation-event-handler", Boolean.FALSE);
        factory.setAddress(strURL + action);
        T webservice = (T) factory.create();
        try {
            //TrustHttpsConnection();
            //configureSSLClient(webservice);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return webservice;
    }

    public static Holder<Header> getHeader() {
        Header header = new Header();

        header.setCommunicationPattern(patternType.value());
        header.setCommunicationStyle(styleType.value());
        header.setBatchSequenceNumber(1L);
        header.setRequestedBatchSize(1000L);
        header.setSecurity(strUser + ":" + strPassword);
        return (new Holder<Header>(header));
    }
}

2、应用示例

从下面密密麻麻的import可以看出,大部分都是引用Stub代码的。

java 复制代码
import org.springframework.stereotype.Component;
import org.tmforum.mtop.fmw.xsd.gen.v1.NameAndAnyValueType;
import org.tmforum.mtop.fmw.xsd.gen.v1.ObjectEnumType;
import org.tmforum.mtop.fmw.xsd.nam.v1.NamingAttributeType;
import org.tmforum.mtop.fmw.xsd.nam.v1.RelativeDistinguishNameType;
import org.tmforum.mtop.mri.wsdl.mer.v1_0.ManagedElementRetrieval_RPC;
import org.tmforum.mtop.mri.wsdl.tlr.v1_0.GetAllTopLevelTopologicalLinksException;
import org.tmforum.mtop.mri.wsdl.tlr.v1_0.TopologicalLinkRetrievalRPC;
import org.tmforum.mtop.mri.wsdl.tpr.v1_0.GetAllPhysicalTerminationPointsWithoutFtpsException;
import org.tmforum.mtop.mri.wsdl.tpr.v1_0.GetContainedPotentialConnectionTerminationPointsException;
import org.tmforum.mtop.mri.wsdl.tpr.v1_0.TerminationPointRetrievalRPC;
import org.tmforum.mtop.mri.wsdl.tvr.v1_0.GetAllTopoViewNodesInfoException;
import org.tmforum.mtop.mri.wsdl.tvr.v1_0.TopoViewRetrievalRPC;
import org.tmforum.mtop.mri.xsd.mer.v1.GetAllManagedElementsRequest;
import org.tmforum.mtop.mri.xsd.mer.v1.MultipleMeObjectsResponseType;
import org.tmforum.mtop.mri.xsd.tlr.v1.GetAllTopLevelTopologicalLinksRequest;
import org.tmforum.mtop.mri.xsd.tlr.v1.MultipleTlObjectsResponseType;
import org.tmforum.mtop.mri.xsd.tpr.v1.GetAllConnectionTerminationPointsType;
import org.tmforum.mtop.mri.xsd.tpr.v1.GetAllTerminationPointsType;
import org.tmforum.mtop.mri.xsd.tpr.v1.MultipleTerminationPointObjectsResponseType;
import org.tmforum.mtop.mri.xsd.tvr.v1.GetAllTopoViewNodesInfoRequest;
import org.tmforum.mtop.mri.xsd.tvr.v1.GetAllTopoViewNodesInfoResponse;
import org.tmforum.mtop.nra.xsd.alm.v1.AlarmListType;
import org.tmforum.mtop.nra.xsd.alm.v1.AlarmType;
import org.tmforum.mtop.nra.xsd.pm.v1.PerformanceMonitoringParameterNameListType;
import org.tmforum.mtop.nra.xsd.pmdata.v1.PerformanceMonitoringDataType;
import org.tmforum.mtop.nra.xsd.pmmsrt.v1.PerformanceMonitoringMeasurementType;
import org.tmforum.mtop.nra.xsd.pmtgt.v1.ObjectFactory;
import org.tmforum.mtop.nra.xsd.pmtgt.v1.PerformanceMonitoringObjectSelectListType;
import org.tmforum.mtop.nra.xsd.pmtgt.v1.PerformanceMonitoringObjectSelectType;
import org.tmforum.mtop.nrf.xsd.me.v1.ManagedElementType;
import org.tmforum.mtop.nrf.xsd.tl.v1.TopologicalLinkType;
import org.tmforum.mtop.nrf.xsd.topo.v1.NodeType;
import org.tmforum.mtop.nrf.xsd.tp.v1.TerminationPointType;
import org.tmforum.mtop.rpm.wsdl.pmr.v1_0.GetAllCurrentPerformanceMonitoringDataException;
import org.tmforum.mtop.rpm.wsdl.pmr.v1_0.PerformanceManagementRetrieval;
import org.tmforum.mtop.rpm.xsd.pmr.v1.GetAllCurrentPerformanceMonitoringDataRequest;
import org.tmforum.mtop.rpm.xsd.pmr.v1.MultiplePerformanceMonitoringDataObjectsResponseType;
import org.tmforum.mtop.rtm.wsdl.ar.v1_0.AlarmRetrieval;
import org.tmforum.mtop.rtm.wsdl.ar.v1_0.GetActiveAlarmsCountException;
import org.tmforum.mtop.rtm.wsdl.ar.v1_0.GetActiveAlarmsException;
import org.tmforum.mtop.rtm.xsd.ar.v1.GetActiveAlarmsCountRequest;
import org.tmforum.mtop.rtm.xsd.ar.v1.GetActiveAlarmsCountResponse;
import org.tmforum.mtop.rtm.xsd.ar.v1.GetActiveAlarmsRequest;
import org.w3c.dom.Element;

import javax.xml.bind.JAXBElement;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

。。。

 /**
  * 故障告警信息数量
  */
 public long getActiveAlarmsCount() {
     long count = 0L;

     try {
         AlarmRetrieval alarmRetrieval = WebServiceUtil.getWebService("AlarmRetrieval", AlarmRetrieval.class);
         GetActiveAlarmsCountRequest request = new GetActiveAlarmsCountRequest();
         GetActiveAlarmsCountResponse response = alarmRetrieval.getActiveAlarmsCount(WebServiceUtil.getHeader(), request);
         count = response.getActiveAlarmCount();
     } catch (GetActiveAlarmsCountException e) {
         e.printStackTrace();
         System.err.println("failed getActiveAlarmsCount");
     } catch (Exception ex) {
         System.err.println(String.valueOf(ex.getCause()));
     }

     return count;
 }

对应的NCE XML接口说明

三、总结

NCE的XML接口感觉就是异常繁琐,数据类型非常多,传参、返回值都非常复杂。如果是http接口的话,参数全部是json,结构简单明了。而且,利用XML传数据,少量数据还好,大批量数据就不行,XML相比json,实在笨重,传输量太大了。

华为这个nce软件,叫网管软件,它接管了整个局域网,然后在上面做各种逻辑划分和管理。不过,它加载需要一段时间。比如我们项目,设备通电以后,20分钟后网络才能访问。再上面做一些更改,比如用户解锁,要约2个小时才生效。之前遇到明明用户已经解锁了,还是不能登录,正疑惑的时候,忽然就可以了。这时已经过去了2个小时。

相关推荐
北京智和信通2 天前
卫星一体化智能监控运维解决方案
网络监控·网络管理·网管平台·网管软件·卫星监控
北京智和信通14 天前
某部队IT基础设施及机房动环统一运维建设实例
运维·网管平台·网管软件·网络管理系统·网络运维平台·网络运维系统
北京智和信通14 天前
智和信通IT设备在线统计及能耗管理方案
网管平台·网管软件·运维系统
北京智和信通1 个月前
智和信通助力某信息工程大学实现校园全域运维监控
运维·服务器·网络监控·网络管理软件·网管软件·网管运维·网络管理系统
北京智和信通1 个月前
异构环境下网络统一监控与智能运维解决方案
网管平台·网管软件·网络管理系统·网络运维平台·网络运维系统
北京智和信通1 个月前
【标杆案例】全域可视 智能护航——某大型医药流通企业一体化智能运维平台建设实践
服务器监控·网管平台·网管软件·超融合监控·运维系统
北京智和信通1 个月前
全栈IT资源一体化智能运维管理解决方案
网络监控·网络管理软件·网管软件·网管运维·网络管理系统
北京智和信通2 个月前
统一监控,智能预警:智和信通天津某部队项目落地
网络监控·网络管理·网管平台·网管软件·it综合监控
北京智和信通3 个月前
可视・可管・可靠:智和信通赋能清华某院构建新一代监控运维平台
运维·网络监控·网管软件·信创运维·高校网络运维·高校网管
北京智和信通3 个月前
面向超融合的全域监控与一体化运维方案
运维·网管软件·超融合监控·超融合运维