Web Service ~ 从入门到入坑。

Web Service ~ 从入门到入坑。



What。

Web Service 是一个平台独立的,低耦合的,自包含的、基于可编程的 web 的应用程序,可使用开放的 XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序。
Web Service 技术,能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件,就可相互交换数据或集成。依据 Web Service 规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。Web Service 是自描述、自包含的可用网络模块,可以执行具体的业务功能。Web Service 也很容易部署,因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集 XML、HTTP。Web Service 减少了应用接口的花费。Web Service 为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。
~ 百度百科。



应用场景。

  • 不同系统、不同平台、不同语言之间的通信访问和调用。

  • 应用程序的集成,不同业务的整合。

  • 解决企业内部异构系统的整合问题。

异构系统(A, B, C, D, E),信息的孤岛。

方案一:全部重构一遍,一般不采用。

方案二。

A-interface(Java)
B-interface(.NET)
推出一种统一的方法,webservice, 标准,xml,SOAP。

  • 解决一些公共资源复用问题。

淘宝查物流信息。
qq 查看天气。
火车票、机票。

  • 传统的 WebService。

SOAP 协议,XML。

  • 现在推荐的 WebService。

http,Json。



定义。

Web Service 是一种服务导向架构的技术,通过标准的 Web 协议提供服务,目的是保证不同平台的应用服务可以互操作。

表面上看 Web Service 就是一个应用程序,ta 向外界暴露出一个能够通过 Web 进行调用的方法 API,能用编程的方法通过 Web 调用来实现某个功能的应用程序。

深层次上看 Web Service 是一种新的 Web 应用程序分支,它们是自包含、自描述模块化的应用,可以在网络中被描述、发布、查找以及通过 Web 来调用。

  • Java 中共有三种 WebService 规范,分别是 JAX-WS(JAX-RPC)(SOAP 协议,xml 传输数据)、JAXM&SAAJ、JAX-RS(HTTP 协议,RESTful 风格)。


三种规范。
JAX-WS。

JAX-WS(Java API For XML-WebService),JDK1.6 自带的版本位 JAX-WS2.1,其底层支持位 JAXB。JAX-WS(JSR 224)规范的 API 位于 javax.xml.ws.* 包,其中大部分都是注解,提供 API 操作 Web 服务(通常在客户端使用的较多, 由于客户端可以借助 SDK 生成,因此这个包中的 API 我们较少会直接使用)。



JAXM & SAAJ。

JAXM(Java API For XML Message)主要定义了包含了发送和接收消息所需的 API,相当于 Web 服务的服务器端,其 API 位于 javax.messaging.* 包,ta 是 JavaEE 的可选包, 因此,需要单独下载。

SAAJ(SOAP With Attachment API For Java, SR67)是与 JAXM 搭配使用的 API,为构建 SOAP 包和解析 SOAP 包提供了重要的支持,支持附件传输,ta 在服务器端、客户端都需要使用。这里还要提到的是 SAAJ 规范,其 API 位于 javax.xml.soap.* 包。

JAXM & SAAJ 与 JAX-WS 都是基于 SOAP 的 Web 服务,相比之下 JAXM & SAAJ 暴漏了 SOAP 更多的底层细节,编码比较麻烦,而 JAX-WS 更加抽象,隐藏了更多的细节,更加面向对象,实现起来你基本上不需要关心 SOAP 的任何细节。那么如果你想控制 SOAP 消息的更多细节,可以使用 JAXM&SAAJ,目前版本为 1.3。



JAX-RS。

JAX-RS 是 Java 针对 REST(RepresentationState Transfer)风格制定的一套 Web 服务。由于推出的较晚,该规范(SR311,目前 JAX-RS 的版本为 1.0),并未随 JDK1.6 一起发行,你需要到 JCP 上单独下载 JAX-RS 规范的接口,其 API 位于 javax.ws.rs.* 包。

