Web Service 学习笔记

Web Service 学习笔记

Web Service 基本概念

Web Service 即 web 服务,它是一种跨编程语言和跨操作系统平台的远程调用技术。

Java 中共有三种 Web Service 规范:

  • JAX-WS(JAX-RPC): 基于 xml 数据
  • JAXM&SAAJ
  • JAX-RS:基于 xml 或 json 数据

Web Service 的三要素:

  • SOAP
  • WSDL
  • UDDI

术语

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.* 包,它是 Java EE 的可选包,因此你需要单独下载。
  • SAAJ(SOAP With Attachment API For Java, JSR 67) 是与 JAXM 搭配使用的 API,为构建 SOAP 包和解析 SOAP 包提供了重要的支持,支持附件传输,它在服务器端、客户端都需要使用,其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 服务规范。由于推出的较晚,该规范(JSR311, 目前JAX-RS的版本为1.0)并未随JDK1.6 一起发行,你需要到 JCP 上单独下载 JAX-RS 规范的接口,其API位于 Javax.ws.rs.* 包。

这里的 JAX-WS 和 JAX-RS 规范我们采用 Apache CXF 作为实现,CXF 是ObjectWeb Celtix和CodeHaus XFire的合并,旨在提供高性能、可扩展且直观易用的环境来实现SOA(面向服务的架构)解决方案。 CXF支持多种标准,包括JAX-WS、JAX-RS,以及各种SOAP和WSDL版本。

SOAP 协议:

  • SOAP 即简单对象访问协议(Simple Object Access Protocol),它是用于交换 XML (标准通用标记语言下的一个子集),编码信息的轻量级协议,它有三个主要方面,XML-envelope 为描述消息内容和如何处理内容定义了框架,将程序对象编码成为 XML 对象的规则,执行远程过程调用(RPC)的约定。SOAP 可以运行在任何其他传输协议上。
  • SOAP作为一个基于XML语言的协议用于在网上传输数据。
  • SOAP = 在HTTP基础上 + XML 数据
  • SOAP 是基于 HTTP 的
  • SOAP 的组成:
    • Envelope:必须的部分,以 XML 的根元素出现
    • Headers: 可选的
    • Body: 必须的,在 Body 部分,包含要执行的服务器方法,和发送到服务器的数据。

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

  • 通过 WSDL 说明书,就可以描述 Web service 服务端对外发布的服务
  • WSDL 说明书是一个基于 XML 的文件,通过 XML 语言描述整个服务
  • 在 WSDL 说明中,描述了对外发布的服务名称(类)、接口方法名称(方法)、接口参数(方法参数)、服务返回的数据类型(方法返回值)

UDDI: UDDI 即(Universal Descriptoin, Discovery And Integration) 也就是通用的描述、发行以及整合。是一个跨产业、跨平台的开放性架构,可以帮助 Web 服务提供商在互联网上发布 Web 服务的信息。UDDI 是一种目录服务,企业可以通过 UDDI 来注册和搜索 Web服务,并且 UDDI 通过 SOAP 进行通讯,构建于 .net 之上。

应用场景

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

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

优缺点

优点:

  • 异构平台的互通性
  • 更广泛的软件复用
  • 成本低、可读性强、应用范围广
  • 迅捷的软件发行方式

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

面向服务架构 SOA

SOA(Service-OrientedArchitecture)面向服务架构是一种思想,它将应用程序的不同功能单元通过中立的契约(独立于硬件平台、操作系统和编程语言)联系起来,使得各种形式的功能单元更好的集成。目前来说,WebService是SOA的一种较好的实现方式,WebService 采用 HTTP 作为传输协议,SOAP(Simple Object Access Protocol)作为传输消息的格式。但 WebService 并不是完全符合 SOA 的概念,因为 SOAP 协议是WebService 的特有协议,并未符合SOA的传输协议透明化的要求。SOAP是一种应用协议,早期应用于RPC的实现,传输协议可以依赖于HTTP、SMTP等。

