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包含了大量的功能特性,但是主要集中在以下几个方面:
- 支持Web Services 标准:CXF支持多种 Web Services 标准,包含 SOAP、BasicProfile、WS-Addressing、WS-Policy、WS-ReliableMessaging 和 WS-Security.
- Frontends:CXF支持多种“Frontend"编程模型,CXF 实现了JAX-WS API(遵循JAX-WS 2.0TCK版本),它也包含一个“simple frontend"允许客户端和 EndPoint 的创建,而不需要 Annotation 注解。CXF既支持WSDL优先开发,也支持从Java 的代码优先开发模式。
- 容易使用:CXF设计得更加直观与容易使用。有大量简单的API用来快速地构建代码优先的 Services,各种 Maven 的插件也使集成更加容易,支持JAX-WS API,支持Spring 2.0 更加简化的 XML 配置方式,等等。
- 支持二进制和遗留协议:CXF的设计是一种可插拨的架构。
ApacheCXF 实现 WebService (JAX-WS)
服务端
项目创建:
项目结构:
项目依赖:
<?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
客户端
项目创建:
项目结构:
项目依赖:
<?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);
}
}
测试结果:
添加 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)
服务端
项目创建:
项目结构:
项目依赖:
<?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>
客户端
项目创建:
项目结构:
项目依赖:
<?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)
服务端
项目创建:
项目结构:
项目依赖:
<?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);
}
}
客户端
项目创建:
项目结构:
项目依赖:
<?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生成客户端代码:
核心代码:
// 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风格
参考文献
黑马程序员