博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用HttpURLConnection实现SOAP调用
阅读量:6890 次
发布时间:2019-06-27

本文共 12639 字,大约阅读时间需要 42 分钟。

  hot3.png

我们完全可以利用J2SE中的HttpURLConnection类来实现SOAP调用,而不一定需要AXIS之类的第三方组件包。下面就来仔细讲解:
        通过HttpURLConnection来实现SOAP调用,无非就是向远端的WEB Service发出HTTP请求,请求的过程通过双方可以理解的XML格式流来传递数据信息。我以下面的SOAP请求的XML格式为基础来讲解:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SmInf="http://jx.ct10000.com/SmInf">
 <soapenv:Header />
 <soapenv:Body>
  <tns:SendInstantSms xmlns:tns="SmInf" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <sequenceId type="xsd:long">1</sequenceId>
   <accountCode type="xsd:string">user_id</accountCode>
   <accountPasswd type="xsd:string">user_password</accountPasswd>
   <sendPhoneNo type="xsd:string">1234567890</sendPhoneNo>
   <msgContent type="xsd:string">7D27 6025 901A 77E5 FF1A 7279 522B 7D27 6025 FF0C 5341 4E07 706B 6025 002E</msgContent>
   <recvPhoneNo type="xsd:string">1234567890</recvPhoneNo>
   <scheduleTime type="xsd:dateTime">2000-10-10T09:35:12.123</scheduleTime>
  </tns:SendInstantSms>
 </soapenv:Body>
</soapenv:Envelope>
        这个SOAP请求包格式并不能完全通用于任何场合,大家具体实现某个SOAP调用时,需要根据具体情况进行调整,可以通过Web Service服务提供商获取详情。
        通过HttpURLConnection实现SOAP调用的过程简要概述如下:
        1、拼接实现如上所示的SOAP请求包的XML格式的字符流;
        2、上面讲到过SOAP调用就是一个HTTP请求,因此通过HttpURLConnection类设置相应的请求属性;
        3、通过HttpURLConnection类的getOutputStream方法获得一个输出流,然后将SOAP请求包字符流写入此输出流;
        4、通过HttpURLConnection类的getResponseCode方法获得服务器响应代码,如果响应代码为200(即HttpURLConnection.HTTP_OK)则表示请求成功,否则请求失败,请求失败后,可以通过getErrorStream方法来了解具体的错误详情;
        5、通过HttpURLConnection类的getInputStream方法获得一个输入流,由此输入流获得服务器反馈结果数据;
        大体通过HttpURLConnection实现SOAP调用的过程就是这样。下面来看具体实现代码:

        编写CSOAPClient类,并定义成员变量_url和_httpConn,在构造函数中对其进行实例化。

        _url=new URL(url);          //这里url变量是SOAP服务的网址,如http://10.5.3.134/Webservices/methods1?wsdl

       _httpConn = (HttpURLConnection) _url.openConnection();   //这里就是获得一个SOAP服务的HttpURLConnection实例
       String send_soap=createSendSOAPPackage();    //createSendSOAPPackage函数就是用来构造如上所示SOAP请求的数据包的XML字符串
       _httpConn.setReadTimeout(TIME_OUT);        //为HttpURLConnection对象指定一个读超时
       _httpConn.setRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 5.0; Windows XP; DigExt)");
       _httpConn.setRequestProperty( "Content-Length",String.valueOf( send_soap.length() ) );
       _httpConn.setRequestProperty("Content-Type","text/xml; charset=UTF-8");
       _httpConn.setRequestProperty("SOAPAction",_soap_action_str);
       //以上都是为HTTP请求设定请求属性,其中SOAPAction中用来指定SOAP Action的字符串。
       _httpConn.setRequestMethod( "POST" );   //为请求指定提交数据模式,对于调用Web Service来说请求模式要被设置成POST模式。
       _httpConn.setDoInput(true);
        _httpConn.setDoOutput(true);
        _httpConn.setUseCaches(false);
       _httpConn.connect();  //连接远程Url
       OutputStream out = _httpConn.getOutputStream();   //获取输出流对象
        out.write( send_soap.getBytes() );       //将要提交服务器的SOAP请求字符流写入输出流
        out.flush();
        out.close();
       int code=0;
        code = _httpConn.getResponseCode();    //用来获取服务器响应状态
       if (code == HttpURLConnection.HTTP_OK) {
            //服务器响应状态表示成功,这此处可以来获取服务器反馈的数据信息
            InputStream is=_httpConn.getInputStream();    //获取输入流对象,通过此对象可以获取服务器传回的数据信息
            InputStreamReader isr = new InputStreamReader(is,"utf-8");
            Document _doc=_sax.build(isr);     //此处Document是jdom中的类,因为要解析服务器传回的xml数据
            Element _root = _doc.getRootElement();  //此处Element是jdom中的类
            ......(略)
            
       }
       else{
            //如果服务器返回的HTTP状态不是HTTP_OK,则表示发生了错误,此时可以通过如下方法了解错误原因。
            InputStream is=_httpConn.getErrorStream();    //通过getErrorStream了解错误的详情,因为错误详情也以XML格式返回,因此也可以用JDOM来获取。
            InputStreamReader isr = new InputStreamReader(is,"utf-8");
            Document _doc=_sax.build(isr);     //此处Document是jdom中的类,因为要解析服务器传回的xml数据
            Element _root = _doc.getRootElement();  //此处Element是jdom中的类
            ......(略)
       }
       以上就是通过HttpURLConnection调用SOAP的简介。
      下面附上实现类的代码,供参考(未优化,大家使用时要优化一下)

