Web Service 运行原理详细介绍

网友投稿 195 2023-07-01


Web Service 运行原理详细介绍

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

Web服务中,我们应该首先了解相关的术语含义:WSDL、UDDI....相关术语方面的介绍在此不再赘述,重点放在原理上。

在Web服务中,存在三个角色:服务提供者、服务请求者和服务中介,三者之间的关系如图1-1所示

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

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

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

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

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

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

图1-1 Web service的体系结构

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

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

UserService

com.sun.xmllhjrZ.ws.transport.http.servlet.WSServlet

1

UserService

/user

红色代码部分很重要,会在Web容器启动的时候加载相应的servlet。绿色部分为该服务的外部接口。以此找到相应的jax-ws.xml文件(如下所示)

url-pattern="/user">

url-pattern="/user">

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

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

-

-

{"username":"shq","password":"shq"}

以下为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 headerParameters,

Map 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("

xmlns:xsd=\"http://w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" ");

sb.append("xmlns:ns0=\"" + namespace + "\"");

sb.append(">");

//拼装消息头

if (headerParameters != null) {

sb.append("");

for (Entry headerParameter : headerParameters

.entrySet()) {

sb.append("

sb.append(headerParameter.getKey());

sb.append(">");

sb.append(headerParameter.getValue());

sb.append("

sb.append(headerParameter.getKey());

sb.append(">");

}

sb.append("");

}

//拼装消息体

sb.append("

sb.append(method);

sb.append(">");

// 输入参数

if (bodyParameters != null) {

for (Entry inputParameter : bodyParameters

.entrySet()) {

if (isBodyParametersNS) {

sb.append("

sb.append(inputParameter.getKey());

sb.append(">");

sb.append(inputParameter.getValue());

sb.append("

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("

sb.append(method);

sb.append(">

");

xmlns:xsd=\"http://w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" ");

sb.append("xmlns:ns0=\"" + namespace + "\"");

sb.append(">");

//拼装消息头

if (headerParameters != null) {

sb.append("");

for (Entry headerParameter : headerParameters

.entrySet()) {

sb.append("

sb.append(headerParameter.getKey());

sb.append(">");

sb.append(headerParameter.getValue());

sb.append("

sb.append(headerParameter.getKey());

sb.append(">");

sb.append(headerParameter.getValue());

sb.append("

sb.append(headerParameter.getKey());

sb.append(">");

}

sb.append("");

}

//拼装消息体

sb.append("

sb.append(method);

sb.append(">");

// 输入参数

if (bodyParameters != null) {

for (Entry inputParameter : bodyParameters

.entrySet()) {

if (isBodyParametersNS) {

sb.append("

sb.append(inputParameter.getKey());

sb.append(">");

sb.append(inputParameter.getValue());

sb.append("

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("

sb.append(method);

sb.append(">

sb.append(method);

sb.append(">");

// 输入参数

if (bodyParameters != null) {

for (Entry inputParameter : bodyParameters

.entrySet()) {

if (isBodyParametersNS) {

sb.append("

sb.append(inputParameter.getKey());

sb.append(">");

sb.append(inputParameter.getValue());

sb.append("

sb.append(inputParameter.getKey());

sb.append(">");

sb.append(inputParameter.getValue());

sb.append("

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("

sb.append(method);

sb.append(">

//测试用

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):

-

-

1

客户端接收到服务端发来的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);

} catchttp://h (Exception e) {

e.printStackTrace();

}

return document;

}

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

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

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:一道Java集合框架题 多种解题思路
下一篇:微信小程序 使用picker封装省市区三级联动实例代码
相关文章

 发表评论

暂时没有评论,来抢沙发吧~