这里的 JAX-WS 和 JAX-RS 规范我们采用 Apache CXF 作为实现,CXF 是 Objectweb Celtix 和 Codehaus XFire 合并而成。CXF 的核心是 org.apache.cxf.Bus(总线),类似于 Spring 的 ApplicationContext,Bus 由 BusFactory 创建,默认是 SpringBusFactory 类,可见默认 CXF 是依赖于Spring 的,Bus 都有一个 ID,默认的 BUS 的 ID 是 cxf。你要注意的是 Apache CXF 2.2 的发行包中的 jar 你如果直接全部放到 lib 目录,那么你必须使用 JDK1.6,否则会报 JAX-WS 版本不一致的问题。对于 JAXM&SAAJ 规范我们采用 JDK 中自带的默认实现。



Web Service 三要素。

SOAP(Simple Object Access Protocol)、
WSDL(Web Services Description Language)、
UDDI(Universal Description Discovery and Integration)。

三者构成了 Web Service 的三要素。

SOAP ~ Simple Object Access Protocol。

Web Service 通过 HTTP 协议发送请求和接收结果时,发送的请求内容和结果内容都采用 XML 格式封装,并增加了一些特定的 HTTP 消息头,以说明 HTTP 消息的内容格式,这些特定的 HTTP 消息头和 XML 内容格式就是 SOAP 协议。SOAP 提供了标准的 RPC(远程调用技术)方法来调用 web service。

  • SOAP 协议组成。
    SOAP 协议 = HTTP 协议 + XML 数据格式。
    SOAP 协议定义了 SOAP 消息的格式,SOAP 协议是基于 HTTP 协议的,XML 是 SOAP 的数据编码方式。
  • SOAP 即简单对象访问协议(Simple Object Access Protocol),ta 是用于交换 XML(标准通用标记语言下的一个子集)编码信息的轻量级协议。ta 有三个主要方面:
    XML-envelope 为描述信息内容和如何处理内容定义了框架,将程序对象编码成为 XML 对象的规则,执行远程过程调用(RPC)的约定。SOAP 可以运行在任何其他传输协议上。

  • SOAP 作为一个基于 XML 语言的协议用于有网上传输数据。

  • SOAP = 在 HTTP 的基础上 + XML 数据。

  • SOAP 是基于 HTTP 的。

  • SOAP 的组成如下。

  • Envelope - 必须的部分。以 XML 的根元素出现。
  • Headers - 可选的。
  • Body - 必须的。在 body 部分,包含要执行的服务器的方法和发送到服务器的数据。


WSDL ~ 说明书。

好比我们去商店买东西,首先要知道商店里有什么东西可买,然后再来购买,商家的做法就是张贴广告海报。Web Service 也一样,Web Service 客户端要调用一个 Web Service 服务,首先要知道这个服务的地址在哪里,以及这个服务里有什么方法可以调用。所以,Web Service 服务端首先要通过一个 WSDL 文件来说明自己家里有啥服务可以对外调用,服务是什么(服务中有哪些方法,方法接收的参数是什么,返回值是什么),服务的网络地址用哪个 url 地址表示,服务通过什么方式来调用。

WSDL(Web Services Description Language)就是这样一个基于 XML 的语言,用于描述 Web Service 及其函数、参数和返回值。ta 是 Web Service 客户端和服务端都能理解的标准格式。因为是基于 XML 的,所以 WSDL 既是及其可阅读的,又是人可阅读的,这将是一个很大的好处。一些最新的开发工具既能根据你的 Web Service 生成 WSDL 文档,又能导入 WSDL 文档,生成调用相应的 Web Service 代理类代码。

WSDL(Web 服务描述语言,Web Services Description Language)是为描述 Web 服务发布的 XML 格式。W3C 组织(World Wide Web Consortium)没有批准 1.1 版的 WSDL,当前的 WSDL 版本是 2.0,是 W3C 的推荐标准(recommendation)(一种官方标准),并将被 W3C 组织批准为正式标准。
在诸多技术文献中通常将 Web 服务描述语言简写为 WSDL,读音通常发为:“wiz-dəl”。

WSDL 描述 Web 服务的公共接口。这是一个基于 XML 的关于如何与 Web 服务通讯和使用的服务描述;也就是描述与目录中列出的 Web 服务进行交互时需要绑定的协议和信息格式。通常采用抽象语言描述该服务支持的操作和信息,使用的时候再将实际的网络协议和信息格式绑定给该服务。

