Web Service 运行原理详细介绍

利用清明小假期,温习了一遍Web Service的相关内容,对其工作原理进行了简要总结。以供有需求的朋友和自己日后参考。文章若有不当之处,敬请朋友们提出宝贵建议,以求共勉。

Web服务中,我们应该首先了解相关的术语含义:WSDL、UDDI....相关术语方面的介绍在此不再赘述,重点放在原理上。
在Web服务中,存在三个角色:服务提供者、服务请求者和服务中介,三者之间的关系如图1-1所示

实现一个完整的Web服务包括以下步骤:

◆ Web服务提供者设计实现Web服务,并将调试正确后的Web服务通过Web服务中介者发布,并在UDDI注册中心注册; (发布)

◆ Web服务请求者向Web服务中介者请求特定的服务,中介者根据请求查询UDDI注册中心,为请求者寻找满足请求的服务; (发现)

◆ Web服务中介者向Web服务请求者返回满足条件的Web服务描述信息,该描述信息用WSDL写成,各种支持Web服务的机器都能阅读;(发现)

◆ 利用从Web服务中介者返回的描述信息(WSDL)生成相应的SOAP消息,发送给Web服务提供者,以实现Web服务的调用;(绑定)

◆ Web服务提供者按SOAP消息执行相应的Web服务,并将服务结果返回给Web服务请求者。(绑定)

图1-1 Web service的体系结构

注:WSDL的作用就是一个Web服务说明书。服务请求者根据此WSDL生成相应的SOAP消息,服务提供者在收到SOAP请求消息后,进行服务的绑定。

以下代码是在web.xml中的servlet配置

  <!-- 在向servlet或JSP页面制定初始化参数或定制URL时,必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。 -->
  <servlet>
  <servlet-name>UserService</servlet-name>
  <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
  <!-- 标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法;正数的值越小,该servlet的优先级越高,应用启动时就越先加载 -->
  <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- 服务器一般为servlet提供一个缺省的URL:http://host/webAppPrefix/servlet/ServletName。
   但是,常常会更改这个URL,以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时,使用servlet-mapping元素。 -->
  <servlet-mapping>
   <servlet-name>UserService</servlet-name>
   <!-- 描述了相对于Web应用的根目录的URL。url-pattern元素的值必须以斜杠(/)起始。 -->
   <url-pattern>/user</url-pattern>
  </servlet-mapping>
  红色代码部分很重要,会在Web容器启动的时候加载相应的servlet。绿色部分为该服务的外部接口。以此找到相应的jax-ws.xml文件(如下所示)
  <endpoint name="UserPort" implementation="cn.ujn.service.UserService"
    url-pattern="/user">
  </endpoint>

进而绑定到相关的相应的实现类cn.ujn.service.UserService中。客户端发送的SOAP请求消息消息体body中包含有客户端所请求的方法名和参数信息。

以下为客户端封装的soap消息体(以Json方式与服务端进行数据传输)(SOAP Rerquest Envelope):

  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://ujn.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <soapenv:Body>
-  <q0:login>
     <arg0>{"username":"shq","password":"shq"}</arg0>
 </q0:login>
 </soapenv:Body>
 </soapenv:Envelope>

以下为SOAP1.1协议调用Web服务