Apache CXF 框架介绍

Apache CXF

Apache CXF = Celtix + XFire, ApacheCXF 的前身叫 Apache CeltiXfire,现在已经正式更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和XFire 两大开源项目的精华,提供了对JAX-WS 全面的支持,并且提供了多种 Binding、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者WSDL优先(WSDLFirst)来轻松地实现 Web Services 的发布和使用。目前它仍只是 Apache 的一个孵化项目。
Apache CXF 是一个开源的 Services 框架,CXF 帮助您利用 Frontend 编程 API 来构建和开发Services,像 JAX-WS。这些 Services 可以支持多种协议,比如: SOAPXML/HTTP、RESTfulHTTP或者CORBA,并且可以在多种传输协议上运行,比如:HTTP、JMS 或者JBI,CXF 大大简化了 Services 的创建,同时它继承了 XFire 传统,样可以天然地和 Spring 进行无缝集成。

功能特性

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

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

ApacheCXF 实现 WebService (JAX-WS)

服务端

项目创建:
Server项目创建

项目结构:

Server项目结构

项目依赖:

<?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>com.joe</groupId>
    <artifactId>jaxws_server</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>jaxws_server</name>

    <dependencies>
        <!-- 要进行jaxws 服务开发 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.0.1</version>
        </dependency>

        <!-- 内置jetty web服务器  -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>3.0.1</version>
        </dependency>

        <!-- 日志实现 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <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>
        </plugins>
    </build>
</project>

核心代码:

// HelloService.java
package com.joe.service;

import javax.jws.WebService;

/**
 * @Description 对外发布服务的接口
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@WebService
public interface HelloService {

    /**
     * 对外发布的服务的接口的方法
     * @param name
     * @return
     */
    String sayHello(String name);
}

// HelloServiceImpl.java
package com.joe.service.impl;

import com.joe.service.HelloService;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "Say Hello:".concat(name);
    }
}

// Server.java
package com.joe;

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

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
public class Server {

    public static void main(String[] args) {
        // 发布服务的工厂
        JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
        // 设置服务地址
        factoryBean.setAddress("http://127.0.0.1:8081/ws/hello");
        // 设置服务类
        factoryBean.setServiceBean(new HelloServiceImpl());
        // 发布服务
        factoryBean.create();

        System.out.println("发布服务成功,地址: " + factoryBean.getAddress());
    }
}

WSDL文档访问: 访问地址 http://127.0.0.1:8081/ws/hello?wsdl

WSDL文档

客户端

项目创建:

Client项目创建

项目结构:

Client项目结构

项目依赖:

<?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>com.joe</groupId>
    <artifactId>jaxws_client</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>jaxws_client</name>

    <dependencies>
        <!-- 要进行jaxws 服务开发 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.0.1</version>
        </dependency>

        <!-- 内置jetty web服务器  -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>3.0.1</version>
        </dependency>

        <!-- 日志实现 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <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>
        </plugins>
    </build>
</project>

核心代码:

# log4j.properties
# Root logger option
log4j.rootLogger=INFO, stdout, file
# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Redirect log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=/logs/logfile.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
// HelloService.java
package com.joe.service;

import javax.jws.WebService;

/**
 * @Description 对外发布服务的接口
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@WebService
public interface HelloService {

    /**
     * 对外发布的服务的接口的方法
     * @param name
     * @return
     */
    String sayHello(String name);
}

// Client.java
package com.joe;

import com.joe.service.HelloService;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@Slf4j
public class Client {

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

        // 创建 CXF 代理工厂
        JaxWsProxyFactoryBean proxyFactoryBean = new JaxWsProxyFactoryBean();
        // 设置远程访问服务端的地址
        proxyFactoryBean.setAddress("http://127.0.0.1:8081/ws/hello");
        // 设置接口类型
        proxyFactoryBean.setServiceClass(HelloService.class);
        // 对接口生成代理对象
        HelloService helloService = proxyFactoryBean.create(HelloService.class);

