Web Service进阶(一)运行原理[通俗易懂]

Web Service进阶(一)运行原理[通俗易懂]利用清明小假期,温习了一遍WebService的相关内容,对其工作原理进行了简要总结。以供有需求的朋友和自己日后参考。文章若有不当之处,敬请朋友们提出宝贵建议,以求共勉。Web服务中,我们应该首先了解相关的术语含义:WSDL、UDDI….相关术语方面的介绍在此不再赘述,重点放在原理上。在Web服务中,存在三个角色:服务提供者、服务请求者和服务中介,三者之间的关系如图1…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

      利用清明小假期,温习了一遍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服务请求者。(绑定)

   Web Service进阶(一)运行原理[通俗易懂]

图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服务的基本工作原理。在此感谢实验室徐师兄的技术支持。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/164080.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Java.Utils:网络工具包[通俗易懂]

    Java.Utils:网络工具包[通俗易懂]packagecom.boob.common.utils;importorg.springframework.util.MultiValueMap;importorg.springframework.web.util.UriComponentsBuilder;importjavax.net.ssl.HttpsURLConnection;importjavax.servlet….

  • VS2015序列号_autocad2008激活序列号

    VS2015序列号_autocad2008激活序列号
    VisualStudioTeamSystem2008TeamSuite(vs2008)正式中文版   
    VS2008简体中文正式版序列号大全
      
    1.VisualStudio2008ProfessionalEdition:
    XMQ2Y-4T3V6-XJ48Y-D3K2V-6C4WT
      
    2.VisualStudio2008TeamTestLoadAgent:
    WPX3J-BXC3W-BPYW

  • mysql自定义函数详解_sql自定义函数例子

    mysql自定义函数详解_sql自定义函数例子摘要腾兴网为您分享:mysql自定义函数与动态查询,智学网,夜读小说,小睡眠,西餐菜谱等软件知识,以及猫语翻译器,江西校讯通,刷qq业务的网站,房洽洽,学士服照,爱站seo工具包,虚拟声卡驱动,隐藏分,卦象,供零在线永辉,七猫精品小说,海纳百川器,华尔街日报,双十一图片,中国地震信息网等软件it资讯,欢迎关注腾兴网。介绍下mysql自定义函数的例子,以及插入单引号的方法,动态执行查询与字符串拼接…

  • [Python从零到壹] 十七.可视化分析之Matplotlib、Pandas、Echarts入门万字详解[通俗易懂]

    [Python从零到壹] 十七.可视化分析之Matplotlib、Pandas、Echarts入门万字详解[通俗易懂]前一篇文章讲述了数据预处理、Jieba分词和文本聚类知识,这篇文章主要介绍Matplotlib和Pandas扩展包绘图的基础用法,同时引入Echarts技术,该技术主要应用于网站可视化展示中。本文内容以实例为主,给读者最直观的图形感受。两万字基础文章,希望对您有所帮助。

  • scratch编程小游戏咬指大冒险

    scratch编程小游戏咬指大冒险咬指大冒险是一款非常好玩的玩具,玩法就是玩家不断按下小动物的牙齿,牙齿中只有一个是危险的,按下后小动物的嘴巴会闭上咬住手指,其余的牙齿都是安全的。今天我们就来用scratch来做一个电子版的咬指大冒险!这里我们选用一个鳄鱼的造型,首先画出鳄鱼的两个造型,一个张嘴和一个闭嘴,张嘴的造型不需要画下牙齿:要画大一点哦!程序:下面是牙齿的造型,一个有三个:牙齿的排列方式是一段弧,可以先排列好后再调整鳄鱼的嘴巴:最后是被咬时血液的程序:注意,这里的自定义模块需要勾选运行时屏幕不刷新,如果不

  • 用js来实现那些数据结构02(数组篇02-数组方法)

    上一篇文章简单的介绍了一下js的类型,以及数组的增删方法。这一篇文章,我们一起来看看数组还有哪些用法,以及在实际工作中我们可以用这些方法来做些什么。由于其中有部分内容并不常用,所以我尽量缩小篇幅。在这

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号