/**
* 通过SOAP1.1协议调用Web服务
*
* text/xml 这是基于soap1.1协议
*
* @param wsdl WSDL路径
* @param method方法名
* @param namespace命名空间
* @param headerParameters 头参数
* @param bodyParameters  体参数
* @param isBodyParametersNS 体参数是否有命名空间
* @return String
* @throws Exception
*/
public static String invokeBySoap11(String wsdl, String method,
String namespace, Map<String, String> headerParameters,
Map<String, String> bodyParameters, boolean isBodyParametersNS)
throws Exception {
StringBuffer soapOfResult = null; 

// 去除 ?wsdl,获取方法列表
int length = wsdl.length();
wsdl = wsdl.substring(0, length - 5);
//以字符串为参数创建URL实例
URL url = new URL(wsdl);
//创建连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//设置请求方式
conn.setRequestMethod("POST");
//如果打算使用 URL连接进行输入,则将 DoInput 标志设置为 true
conn.setDoInput(true);
//如果打算使用 URL连接进行输出,则将 DoInput 标志设置为 true
conn.setDoOutput(true);
//主要是设置HttpURLConnection请求头里面的属性(K-V)
conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
//获取输入流(相对于客户端来说,使用的是OutputStream)
OutputStream out = conn.getOutputStream();
// 获取soap1.1版本消息
StringBuilder sb = new StringBuilder();
sb.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" ");
sb.append("xmlns:ns0=\"" + namespace + "\"");
sb.append(">");
//拼装消息头
if (headerParameters != null) {
sb.append("<soap:Header>");
for (Entry<String, String> headerParameter : headerParameters
.entrySet()) {
sb.append("<ns0:");
sb.append(headerParameter.getKey());
sb.append(">");
sb.append(headerParameter.getValue());
sb.append("</ns0:");
sb.append(headerParameter.getKey());
sb.append(">");
}
sb.append("</soap:Header>");
}
//拼装消息体
sb.append("<soap:Body><ns0:");
sb.append(method);
sb.append(">");
// 输入参数
if (bodyParameters != null) {
for (Entry<String, String> inputParameter : bodyParameters
.entrySet()) {
if (isBodyParametersNS) {
sb.append("<ns0:");
sb.append(inputParameter.getKey());
sb.append(">");
sb.append(inputParameter.getValue());
sb.append("</ns0:");
sb.append(inputParameter.getKey());
sb.append(">");
} else {
sb.append("<");
sb.append(inputParameter.getKey());
sb.append(">");
sb.append(inputParameter.getValue());
sb.append("</");
sb.append(inputParameter.getKey());
sb.append(">");
}
}
}
sb.append("</ns0:");
sb.append(method);
sb.append("></soap:Body></soap:Envelope>");
//测试用
System.out.println(sb.toString());
//写入SOAP消息(相对于客户端来说,使用的是out.write())
out.write(sb.toString().getBytes());
//获取服务器端的相应
int code = conn.getResponseCode();
if (code == 200) {
InputStream is = conn.getInputStream();
byte[] b = new byte[1024];
int len = 0;
soapOfResult = new StringBuffer();
//从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数
//如果因为流位于文件末尾而没有可用的字节,则返回值 -1;
while ((len = is.read(b)) != -1) {
//Converts the byte array to a string using the named charset.
String s = new String(b, 0, len, "UTF-8");
soapOfResult.append(s);
}
}
conn.disconnect();
return soapOfResult == null ? null : soapOfResult.toString();
}

注:在客户端发送SOAP请求消息后便处于阻塞状态。直至服务端返回状态码。

以下为服务端进行响应(SOAP Response Envelope):

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
-<S:Body>
-<ns2:loginResponse xmlns:ns2="http://ujn.cn/">
 <return>1</return>
</ns2:loginResponse>
 </S:Body>
</S:Envelope>

客户端接收到服务端发来的Json数据后会进行相应的解析操作。如下:

// 将Soap协议进行解析(DOM解析只能用于解析XML文档类型,而SOAP消息就是采用XML数据格式)
Document doc = XmlUtil.string2Doc(result);
Element ele = (Element) doc.getElementsByTagName("return").item(0);
方法中使用到的string2Doc()方法体如下:
public static Document string2Doc(String str) {
//将XML文档解析成DOM树
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document document = null;
DocumentBuilder build;
if (str == null || str.equals("")) {
return null;
}
try {
InputStream bais = new ByteArrayInputStream(str.getBytes("UTF-8"));
build = factory.newDocumentBuilder();
//Parse the content of the given InputStream as an XML document and return a new DOM Document object.
document = build.parse(bais);
} catch (Exception e) {
e.printStackTrace();
}
return document;
}

根据返回结果,客户端再进行相应的处理。