        // 代理对象
        log.info("helloService: {}", helloService.getClass());
        // 远程访问服务端方法
        String res = helloService.sayHello("joe");
        log.info("helloService sayHello: {}", res);
    }
}

测试结果:

client测试结果

添加 ApacheCXF 日志拦截器观察soap请求、soap响应格式内容

// Server.java
package com.joe;

import com.joe.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;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@Slf4j
public class Server {

    public static void main(String[] args) {
        // 发布服务的工厂
        JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
        // 设置服务地址
        factoryBean.setAddress("http://127.0.0.1:8081/ws/hello");
        // 设置服务类
        factoryBean.setServiceBean(new HelloServiceImpl());
        // 设置日志输入、输出拦截器,观察 soap 请求、soap响应内容
        factoryBean.getInInterceptors().add(new LoggingInInterceptor());
        factoryBean.getOutInterceptors().add(new LoggingOutInterceptor());

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

        log.info("发布服务成功,地址: {}", factoryBean.getAddress());
    }
}

测试结果:

日志拦截器

Spring 整合 ApacheCXF 实现 WebService (JAX-WS)

服务端

项目创建:

SpringServer项目创建

项目结构:

SpringServer项目结构

项目依赖:

<?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>com.joe</groupId>
    <artifactId>spring_jaxws_server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>spring_jaxws_server Maven Webapp</name>
    <dependencies>
        <!-- CXF WS开发  -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.0.1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <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>
    </build>
</project>

核心代码:

// HelloService.java
package com.joe.service;

import javax.jws.WebService;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@WebService
public interface HelloService {

    String sayHello(String name);
}

// HelloServiceImpl.java
package com.joe.service.impl;

import com.joe.service.HelloService;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "say hello, " + name;
    }
}
<!-- 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"
       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.服务地址
        2.服务类
        服务的完整访问地址
            http://127.0.0.1:8080/ws/hello
    -->
    <jaxws:server address="/hello">
        <jaxws:serviceBean>
            <bean class="com.joe.service.impl.HelloServiceImpl"></bean>
        </jaxws:serviceBean>
    </jaxws:server>

</beans>

<!-- web.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app
        version="4.0"
        xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:javaee="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xml="http://www.w3.org/XML/1998/namespace"
        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">
    <display-name>Archetype Created Web Application</display-name>
    <!-- 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>
    <!-- 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>

客户端

项目创建:

SpringClient项目创建

项目结构:

SpringClient项目结构

项目依赖:

<?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>com.joe</groupId>
    <artifactId>spring_jaxws_client</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>spring_jaxws_client</name>
    <dependencies>
        <!-- CXF WS开发  -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.0.1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <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>
    </build>
</project>

核心代码:

// HelloService.java
package com.joe.service;

import javax.jws.WebService;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@WebService
public interface HelloService {

    String sayHello(String name);
}

// Client.java
package com.joe;

import com.joe.service.HelloService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Client {

    @Resource
    private HelloService helloService;

    @Test
    public void callSayHello(){
        // 查看接口的代理状态
        System.out.println(helloService.getClass());
        // 远程访问服务端的方法
        String res = helloService.sayHello("joe");
        System.out.println("helloService sayHello: ".concat(res));
    }
}

<!-- 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"
       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.服务接口类型
        服务的完整访问地址

    -->
    <jaxws:client
            id="helloService"
            serviceClass="com.joe.service.HelloService"
            address="http://127.0.0.1:8080/ws/hello">
    </jaxws:client>

</beans>

SpringBoot 整合 ApacheCXF 实现 WebService (JAX-WS)

服务端

项目创建:

SpringBootServer项目创建

项目结构:

SpringBootServer项目结构

项目依赖:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.13</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.joe</groupId>
    <artifactId>springboot_jaxws_server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot_jaxws_server</name>
    <description>springboot_jaxws_server</description>

    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

核心代码:

