java 课堂笔记——WebService

一:什么是WebService
    WebService(Web服务)是使应用程序可以以与平台和编程语言无关的方式进行相互通信的一项技术。Web 服务是一个软件接口,它描述了一组可以在网络上通过标准化的 XML 消息传递访问的操作。它使用基于 XML 语言的协议来描述要执行的操作或者要与另一个 Web 服务交换的数据。一组以这种方式交互的 Web 服务在面向服务的体系结构(Service-Oriented Architecture,SOA)中定义了特殊的 Web 服务应用程序。
  1:Web 服务体系结构
     Web 服务体系结构描述了一个框架,在这个框架中服务可在分布式计算环境中被动态地描述、发布、发现和调用。这个体系结构定义了四个基本构件(它们的名称在接下去的两段中用粗体字来标明)和三个决定这些构件之间如何交互的标准操作。
     服务这个概念处于 Web 服务模型的核心,它被定义为执行某种任务(如订购图书或翻译信件)的一组操作。在 Web 服务的上下文中,可以使用标准的 XML 技术(如 SOAP、WSDL 和 UDDI)来描述、发现和调用服务。
     服务由服务提供者来实现和发布。服务由服务请求者来发现和调用。有关服务的信息可被保存在服务注册中心。 


     从企业角度看,服务提供者是服务的所有者。从技术角度看,它是提供对服务的访问的平台。同样,服务请求者既是一个需要完成一项具体任务的企业,也是发现和调用服务所需的工具。
     可以从如下角度对上图所示的三种基本操作进行描述:
         a.发布(Publish):由服务提供者来执行以使大家知道服务的存在和功能。
         b.发现(Find):由服务请求者来执行以定位能满足某种需要的服务。
         c.绑定(Bind):由服务请求者来执行以调用由服务提供者提供的服务。
 
二:能干什么
  1:成为各孤立的站点之间的信息能够相互通信、共享的一种接口
  2:由于webservice基于标准的协议和xml,使得大量异构程序和平台之间就能够互相操作,大家都面向webservice,而不用去关心具体的实现是由什么开发语言提供的。
 
三:有什么
  1:基本 Web 服务规范
  Web 服务规范通常归为两类:基本 Web 服务规范和扩展 Web 服务规范。基本规范有:
  (1)SOAP(Simple Object Access Protocol):
       简单对象访问协议是在分散或分布式的环境中交换信息并执行远程过程调用的轻量级协议,是一个基于XML的协议。使用SOAP,不用考虑任何特定的传输
       协议(最常用的还是HTTP协议),可以允许任何类型的对象或代码,在任何平台上,以任何一种语言相互通信。
       SOAP包括四个部分:
          a.SOAP封装(envelop),封装定义了一个描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们的框架;
          b.SOAP编码规则(encoding rules),用于表示应用程序需要使用的数据类型的实例;
          c.SOAP RPC表示(RPC representation),表示远程过程调用和应答的协定;
          d.SOAP绑定(binding),使用底层协议交换信息。
       *应用中比较关注的是envelop,由一个或多个Header和一个Body组成。
  (2)WSDL(Web Services description Language):
       Web服务描述语言是详细说明描述基于 SOAP 的 Web 服务的标准方式的规范,由Ariba、Intel、IBM、MS等共同提出,包括消息应采用的形式以及应将其发送到何处。其中还详细说明了此类消息的响应。当与相应的工具结合使用时,WSDL 允许以编程方式创建对 Web 服务的调用,甚至不用知道所查找的 Web 服务是什么;应用程序可以从 WSDL 文件中提取这些详细信息,并提供要使用的编程接口。
       可描述Web服务的三个基本属性:
          ?服务做些什么——服务所提供的操作(方法)
          ?如何访问服务——和服务交互的数据格式以及必要协议
          ?服务位于何处——协议相关的地址,如URL
       WSDL文档以端口集合的形式来描述Web服务,WSDL 服务描述包含对一组操作和消息的一个抽象定义,绑定到这些操作和消息的一个具体协议,和这个绑定的一个网络端点规范。
       WSDL描述语言一般包含三部分
          (1)服务做些什么部分:包括了type、message和portType元素
       Type:定义了Web Service使用的数据结构(使用XML Schema定义)
       Message:一个Message是SOAP的基本通信元素。每个Message可以有一个或多个Part,每个Part代表一个参数。
       PortType:消息汇总为不同的操作并归入到一个被称为portType的实体中。一个portType代表一个接口(Web Service支持的操作集合),每个Web Service可以有多个接口,它们都使用portType表示。每个操作又包含了input和output部分。
          (2)如何访问服务部分:包含binding元素
       binding元素将portType绑定到特定的通信协议上(如HTTP上的SOAP协议)
          (3)服务位于何处部分:由service元素组成
       它将portType,binding以及Web Service实际的位置(URI)放在一起描述

 <?xml version="1.0" ebcoding="UTF-8"?>