以上是web服务的基本工作原理。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • js调用webservice构造SOAP进行身份验证

    本文实例为大家分享了js调用webservice构造SOAP进行身份验证的相关内容,注释清除,供大家参考,具体内容如下 <html> <head> <title>无标题页</title> <script language="javascript" type="text/javascript"> // <!CDATA[ //define var xmlhttp; var value=new Array(

  • java webservice上传下载文件代码分享

    本文实例为大家分享了java webservice上传下载文件代码,供大家参考,具体内容如下 1.新建动态web工程youmeFileServer,新建包com,里面新建类FileProgress package com; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.sql.Date; import java.text.Simple

  • ASP调用WebService转化成JSON数据,附json.min.asp

    首先定义SOAP数据,然后创建HTTP对象,然后使用POST提交,获取状态码为200,就说明调用成功,再进行下一步操作-- 看一下具体实现的代码吧 <!--#Include virtual="/Include/json.min.asp"--> <% Dim strxml Dim str '定义soap消息 strxml = "<?xml version='1.0' encoding='utf-8'?>" strxml = strxml

  • PHP使用SOAP扩展实现WebService的方法

    本文实例讲述了PHP使用SOAP扩展实现WebService的方法.分享给大家供大家参考,具体如下: 最近在一个PHP项目中对接外部接口涉及到WebService,搜索引擎上相关文章不是很多,找到的大都是引用一个号称很强大的开源软件NuSOAP(下载地址:http://sourceforge.net/projects/nusoap/),即一些类.文章写描述的环境是PHP 4.3,现在都流行PHP 5.2或PHP 5.3了.先拿来试试,运行出错,原来NuSOAP提供的soapclient类与PHP

  • ASP.NET调用WebService服务的方法详解

    本文实例讲述了ASP.NET调用WebService服务的方法.分享给大家供大家参考,具体如下: 一.WebService:WebService是以独立于平台的方式,通过标准的Web协议,可以由程序访问的应用程序逻辑单元. (1)应用程序逻辑单元:web服务包括一些应用程序逻辑单元或者代码.这些代码可以完成运算任务,可以完成数据库查询,可以完成计算机程序能够完成的任何工作. (2)可由程序访问:当前大多是web站点都是通过浏览器由人工访问的,web服务可以由计算机程序来访问. (3)标准的we协

  • ASP.NET使用WebService实现天气预报功能

    本文使用Asp.Net (C#)调用互联网上公开的WebServices(http://www.webxml.com.cn/WebServices/WeatherWebService.asmx)来实现天气预报,该天气预报 Web 服务,数据来源于中国气象局http://www.cma.gov.cn/,数据每2.5小时左右自动更新一次,准确可靠.包括 340 多个中国主要城市和 60 多个国外主要城市三日内的天气预报数据. 效果图 : 步骤 : 1 .新建web 项目,添加窗体. 2 . 引用右键

  • jQuery中通过ajax调用webservice传递数组参数的问题实例详解

    下面通过实例给大家说明比较直观些,更方便大家了解. 本人的项目中通过jquery.ajax调用webservice. 客户端代码如下: $.ajax({ url: "test/xxx.asmx", type: 'POST', dataType: 'xml', timeout: , data: { name: "zhangsan", tags: ["aa", "bb", "cc"] }, error: fun

  • ajax跨域调用webservice的实现代码

    最近ajax访问webservice遇到跨域的问题,网上搜索资料,总结如下(很多都是觉得人家总结不错的复制下来) <<用JSON来传数据,靠JSONP来跨域>> 先上我的已实现代码: 前端代码: $.ajax({ type: "get", url: "http://localhost/Service1.asmx/getElevatorStatusJsonData?jsoncallback=?", dataType: "jsonp&q

  • C# WebService发布以及IIS发布

    首先我们要做的就是先把IIS(Internet信息服务)打开,我用的是win8 的系统,所以这里以win8系统的操作来讲 一.IIS的一些事先操作 1.打开控制面板,然后进入程序 2.进入程序以后我们找到 启用或关闭Windows功能 3.进入以后把  Internet信息服务  的都选上,单击"确定" 上述的步骤好了以后我们退回到控制面板  ,找到   系统和安全 里面的  管理工具     点击"管理工具"    ,第一个就是我们的IIS了,双击打开它 我们会弹

  • Web Service 运行原理详细介绍

    利用清明小假期,温习了一遍Web Service的相关内容,对其工作原理进行了简要总结.以供有需求的朋友和自己日后参考.文章若有不当之处,敬请朋友们提出宝贵建议,以求共勉. Web服务中,我们应该首先了解相关的术语含义:WSDL.UDDI....相关术语方面的介绍在此不再赘述,重点放在原理上. 在Web服务中,存在三个角色:服务提供者.服务请求者和服务中介,三者之间的关系如图1-1所示 实现一个完整的Web服务包括以下步骤: ◆ Web服务提供者设计实现Web服务,并将调试正确后的Web服务通过

  • Android组件化原理详细介绍

    目录 什么是组件化? 为什么使用组件化? 一步步搭建组件化 1.新建模块 2.统一Gradle版本号 3.创建基础库 4.组件模式和集成模式转换 5.AndroidManifest的切换 6.*业务Application切换 组件之间的跳转 1.添加依赖 2.初始化ARouter 3.添加跳转 组件之间的数据传递 1.定义接口 2.实现接口 组件Application的动态切换 1.定义抽象类 BaseApplication 继承 Application 2.所有的组件的 Application

  • Linux系统运行级别详细介绍

    目录 1.Linux系统运行级别介绍 2.查看运行级别 3.修改当前系统的运行级别 4.系统默认运行级别 5./etc/rc.d/rc.local文件说明 1.Linux系统运行级别介绍 Linux默认有7个运行级别,Linux 系统任何时候都运行在一个指定的运行级别上.不同的运行级别所运行的程序和服务不尽相同,所要完成的工作和要达到的目的也不相同. 0:关机. 1:单用户模式,可以想象为Windows系统的安全模式,主要用于系统修复. 2:不完全的命令行模式(命令行模式就是命令界面),不含NF

  • Android Service总结及详细介绍

    1.Service的种类 按运行地点分类: 类别 区别  优点 缺点   应用 本地服务(Local) 该服务依附在主进程上,  服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL.相应bindService会方便很多.  主进程被Kill后,服务便会终止.  非常常见的应用如:HTC的音乐播放服务,天天动听音乐播放服务. 远程服务(Remote) 该服务是独立的进程,  服务为独立的进程,对应进程名格式为所在包名

  • Java中GC的工作原理详细介绍

    Java中GC的工作原理 引子:面试时被问到垃圾回收机制,只是粗略的讲'程序员不能直接对内存操作,jvm负责对已经超过作用域的对象回收处理',面官表情呆滞,也就没再继续深入. 转文: 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只有全面提升内存的管理效率,才能提高整个应用程序的性能.本文将从GC的工作原理.GC的几个关键问题进行探讨,最后提出一些Java程序设计建议,如何从GC角度提高Ja

  • JAVA JNI原理详细介绍及简单实例代码

    JAVA JNI原理 JNI是JAVA标准平台中的一个重要功能,它弥补了JAVA的与平台无关这一重大优点的不足,在JAVA实现跨平台的同时,也能与其它语言(如C.C++)的动态库进行交互,给其它语言发挥优势的机会. 有了JAVA标准平台的支持,使JNI模式更加易于实现和使用.在此总结了下面这个知识图: 实例: 环境说明:ubuntu 10.4.2 LTS系统 程序清单1:src/com/magc/jni/HelloWorld.java /** * */ package com.magc.jni;

  • Java 什么是注解及注解原理详细介绍

    Java 注解的原理 java : 注解使用,http://www.jb51.net/article/101747.htm 什么是注解 注解也叫元数据,例如我们常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包.类.接口.字段.方法参数.局部变量等进行注解.它主要的作用有以下四方面: 生成文档,通过代码里标识的元数据生成javadoc文档. 编译检查,通过代码里标识的元数据让编译器在编译期间进行检查验证. 编译时动态处理,编译

  • python 开发的三种运行模式详细介绍

    Python 三种运行模式 Python作为一门脚本语言,使用的范围很广.有的同学用来算法开发,有的用来验证逻辑,还有的作为胶水语言,用它来粘合整个系统的流程.不管怎么说,怎么使用python既取决于你自己的业务场景,也取决于你自己的python应用能力.就我个人而言,我觉得python作为既可以用来进行业务的开发,也可以进行产品原型的开发.一般来说,python的运行主要下面这三种模式. 1.单循环模式 单循环模式使用的最多,也最简单,当然也最稳定.为什么呢,因为单循环本来代码就写的很少,出错

  • Docker 特性与原理详细介绍与解析

    Docker 特性与原理 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上,例如运行一个一次性交互shell 文件系统隔离:每个进程容器运行在完全独立的根文件系统里 写时复制:采用写时复制方式创建根文件系统,这让部署变得极其快捷,并且节省内存和硬盘空间 资源隔离:可以使用cgroup为每个进程容器分配不同的系统资源 网络隔离:每个进程容器运行在自己的网络命名空间里,拥有自己的虚拟接口和IP地址 日志记录:Docker将会收集和记

  • Jdk1.8 HashMap实现原理详细介绍

    HashMap概述 HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变. HashMap的数据结构 在Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外.HashMap实际上是一个"链表散列"的数据结构,即数组和链表的结构,但是在jdk1.8里 加入了红黑树的实现,当链表的

随机推荐