Web Service 描述语言 WSDL(Web Service Definition Language)就是用机器能阅读的方式提供的一个正式描述文档而基于 XML(标准通用标记语言下的一个子集)的语言,用于描述 Web Service 及其函数、参数和返回值。因为是基于 XML 的,所以 WSDL 既是机器可阅读的,又是人可阅读的。

  • 通过 wsdl 说明书,就可以描述 webservice 服务端对外发布的服务。

  • wsdl 说明书是一个基于 xml 文件,通过 xml 语言描述整个服务。

  • 在 wsdl 说明中,描述了。

  • 对外发布的服务名称(类)。
  • 接口方法名称(方法)。
  • 接口参数(方法参数)。
  • 服务返回的数据类型(方法返回值)。


UDDI。

UDDI 是一个跨产业,跨平台的开放性架构,可以帮助 web 服务提供商在互联网上发布 web 服务的信息。UDDI 是一种目录服务,企业可以通过 UDDI 来注册和搜索 web 服务。简单来说,UDDI 就是一个目录,只不过在这个目录中存放的是一些关于 web 服务的信息而己。

  • Java 中共有三种 WebService 规范,分别是 JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。


优缺点。

优点。
  • 异构平台的互通。

理论上,Web Service 最大的优势是提供了异构平台的无缝街接技术手段。由于不同的用户使用不同的硬件平台,不同的操作平台,不同的臊作系统,不同的软件,不同的协议通信,这就产生了互相通信的需求。WebService 使任何两个应用程序,只要能读写 XML,那么就能互相通信。

  • 更广泛的软件复用(例如手机淘宝可以复用己有淘宝的业务逻辑)。

软件的复用技术通过组合己有模块来搭建应用程序,能大幅度提高软件的生产效率和质量。用户只要获得了描述 web service 的 WSDL 文件,就可以方便地生成客户端代理,并通过代理访问 Web Service。

  • 成本低、可读性强、应用范围广。

Web Service 可用基于 XML 的 SOAP 来表示数据和调用请求。并且通过 HTTP 协议传输 XML 格式的数据。

  • 迅捷的软件发行方式。

每个 Web Service 称为一个生产者,不同的生产者可以相互协同合作完成整个应用。软件供应商可以把软件分解成若干 Web Service 模块构成的系统,直接在 Web 上发布。

  • 最重要的一点。

客户端与服务端可能是不同的语言开发的,但是,通过 Web Service 提供的服务接口,客户端与服务端之前可以传递对象。



缺点。

由于 soap 是基于 xml 传输,本身使用 xml 传输会传输一些无关内容从而影响率,随着 SOAP 协议的完善,SOAP 协议增加了许多内容,这样就导致了使用 SOAP 去完成简单的数据传输向携带的信息更多效率再受影响。

Web Service 作为 web 跨平台访问的标准技术,很多公司都限定要求使用 Web Service,但如果是简单的接口可以直接使用 http 传输自定义数据格式,开发更快捷。



面向服务架构 SOA ~ Service-Oriented Architecture 。

面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和协议联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。



ApacheCXF 框架。

Apache CXF = Celtix + XFire,ApacheCXF 的前身叫 Apache CeltiXfire,现在已经正式更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用。目前它仍只是 Apache 的一个孵化项目。

Apache CXF 是一个开源的 Services 框架,CXF 帮助您利用 Frontend 编程 API 来构建和开发 Services,像 JAX-WS 。这些 Services 可以支持多种协议,比如:SOAP、XML/HTTP、RESTfulHTTP 或者 CORBA ,并且可以在多种传输协议上运行,比如:HTTP、JMS 或者 JBI,CXF 大大简化了 Services 的创建,同时它继承了 XFire 传统,一样可以天然地和 Spring 进行无缝集成。

功能特性。

