Web Services 入门

webservice是开发中比较常用的技术。

由于企业中的开发平台平台,或平台下所有的系统,均可通过Web浏览器访问,那么就涉及到不同平台下的系统之间的交互协同工作。webservice为此提供了技术支持。

Web services 把 Web 应用程序提升到了另外一个层面:

  1. Web Service平台需支持XML + HTTP,HTTP协议是最常用的因特网协议,XML提供了一种可用于不同平台和编程语言之间的语言。
  2. Web Services能够解决不同平台、不同语言编写的应用之间如何相互调用问题
  3. 使用 Web Services,我们的应用程序可以向全世界发布信息,或提供某项功能。

一、webservice 基本概念

Web Service所使用的是Internet上统一、开放的标准,如HTTP、XML、SOAP(简单对象访问协议)、WSDL等,所以Web Service可以在任何支持这些标准的环境(Windows,Linux)中使用。

这有助于大量异构程序和平台之间的互操作性,从而使存在的应用程序能够被广泛的用户访问。

从应用来说,Web Service是一件值得企业特别注意的事情。Web Service的应用范围目前包括两个方面:企业之间的应用、以及企业内部的应用。

企业之间的应用主要包括人们熟悉的企业间的电子商务(B2B)和企业与消费者之间的电子商务(B2C)。

Web Service在B2B的应用包括:以企业采购、物流和分销为内容的供应链;以及涉及到零售、B2C以及中间业务的支付系统。

而相对来说,企业内部的应用比企业之间的电子商务应用要成熟一些,并得到广泛的采用。最为普遍的应用是:采用中间件应用服务器软件作为工具将企业各项应用都进行改造和开发,开发目标是以Web为基础的应用,或者称为应用软件的网络化。目前企业内部这种网络应用还包括现在流行的ERP以及CRM等等。

1 简介

(1) webservice 即web服务,它是一种跨编程语言跨操作系统平台的远程调用技术。

如图:

在这里插入图片描述

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

(3) webService三要素:soap、wsdl、uddi

2 术语

2.1 webservice开发规范

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

下面来分别简要的介绍一下这三个规范。

1.) 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 我们较少会直接使用)。

2. JAXM&SAAJ:

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

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

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

3.) JAX-RS(重点):

JAX-RS 是JAVA 针对REST(RepresentationState Transfer)风格制定的一套Web 服务规范,由于推出的较晚,该规范(JSR 311,目前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 中自带的默认实现。

2.2 SOAP 协议

(1) SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML(标准通用标记语言下的一个子集)编码信息的轻量级协议。

它有三个主要方面:XML-envelope为描述信息内容和如何处理内容定义了框架,将程序对象编码成为XML对象的规则,执行远程过程调用(RPC)的约定。SOAP可以运行在任何其他传输协议上。

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

(3) SOAP = 在HTTP的基础上+XML数据

(4) SOAP是基于HTTP的

(5) SOAP的组成如下

  • a) Envelope – 必须的部分。以XML的根元素出现。

  • b) Headers – 可选的。

  • c) Body – 必须的。在body部分,包含要执行的服务器的方法。和发送到服务器的数据。

2.3 wsdl说明书

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

wsdl说明书:

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

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

3) 在wsdl说明中,描述了:

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

2.4 UDDI

Web 服务提供商又如何将自己开发的 Web 服务公布到因特网上,这就需要使用到 UDDI 了,UDDI的话,是一个跨产业,跨平台的开放性架构,可以帮助 Web 服务提供商在互联网上发布 Web 服务的信息。

UDDI 是一种目录服务,企业可以通过 UDDI 来注册和搜索 Web 服务。简单来时候话,UDDI 就是一个目录,只不过在这个目录中存放的是一些关于 Web 服务的信息而已。并且 UDDI 通过SOAP 进行通讯,构建于 . Net 之上。

UDDI 即 Universal Description,Discovery andIntegration,也就是通用的描述,发现以及整合。

UDDI 的目的是为电子商务建立标准;UDDI是一套基于Web的、分布式的、为WebService提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。

3 应用场景

Web Service 可以适用于应用程序集成、软件重用、跨防火墙通信等需求。不同的业务要求不同。具体如下:

  • 跨防火墙通信
  • 应用系统集成
  • 软件和数据重用

简单来说,如果一个功能,需要被多个系统使用可以使用webservice开发一个服务端接口,供不同的客户端应用。主要应用在企业内部系统之间的接口调用、面向公网的webservice服务。

4 优缺点

4.1 优点:

a) 异构平台的互通性

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

b) 更广泛的软件复用(例如手机淘宝可以复用已有淘宝的业务逻辑.)

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

