zoukankan      html  css  js  c++  java
  • WebService使用介绍(二)

    Soap

    soap是什么

    SOAP 是一种网络通信协议

    SOAPSimple Object Access Protocol简易对象访问协议

    SOAP 用于跨平台应用程序之间的通信

    SOAP 被设计用来通过因特网(http)进行通信

    SOAP HTTP+XML,其实就是通过HTTPxml数据

    SOAP 很简单并可扩展支持面向对象

    SOAP 允许您跨越防火墙

    SOAP 将被作为 W3C 标准来发展

    使用TCP/IP Monitor监视Soap协议

    使用TCP/IP Monitor可以监视tcp/ip协议的报文内容,由于http是基于Tcp的应用协议,而webservice是基于http实现,所以通过tcp/ip monitor可以监视webservice请求及响应的内容。

    Soap1.1

    客户端代码:

         //定义url,参数为wsdl地址
            URL url = new URL("http://127.0.0.1:54321/weather?wsdl");
            //定义qname,第一个参数是命名空间,第二个参数名称是wsdl里边的服务名
            QName qName = new QName("http://server.jaxws.webservice.itcast.cn/", "WeatherInterfaceImplService");
            //创建服务视图
            Service service = Service.create(url, qName);
            //通过服务视图得到服务端点
            WeatherInterfaceImpl weatherInterfaceImpl =service.getPort(WeatherInterfaceImpl.class);
            //调用webservice
            System.out.println(weatherInterfaceImpl.queryWeather("郑州"));

    请求:

    注意蓝底标注

    POST /weather HTTP/1.1
    Accept: text/xml, multipart/related
    Content-Type: text/xml; charset=utf-8
    SOAPAction: "http://server.jaxws.ws.itcast.cn/WeatherServer/queryWeatherRequest"
    User-Agent: JAX-WS RI 2.2.8 svn-revision#13980
    Host: 127.0.0.1:4321
    Connection: keep-alive
    Content-Length: 232
    
    
    <?xml version='1.0' encoding='UTF-8'?>
    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
    <ns2:queryWeather xmlns:ns2="http://server.jaxws.ws.itcast.cn/">
    <arg0>郑州</arg0>
    </ns2:queryWeather>
    </S:Body>
    </S:Envelope>

    响应:

    HTTP/1.1 200 OK
    Transfer-encoding: chunked
    Content-type: text/xml; charset=utf-8
    
     
    
    <?xml version='1.0' encoding='UTF-8'?>
    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
    <ns2:queryWeatherResponse xmlns:ns2="http://server.jaxws.ws.itcast.cn/">
    <return>天气晴朗</return>
    </ns2:queryWeatherResponse>
    </S:Body>
    </S:Envelope>

    soap协议体包含下列元素

    必需有 Envelope 元素,此元素将整个 XML 文档标识为一条 SOAP 消息

    可选的 Header 元素,包含头部信息

    必需有Body 元素,包含所有的调用和响应信息

    可选的 Fault 元素,提供有关在处理此消息所发生错误的信息

    soap消息基本结构

    <?xml version="1.0"?> 
    <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> 
    <soap:Header>
     ... ... 
    </soap:Header> 
    <soap:Body>
     ... ...
     <soap:Fault>
     ... ... 
     </soap:Fault> 
    </soap:Body>
    </soap:Envelope>

    http发送soap协议测试

    webservice使用soap协议传输数据,soap是基于http的应用协议,可以使用http发送soap协议数据完成webservice的请求。

    本例子解析响应的xml数据使用dom4j

    /**
     * 通过http发送soap协议请求webservice
     * @author SMN
     * @version V1.0
     */
    public class HttpRequestSoap {
        
            public static void main(String[] args) throws IOException {
                //webservice地址
                String webservice_url = "http://127.0.0.1:1234/weather";
                //发送的soap协议内容
                String soap_xml = soap_xml("郑州");
                System.out.println(soap_xml);
                //创建url
                URL url = new URL(webservice_url);
                //创建http链接对象
                HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
                //设置请求方法
                httpURLConnection.setRequestMethod("POST");
                //设置Content-type
                httpURLConnection.setRequestProperty("Content-type", "text/xml;charset="utf-8"");
                //使用http进行输出
                httpURLConnection.setDoOutput(true);
                //使用http进行输入
                httpURLConnection.setDoInput(true);
                
                //通过输出流发送数据
                OutputStream outputStream = httpURLConnection.getOutputStream();
                outputStream.write(soap_xml.getBytes());
                outputStream.close();
                
                //接收服务端响应数据
                InputStream inputStream =  httpURLConnection.getInputStream();
                
                //使用buffer存在读取的数据
                byte[] buffer = new byte[1024];
                
                //使用字节输出流存储读取的数据
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                while(true){
                    int len = inputStream.read(buffer);
                    //如果流水读取完则退出循环
                    if(len == -1){
                        break;
                    }
                    byteArrayOutputStream.write(buffer,0,len);
                }
    
                //得到响应数据
                String response_string = byteArrayOutputStream.toString();
                
                System.out.println(response_string);
                
                parseXml(response_string);
            }
            //soap协议内容
            public static String soap_xml(String cityName){
                String soap_xml = "<?xml version="1.0" encoding="utf-8"?>"
                        + "<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">"
                        + "<S:Body>"
                        + "<ns2:queryWeather xmlns:ns2="http://impl.sei.jaxws.ws.itcast.cn/">"
                        + "<arg0>"+ cityName  + "</arg0>"
                        + "</ns2:queryWeather>"
                        + "</S:Body>"
                        + "</S:Envelope>";
                
                return soap_xml;
            }
    
    
            //解析响应的xml
        public static String parseXml(String xmlString){
            String result = null;
            
            try {
                Document document = DocumentHelper.parseText(xmlString);
                //创建xpath解析对象
                DefaultXPath defaultXPath = new DefaultXPath("//ns2:queryWeatherResponse");
                //指定命名空间
                defaultXPath.setNamespaceURIs(Collections.singletonMap("ns2", "http:// impl.sei.jaxws.ws.itcast.cn/"));
                
                List<Element> elements= defaultXPath.selectNodes(document);
                
                Element response = elements.get(0);
                
                List<Element> results = response.selectNodes("return");
                
                System.out.println(results.get(0).getText());
                
            } catch (DocumentException e) {
                e.printStackTrace();
            }
    
            return result;
        }
            
    }

    Soap1.2

    下载 jaxws-ri-2.2.8

    Jaxws实现soap1.2需要加入jaxws扩展包,从sun下载jaxws-ri-2.2.8,解压jaxws-ri-2.2.8并将lib下的jar包加载到java工程中。

    添加BindingType

    SEI实现类上添加如下注解

    @BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)

    请求:

    POST /weather HTTP/1.1
    Accept: application/soap+xml, multipart/related
    Content-Type: application/soap+xml; charset=utf-8;action="http://server.jaxws.ws.itcast.cn/WeatherServer/queryWeatherRequest"
    User-Agent: JAX-WS RI 2.2.8 svn-revision#13980
    Host: 127.0.0.1:4321
    Connection: keep-alive
    Content-Length: 230
    
    <?xml version='1.0' encoding='UTF-8'?>
    <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
    <S:Body>
    <ns2:queryWeather xmlns:ns2="http://server.jaxws.ws.itcast.cn/">
    <arg0>郑州</arg0>
    </ns2:queryWeather>
    </S:Body>
    </S:Envelope>

    响应:

    HTTP/1.1 200 OK
    Transfer-encoding: chunked
    Content-type: application/soap+xml; charset=utf-8
    <?xml version='1.0' encoding='UTF-8'?>
    <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
    <S:Body>
    <ns2:queryWeatherResponse xmlns:ns2="http://server.jaxws.ws.itcast.cn/">
    <return>天气晴朗</return>
    </ns2:queryWeatherResponse>
    </S:Body>
    </S:Envelope>

    Soap1.1soap1.2异同

    相同之处:

    soap1.1soap1.2都是使用post方法

    都包括Envelopebody

    内容类型context-type不同:

    soap1.1使用text/xml

    soap1.2使用application/soap+xml

    命名空间Envelope xmlns不同:

    soap1.1使用http://schemas.xmlsoap.org/soap/envelope/

    soap1.2使用http://www.w3.org/2003/05/soap-envelope

    webservice 发送xml数据

    由于xml的跨平台特性,企业中在实际开发接口时方法只定义一个参数传递复杂的xml数据,这样做可以省去自定义复杂java数据类型的麻烦,且webservice接口简单,接口双方将xml数据格式规定好,实质上是通过webservicesoap协议传递xml数据。

    功能说明:

    创建区域查询webservice服务,客户端调用服务端查询区域信息,客户端向服务端传递xml格式数据,服务端向客户端响应xml格式数据。

    接口描述:

    客户端发送数据格式:

    <?xml version="1.1"  encoding="utf-8"?>
    <queryarea>
    <parentid> </parentid>//父级区域id
    <start></start>//起始记录,从1开始
    <end></end>//结束记录
    </queryarea>

    服务端响应数据格式:

    <?xml version="1.0" encoding="UTF-8"?>
    <areas>
    <area>
    <areaid> </areaid>//区域id
    <areaname></areaname>//区域名称
    <arealevel></arealevel>//区域等级
    <parentid></parentid>//父级区域id
    </area>
    //…..
    </areas>

    服务端:

    Dao

    public class Area {
        private String areaid;    
        private String areaname;
        private String parentid;
        private String arealevel;
        private int start;
        private int end;
    ...
    ...
    public interface AreaDao {
        /**
         * 区域查询
         * @param parentid 父级区域id
         * @param start  查询开始下标
         * @param end  查询结束下标
         * @return
         * @throws Exception
         */
        public List<Area> queryArea(String parentid,int start,int end) throws Exception;
    }
    public class AreaDaoImpl implements AreaDao {
        
        //区域查询sql
        private static String sql = "SELECT areaid,areaname,arealevel,parentid FROM AREA where parentid = ? LIMIT ?,?";
        
        
        public List<Area> queryArea(String parentid,int start,int end){
            
            //数据库链接
            Connection connection = null;
            
            //预编译statement
            PreparedStatement preparedStatement = null;
            
            //结果集
            ResultSet resultSet = null;
            
            //区域列表
            List<Area> areaList = new ArrayList<Area>();
            try {
                //加载数据库驱动
                Class.forName("com.mysql.jdbc.Driver");
                //连接数据库
                connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/webservice", "root", "mysql");
                //创建preparedStatement
                preparedStatement = connection.prepareStatement(sql);
                
                //查询的记录数
                int length = end - start +1;
                //起始坐标
                start = start -1;
                //设置查询参数
                preparedStatement.setString(1, parentid);
                preparedStatement.setInt(2, start);
                preparedStatement.setInt(3, length);
                //获取结果集
                resultSet = preparedStatement.executeQuery();
                
                //结果集解析
                while(resultSet.next()){
                    Area area = new Area();
                    area.setAreaid(resultSet.getString("areaid"));
                    area.setAreaname(resultSet.getString("areaname"));
                    area.setArealevel(resultSet.getString("arealevel"));
                    area.setParentid(resultSet.getString("arealevel"));
                    areaList.add(area);
                }
                 
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            return areaList;
            
        }
    }

    service

    public interface AreaService {
        /**
         * 区域查询
         * @param queryinfo  查询信息,xml格式详见接口描述
         * @return
         * @throws Exception
         */
        public String queryArea(String queryinfo) throws Exception;
    }
    @WebService
    public class AreaServiceImpl implements AreaService {
        
        //区域查询dao
        private AreaDao areaDao = new AreaDaoImpl();
    
        @Override
        public String queryArea(String queryinfo) throws Exception {
    
            //解析查询条件
            Area area_query = parseXml(queryinfo); 
            
            //调用dao查询区域
            List<Area> listAreas = areaDao.queryArea(area_query.getParentid(),area_query.getStart(), area_query.getEnd());
            
            //将list数据传为xml数据
            Document document = DocumentHelper.createDocument();
            
            Element root = DocumentHelper.createElement("areas");
            document.setRootElement(root);
            
            for(Area area:listAreas){
                
                Element element_area= root.addElement("area");
                element_area.addElement("areaid").addText(area.getAreaid());
                element_area.addElement("areaname").addText(area.getAreaname());
                element_area.addElement("arealevel").addText(area.getArealevel());
                element_area.addElement("parentid").addText(area.getParentid());
    
            }
            //转换后的xml数据
            String responseString = document.asXML();
            //返回给客户端
            return responseString;
        }
    
    
        //解析查询信息
        private Area parseXml(String xmlString){
            
            Area areainfo = new Area();
            
            try {
                Document document = DocumentHelper.parseText(xmlString);
                
                String start = document.selectSingleNode("/queryarea/start").getText();
                String end = document.selectSingleNode("/queryarea/end").getText();
                String parentid = document.selectSingleNode("/queryarea/parentid").getText();
                
                areainfo.setStart(Integer.parseInt(start));
                areainfo.setEnd(Integer.parseInt(end));
                areainfo.setParentid(parentid);
                
            } catch (DocumentException e) {
                e.printStackTrace();
            }
    
            return areainfo;
                    
            
        }
        
    }

    发布服务

    public class AreaServer {
        public static void main(String[] args) {
            //发布区域查询服务
            Endpoint.publish("http://127.0.0.1:12345/queryarea", new AreaServiceImpl());
        }
    }

    客户端:

    public class AreaClient {
        public static void main(String[] args) throws MalformedURLException, Exception_Exception {
            //区域查询服务地址
            URL url = new URL("http://127.0.0.1:12345/queryarea");
            QName qName =new QName("http://service.area.ws.itcast.cn/", "AreaServiceImplService");
            
            //创建service
            Service service = Service.create(url, qName);
            //创建porttype
            AreaServiceImpl areaService = service.getPort(AreaServiceImpl.class);
            //调用服务接口查询区域
            String queryString = areaService.queryArea(queryXmlString("1.",1,20));
            //服务端响应的xml数据
            System.out.println(queryString);
            //xml数据解析
            parseXml(queryString);
        }
        
        //查询的xml信息
        public static String queryXmlString(String parentid,int start,int end){
            
            String queryString= "<?xml version="1.0" encoding="utf-8"?>"
                    + "<queryarea>"
                    + "<parentid>"+parentid+"</parentid>"
                    + "<start>"+start+"</start>"
                    + "<end>"+end+"</end>"
                    + "</queryarea>";
            
            return queryString;
            
        }
        //将服务端响应的xml数据解析为list
        public static List<Area> parseXml(String xmlString){
            List<Area> areas = new ArrayList<Area>();
            try {
                Document document = DocumentHelper.parseText(xmlString);
                
                List<Node> areaList = document.selectNodes("//areas/area");
                for(Node node:areaList){
                    Area area_i  =new Area();
                    Element element = (Element)node;
                    area_i.setAreaid(element.elementText("areaid"));
                    area_i.setAreaname(element.elementText("areaname"));
                    area_i.setArealevel(element.elementText("arealevel"));
                    area_i.setParentid(element.elementText("parentid"));
                    System.out.println(area_i);
                    areas.add(area_i);
                }
            } catch (DocumentException e) {
                e.printStackTrace();
            }
            return areas;
            
        }
        
    }

    总结:

    Webservice发送xml数据其实是将xml数据作为大字符串发送,工作量主要在解析xml数据上。虽然解析xml数据比较麻烦但是webservice接口简单,大家遵守xml格式开发接口,这种方式在企业中也较常用。

    建议:数据量大的xml建议使用SAX解析提高解析速度。

     http://www.cnblogs.com/lm970585581/p/7728280.html

  • 相关阅读:
    export ,export default 和 import 区别 以及用法
    koa2 安装环境
    Webstorm在MAC下的安装方法
    Mac 下搭建vue开发环境
    Mac系统下安装Vue-cli详细步骤
    npm 安装vue 报错Failed at the chromedriver@2.34.0 install script 'node install.js'
    #001 WebStrom SVN使用技巧
    #006 dependencies和devDependencies的区别
    #001 GIT创建分支
    #003 React 组件 继承 自定义的组件
  • 原文地址:https://www.cnblogs.com/lm970585581/p/7771163.html
Copyright © 2011-2022 走看看