CXF 包含了大量的功能特性,但是主要集中在以下几个方面。

  • 支持 Web Services 标准。
    CXF 支持多种 Web Services 标准,包含 SOAP、Basic Profile、WS-Addressing、WS-Policy、WS-ReliableMessaging 和 WS-Security。
  • Frontends。
    CXF 支持多种“Frontend”编程模型,CXF 实现了 JAX-WS API (遵循 JAX-WS 2.0 TCK 版本),ta 也包含一个“simple frontend”允许客户端和 EndPoint 的创建,而不需要 Annotation 注解。CXF 既支持 WSDL 优先开发,也支持从 Java 的代码优先开发模式。
  • 容易使用。
    CXF 设计得更加直观与容易使用。有大量简单的 API 用来快速地构建代
    码优先的 Services,各种 Maven 的插件也使集成更加容易,支持 JAX-WS API ,支持 Spring 2.0 更加简化的 XML 配置方式,等等。
  • 支持二进制和遗留协议。
    CXF 的设计是一种可插拨的架构,既可以支持 XML,也可以支持非 XML 的类型绑定,比如:JSON 和 CORBA。


开发。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.geek</groupId>
    <artifactId>jaxws_server</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>jaxws_server</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <!-- jaxws。-->
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-frontend-jaxws -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.0.1</version>
        </dependency>
        <!-- 内置 jetty web 服务器。-->
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-transports-http-jetty -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>3.0.1</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

服务端。
package com.geek.service;

import javax.jws.WebService;

/**
 * 对外发布服务接口。
 *
 * @author geek
 */
@WebService
public interface IHelloService {

    String sayHello(String name);

}

package com.geek.service.impl;

import com.geek.service.IHelloService;

/**
 * 对外发布服务实现。
 *
 * @author geek
 */
public class HelloServiceImpl implements IHelloService {

    @Override
    public String sayHello(String name) {
        return name + ", Welcome.";
    }

}

package com.geek;

import com.geek.service.impl.HelloServiceImpl;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

/**
 * @author geek
 */
public class Server {

    public static void main(String[] args) {
        // 发布服务工厂。
        JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();

        // 设置服务地址。
        jaxWsServerFactoryBean.setAddress("http://192.168.0.104:8000/ws/hello");

        // 设置服务类。
        jaxWsServerFactoryBean.setServiceBean(new HelloServiceImpl());

        // 发布服务。
        jaxWsServerFactoryBean.create();

        System.out.println("发布服务成功,端口 8000");
    }

}

/*
Connected to the target VM, address: '127.0.0.1:51928', transport: 'socket'
Jan 17, 2021 9:48:44 PM org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
信息: Creating Service {http://impl.service.geek.com/}HelloServiceImplService from class com.geek.service.IHelloService
Jan 17, 2021 9:48:45 PM org.apache.cxf.endpoint.ServerImpl initDestination
信息: Setting the server's publish address to be http://192.168.0.104:8000/ws/hello
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
发布服务成功,端口 8000
 */
  • 访问。

在这里插入图片描述
查看 wsdl 说明书。

192.168.0.104:8000/ws/hello?wsdl

在这里插入图片描述



客户端。
package com.geek.service;

import javax.jws.WebService;

/**
 * 对外发布服务接口。
 *
 * @author geek
 */
@WebService
public interface IHelloService {

    String sayHello(String name);

}

package com.geek;

import com.geek.service.IHelloService;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

/**
 * @author geek
 */
public class Client {

    public static void main(String[] args) {
        // 服务接口的访问地址。http://192.168.0.104:8000/ws/hello

        // 创建 cxf 代理工厂。
        JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();

        // 设置远程访问服务地址。
        jaxWsProxyFactoryBean.setAddress("http://192.168.0.104:8000/ws/hello");

        // 设置接口类型。
        jaxWsProxyFactoryBean.setServiceClass(IHelloService.class);

        // 对接口生成代理对象。
        IHelloService helloService = jaxWsProxyFactoryBean.create(IHelloService.class);
        // 代理对象类型。
        System.out.println(helloService.getClass());

        // 远程访问服务端方法。
        String content = helloService.sayHello("Geek");
        System.out.println("content = " + content);
        // class com.sun.proxy.$Proxy34
        //content = Geek, Welcome.

        // Java 代理。
        //      静态代理。
        //      动态代理(jdk 接口代理,cglib 子类代理。
    }

}