c) 成本低、可读性强、应用范围广

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

d) 迅捷的软件发行方式

(每个web Service称为一个生产者.不同的生产者可以相互协同合作完成整个应用)

Web Service 将彻底地改变软件的发行方式。

软件供应商可以把软件分解成若Web Service 模块构成的系统,直接在 Web 上发布。

e) 最重要的一点

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

4.2 缺点:

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

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

在这里插入图片描述

5 面向服务架构SOA

SOA(Service-OrientedArchitecture)面向服务架构是一种思想,它将应用程序的不同功能单元通过中立的契约(独立于硬件平台、操作系统和编程语言)联系起来,使得各种形式的功能单元更好的集成。

目前来说,WebService 是SOA 的一种较好的实现方式

WebService 采用HTTP 作为传输协议,SOAP(Simple Object Access Protocol)作为传输消息的格式。但WebService 并不是完全符合SOA 的概念,因为SOAP 协议是WebService 的特有协议,并未符合SOA 的传输协议透明化的要求。SOAP 是一种应用协议,早期应用于RPC 的实现,传输协议可以依赖于HTTP、SMTP 等。

二、 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 包含了大量的功能特性,但是主要集中在以下几个方面:

(1) 支持 Web Services 标准:CXF 支持多种 Web Services 标准,包含 SOAP、Basic Profile、WS-Addressing、WS-Policy、WS-ReliableMessaging 和 WS-Security。

(2) Frontends:CXF 支持多种“Frontend”编程模型,CXF 实现了 JAX-WS API (遵循 JAX-WS 2.0 TCK 版本),它也包含一个“simple frontend”允许客户端和 EndPoint 的创建,而不需要 Annotation 注解。CXF 既支持 WSDL 优先开发,也支持从 Java 的代码优先开发模式。

(3) 容易使用: CXF 设计得更加直观与容易使用。有大量简单的 API 用来快速地构建代码优先的 Services,各种 Maven 的插件也使集成更加容易,支持 JAX-WS API ,支持 Spring 2.0 更加简化的 XML 配置方式,等等。

(4) 支持二进制和遗留协议:CXF 的设计是一种可插拨的架构,既可以支持 XML ,也可以支持非 XML 的类型绑定,比如:JSON 和 CORBA。

三、 ApacheCXF 实现WebService(Jax-ws)

——JAXWS规范下的webservice开发

1 服务端

添加cxf依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         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>top.onefine</groupId>
    <artifactId>jaxws_server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <build>
        <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>
                    <encoding>UTF-8</encoding>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- 要进行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.3.6</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.3.6</version>
            <scope>test</scope>
        </dependency>

        <!-- 日志实现 -->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

写服务接口

package top.onefine.service;

import javax.jws.WebService;

/**
 * 对外发布服务的接口
 *
 * @author one fine<br/>
 */
@WebService  // 用来标识这是一个webservice接口
public interface IHelloService {
    
    

    String sayHello(String name);
}

写服务接口实现

package top.onefine.service.impl;

import top.onefine.service.IHelloService;

/**
 * @author one fine<br/>
 */
public class HelloService implements IHelloService {
    
    
    @Override
    public String sayHello(String name) {
    
    
        return "Hello " + name + "!";
    }
}

测试:发布服务

package top.onefine.test;

import lombok.extern.java.Log;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import top.onefine.service.impl.HelloService;

/**
 * 测试:发布服务
 *
 * @author one fine<br/>
 */
@Log
public class service {
    
    

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

        // 设置webservice服务的地址
        factory.setAddress("http://127.0.0.1:8888/ws/hello");

        // 设置服务类
        factory.setServiceBean(new HelloService());

        // 发布服务
        factory.create();

        log.info("成功发布服务!服务端口:8888.");
    }
}
  • 服务发布成功:

在这里插入图片描述

  • 访问wsdl说明书

地址:http://127.0.0.1:8888/ws/hello?wsdl

阅读顺序,从下往上读。

在这里插入图片描述

2 客户端

写客户端之前要先明确:

  1. 服务端地址
  2. 服务端接口、接口方法(方法参数、返回值)

添加依赖:与服务端项目依赖一致。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         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>top.onefine</groupId>
    <artifactId>jaxws_client</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <build>
        <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>
                    <encoding>UTF-8</encoding>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- 要进行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.3.6</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.3.6</version>
            <scope>test</scope>
        </dependency>

        <!-- 日志实现 -->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>


</project>

服务接口:与服务端的服务接口一致。

package top.onefine.service;

import javax.jws.WebService;

/**
 * 对外发布服务的接口
 *
 * @author one fine<br/>
 */
@WebService  // 用来标识这是一个webservice接口
public interface IHelloService {
    
    

