纵有疾风起
人生不言弃

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("https://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.1Accept: text/xml, multipart/relatedContent-Type: text/xml; charset=utf-8SOAPAction: "http://server.jaxws.ws.itcast.cn/WeatherServer/queryWeatherRequest"User-Agent: JAX-WS RI 2.2.8 svn-revision#13980Host: 127.0.0.1:4321Connection: keep-aliveContent-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 OKTransfer-encoding: chunkedContent-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.1Accept: application/soap+xml, multipart/relatedContent-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#13980Host: 127.0.0.1:4321Connection: keep-aliveContent-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 OKTransfer-encoding: chunkedContent-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;}
@WebServicepublic 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("https://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

文章转载于:https://www.cnblogs.com/lm970585581/p/7771163.html

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » WebService使用介绍(二)

分享到: 生成海报
avatar

评论 抢沙发

评论前必须登录!

立即登录   注册

切换注册

登录

忘记密码 ?

切换登录

注册

我们将发送一封验证邮件至你的邮箱, 请正确填写以完成账号注册和激活