/*
Connected to the target VM, address: '127.0.0.1:51961', transport: 'socket'
Jan 17, 2021 9:49:30 PM org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
信息: Creating Service {http://service.geek.com/}IHelloServiceService from class com.geek.service.IHelloService
class com.sun.proxy.$Proxy34
content = Geek, Welcome.
Disconnected from the target VM, address: '127.0.0.1:51961', transport: 'socket'

Process finished with exit code 0

 */


日志。
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
        </dependency>
package com.geek;

import com.geek.service.impl.HelloServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

/**
 * @author geek
 */
@Slf4j
public class Server {

    public static void main(String[] args) {
        // 发布服务工厂。
        JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();

        // 设置服务地址。
        jaxWsServerFactoryBean.setAddress("http://192.168.0.104:8000/ws/hello");

        // 设置服务类。
        jaxWsServerFactoryBean.setServiceBean(new HelloServiceImpl());

        // 添加日志输入输出拦截器。观察soap 请求和相应内容。
        jaxWsServerFactoryBean.getInInterceptors().add(new LoggingInInterceptor());
        jaxWsServerFactoryBean.getInInterceptors().add(new LoggingOutInterceptor());

        // 发布服务。
        jaxWsServerFactoryBean.create();

        System.out.println("发布服务成功,端口 8000");
    }

}