-<wsdl:definitiongs xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd"
  xmlsn:ns="http://ws.javasscn" xmlns:wsaw="http://www.w3org/2006/05/addressing/wsdl"
  xmlsn:http="http://schemas.xmlsoap.org/wsdl/http" xmlsn:xs="http://www.w3org/2001/XMLSchema"
  xmlsn:mime=" http://schemas.xmlsoap.org/wsdl/mime" xmlsn:soap=" http://schemas.xmlsoap.org/wsdl/soap"
  xmlsn:soap12="http://schemas.xmlsoap.org/wsdl/soap12" targetNamespace=http://ws.javass.cn>
  <wsdl:documentation>HelloWorldService</wsdl:documentation>
 +<wsdl:types>
 +<wsdl:message name="helloWorldServiceRequest">
 +<wsdl:message name="helloWorldServiceResponse">
 +<wsdl:portType name="HelloWorldService portType">
 +<wsdl:binding name="HelloWorldServiceSoap11Binding"type="ns: HelloWorldService portType">
 +<wsdl:binding name="HelloWorldServiceSoap12Binding" type="ns: HelloWorldService portType">
 +<wsdl:binding name="HelloWorldServiceHttpBinding" type="ns: HelloWorldService portType">
 +<wsdl:service name="HelloWorldService
 </wsdl:definitiongs>[/

  
          (3)WSDD(Web Service Deployment Descriptor)就是WEB服务分布描述, 它定义了WEB服务的接口,如服务名、提供的方法、方法的参数等信息。
          (4)UDDI(Universal Description, Discovery and Integration):
               统一描述、发现和集成是一项从最初提出后发生了一系列变化的标准。UDDI用于集中存放和查找WSDL描述文件,起着目录服务器的作用。
               其最初的目的是为了给各个公司提供在全球注册中心中注册服务并在此注册中心中搜索可能想使用的服务的机制。不过,由于很多公司对于将其系统对外开放的问题上都相当保守,这个目标并没有完全实现。但是,很多公司已将 UDDI 作为内部的服务及服务信息注册中心使用
  2:扩展 Web 服务规范
     总共有数十种 WS-* 规范,其中几种对企业尤为有用。即:
        WS-Security:此规范处理加密和数字签名,允许创建特定类型的应用程序,以防止窃*听消息,且能实现不可否认功能。
        WS-Policy:此规范对 WS-Security 进行了扩展,允许更具体地说明谁可以采用何种方式使用服务。
        WS-I:尽管 Web 服务应设计成具有互操作性,但在实际中,各个规范对不同实现的解释的灵活性常常足以导致出现问题。WS-I 提供了一组可用于防止出现各种问题的标准和实践,并提供了标准化测试来检查问题。
        WS-BPEL:单个服务很好处理,但应用程序在大多数情况下则较难处理。企业级计算要求至少将多个服务组合为一个完整的系统,而 WS-BPEL 提供了用于指定创建此类系统所必需的交互(如分支和并发处理)。

四:怎么做
  (一)目前常见的实现方式:
        开源最流行的是Apache的Axis(Apache Extensible Interaction System),可以跟所有的主流服务器结合。
        SUN,早期时JAX-RPC,现在是JAX-WS
        IBM采用的是自行开发的WSDK(IBM WebSphere SDK for Web Services)
        我们采用:tomcat+axis2
  (二):HelloWorld一
       1:构建运行环境
         (1)把axis2-1.4.1-war.zip中的axis2.war包放到tomcat的webapps中,然后启动tomcat,会发布axis2,如果启动没有错误,就可以下一步
         (2)验证:在地址栏输入http://localhost:8080/axis2 ,如果能正常显示,说明axis2的运行环境已经OK了。可以点击Administration,然后输入用户名admin和密码axis2进入管理台。
       2:构建开发环境
          把axis2-1.4.1-bin.zip中lib里面的都引入到当前的开发环境中就好了
       3:写自己的第一个服务的类

package cn.javass.ws.helloworld.server;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
public class MyService {
   /**
    * 读取client端传递来的参数,然后执行自己的功能,并返回值给客户端 
    */
   public OMElement helloWorldService(OMElement in) {
      //1:接收参数,将in转换为String
      String requestMessage = in.getText();

      //2:这里添加服务端的具体处理
     
      //3:准备返回
      //3.1 创建响应用的SOAP包。
      OMFactory f = OMAbstractFactory.getOMFactory();
      //3.2 OMNamespace指定此SOAP文档名称空间,可以随便写
      OMNamespace omNs = f.createOMNamespace("http://www.javass.cn/", "cc");
      //3.3 创建返回元素,并指定其在omNs指代的名称空间中。
      OMElement retElement = f.createOMElement("myRet", omNs);
      //3.4 指定返回元素的文本内容
      String retMessage = requestMessage + ",这是第一个WebService,已经处理!";
      retElement.setText(retMessage);
    
      return retElement;
   }
}

 

       4:在src目录下面建立一个META-INF的文件夹,在里面放Services.xml文件

<service name="HelloWorldService">
  <parameter name="ServiceClass" locked="xsd:false">
    cn.javass.ws.helloworld.server.MyService
  </parameter>
  <operation name="helloWorldService">
    <messageReceiver
      class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver" />
  </operation>
</service>

 

       5:运行cmd,到classes的目录,然后打包,输入:jar cvf hello.aar . ,注意后面的”.”不能少,表示输出到当前位置,然后打出一个hello.aar的包来。
       6:然后可以直接把这个文件拷贝到tomcat的webapps\axis2\WEB-INF\services文件夹下面,就会自动发布了。当然也可以进到axis2的控制台,然后使用upload service的方式也行。如果发布没有错误,那么服务就做好了。
       7:开始写客户端

package cn.javass.ws.helloworld;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.clustering.MessageSender;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;

public class Client {

  public static void main(String[] args) {
    try {
      //1:targetEPR指定打包的Service(hello.aar文件)在容器中的物理位置
      EndpointReference targetEPR = new EndpointReference(
          "http://localhost:9000/axis2/services/HelloWorldService");
      
      //2:准备客户端调用
      ServiceClient sender = new ServiceClient();
      //2.1 准备options,设置要访问的web服务在什么地方
      Options options = new Options();
      options.setTo(targetEPR);
      sender.setOptions(options);
      
      //2.2 创建request的SOAP包
      OMFactory f = OMAbstractFactory.getOMFactory();
      //2.3 OMNamespace指定此SOAP文档名称空间,要跟服务那边的对应上
      OMNamespace omNs = f.createOMNamespace("http://www.javass.cn/","cc");
      //2.4 创建元素reqElement,并指定其在omNs指代的名称空间中,第一个参数就是要访问的operation
      OMElement reqElement = f.createOMElement("helloWorldService", omNs);
      //2.5 指定元素的文本内容。
      reqElement.setText("测试第一个WebService");

      //3:发出request SOAP,同时将得到的远端由helloWorldService方法返回的信息保存到result
      OMElement result = sender.sendReceive(reqElement);

      System.out.println(result);
    } catch (Exception axisFault) {
      axisFault.printStackTrace();
    }
  }
}

 

       8:运行结果如下:
          客户端:
          <cc:myRet xmlns:cc="http://www.javass.cn/">测试第一个WebService,这是第一个WebService,已经处理!</cc:myRet>
  (三):HelloWorld二(Pojo)
       1:把axis2-1.4.1-bin包解开,然后把下面直到bin的路径设置到path中去,还要设置AXIS2_HOME的值
       2:到axis2-1.4.1-bin包的samples文件夹中,找到quickstart,建立一个工程来测试和运行它,类文件如下:

package samples.quickstart.service.pojo;
import java.util.HashMap;
public class StockQuoteService {
    private HashMap map = new HashMap();
    public double getPrice(String symbol) {
        Double price = (Double) map.get(symbol);
        if(price != null){
            return price.doubleValue();
        }
        return 42.00;
    }
    public void update(String symbol, double price) {
        map.put(symbol, new Double(price));
    }
}

 
       3:运行cmd,把路径设置到classes下面,然后运行:java2wsdl -cp . -cn samples.quickstart.service.pojo.StockQuoteService -of META-INF/StockQuoteService.wsdl,就会生成相应的wsdl文件
       4:在META-INF中建立services文件,内容如下:

<service name="StockQuoteService" scope="application">
    <description>
        Stock Quote Sample Service
    </description>
    <messageReceivers>
        <messageReceiver 
            mep="http://www.w3.org/2004/08/wsdl/in-only"
    class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
        <messageReceiver
            mep="http://www.w3.org/2004/08/wsdl/in-out"
    class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
    </messageReceivers>
    <parameter name="ServiceClass">
        samples.quickstart.service.pojo.StockQuoteService
    </parameter>
</service>

 
       5:运行cmd,把路径设置到classes下面,然后运行:jar -cvf ht.aar.,注意后面有个”.”,然后打好包,文件名称叫ht.aar
       6:把ht.aar拷贝到tomcat的webapps\axis2\WEB-INF\services
       7:启动tomcat,然后运行http://localhost:8080/axis2/services/listServices就可以查看所有发布的服务了
       8:可以通过http://localhost:8080/axis2/services/StockQuoteService?wsdl来查看wsdl的文件,对应的schema在http://localhost:8080/axis2/services/StockQuoteService?xsd

 <?xml version="1.0" ebcoding="UTF-8"?>
-<wsdl:definitiongs xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd"
  xmlsn:ns="http://pojo.javasscn" xmlns:wsaw="http://www.w3org/2006/05/addressing/wsdl"
  xmlsn:http="http://schemas.xmlsoap.org/wsdl/http" xmlsn:xs="http://www.w3org/2001/XMLSchema"
  xmlsn:mime=" http://schemas.xmlsoap.org/wsdl/mime" xmlsn:soap=" http://schemas.xmlsoap.org/wsdl/soap"
  xmlsn:soap12="http://schemas.xmlsoap.org/wsdl/soap12" targetNamespace=http://pojo.javass.cn>
  <wsdl:documentation>MyPojoService</wsdl:documentation>
 +<wsdl:types>
 +<wsdl:message name="testRequest">
 +<wsdl:message name="testResponse">
 +<wsdl:portType name="MyPojoService portType">
 +<wsdl:binding name="MyPojoServiceSoap11Binding"type="ns: MyPojoService portType">
 +<wsdl:binding name="MyPojoServiceSoap12Binding" type="ns:MyPojoService portType">
 +<wsdl:binding name="MyPojoServiceHttpBinding" type="ns:MyPojoService portType">
 +<wsdl:service name="MyPojoService
 </wsdl:definitiongs>

 

       9:可以在IE里面进行测试,测试步骤如下:
         (1)运行下述语句进行查看
http://localhost:8080/axis2/services/StockQuoteService/getPrice?symbol=javasscn会得到如下结果:
<ns:getPriceResponse xmlns:ns="http://pojo.service.quickstart.samples">
  <ns:return>42.0</ns:return>
</ns:getPriceResponse>
         (2)然后运行下述语句进行修改
http://localhost:8080/axis2/services/StockQuoteService/update?symbol=javasscn&price=100
         (3)再次运行(1),你会发现结果变成了:

<ns:getPriceResponse xmlns:ns="http://pojo.service.quickstart.samples">
  <ns:return>100.0</ns:return> 
</ns:getPriceResponse>

 
(四):HelloWorld二改进版(AXIOM)
       1:类文件修改成为

package samples.quickstart.service.axiom;

import javax.xml.stream.XMLStreamException;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;

import java.util.HashMap;

public class StockQuoteService {
  private HashMap map = new HashMap();
  
  public OMElement getPrice(OMElement element) throws XMLStreamException {
    //构建节点本身
    element.build();
    //从父节点删除本节点
    element.detach();

    //获取节点的第一个子节点
    OMElement symbolElement = element.getFirstElement();
    //获取这个子节点的文本值
    String symbol = symbolElement.getText();

    //准备返回的值
    String returnText = "42";
    Double price = (Double) map.get(symbol);
    if (price != null) {
      returnText = "" + price.doubleValue();
    }

    //组装需要返回的xml,值也包含在这个xml当中
    //<getPriceResponse>
    //   <price>
    //       returnText
    //   </price>
    //</getPriceResponse>
    OMFactory fac = OMAbstractFactory.getOMFactory();
    OMNamespace omNs = fac.createOMNamespace(
        "http://axiom.service.quickstart.samples/xsd", "tns");
    OMElement method = fac.createOMElement("getPriceResponse", omNs);
    OMElement value = fac.createOMElement("price", omNs);
    value.addChild(fac.createOMText(value, returnText));
    method.addChild(value);

    return method;
  }

  public void update(OMElement element) throws XMLStreamException {
    //构建节点本身
    element.build();
    //从父节点删除本节点
    element.detach();

    //获取节点的第一个子节点——symbol
    OMElement symbolElement = element.getFirstElement();
    //获取这个子节点的文本值
    String symbol = symbolElement.getText();
    //获取节点的第二个字节点——price
    OMElement priceElement = (OMElement) symbolElement.getNextOMSibling();
    //获取price的值
    String price = priceElement.getText();

    //把值放置到缓存中
    map.put(symbol, new Double(price));
  }
}

 

       2:service.xml如下:

<service name="StockQuoteService" scope="application">
    <description>
        Stock Quote Service
    </description>
    <operation name="getPrice">
        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </operation>
    <operation name="update">
        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/>
    </operation>
    <parameter name="ServiceClass">samples.quickstart.service.axiom.StockQuoteService</parameter>
</service>

 

       3:重新打包,然后拷贝到webapps\axis2\WEB-INF\services下面,覆盖ht.aar
       4:客户端:

package samples.quickstart.service.axiom;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.clustering.MessageSender;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;

public class Client {
  //指定打包的Service在容器中的物理位置
  private static EndpointReference targetEPR = 
        new EndpointReference("http://localhost:8080/axis2/services/StockQuoteService");
  /**
   * 准备访问getPrice方法时需要传递的xml节点
   * <getPrice>
   *   <symbol>
   *     value
   *  </symbol>
   * </getPrice>
   * @param symbol
   * @return
   */
    public static OMElement getPricePayload(String symbol) {
        OMFactory fac = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");

        OMElement method = fac.createOMElement("getPrice", omNs);
        OMElement value = fac.createOMElement("symbol", omNs);
        value.addChild(fac.createOMText(value, symbol));
        method.addChild(value);
        return method;
    }
    /**
   * 准备访问update方法时需要传递的xml节点
   * <update>
   *   <symbol>
   *     value
   *  </symbol>
   *  <price>
   *    price value
   *  </price>
   * </update>
   * @param symbol
   * @return
   */
    public static OMElement updatePayload(String symbol, double price) {
        OMFactory fac = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");

        OMElement method = fac.createOMElement("update", omNs);

        OMElement value1 = fac.createOMElement("symbol", omNs);
        value1.addChild(fac.createOMText(value1, symbol));
        method.addChild(value1);

        OMElement value2 = fac.createOMElement("price", omNs);
        value2.addChild(fac.createOMText(value2, Double.toString(price)));
        method.addChild(value2);
        return method;
    }
    public static void main(String[] args) {
        try {
          //获或得先从服务上查找WSO的值的节点
            OMElement getPricePayload = getPricePayload("WSO");
            //获得修改WSO的值的节点
            OMElement updatePayload = updatePayload("WSO", 123.42);
            
            //准备options,设置要访问的web服务在什么地方
            Options options = new Options();
            options.setTo(targetEPR);
            options.setTransportInProtocol(Constants.TRANSPORT_HTTP);

            ServiceClient sender = new ServiceClient();
            sender.setOptions(options);
            
            //直接调用In-Only的服务
            sender.fireAndForget(updatePayload);
            
            System.err.println("price updated");
            //直接调用In-Out的服务
            OMElement result = sender.sendReceive(getPricePayload);
            //获取到的返回值也是xml
            String response = result.getFirstElement().getText();
            System.err.println("Current price of WSO: " + response);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值