CSOAPClient.java

package util;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.Hashtable;import java.util.LinkedList;import java.util.Set;import org.jdom.Attribute;import org.jdom.Document;import org.jdom.Element;import org.jdom.Namespace;import org.jdom.output.Format;import org.jdom.output.XMLOutputter;/** * * @author zhaob */public class CSOAPClient {    private static int TIME_OUT=15000;        private URL _url = null;    private String _service_id=null;    private String _method=null;    private String _soap_action_str=null;    private LinkedList
_params = new LinkedList
(); private HttpURLConnection _httpConn=null; private String _root_master_namespace_name=null; private Hashtable
_root_namespace=new Hashtable
(); private boolean _setted_root_master_namespace_flag=false; private boolean _hasHead=true; private boolean _hasParamType=true; private Hashtable
_method_attrib=new Hashtable
(); private Hashtable
_method_attrib_namespace=new Hashtable
(); private Hashtable
_methodattrib_namespace=new Hashtable
(); private Hashtable
_methods_namespace=new Hashtable
(); public CSOAPClient(String url,String service_id,String method,String soap_action) throws Exception { _url=new URL(url); //SOAP服务的网址 if((service_id==null)||(service_id.trim().equals(""))){ _service_id=null; } else{ _service_id=service_id; } _method=method; _soap_action_str=soap_action; createSocket(); } public void setHasParamType(boolean v){ _hasParamType=v; } public void setHasHead(boolean v){ _hasHead=v; } protected void createSocket() throws Exception { if(_httpConn==null){// Properties systemProperties = System.getProperties();// systemProperties.setProperty("http.proxyHost","192.168.1.1");// systemProperties.setProperty("http.proxyPort","8080"); _httpConn = (HttpURLConnection) _url.openConnection();; } } public void addParams(String params_name,Object v,EParamType type){ NParam np=new NParam(params_name,v,type); _params.add(np); } public void addMethodNamespace(String namespace_name,String namespace_v){ _methods_namespace.put(namespace_name,namespace_v); } public void addMethodAttrib(String attrib_name,String v,String namespace_name,String namespace_v){ _method_attrib.put(attrib_name, v); _method_attrib_namespace.put(attrib_name, namespace_name); _methodattrib_namespace.put(namespace_name,namespace_v); } public void addMethodAttrib(String attrib_name,String v){ _method_attrib.put(attrib_name, v); } public void setRootMasterNamespace(){ if(!_setted_root_master_namespace_flag){ _root_master_namespace_name="soapenv"; _root_namespace.put(_root_master_namespace_name, "http://schemas.xmlsoap.org/soap/envelope/"); _setted_root_master_namespace_flag=true; } } public void setRootMasterNamespace(String name){ if(!_setted_root_master_namespace_flag){ _root_master_namespace_name=name; _root_namespace.put(_root_master_namespace_name, "http://schemas.xmlsoap.org/soap/envelope/"); _setted_root_master_namespace_flag=true; } } public void addRootNamespace(String name,String v){ _root_namespace.put(name, v); } public String createSendSOAPPackage(){ Hashtable
namespace_set=new Hashtable
(); // 创建根节点 root; Element root = new Element("Envelope"); Set
sets=_root_namespace.keySet(); Namespace master_namespace=null; for(String s:sets){ String v=_root_namespace.get(s); Namespace sn=Namespace.getNamespace(s, v); namespace_set.put(s, sn); if(s.equals(_root_master_namespace_name)){ root.setNamespace(sn); master_namespace=sn; } else{ root.addNamespaceDeclaration(sn); } } // 根节点添加到文档中; Document doc = new Document(root); if(_hasHead){ //创建Header节点 Element head=new Element("Header"); head.setNamespace(master_namespace); //加入根节点 root.addContent(head); } //创建Body节点 Element body=new Element("Body"); body.setNamespace(master_namespace); //加入根节点 root.addContent(body); //创建调用的方法节点 Element method=new Element(_method); body.addContent(method); Set
method_attrib_set=_method_attrib.keySet(); boolean flag=false; Namespace ns=null; for(String attrib_name:method_attrib_set){ String attrib_v=_method_attrib.get(attrib_name); flag=_method_attrib_namespace.containsKey(attrib_name); if(flag){ String namespace_name=_method_attrib_namespace.get(attrib_name); flag=namespace_set.containsKey(namespace_name); if(flag){ ns=namespace_set.get(namespace_name); } else{ String namespace_v=_methodattrib_namespace.get(namespace_name); ns=Namespace.getNamespace(namespace_name, namespace_v); method.setNamespace(ns); namespace_set.put(namespace_name, ns); } Attribute attrib=new Attribute(attrib_name, attrib_v,ns); method.setAttribute(attrib); } else{ Attribute attrib=new Attribute(attrib_name, attrib_v); method.setAttribute(attrib); } } Set
methods_attrib=_methods_namespace.keySet(); for(String namespace_name:methods_attrib){ flag=namespace_set.containsKey(namespace_name); if(flag){ } else{ String namespace_v=_methods_namespace.get(namespace_name); ns=Namespace.getNamespace(namespace_name, namespace_v); method.setNamespace(ns); namespace_set.put(namespace_name, ns); } } if(_service_id!=null){ Namespace nsl=Namespace.getNamespace("tns", _service_id); method.setNamespace(nsl); } //创建调用方法的参数节点 int count=_params.size(); for(int i=0;i

CXML.java

package util;import java.io.InputStream;import java.io.InputStreamReader;import org.jdom.Document;import org.jdom.Element;import org.jdom.Namespace;import org.jdom.input.SAXBuilder;import org.jdom.output.Format;import org.jdom.output.XMLOutputter;import org.jdom.xpath.XPath;/** * * @author zhaob */public class CXML {    private SAXBuilder _sax=new SAXBuilder();    private Document _doc=null;    private Element _root = null;    private Namespace _master_namespace=null;    public CXML(InputStream is,String namespace_name,String namespace_v) throws Exception {        InputStreamReader isr = new InputStreamReader(is,"utf-8");        _doc=_sax.build(isr);        _root = _doc.getRootElement();        _master_namespace=Namespace.getNamespace(namespace_name, namespace_v);    }    public String getElementTextByXPath(String xpath) throws Exception {        String rtn=null;        XPath xpathobj=XPath.newInstance(xpath);        xpathobj.addNamespace(_master_namespace);        Element obj=(Element)xpathobj.selectSingleNode(_doc);        rtn=obj.getTextTrim();        return rtn;    }    public String toString(){        XMLOutputter o=new XMLOutputter();        //设置格式        Format format = Format.getPrettyFormat();        format.setEncoding("UTF-8"); //设置 xml文件的字符为UTF-8        format.setIndent(" "); //设置xml文件的缩进为4个空格        o.setFormat(format);        String xmlstr=o.outputString(_doc);                return xmlstr;    }}

3、CSOAPClinetTest   这是一个JUNIT的测试类,看其中RUN方法即可。

package util;import java.util.List;import org.junit.After;import org.junit.AfterClass;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Test;import util.CSOAPClient.EParamType;/** * * @author zhaob */public class CSOAPClinetTest {    public CSOAPClinetTest() {    }    @BeforeClass    public static void setUpClass() throws Exception {    }    @AfterClass    public static void tearDownClass() throws Exception {    }    @Before    public void setUp() {    }    @After    public void tearDown() {    }    // TODO add test methods here.    // The methods must be annotated with annotation @Test. For example:    //    // @Test    // public void hello() {}    @Test    public void run(){        CSOAPClient soap_client=null;        try{            soap_client=new CSOAPClient("http://10.20.4.21:8080/Webservices/SmsInf","SmInf","SendInstantSms","http://w.rr.com/SmsInf/SendInstantSms");        }        catch(Exception e){            System.out.println("Error:"+e.getMessage());        }        if(soap_client!=null){            soap_client.setHasHead(true);            soap_client.setRootMasterNamespace("soapenv");            soap_client.addRootNamespace("SmInf", "http://x.rr.com/SmInf");            soap_client.addMethodAttrib("encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/","soapenv","");            soap_client.setHasParamType(true);            soap_client.addParams("sequenceId", 2, EParamType.Long);            soap_client.addParams("accountCode", "user_id", EParamType.String);            soap_client.addParams("accountPasswd", "user_password", EParamType.String);            soap_client.addParams("sendPhoneNo", "1234567890", EParamType.String);            soap_client.addParams("msgContent", soap_client.toUTF8("紧急通知:特别紧急,十万火急."), EParamType.String);            soap_client.addParams("recvPhoneNo", "07919999999", EParamType.String);            soap_client.addParams("scheduleTime", "2000-10-10T09:35:12.123", EParamType.Datetime);            try{                CXML xmlobj=soap_client.call();                System.out.println("返回的XML:");                System.out.println(xmlobj.toString());            }            catch(Exception e){                System.out.println("Error:"+e.getMessage());            }        }    }}

4、注意:运行此代码需要加入JDOM的全部lib目录下的包,否则使用XPATH时将报告错误。
如果还有什么疑问,可直接联系我。

转载于:https://my.oschina.net/boltwu/blog/416455

你可能感兴趣的文章
idea上使用maven模块开发
查看>>
学习记录:浏览器JAVASCRIPT里的WINDOWS,DOCUMNET
查看>>
ecshop后台增加|添加商店设置选项和使用方法详解
查看>>
Android Studio快捷键每日一练(1)
查看>>
js 跨域
查看>>
[工具] Snipaste
查看>>
iOS:crash崩溃日志分析
查看>>
Java程序员的日常—— IOUtils总结
查看>>
java List<Map> 排序问题
查看>>
[Angular2 Animation] Use Keyframes for Fine-Tuned Angular 2 Animations
查看>>
教你如何在word中像LaTex那样打出漂亮的数学公式
查看>>
java中类名,方法,变量,包名等大小写命名规范
查看>>
【转】在Ubuntu中安装HBase
查看>>
Nginx内置变量以及日志格式变量参数详解
查看>>
python基础-RE正则表达式
查看>>
Linux下查看Nginx安装目录、版本号信息?
查看>>
MVC ---- 标准查询运算符
查看>>
巧用“搜索”解决自学编程遇到的难题
查看>>
移动端布局解决方案+神器
查看>>
pom.xml详解
查看>>