WEBSERVICE发布与调用

Posted zhuqingxin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WEBSERVICE发布与调用相关的知识,希望对你有一定的参考价值。

一.背景说明

最近在做一个任务,主要目的就是将客户SAP系统里的RFC函数发布成WebService,并在我们的前置机程序里面调用,得到返回的数据并经过解析处理后按照和原有逻辑类似的方式去处理。

二.具体操作

可以知道问题的关键在于WebService的发布与调用。因为之前在EBS系统里面部署配置过Intergrated soa gateway,并发布过Webservice接口。所以对相关概念有一定的了解,这次正好趁这个机会,算是重新加深一波理解了。这里主要记录下,过程中了解到的一些相关的东西以及问题。本文暂时只讨论soap协议的webservice。

2.1 Webservice发布

SAP里的Webservice发布可以参考: http://www.cnblogs.com/zohoo/p/7295920.html
对比来说,可能是因为EBS版本问题,感觉比EBS里的Webservice发布要简单,因为至少不用再去自己部署集成soa网关了,也就不用再去自己打一些相关的数据库及应用补丁了。但是因为这个工作主要由公司的SAP顾问完成,他们没弄好,我这边不可能一直干等着啊,所以先简略的用Java发布个Webservice以用于调用测试,再对比来说,Java直接发布Webservice比SAP里更加的简单,方式有很多,尽量用简单的。主要就两个注解:类上加上@WebService,要发布的方法上加上@WebMethod。具体参考:
https://www.cnblogs.com/redjh/p/6841665.html

2.2 Webservice调用

Java里关于Webservice的调用方式也是很多。这里只说我用到的几个,其他的如什么CXF,wsimport等需要用到的时候再细说。关键是在于从他们之中提取共同点,这些才是最基础最重要的东西。也就是所谓的Webservice三要素:WSDL,SOAP,UUDI,另外还有我们永远绕不开的HTTP。但我们这里概念先不去细说,有需要可以去搜索了解下,还是先看看用法。
(1). 使用axis2的wsdl2java直接生成调用类
wsdl2java -uri ./gen_wsdl/zws_apdoc1.wsdl -p com.zqx.test -o feedback
这种方式其实类似于wsimport,这里的uri可以是本地也可以是远程wsdl地址,-p 指定包名,- o指定生成代码路径。以上命令可能会给你生成类似于这样的两个java文件:

调用方式可能就是类似于下面这样。这也是我要说的这种方式的问题所在了,你必须找到你wsdl里面定义的传入传出参数类型和他生成的类里面的什么对应,这样才好去调用这个service获得response。好处在于,如果你足够熟练的话,可以按自己的需要去重写生成的类以满足自己的需求,比如在调用过程中加一些写日志的代码,以方便出问题时好调试定位错误。

    //服务
    ZWS_APDOC1Stub service = new ZWS_APDOC1Stub();
    //参数
    ZWS_APDOC1Stub.ZhscfApdocE params = new ZWS_APDOC1Stub.ZhscfApdocE();
    ZWS_APDOC1Stub.Date10 arg0 = new ZWS_APDOC1Stub.Date10();
    arg0.setDate10("2015-02-01");
    ZWS_APDOC1Stub.Numeric2 arg1 = new ZWS_APDOC1Stub.Numeric2();
    arg1.setNumeric2("7");
    ZWS_APDOC1Stub.TableOfZhscfApdoc arg2 = new ZWS_APDOC1Stub.TableOfZhscfApdoc();
    //arg2.setItem();
    params.setIDate(arg0);
    params.setIDays(arg1);
    params.setTHead(arg2);
    ZWS_APDOC1Stub.ZhscfApdocResponse response = service.zhscfApdoc(params);
    ZWS_APDOC1Stub.ZhscfApdoc[] items = response.getTHead().getItem();

    System.out.println(":"+ JSONObject.toJSONString(response));

    for (int i = 0; i <items.length ; i++) {
        System.out.println(i+":"+ JSONObject.toJSONString(items[i]));
    }
   

(2). 使用HttpURLConnection直接调用
这个在.NET里类似的东西好像叫做HttpWebRequest,不同的平台不同叫法,本质其实还是一样的东西。这种方式就相对原始了,但不知道为什么,可能是从C语言里养成的习惯,天生对这种东西有莫名的好感。因为尽管可能繁琐一点,但不用被所谓的”框架”遮蔽双眼了,各有利弊吧。使用方式可能就类似于这样:

public static String doPost(String url, String params) {
    try {
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setDoInput(true);
        // 超时时间30秒
        int timeout = 30 * 1000;
        conn.setConnectTimeout(timeout);
        conn.setReadTimeout(timeout);
        //add by zhuqingxin <begin>
        //conn.setRequestProperty("Content-Type","text/xml");
        conn.setRequestProperty("Content-Type","text/xml; charset=UTF-8");
        //conn.setRequestProperty("Content-Type","application/json; charset=UTF-8");
        //add by zhuqingxin <end>
        conn.connect();
        if (params != null) {
            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), CHARSET_NAME);
            out.write(params);
            out.flush();
            out.close();
        }
        InputStreamReader r = new InputStreamReader(conn.getInputStream(), CHARSET_NAME);
        BufferedReader reader = new BufferedReader(r);
        String line;
        StringBuffer sb = new StringBuffer();
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        return sb.toString();
    } catch (IOException e) {
        return null;
    }
}

注意下这里的url可以就是我们的wsdl链接,但是params参数需要是一个完整的soap请求报文,怎么获得这个报文呢?如果你足够熟悉wsdl,可以直接用字符串拼接的方式去构造,不熟的话就可以用工具帮你自动生成了,比如有个叫storm的软件,或者用我们最常用的soapUI:

(3). 使用axis的rpc调用方式
以前我一直觉得,至少在Java里,这种方式是最简单方便的。自从经历了这次的问题之后,我才发现以前的想法还是太简单,了解的东西还是太浅薄。这个后面说,依旧还是先看看用法:

 private static void testhello() throws Exception{
    String endpoint = "http://localhost:9000/hello?wsdl";
    String namespace = "http://zqx.com/";
    // 直接引用远程的wsdl文件
    // 以下都是套路
    Service service = new Service();
    Call call = (Call) service.createCall();
    call.setTargetEndpointAddress(endpoint);
    // WSDL里面描述的接口名称(要调用的方法)
    call.setOperationName(new QName(namespace,"sayHello"));
    call.addParameter("arg0", XMLType.XSD_STRING, ParameterMode.IN);// 接口的参数
    call.setReturnType(XMLType.XSD_STRING);// 设置返回类型
    call.setEncodingStyle(namespace);
    String result = (String )call.invoke(new Object[]{"测试人员"});
    System.out.println(result);

}           

三. 参考

https://blog.csdn.net/qq_31763083/article/details/53812208
https://blog.csdn.net/menghuanzhiming/article/details/78489527
https://bbs.csdn.net/topics/392013286
https://www.cnblogs.com/luoxf/p/5881970.html
https://blog.csdn.net/sisierda/article/details/52998888
http://tieba.baidu.com/p/1913611121

以上是关于WEBSERVICE发布与调用的主要内容,如果未能解决你的问题,请参考以下文章

WEBSERVICE发布与调用

C#动态调用webService出现 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。

怎样调用java的webservice,wsdl怎样生成java代码

webService的发布与调用

js调用webservice接口

springboot 整合 cxf 发布webservice与调用