// CxfConfig.java
package com.joe.demo.config;

import com.joe.demo.service.HelloService;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import javax.xml.ws.Endpoint;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@Configuration
public class CxfConfig implements WebMvcConfigurer {

    @Resource
    private HelloService helloService;

    /**
     * 非必要项
     * 用于打印cxf日志信息
     */
    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        SpringBus springBus = new SpringBus();

        //将cxf拦截器添加到bus里
        CxfInterceptor cxfInterceptor = new CxfInterceptor();
        springBus.getInInterceptors().add(cxfInterceptor);
        return springBus;
    }

    /**
     * 发布endpoint
     */
    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), helloService);
        endpoint.publish("/ws");
        return endpoint;
    }

    @Bean
    public CxfInterceptor getCxfInterceptor() {
        return new CxfInterceptor();
    }
}

// CxfInterceptor.java
package com.joe.demo.config;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.List;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
public class CxfInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

    private static final Logger log = LogManager.getLogger(CxfInterceptor.class);

    public CxfInterceptor(String phase) {
        super(phase);
    }

    public CxfInterceptor(){
        super(Phase.PRE_PROTOCOL);
    }

    @Override
    public void handleMessage(SoapMessage message) throws Fault {

        System.out.println("=======================================");
        List<Header> headers = message.getHeaders();
        log.info(headers);
    }
}

// HelloService.java
package com.joe.demo.service;

import javax.jws.WebService;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@WebService
public interface HelloService {

    public String sayHello(String name);
}

// HelloServiceImpl.java
package com.joe.demo.service.impl;

import com.joe.demo.service.HelloService;
import org.springframework.stereotype.Component;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
@Component
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "say hello ".concat(name);
    }
}

// SpringbootJaxwsServerApplication.java
package com.joe.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootJaxwsServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootJaxwsServerApplication.class, args);
    }

}

客户端

项目创建:

SpringBootClient项目创建

项目结构:

SpringBootClient项目结构

项目依赖:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.13</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.joe</groupId>
    <artifactId>springboot-jaxws-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-jaxws-client</name>
    <description>springboot-jaxws-client</description>

    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

根据wsdl生成客户端代码:

step-1

step-2

step-3

核心代码:

// HelloWorldClient.java
package example;

import com.joe.springbootjaxwsclient.client.HelloService;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

/**
 * @Description
 * @Author 高建伟-joe
 * @Date 2024-11-17
 */
public class HelloWorldClient {
  public static void main(String[] argv) {
    String address = "http://127.0.0.1:8080/services/ws?wsdl";
    // 代理工厂
    JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
    // 设置代理地址
    jaxWsProxyFactoryBean.setAddress(address);
    // 设置接口类型
    jaxWsProxyFactoryBean.setServiceClass(HelloService.class);
    // 创建一个代理接口实现
    HelloService cs = (HelloService) jaxWsProxyFactoryBean.create();
    // 调用代理接口的方法调用并返回结果
    String rs = cs.sayHello("joe");
    System.out.println("==============\n返回结果:" + rs);
  }
}


// SpringbootJaxwsClientApplication.java
package com.joe.springbootjaxwsclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootJaxwsClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootJaxwsClientApplication.class, args);
    }
}

Restful 介绍

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

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

Restful 风格:

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

访问服务器资源,通过不同的http请求方式,服务器就知道对CRUD的哪个操作!
JAX-RS 发布服务就是使用RESTFUL风格

参考文献

黑马程序员

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/917958.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫——JSON数据处理

第三节&#xff1a;JSON数据处理 在爬虫开发中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;是最常见的数据格式之一&#xff0c;特别是在从API或动态网页中抓取数据时。JSON格式因其结构简单、可读性强、易于与其他系统交互而广泛应用于前端与后端的数…

计算机编程中的设计模式及其在简化复杂系统设计中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 计算机编程中的设计模式及其在简化复杂系统设计中的应用 计算机编程中的设计模式及其在简化复杂系统设计中的应用 计算机编程中的…

