本文主要详细介绍了关于Web服务运行原理的相关信息,有需要的朋友可以参考一下。
在清明假期,我复习了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服务的架构
注意:WSDL的功能是一个Web服务规范。服务请求者根据这个WSDL生成相应的SOAP消息,服务提供者收到SOAP请求消息后绑定服务。
以下是web.xml中的servlet配置
!-设置初始化参数或定制servlet或JSP页面的URL时,必须首先命名servlet或JSP页面。Servlet元素用于完成这项任务。-
小型应用程序
servlet-name userservice/servlet-name
servlet-class com . sun . XML . ws . transport . http . servlet . ws servlet/servlet-class
!-标记容器是否在启动时加载这个servlet(实例化并调用其init()方法;的正值越小,这个servlet的优先级越高,应用程序在启动时加载得越早-
启动时加载1/启动时加载
/servlet
!-服务器通常为servlet提供一个默认的URL:http://host/web app Prefix/servlet/servlet name。
但是,这个URL经常被更改,以便servlet可以更容易地访问初始化参数或处理相对URL。更改默认URL时使用servlet-mapping元素。-
servlet映射
servlet-name userservice/servlet-name
!-描述相对于Web应用程序根目录的URL。url-pattern元素的值必须以斜杠(/)开头。-
url模式/用户/url模式
/servlet-映射
红队部分很重要,启动Web容器时会加载相应的servlet。绿色部分是该服务的外部接口。找到相应的jax-ws.xml文件(如下所示)
端点名称=UserPort 实现=cn.ujn.service.UserService
url-pattern=/user
/端点
然后绑定到相关的对应实现类cn.ujn.service.UserService.客户端发送的SOAP请求消息的主体包含客户端请求的方法名称和参数信息。
下面是为客户端封装的soap消息体(以Json模式与服务器进行数据传输)(SOAP请求信封):
soap env:Envelope xmlns:soap env= http://schemas . XML soap . org/soap/Envelope/ xmlns:Q0= http://ujn . cn/ xmlns:xsd= http://www . w3 . org/2001/XML schema xmlns:xsi= http://www . w3 . org/2001/XML schema-instance
- soapenv:Body
- q0:登录
arg0{username:shq , password:shq}/arg0
/q0:登录
/soapenv:Body
/soapenv:Envelope
下面调用SOAP1.1协议的Web服务
/**
*通过SOAP1.1协议调用Web服务
*
* text/xml这是基于soap1.1协议的。
*
* @param wsdl WSDL路径
* @param方法方法名
* @param命名空间命名空间
* @param headerParameters标头参数
* @ param参数体参数
* @param isBodyParametersNS体参数是否有命名空间
* @返回字符串
* @抛出异常
*/
公共静态字符串invokeBySoap11(字符串wsdl,字符串方法,
字符串命名空间,映射字符串,字符串头参数,
MapString,String bodyParameters,boolean isBodyParametersNS)
引发异常{
StringBuffer soapOfResult=null
//去除?wsdl,获取方法列表
int length=wsdl.length().
wsdl=wsdl.substring(0,长度-5);
//以字符串为参数创建统一资源定位器实例
URL url=新URL(wsdl);
//创建连接
http URL connection conn=(http URL connection)URL。打开连接();
//设置请求方式
conn . setrequestmethod( POST );
//如果打算使用统一资源定位器连接进行输入,则将输入输出标志设置为真实的
conn . setdoinput(true);
//如果打算使用统一资源定位器连接进行输出,则将输入输出标志设置为真实的
conn . setdoooutput(true);
//主要是设置HttpURLConnection请求头里面的属性(K-V)
conn . setrequestproperty( Content-Type , text/XML;charset=utf-8 );
//获取输入流(相对于客户端来说,使用的是输出流)
输出流out=conn . get输出流();
//获取soap1.1版本消息
StringBuilder sb=new StringBuilder();
某人(somebody的简写)append( soap:Envelope xmlns:xsi= http://www。w3。 org/2001/XML架构-实例
xmlns:xsd= http://。w3。org/2001/XML schema xmlns:soap= http://架构。XML soap。org/soap/envelope/ );
sb.append(xmlns:ns0=)命名空间 );
某人追加();
//拼装消息头
if (headerParameters!=null) {
某人(somebody的简写)append( soap:Header );
for (EntryString,字符串头参数:头参数。entrySet()) {
某人(somebody的简写)追加( ns0:);
某人(somebody的简写)append(头参数。getkey());
某人追加();
某人(somebody的简写)append(头参数。getvalue());
某人(somebody的简写)追加(/ns0:);
某人(somebody的简写)append(头参数。getkey());
某人追加();
}
某人(somebody的简写)追加(/soap:Header );
}
//拼装消息体
某人(somebody的简写)append( soap:body ns0:);
某人追加(方法);
某人追加();
//输入参数
if (bodyParameters!=null) {
for (EntryString,字符串输入参数:车身参数。entrySet()) {
if (isBodyParametersNS) {
某人(somebody的简写)追加( ns0:);
某人(somebody的简写)追加(输入参数。getkey());
某人追加();
某人(somebody的简写)追加(输入参数。getvalue());
某人(somebody的简写)追加(/ns0:);
某人(somebody的简写)追加(输入参数。getkey());
某人追加();
}否则{
某人追加();
某人(somebody的简写)追加(输入参数。getkey());
某人追加();
某人(somebody的简写)追加(输入参数。getvalue());
某人(somebody的简写)追加(/);
某人(somebody的简写)追加(输入参数。getkey());
某人追加();
}
}
}
某人(somebody的简写)追加(/ns0:);
某人追加(方法);
某人(somebody的简写)append(/soap:Body/soap:Envelope );
//测试用
系统。出去。印刷(某人)。tostring());
//写入肥皂消息(相对于客户端来说,使用的是out.write())
输出.写入(某人的字符串)。getBytes());
//获取服务器端的相应
int code=conn . getresponsecode();
如果(代码==200) {
InputStream is=conn . getinputstream();
字节[] b=新字节[1024];
int len=0;
soapOfResult=新字符串缓冲区();
//从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。以整数形式返回实际读取的字节数
//如果因为流位于文件末尾而没有可用的字节,则返回值-1;
while ((len=is.read(b))!=-1) {
//使用命名字符集将字节数组转换为字符串。
字符串s=新字符串(b,0,len, UTF-8 );
肥皂的结果。追加;
}
}
conn . disconnect();
返回soapOfResult==null?null:soapofresult。tostring();
}
注:在客户端发送肥皂请求消息后便处于阻塞状态。直至服务端返回状态码。
以下为服务端进行响应(肥皂响应信封):
S:Envelope xmlns:S= http://模式。XML soap。org/soap/Envelope/
-S:身体
-NS2:登录响应xmlns:NS2= http://ujn。cn/
返回1/返回
/ns2:登录响应
/S:正文
/S:信封
客户端接收到服务端发来的Json数据后会进行相应的解析操作。如下:
//将肥皂协议进行解析(DOM解析只能用于解析可扩展标记语言文档类型,而肥皂消息就是采用可扩展标记语言数据格式)
文档doc=XML util。字符串2g文档(结果);
Element ele=(Element)doc。getelementsbytagname( return ).项目(0);
方法中使用到的string2Doc()方法体如下:
公共静态文档string2Doc(字符串str) {
//将可扩展标记语言文档解析成数字正射影像图树
DocumentBuilderFactory factory=DocumentBuilderFactory。新实例();
文档文档=空
文档生成器生成;
if(str==null | | str。等于(){
返回空
}
尝试{
InputStream Bais=new bytearray InputStream(str。getbytes( UTF-8 );
构建=工厂。newdocumentbuilder();
//将给定输入流的内容解析为可扩展标记语言文档,并返回新的DOM文档对象。
文档=构建。parse(Bais);
} catch(异常e) {
e。printstacktrace();
}
返回文档;
}
根据返回结果,客户端再进行相应的处理。
以上是网服务的基本工作原理。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!