2021-01-17 22:02:20,129 0      [           main] INFO  y.ReflectionServiceFactoryBean  - Creating Service {http://impl.service.geek.com/}HelloServiceImplService from class com.geek.service.IHelloService
2021-01-17 22:02:20,799 670    [           main] INFO  apache.cxf.endpoint.ServerImpl  - Setting the server's publish address to be http://192.168.0.104:8000/ws/hello
2021-01-17 22:02:20,830 701    [           main] INFO  rg.eclipse.jetty.server.Server  - jetty-8.1.15.v20140411
2021-01-17 22:02:20,914 785    [           main] INFO  jetty.server.AbstractConnector  - Started SelectChannelConnector@192.168.0.104:8000
发布服务成功,端口 8000
Connected to the target VM, address: '127.0.0.1:52358', transport: 'socket'
2021-01-17 22:04:37,688 0      [           main] INFO  y.ReflectionServiceFactoryBean  - Creating Service {http://impl.service.geek.com/}HelloServiceImplService from class com.geek.service.IHelloService
2021-01-17 22:04:38,501 813    [           main] INFO  apache.cxf.endpoint.ServerImpl  - Setting the server's publish address to be http://192.168.0.104:8000/ws/hello
2021-01-17 22:04:38,528 840    [           main] INFO  rg.eclipse.jetty.server.Server  - jetty-8.1.15.v20140411
2021-01-17 22:04:38,614 926    [           main] INFO  jetty.server.AbstractConnector  - Started SelectChannelConnector@192.168.0.104:8000
发布服务成功,端口 8000
2021-01-17 22:04:46,835 9147   [tp1119242936-17] INFO  oServiceImplPort.IHelloService  - Inbound Message
----------------------------
ID: 1
Address: http://192.168.0.104:8000/ws/hello
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[192], content-type=[text/xml; charset=UTF-8], Host=[192.168.0.104:8000], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache CXF 3.0.1]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://service.geek.com/"><arg0>Geek</arg0></ns2:sayHello></soap:Body></soap:Envelope>
--------------------------------------



Spring 整合 ApacheCXF 实现 WebService(Jax-ws)。

服务端。
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.geek</groupId>
    <artifactId>spring_apache_cxf_jaxws_server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>spring_apache_cxf_jaxws_server Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--<dependency>-->
        <!--<groupId>org.springframework</groupId>-->
        <!--<artifactId>spring-test</artifactId>-->
        <!--<version>5.0.2.RELEASE</version>-->
        <!--</dependency>-->

    </dependencies>

    <build>
        <finalName>spring_apache_cxf_jaxws_server</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <!--<plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat6-maven-plugin</artifactId>
                <version>2.2</version>
            </plugin>-->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>8080</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>

    </build>

</project>

package com.geek.service;

import javax.jws.WebService;

/**
 * 对外发布服务接口。
 *
 * @author geek
 */
@WebService
public interface IHelloService {

    String sayHello(String name);

}

package com.geek.service.impl;

import com.geek.service.IHelloService;

/**
 * 对外发布服务实现。
 *
 * @author geek
 */
public class HelloServiceImpl implements IHelloService {

    @Override
    public String sayHello(String name) {
        return name + ", Welcome.";
    }

}

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>

    <!-- Spring 容器配置。-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- cxf servlet 配置。-->
    <servlet>
        <servlet-name>cxfservlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>cxfservlet</servlet-name>
        <url-pattern>/ws/*</url-pattern>
    </servlet-mapping>

</web-app>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <!-- Spring 整合 cxf 发布服务。
    http://localhost:8080/ws/hello-->
    <jaxws:server address="/hello">
        <jaxws:serviceBean>
            <bean class="com.geek.service.impl.HelloServiceImpl"/>
        </jaxws:serviceBean>
    </jaxws:server>

</beans>



客户端。



  • 接口及实现类。
package com.geek.webservice.service;

public interface IWeatherService {

    String query(String cityName);

}

package com.geek.webservice.service.impl;

import com.geek.webservice.service.IWeatherService;

import javax.jws.WebService;

@WebService
public class WeatherServiceImpl implements IWeatherService {

    @Override
    public String query(String cityName) {
        System.out.println("查询 " - cityName);
        return "大晴天";
    }

}

  • 发布。
package com.geek.webservice.main;

import com.geek.webservice.impl.WeatherServiceImpl;

import javax.xml.ws.Endpoint;

/**
 * 采用 jdk 的方式发布服务。
 */
public class Main {

    public static void main(String[] args) {

        Endpoint.publish("http://localhost:8080/weatherService", new WeatherServiceImpl());
        System.out.println("发布成功。");
    }

}

访问 http://localhost:8080/weatherService?wsdl。

在这里插入图片描述
(说明书)。

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<!--
 Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. 
-->
<!--
 Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. 
-->
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://impl.webservice.geek.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://impl.webservice.geek.com/" name="WeatherServiceImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://impl.webservice.geek.com/" schemaLocation="http://localhost:8080/weatherService?xsd=1"/>
</xsd:schema>
</types>
<message name="query">
<part name="parameters" element="tns:query"/>
</message>
<message name="queryResponse">
<part name="parameters" element="tns:queryResponse"/>
</message>
<portType name="WeatherServiceImpl">
<operation name="query">
<input wsam:Action="http://impl.webservice.geek.com/WeatherServiceImpl/queryRequest" message="tns:query"/>
<output wsam:Action="http://impl.webservice.geek.com/WeatherServiceImpl/queryResponse" message="tns:queryResponse"/>
</operation>
</portType>
<binding name="WeatherServiceImplPortBinding" type="tns:WeatherServiceImpl">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="query">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="WeatherServiceImplService">
<port name="WeatherServiceImplPort" binding="tns:WeatherServiceImplPortBinding">
<soap:address location="http://localhost:8080/weatherService"/>
</port>
</service>
</definitions>


客户端 方式 1。

~ wsimport 自动生成代码。

创建一个新模块 webservice-client-01。在该模块的 src 目录下使用 wsimport 命令。(该命令是 jdk 的命令)。

geek@ubuntu:~/IdeaProjects/webservice_geek/webservice-client-01/src$ wsimport
Missing WSDL_URI


Usage: wsimport [options] <WSDL_URI>

where [options] include:
  -b <path>                 specify jaxws/jaxb binding files or additional schemas
                            (Each <path> must have its own -b)
  -B<jaxbOption>            Pass this option to JAXB schema compiler
  -catalog <file>           specify catalog file to resolve external entity references
                            supports TR9401, XCatalog, and OASIS XML Catalog format.
  -classpath <path>         specify where to find user class files and wsimport extensions
  -cp <path>                specify where to find user class files and wsimport extensions
  -d <directory>            specify where to place generated output files
  -encoding <encoding>      specify character encoding used by source files
  -extension                allow vendor extensions - functionality not specified
                            by the specification.  Use of extensions may
                            result in applications that are not portable or
                            may not interoperate with other implementations
  -help                     display help
  -httpproxy:<proxy>        set a HTTP proxy. Format is [user[:password]@]proxyHost:proxyPort
                            (port defaults to 8080)
  -J<javacOption>           pass this option to javac
  -keep                     keep generated files
  -p <pkg>                  specifies the target package
  -quiet                    suppress wsimport output
  -s <directory>            specify where to place generated source files
  -target <version>         generate code as per the given JAXWS spec version
                            Defaults to 2.2, Accepted values are 2.0, 2.1 and 2.2
                            e.g. 2.0 will generate compliant code for JAXWS 2.0 spec
  -verbose                  output messages about what the compiler is doing
  -version                  print version information
  -fullversion              print full version information
  -wsdllocation <location>  @WebServiceClient.wsdlLocation value
  -clientjar <jarfile>      creates the jar file of the generated artifacts along with the
                            WSDL metadata required for invoking the web service.
  -generateJWS              generate stubbed JWS implementation file
  -implDestDir <directory>  specify where to generate JWS implementation file
  -implServiceName <name>   local portion of service name for generated JWS implementation
  -implPortName <name>      local portion of port name for generated JWS implementation

Extensions:
  -XadditionalHeaders              map headers not bound to request or response message to 
                                   Java method parameters
  -Xauthfile                       file to carry authorization information in the format 
                                   http://username:password@example.org/stock?wsdl
  -Xdebug                          print debug information
  -Xno-addressing-databinding      enable binding of W3C EndpointReferenceType to Java
  -Xnocompile                      do not compile generated Java files
  -XdisableAuthenticator           disable Authenticator used by JAX-WS RI,
                                   -Xauthfile option will be ignored if set
  -XdisableSSLHostnameVerification disable the SSL Hostname verification while fetching
                                   wsdls

Examples:
  wsimport stock.wsdl -b stock.xml -b stock.xjb
  wsimport -d generated http://example.org/stock?wsdl


geek@ubuntu:~/IdeaProjects/webservice_geek/webservice-client-01/src$ wsimport -s . http://127.0.0.1:8080/weatherService?wsdl
parsing WSDL...



Generating code...


Compiling code...

geek@ubuntu:~/IdeaProjects/webservice_geek/webservice-client-01/src$ 

可以看到自动生成了代码。

在这里插入图片描述

package com.geek.webservice.client;

import com.geek.webservice.service.impl.WeatherServiceImpl;
import com.geek.webservice.service.impl.WeatherServiceImplService;

public class Client {

    public static void main(String[] args) {
        // 创建服务视图。视图是从 service 标签的 name 属性获取。
        WeatherServiceImplService implService = new WeatherServiceImplService();

        // 获取服务的实现类。实现类从 portType 的 name 属性获取。
        // <portType name="WeatherServiceImpl">
        WeatherServiceImpl port = implService.getPort(WeatherServiceImpl.class);

        // 调用方法。从 portType 的 operation 标签获取。
        // <portType name="WeatherServiceImpl">
        //      <operation name="query">
        String query = port.query("大武汉");
        System.out.println("query = " - query);

    }
}

~~~

query = 大晴天

~~~

- 服务端。

发布成功。
查询 大武汉



客户端 方式 2。

~ wsimport 自动生成代码。

geek@ubuntu:~/IdeaProjects/webservice_geek/webservice-client-02/src$ wsimport -s . http://localhost:8080/weatherService?wsdl
parsing WSDL...



Generating code...


Compiling code...

geek@ubuntu:~/IdeaProjects/webservice_geek/webservice-client-02/src$ 

package com.geek.webservice.client;

import com.geek.webservice.service.impl.WeatherServiceImpl;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.net.MalformedURLException;
import java.net.URL;

public class Client {

    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://localhost:8080/weatherService?wsdl");
        QName qName = new QName("http://impl.service.webservice.geek.com/", "WeatherServiceImplService");
        Service service = Service.create(url, qName);

        WeatherServiceImpl port = service.getPort(WeatherServiceImpl.class);

        String query = port.query("大湖北");
        System.out.println("query = " - query);

    }
}

~~~

query = 大晴天

Process finished with exit code 0

~~~

- 服务端。

发布成功。
查询 大武汉
查询 大湖北

如果服务端更新了新功能。客户端不能立即使用。必须重新根据 wsdl 生成代码。



访问网络提供的 Web Service 服务。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lyfGeek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值