【Tealscale + Headscale + 自建服务器】异地组网笔记

文章目录 效果为什么要用 Headscale云服务器安装 Headscale配置 config.yaml创建反向代理搭建管理 UI授权管理 UI添加互联设备参考 效果 首先是连接情况&#xff0c;双端都连接上自建的 Headscale&#xff0c; 手机使用移动流量&#xff0c;测试一下 ping 值 再试试进入游戏 可…

单片机学习笔记 2. LED灯闪烁

目录 0、实现的功能 1、Keil工程 2、代码实现 0、实现的功能 LED灯闪烁 1、Keil工程 闪烁原理&#xff1a;需要进行软件延时达到人眼能分辨出来的效果。常用的延时方法有软件延时和定时器延时。此次先进行软件延时 具体操作步骤和之前的笔记一致。此次主要利用无符号整型的范…

【Cesium】自定义材质,添加带有方向的滚动路线

【Cesium】自定义材质&#xff0c;添加带有方向的滚动路线 &#x1f356; 前言&#x1f3b6;一、实现过程✨二、代码展示&#x1f3c0;三、运行结果&#x1f3c6;四、知识点提示 &#x1f356; 前言 【Cesium】自定义材质&#xff0c;添加带有方向的滚动路线 &#x1f3b6;一、…

Vue之插槽(slot)

插槽是vue中的一个非常强大且灵活的功能&#xff0c;在写组件时&#xff0c;可以为组件的使用者预留一些可以自定义内容的占位符。通过插槽&#xff0c;可以极大提高组件的客服用和灵活性。 插槽大体可以分为三类&#xff1a;默认插槽&#xff0c;具名插槽和作用域插槽。 下面…

从零开始深度学习:全连接层、损失函数与梯度下降的详尽指南

引言 在深度学习的领域&#xff0c;全连接层、损失函数与梯度下降是三块重要的基石。如果你正在踏上深度学习的旅程&#xff0c;理解它们是迈向成功的第一步。这篇文章将从概念到代码、从基础到进阶&#xff0c;详细剖析这三个主题&#xff0c;帮助你从小白成长为能够解决实际…

Python 绘图工具详解:使用 Matplotlib、Seaborn 和 Pyecharts 绘制散点图

目录 数据可视化1.使用 matplotlib 库matplotlib 库 2 .使用 seaborn 库seaborn 库 3 .使用 pyecharts库pyecharts库 注意1. 确保安装了所有必要的库2. 检查Jupyter Notebook的版本3. 使用render()方法保存为HTML文件4. 使用IFrame在Notebook中显示HTML文件5. 检查是否有其他输…

【C++】vector 类模拟实现:探索动态数组的奥秘

&#x1f31f; 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。&#x1f31f; 如果你对string&#xff0c;vector还存在疑惑&#xff0c;欢迎阅读我之前的作品 &#xff1a; 之前文章&#x1f525;&#x1f52…

【ubuntu18.04】vm虚拟机复制粘贴键不能用-最后无奈换版本

我是ubuntu16版本的 之前费老大劲安装的vmware tools结果不能用 我又卸载掉&#xff0c;安装了open-vm-tools 首先删除VMware tools sudo vmware-uninstall-tools.pl sudo rm -rf /usr/lib/vmware-tools sudo apt-get autoremove open-vm-tools --purge再下载open-vm-tools s…

使用原生 OpenTelemetry 解锁各种可能性:优先考虑可靠性,而不是专有限制

作者&#xff1a;来自 Elastic Bahubali Shetti•Miguel Luna Elastic 现在支持使用 OTel Operator 在 Kubernetes 上部署和管理 Elastic Distributions of OpenTelemetry (EDOT)。SRE 现在可以访问开箱即用的配置和仪表板&#xff0c;这些配置和仪表板旨在通过 Elastic Observ…

【freertos】FreeRTOS信号量的介绍及使用