    String sayHello(String name);
}

测试远程访问服务端

package top.onefine.test;

import lombok.extern.java.Log;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import top.onefine.service.IHelloService;

/**
 * @author one fine<br/>
 */
@Log
public class Client {
    
    

    public static void main(String[] args) {
    
    
        // 服务接口访问地址:http://127.0.0.1:8888/ws/hello
        String address = "http://127.0.0.1:8888/ws/hello";

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

        // 设置远程访问服务端地址
        factory.setAddress(address);

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

        // 对接口生成代理对象
        /*
        java中的代理:
            1. 静态代理
            2. 动态代理:(jdk接口代理 + cglib子类代理)
         这里是jdk接口代理(带有$Proxy的标识),$Cglib为cglib子类代理
         */
        IHelloService helloService = factory.create(IHelloService.class);

        log.info("代理对象类型:" + helloService.getClass());

        // 远程访问服务端方法
        String str = helloService.sayHello("one fine");
        System.out.println(str);
    }
}

在这里插入图片描述

3 添加日志拦截器,观察soap协议内容

server和client都引入log4j配置文件:log4j.properties

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=info, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{
    
    ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{
    
    ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

服务端(study_webservice\jaxws_server\src\test\java\top\onefine\test\service.java)添加日志拦截器:

package top.onefine.test;

import lombok.extern.java.Log;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import top.onefine.service.impl.HelloService;

/**
 * 测试:发布服务
 *
 * @author one fine<br/>
 */
@Log
public class service {
    
    

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

        // 设置webservice服务的地址
        factory.setAddress("http://127.0.0.1:8888/ws/hello");

        // 设置服务类
        factory.setServiceBean(new HelloService());

        // 添加日志输入、输出拦截器,观察soap请求以及soap响应内容
        factory.getInInterceptors().add(new LoggingInInterceptor());
        factory.getOutInterceptors().add(new LoggingOutInterceptor());

        // 发布服务
        factory.create();

        log.info("成功发布服务!服务端口:8888.");
    }
}

启动服务端,并客户端(study_webservice\jaxws_client\src\test\java\top\onefine\test\Client.java)调用,观察日志

  • 查看soap请求、soap响应传输的xml数据:

客户端:

2020-06-24 16:25:48,538 0      [           main] INFO  y.ReflectionServiceFactoryBean  - Creating Service {
    
    http://service.onefine.top/}IHelloServiceService from class top.onefine.service.IHelloService
六月 24, 2020 4:25:49 下午 top.onefine.test.Client main
信息: 代理对象类型:class com.sun.proxy.$Proxy35
Hello one fine!

服务端:

2020-06-24 16:25:12,059 1      [           main] INFO  y.ReflectionServiceFactoryBean  - Creating Service {
    
    http://impl.service.onefine.top/}HelloServiceService from class top.onefine.service.IHelloService
2020-06-24 16:25:12,897 839    [           main] INFO  apache.cxf.endpoint.ServerImpl  - Setting the server's publish address to be http://127.0.0.1:8888/ws/hello
2020-06-24 16:25:12,918 860    [           main] INFO      org.eclipse.jetty.util.log  - Logging initialized @1964ms to org.eclipse.jetty.util.log.Slf4jLog
2020-06-24 16:25:13,024 966    [           main] INFO  rg.eclipse.jetty.server.Server  - jetty-9.4.27.v20200227; built: 2020-02-27T18:37:21.340Z; git: a304fd9f351f337e7c0e2a7c28878dd536149c6c; jvm 1.8.0_251-b08
2020-06-24 16:25:13,610 1552   [           main] INFO  jetty.server.AbstractConnector  - Started ServerConnector@17bffc17{
    
    HTTP/1.1, (http/1.1)}{
    
    127.0.0.1:8888}
2020-06-24 16:25:13,610 1552   [           main] INFO  rg.eclipse.jetty.server.Server  - Started @2664ms
2020-06-24 16:25:13,631 1573   [           main] INFO  .server.handler.ContextHandler  - Started o.e.j.s.h.ContextHandler@64b0598{
    
    /ws,null,AVAILABLE}
六月 24, 2020 4:25:13 下午 top.onefine.test.service main
信息: 成功发布服务!服务端口:8888.
2020-06-24 16:25:50,112 38054  [tp2075809815-21] INFO  HelloServicePort.IHelloService  - Inbound Message
----------------------------
ID: 1
Address: http://127.0.0.1:8888/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=[199], content-type=[text/xml; charset=UTF-8], Host=[127.0.0.1:8888], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache-CXF/3.3.6]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://service.onefine.top/"><arg0>one fine</arg0></ns2:sayHello></soap:Body></soap:Envelope>
--------------------------------------
2020-06-24 16:25:50,485 38427  [tp2075809815-21] INFO  HelloServicePort.IHelloService  - Outbound Message
---------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {
    
    }
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHelloResponse xmlns:ns2="http://service.onefine.top/"><return>Hello one fine!</return></ns2:sayHelloResponse></soap:Body></soap:Envelope>
--------------------------------------

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

1 服务端

创建web项目,添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         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>top.onefine</groupId>
    <artifactId>jaxws_spring_server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <!-- CXF WS开发  -->
        <!-- 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.3.6</version>-->
            <!-- module-info.class报错 -->
            <version>3.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.3.6</version>
            <scope>compile</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.7.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-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>
                    <encoding>UTF-8</encoding>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>

            <!-- 运行tomcat7方法:tomcat7:run -->
            <plugin>
                <!-- https://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-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>

web.xml 中配置CXFServlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <display-name>Archetype Created Web Application</display-name>
    <!-- cxfservlet配置 -->
    <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>

    <!-- 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>

</web-app>

idea创建java项目后添加webapp怎么配置?参看:https://blog.csdn.net/qq_44575680/article/details/89449581

在这里插入图片描述

1.1 服务接口、服务实现(和上面一样)

package top.onefine.service;

import javax.jws.WebService;

/**
 * 对外发布服务的接口
 *
 * @author one fine<br/>
 */
@WebService  // 用来标识这是一个webservice接口
public interface IHelloService {
    
    

    String sayHello(String name);
}
package top.onefine.service.impl;

import top.onefine.service.IHelloService;

/**
 * @author one fine<br/>
 */
public class HelloService implements IHelloService {
    
    
    @Override
    public String sayHello(String name) {
    
    
        return "Hello " + name + "!";
    }
}

1.2 Spring 整合 ApacheCXF

src\main\resources\applicationContext.xml:

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

    <!--
        Spring整合ApacheCXF,发布jaxws服务:
        1. 服务地址
        2. 服务bean

        完整服务地址:
        http://localhost:8080/ws/userService
     -->
    <jaxws:server address="/userService">
        <jaxws:serviceBean>
            <bean class="com.itheima.service.impl.UserServiceImpl"></bean>
        </jaxws:serviceBean>
    </jaxws:server>
</beans>

1.3 启动服务,发布服务

在这里插入图片描述
在这里插入图片描述

1.4 访问wsdl说明书

地址:http://127.0.0.1:8080/ws/hello?wsdl

2 客户端

创建项目,添加依赖,和上面一致:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         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>top.onefine</groupId>
    <artifactId>jaxws_spring_client</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>


    <dependencies>
        <!-- CXF WS开发  -->
        <!-- 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.3.6</version>-->
            <version>3.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.3.6</version>
            <scope>compile</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.7.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-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>
                    <encoding>UTF-8</encoding>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>

            <!-- 运行tomcat7方法:tomcat7:run -->
            <plugin>
                <!-- https://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-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>

2.1 service接口

package top.onefine.service;

import javax.jws.WebService;

/**
 * 对外发布服务的接口
 *
 * @author one fine<br/>
 */
@WebService  // 用来标识这是一个webservice接口
public interface IHelloService {
    
    

    String sayHello(String name);
}

2.2 Spring 整合 ApacheCXF 配置

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

    <!--
     Spring整合cxf客户端配置
        1. 服务地址 http://127.0.0.1:8080/ws/hello
        2. 服务接口类型
        
        Spring整合ApacheCXF,客户端配置
        关键点:
            通过Spring整合ApacheCXF,创建客户端的代理对象,远程访问服务端。
        jaxws:client
            id  应用中注入的接口的代理对象的名称
            address 服务端访问地址
            serviceClass  指定接口路径,会根据该类型生成代理对象

     -->
    <jaxws:client id="helloService"
            serviceClass="top.onefine.service.IHelloService"
            address="http://127.0.0.1:8080/ws/hello" />


</beans>

2.3 junit测试

package top.onefine;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import top.onefine.service.IHelloService;

import javax.annotation.Resource;

/**
 * @author one fine<br/>
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Client {
    
    

    // 注入对象
    @Resource
    private IHelloService helloService;

    @Test
    public void remote() {
    
    

        // 查看接口的代理对象类型
        System.out.println(helloService.getClass());

        // 远程访问服务端方法
        System.out.println(helloService.sayHello("One fine"));
    }
}

五、 Restful 风格

一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存(同一地址更易于浏览器查找缓存)等机制。

REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。

所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。所谓"上网",就是与互联网上一系列的"资源"互动,调用它的URI。

表现层,我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。

比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。

Restful 风格: http://bbs.csdn.net/topics/390908212

非resfull风格:http://bbs.csdn.net/topics?tid=390908212

严格地说,有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示格式,属于"表现层"范畴,而URI应该只代表"资源"的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。

状态转化(State Transfer)

访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(StateTransfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:

  • GET用来获取资源,
  • POST用来新建资源,
  • PUT用来更新资源,
  • DELETE用来删除资源。

访问服务器资源,通过不同的http请求方式,服务器就知道对CRUD的哪个操作!

JAX-RS 发布服务就是使用RESTFUL风格。

六、 ApacheCXF 实现webservice (Jax-rs)

——JAXRS规范下的webservice开发

  • 基于restful风格的webservice,请求使用的是http协议,可以传递xml/json数据

1 服务端

添加依赖及日志配置:

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         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>top.onefine</groupId>
    <artifactId>jaxrs_server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <build>
        <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>
                    <encoding>UTF-8</encoding>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- 要进行jaxrs 服务开发 -->
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-frontend-jaxrs -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>3.3.6</version>
        </dependency>

        <!-- 客户端调用时候使用的包(WebClient工具类调用服务端) -->
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-rs-client -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-client</artifactId>
            <version>3.3.6</version>
        </dependency>

        <!-- 基于restful风格的webservice,客户端与服务端之间可以传递json,这个就是json支持相关包 -->
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-rs-extension-providers -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-extension-providers</artifactId>
            <version>3.3.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.codehaus.jettison/jettison -->
        <dependency>
            <groupId>org.codehaus.jettison</groupId>
            <artifactId>jettison</artifactId>
            <version>1.4.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.3.6</version>
            <scope>test</scope>
        </dependency>

        <!-- 日志实现 -->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>


</project>

src\main\resources\log4j.properties:

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=info, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{
    
    ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{
    
    ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

服务接口、实现、实体类

package top.onefine.domain;

import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * 基于restful风格的webservice,客户端与服务器端之间通讯可以传递xml数据、json数据
 * @ XmlRootElement 注解 指定对象序列化为xml或json数据时根节点的名称
 *
 * xml:
 * 		<User>
 * 		 	<id></id>
 * 		 	<username></username>
 * 		 	<city></city>
 * 		</User>
 *
 * json:
 * 		{"User": {"id": 100, "username": "one fine", "city": "昆明"}}
 */
@XmlRootElement(name = "User")
@Data
public class User {
    
    
    private Integer id;
    private String username;
    private String city;
    private List<Car> cars = new ArrayList<>();
}

package top.onefine.domain;

import lombok.Data;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Car")
@Data
public class Car {
    
    
    private Integer id;
    private String carName;
    private Double price;
}

package top.onefine.service;

import top.onefine.domain.User;

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;


@Path("/userService")  // @ Path 注解 表示访问当前服务接口对应的路径
@Produces("*/*")  // @ Produces 注解 表示服务器支持的返回数据格式的类型, */* 表示支持所有格式类型,下同
public interface IUserService {
    
    

	@POST  // 表示处理的请求的类型,这里是post请求
	@Path("/user")  // @ Path 注解 表示访问当前服务接口方法对应的路径,如这里是 .../userService/user
	@Consumes({
    
     "application/xml", "application/json" })  // @ Consumes 注解 表示服务器支持的请求数据格式类型
	void saveUser(User user);

	@PUT
	@Path("/user")
	@Consumes({
    
     "application/xml", "application/json" })
	void updateUser(User user);

	@GET
	@Path("/user")
	@Produces({
    
     "application/xml", "application/json" })
	List<User> findAllUsers();

	@GET
	@Path("/user/{id}")
	@Consumes("application/xml")
	@Produces({
    
     "application/xml", "application/json" })
	User finUserById(@PathParam("id") Integer id);

	@DELETE
	@Path("/user/{id}")
	@Consumes({
    
    "application/xml", "application/json"})
	void deleteUser(@PathParam("id") Integer id);
}

package top.onefine.service;

import top.onefine.domain.Car;
import top.onefine.domain.User;

import java.util.ArrayList;
import java.util.List;


public class UserServiceImpl implements IUserService {
    
    

	public void saveUser(User user) {
    
    
		System.out.println("save user:" + user);
	}

	public void updateUser(User user) {
    
    
		System.out.println("update user:" + user);
	}

	public List<User> findAllUsers() {
    
    
		List<User> users = new ArrayList<User>();
		User user1 = new User();
		user1.setId(1);
		user1.setUsername("小明");
		user1.setCity("北京");

		List<Car> carList1 = new ArrayList<Car>();
		Car car1 = new Car();
		car1.setId(101);
		car1.setCarName("保时捷");
		car1.setPrice(1000000d);
		carList1.add(car1);
		Car car2 = new Car();
		car2.setId(102);
		car2.setCarName("宝马");
		car2.setPrice(400000d);
		carList1.add(car2);
		user1.setCars(carList1);

		users.add(user1);

		User user2 = new User();
		user2.setId(2);
		user2.setUsername("小丽");
		user2.setCity("上海");
		users.add(user2);

		return users;
	}

	public User finUserById(Integer id) {
    
    
		if (id == 1) {
    
    
			User user1 = new User();
			user1.setId(1);
			user1.setUsername("小明");
			user1.setCity("北京");
			return user1;
		}
		return null;
	}

	public void deleteUser(Integer id) {
    
    
		System.out.println("delete user id :" + id);
	}

}

使用的注解分析

使用的注解:

@XmlRootElement 

指定根元素,

作用:客户端与服务端传递对象数据时候,序列化为xml或json的根元素的名称

@Path("/userService")  

路径;访问当前服务接口时候的路径、接口方法的路径。

 

@POST   insert操作

@PUT    update操作

@GET    select 查询操作

@DELETE   delete删除操作

 

@Consumes 服务端支持的请求的数据格式(xml、json)

@Produces 服务端支持的响应的数据格式

发布服务测试:

package top.onefine;

import lombok.extern.java.Log;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import top.onefine.service.UserServiceImpl;

/**
 * 发布restful风格的webservice的服务
 * 
 * @author one fine<br/>
 */
@Log
public class Server {
    
    

    public static void main(String[] args) {
    
    
        // 创建发布服务的工厂
        JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
        // 设置服务地址
        String address = "http://127.0.0.1:8001/ws/";
        factory.setAddress(address);

        // 添加日志输入输出拦截器
        factory.getInInterceptors().add(new LoggingInInterceptor());
        factory.getOutFaultInterceptors().add(new LoggingOutInterceptor());

        // 设置服务类
        factory.setServiceBean(new UserServiceImpl());
        // 发布服务
        factory.create();
        log.info("发布服务成功,地址: " + address);
    }
}

在这里插入图片描述

2 客户端

创建项目,添加依赖、日志输出格式

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         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>top.onefine</groupId>
    <artifactId>jaxrs_client</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <build>
        <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>
                    <encoding>UTF-8</encoding>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- 要进行jaxrs 服务开发 -->
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-frontend-jaxrs -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>3.3.6</version>
        </dependency>

        <!-- 客户端调用时候使用的包(WebClient工具类调用服务端) -->
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-rs-client -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-client</artifactId>
            <version>3.3.6</version>
        </dependency>

        <!-- 基于restful风格的webservice,客户端与服务端之间可以传递json,这个就是json支持相关包 -->
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-rs-extension-providers -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-extension-providers</artifactId>
            <version>3.3.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.codehaus.jettison/jettison -->
        <dependency>
            <groupId>org.codehaus.jettison</groupId>
            <artifactId>jettison</artifactId>
            <version>1.4.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.3.6</version>
            <scope>test</scope>
        </dependency>

        <!-- 日志实现 -->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>


</project>
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=info, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{
    
    ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{
    
    ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n


定义元数据:

package top.onefine.domain.domain;

import lombok.Data;

import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;

@XmlRootElement(name = "User")
@Data
public class User {
    
    
    private Integer id;
    private String username;
    private String city;
    private List<Car> cars = new ArrayList<>();
}

package top.onefine.domain.domain;

import lombok.Data;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Car")
@Data
public class Car {
    
    
    private Integer id;
    private String carName;
    private Double price;
}

写junit,远程访问服务端

WebClient

       .create()     指定服务端地址

       .type()      指定请求数据格式(xml、json)

       .accept()    指定响应数据格式

       .post()/put()/delete()/get()  指定请求类型
package top.onefine;

import org.apache.cxf.jaxrs.client.WebClient;
import org.junit.Test;
import top.onefine.domain.domain.User;

import javax.ws.rs.core.MediaType;

/**
 * @author one fine<br/>
 */
public class Client {
    
    

    // 服务端地址
    private final String address = "http://127.0.0.1:8001/ws/";

    @Test
    public void testSave() {
    
    
        User user = new User();
        user.setUsername("one fine");
        user.setId(101);
        user.setCity("昆明");

        // 通过webclient对象远程调用服务端
        WebClient
                .create(this.address + "userService/user")  // 指定服务端地址
                .type(MediaType.APPLICATION_JSON)  // 请求的数据格式,默认是xml
                .post(user);  // 指定请求类型及数据
    }

    @Test
    public void testGet() {
    
    
        // 查询一个
        User user = WebClient
                .create(this.address + "userService/user/1")  // 指定服务端地址
                .accept(MediaType.APPLICATION_JSON)  // 响应的数据格式
                .get(User.class);
        System.out.println(user);
    }
}

响应结果:

2020-06-27 17:47:20,313 12282  [tp1991313236-20] INFO  terceptor.LoggingInInterceptor  - Inbound Message
----------------------------
ID: 1
Address: http://127.0.0.1:8001/ws/userService/user/1
Http-Method: GET
Content-Type: 
Headers: {
    
    Accept=[application/json], Cache-Control=[no-cache], connection=[keep-alive], Content-Type=[null], Host=[127.0.0.1:8001], Pragma=[no-cache], User-Agent=[Apache-CXF/3.3.6]}
--------------------------------------
2020-06-27 17:47:20,788 12757  [tp1991313236-14] INFO  terceptor.LoggingInInterceptor  - Inbound Message
----------------------------
ID: 2
Address: http://127.0.0.1:8001/ws/userService/user
Encoding: UTF-8
Http-Method: POST
Content-Type: application/json
Headers: {
    
    Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[57], content-type=[application/json], Host=[127.0.0.1:8001], Pragma=[no-cache], User-Agent=[Apache-CXF/3.3.6]}
Payload: {
    
    "User":{
    
    "city":"昆明","id":101,"username":"one fine"}}
--------------------------------------
save user:User(id=101, username=one fine, city=昆明, cars=[])


其他栗子:

package com.itheima;

import com.itheima.domain.User;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.client.WebClient;
import org.junit.Test;

import javax.ws.rs.core.MediaType;
import java.util.Collection;

public class Client {
    
    

    @Test
    public void save() throws Exception {
    
    
        // 基于restful风格的webservice开发的客户端调用,直接通过一个类:WebClient类完成
        WebClient
                .create("http://localhost:8001/rs/userService/user")  // 地址
                .type(MediaType.APPLICATION_JSON)                     // 请求数据格式是json
                .post(new User(100,"Kobe","gz",null));                  // 发送请求的类型
    }

    @Test
    public void update() throws Exception {
    
    
        WebClient
                .create("http://localhost:8001/ws/userService/user")  // 地址
                .type(MediaType.APPLICATION_JSON)                     // 请求数据格式是json
                .put(new User(100,"Kobe","gz",null));                   // 发送请求的类型
    }

    @Test
    public void delete() throws Exception {
    
    

    }

    @Test
    public void findOne() throws Exception {
    
    
        User user =
                WebClient
                        .create("http://localhost:8001/ws/userService/user/1")  // 地址
                        .accept(MediaType.APPLICATION_JSON)  // 响应的数据格式
                        .get(User.class);
        System.out.println(user);
    }

    @Test
    public void findAll() throws Exception {
    
    
        Collection<? extends User> collection =
                WebClient
                        .create("http://localhost:8001/ws/userService/user")
                        .accept(MediaType.APPLICATION_JSON)
                        .getCollection(User.class);
        System.out.println(collection);
    }


}

七、 Sping整合CXF实现基于Restful风格的webservice(jax-rs)

1 服务端

创建web项目,添加依赖和日志格式:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         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>top.onefine</groupId>
    <artifactId>jaxrs_spring_server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <!-- cxf 进行rs开发 必须导入 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>3.0.1</version>
        </dependency>
        <!-- 日志引入 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>

        <!-- 客户端 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-client</artifactId>
            <version>3.0.1</version>
        </dependency>

        <!-- 扩展json提供者 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-extension-providers</artifactId>
            <version>3.0.1</version>
        </dependency>

        <!-- 转换json工具包,被extension providers 依赖 -->
        <dependency>
            <groupId>org.codehaus.jettison</groupId>
            <artifactId>jettison</artifactId>
            <version>1.3.7</version>
        </dependency>

        <!-- spring 核心 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <!-- spring web集成 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <!-- spring 整合junit -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <!-- junit 开发包 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

		<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>


    <build>
        <pluginManagement>
            <plugins>
                <!-- maven的jdk编译插件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.2</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                        <encoding>UTF-8</encoding>
                        <showWarnings>true</showWarnings>
                    </configuration>
                </plugin>
                <!-- 运行tomcat7方法:tomcat7:run -->
                <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>
        </pluginManagement>
    </build>
</project>

日志文件格式:log4j.properties

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=info, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{
    
    ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{
    
    ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <servlet>
        <servlet-name>cxfservlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>cxfservlet</servlet-name>
        <url-pattern>/ws/*</url-pattern>
    </servlet-mapping>

    <!-- 配置springioc容器 -->
    <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>

</web-app>

服务接口、实现、实体类

package top.onefine.domain;

import lombok.Data;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;

@XmlRootElement(name = "User")
@Data
public class User {
    
    
    private Integer id;
    private String username;
    private String city;
    private List<Car> cars = new ArrayList<>();
}

package top.onefine.domain;

import lombok.Data;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Car")
@Data
public class Car {
    
    
    private Integer id;
    private String carName;
    private Double price;
}

package top.onefine.service;

import jakarta.ws.rs.*;
import top.onefine.domain.User;

import java.util.List;


@Path("/userService")  // @ Path 注解 表示访问当前服务接口对应的路径
@Produces("*/*")  // @ Produces 注解 表示服务器支持的返回数据格式的类型, */* 表示支持所有格式类型,下同
public interface IUserService {
    
    

	@POST  // 表示处理的请求的类型,这里是post请求
	@Path("/user")  // @ Path 注解 表示访问当前服务接口方法对应的路径,如这里是 .../userService/user
	@Consumes({
    
     "application/xml", "application/json" })  // @ Consumes 注解 表示服务器支持的请求数据格式类型
	void saveUser(User user);

	@PUT
	@Path("/user")
	@Consumes({
    
     "application/xml", "application/json" })
	void updateUser(User user);

	@GET
	@Path("/user")
	@Produces({
    
     "application/xml", "application/json" })
	List<User> findAllUsers();

	@GET
	@Path("/user/{id}")
	@Consumes("application/xml")
	@Produces({
    
     "application/xml", "application/json" })
	User finUserById(@PathParam("id") Integer id);

	@DELETE
	@Path("/user/{id}")
	@Consumes({
    
    "application/xml", "application/json"})
	void deleteUser(@PathParam("id") Integer id);
}

package top.onefine.service;

import top.onefine.domain.Car;
import top.onefine.domain.User;

import java.util.ArrayList;
import java.util.List;


public class UserServiceImpl implements IUserService {
    
    

	public void saveUser(User user) {
    
    
		System.out.println("save user:" + user);
	}

	public void updateUser(User user) {
    
    
		System.out.println("update user:" + user);
	}

	public List<User> findAllUsers() {
    
    
		List<User> users = new ArrayList<User>();
		User user1 = new User();
		user1.setId(1);
		user1.setUsername("小明");
		user1.setCity("北京");

		List<Car> carList1 = new ArrayList<Car>();
		Car car1 = new Car();
		car1.setId(101);
		car1.setCarName("保时捷");
		car1.setPrice(1000000d);
		carList1.add(car1);
		Car car2 = new Car();
		car2.setId(102);
		car2.setCarName("宝马");
		car2.setPrice(400000d);
		carList1.add(car2);
		user1.setCars(carList1);

		users.add(user1);

		User user2 = new User();
		user2.setId(2);
		user2.setUsername("小丽");
		user2.setCity("上海");
		users.add(user2);

		return users;
	}

	public User finUserById(Integer id) {
    
    
		if (id == 1) {
    
    
			User user1 = new User();
			user1.setId(1);
			user1.setUsername("小明");
			user1.setCity("北京");
			return user1;
		}
		return null;
	}

	public void deleteUser(Integer id) {
    
    
		System.out.println("delete user id :" + id);
	}

}

Spring整合CXF

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

    <!--
        Spring整合ApacheCXF,发布jaxws服务:
        1. 服务地址
        2. 服务bean

        完整服务地址:
        http://localhost:8080/ws/userService
     -->
    <jaxrs:server address="/userService">
        <jaxrs:serviceBeans>
            <bean class="top.onefine.service.UserServiceImpl"></bean>
        </jaxrs:serviceBeans>
        <jaxrs:inInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
        </jaxrs:inInterceptors>
        <jaxrs:outInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
        </jaxrs:outInterceptors>
    </jaxrs:server>


</beans>

2 客户端

创建项目,添加依赖,日志格式,实体类——上面已经完成(无需service)

测试

package top.onefine;

import top.onefine.domain.User;
import org.apache.cxf.jaxrs.client.WebClient;

public class Client {
    
    

    public static void main(String[] args) {
    
    
        // 测试1: 保存
        WebClient
                .create("http://localhost:8080/ws/userService/userService/user")
                .post(new User());

        // 测试2:删除(传入id)
        WebClient
                .create("http://localhost:8080/ws/userService/userService/user/100")
                .delete();
    }
}

八、 小结

所以,以后如果在开发中涉及多个系统之间的交互,webservice是不错的选择。

个人认为使用service最大的好处是客户端与服务端语言的兼容性及交互时候可以传递对象。

猜你喜欢

转载自blog.csdn.net/jiduochou963/article/details/106943189