FreeRTOS信号量 一、概述二、PV原语三、函数接口1.创建一个计数信号量2.删除一个信号量3.信号量释放4.在中断释放信号量5.获取一个信号量&#xff0c;可以是二值信号量、计数信号量、互斥量。6.在中断获取一个信号量&#xff0c;可以是二值信号量、计数信号量7.创建一个二值信号…

【生物服务器】数据分析//论文润色/组学技术服务 、表观组分析、互作组分析、遗传转化实验、生物医学

DNA亲和纯化测序&#xff08;DAP-seq&#xff09;和组蛋白甲基化修饰是表观遗传学研究中两个重要的技术手段&#xff0c;它们在揭示基因表达调控机制和染色质结构动态变化中发挥着关键作用。然而&#xff0c;在实践过程中&#xff0c;这两种技术也存在一些痛点和挑战。 DNA亲和…

丹摩征文活动| 摩智云端深度解析:Faster R-CNN模型的训练与测试实战指南

目录 丹摩简介 文章前言Faster R-CNN的简介Faster RCNN的训练与测试提前准备1.1 mobaxterm&#xff08;远程连接服务器&#xff09;1.2 本文的源码下载 目标检测模型 Faster-Rcnn2.1云服务器平台 数据上传内置JupyterLab的使用本地连接使用DAMODEL实例获取实例的SSH访问信息通过…

二叉搜索树介绍

⼆叉搜索树 二叉搜索树的概念二叉搜索树的性能分析查找性能插入性能删除性能 二叉搜索树的插入二叉搜索树的查找二叉搜索树的删除⼆叉搜索树的实现代码测试代码 二叉搜索树key和key/value使⽤场景key搜索场景key/value搜索场景key/value⼆叉搜索树代码实现测试代码 二叉搜索树的…

7.揭秘C语言输入输出内幕:printf与scanf的深度剖析

揭秘C语言输入输出内幕&#xff1a;printf与scanf的深度剖析 C语言往期系列文章目录 往期回顾&#xff1a; VS 2022 社区版C语言的安装教程&#xff0c;不要再卡在下载0B/s啦C语言入门&#xff1a;解锁基础概念&#xff0c;动手实现首个C程序C语言概念之旅&#xff1a;解锁关…

5.4.2-1 编写Java程序在HDFS上创建文件

本次实战涉及使用Java操作Hadoop HDFS&#xff0c;包括创建文件、判断文件存在性及异常处理。通过手动添加依赖、启动HDFS服务&#xff0c;成功在HDFS上创建和检查文件。进一步探索了文件操作的最佳实践&#xff0c;如检查文件存在性以避免重复创建&#xff0c;以及处理HDFS安全…

RabbitMQ教程:路由(Routing)(四)

文章目录 RabbitMQ教程&#xff1a;路由&#xff08;Routing&#xff09;&#xff08;四&#xff09;一、引言二、基本概念2.1 路由与绑定2.2 Direct交换机2.3 多绑定2.4 发送日志2.5 订阅 三、整合代码3.1 EmitLogDirectApp.cs3.2 ReceiveLogsDirectApp.cs3.3 推送所有和接收e…

智云-一个抓取web流量的轻量级蜜罐v1.5

智云-一个抓取web流量的轻量级蜜罐v1.5 github地址 https://github.com/xiaoxiaoranxxx/POT-ZHIYUN 新增功能-自定义漏洞信息 可通过正则来添加相关路由以及响应来伪造 nacos的版本响应如下 日流量态势 月流量态势 抓取流量效果

21.UE5游戏存档,读档,函数库

2-23 游戏存档、读档、函数库_哔哩哔哩_bilibili 目录 1.存档蓝图 2.函数库 2.1保存存档 2.2读取存档&#xff1a; 3.加载游戏&#xff0c;保存游戏 3.1游戏实例对象 3.2 加载游戏 3.3保存游戏 这一节的内容较为错综复杂&#xff0c;中间没有运行程序进行阶段性成果的验…