WebService 是一种基于标准化协议的网络服务技术,允许不同平台、不同语言的应用程序通过互联网进行交互。其核心目标是实现 跨平台、跨语言的系统间通信。
技术本质:
WebService 使用 XML 作为数据交换格式,通过 SOAP(Simple Object Access Protocol) 协议传输消息。
服务接口则通过 WSDL(Web Services Description Language) 描述,客户端可通过 WSDL 自动生成代码调用服务。
服务注册与发现可通过 UDDI(Universal Description, Discovery, Integration) 实现(尽管 UDDI 现在较少直接使用)。
SOAP是什么?
SOAP 就是一种基于 XML 的通信协议,是 WebService 的核心传输协议,设计目标是确保不同平台、不同语言的系统之间能可靠通信。
核心特点:
平台和语言无关:基于 XML 的纯文本格式,任何支持 HTTP 和 XML 的系统均可使用。
协议中立:虽然通常基于 HTTP,但也支持 SMTP、TCP 等传输协议。
强类型和严格规范:通过 XML Schema 定义数据类型,确保消息结构的严格性。
可扩展性:支持通过 SOAP Header 添加安全、事务等扩展功能(如 WS-Security)。
<!-- SOAP 消息示例 -->
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<!-- 可选的扩展信息(如认证令牌、事务ID) -->
<auth:Token xmlns:auth="http://example.com/auth">
<auth:Value>ABC123</auth:Value>
</auth:Token>
</soap:Header>
<soap:Body>
<!-- 实际请求或响应的数据 -->
<m:sayHello xmlns:m="http://example.com/ws">
<m:name>World</m:name>
</m:sayHello>
</soap:Body>
</soap:Envelope>
Envelope:根元素,标识这是一个 SOAP 消息。
Header(可选):包含元数据(如安全令牌、事务信息)。
Body:核心内容,存放请求或响应的具体数据。
SOAP 的请求-响应流程:
客户端构造一个 SOAP 请求(XML),通过 HTTP POST 发送到服务端。
服务端解析请求,执行业务逻辑,生成 SOAP 响应(XML)返回给客户端。
客户端解析响应,提取所需数据。
WSDL是什么?
WSDL 是一种基于 XML用于描述 WebService 接口的说明文档。
它定义了以下内容:
服务提供哪些操作(方法)。
如何调用这些操作(输入/输出参数的数据类型)。
服务访问的地址(URL)和通信协议(如 SOAP)。
<!-- WSDL 文件结构示例 -->
<wsdl:definitions
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://example.com/ws"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="HelloService" targetNamespace="http://example.com/ws">
<wsdl:types>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://example.com/ws" elementFormDefault="unqualified" targetNamespace="http://example.com/ws" version="1.0">
<xs:element name="sayHello" type="tns:sayHello"/>
<xs:element name="sayHelloResponse" type="tns:sayHelloResponse"/>
<xs:complexType name="sayHello">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sayHelloResponse">
<xs:sequence>
<xs:element minOccurs="0" name="response" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="sayHelloResponse">
<wsdl:part element="tns:sayHelloResponse" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="sayHello">
<wsdl:part element="tns:sayHello" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:portType name="HelloService">
<wsdl:operation name="sayHello">
<wsdl:input message="tns:sayHello" name="sayHello"></wsdl:input>
<wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloServiceSoapBinding" type="tns:HelloService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHello">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="sayHello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sayHelloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloService">
<wsdl:port binding="tns:HelloServiceSoapBinding" name="HelloServicePort">
<soap:address location="http://localhost:8080/services/hello"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
types:定义方法参数和返回值的数据类型(基于 XML Schema)。
message:定义方法调用的输入/输出消息格式。
portType:定义服务提供的操作(类似 Java 接口)。
binding:指定协议(如 SOAP)和传输方式(如 HTTP)。
service:定义服务的访问地址(URL)。
作用:
服务描述:客户端通过 WSDL 了解如何调用服务(方法名、参数、返回值)。
代码生成:工具(如 wsimport)可根据 WSDL 自动生成客户端代理代码。
# 使用 wsimport 生成客户端代码(Java)
wsimport -keep http://localhost:8080/hello?wsdl
WebService 开发规范
webserivce实现框架
Apache CXF 实现 WebService
其核心原理如下:
服务端定义接口并实现:使用 @WebService 注解标记服务接口,并实现它。
CXF 负责将 Java 方法转换为 SOAP WebService:CXF 使用 JAX-WS 标准,将 Java 代码映射为 WSDL,并提供基于 HTTP/SOAP 协议的通信方式。
客户端使用 CXF 生成代码进行调用:通过maven插件生成客户端代理代码,或者直接使用 Service 代理调用远程 WebService。
<!-- Apache CXF Starter(支持 JAX-WS) -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>4.0.2</version>
</dependency>
package com.example.webservice;
import jakarta.jws.WebMethod;
import jakarta.jws.WebParam;
import jakarta.jws.WebResult;
import jakarta.jws.WebService;
// 定义 WebService 接口
@WebService(name = "HelloService", targetNamespace = "http://example.com/ws")
public interface HelloService {
@WebMethod
@WebResult(name = "response")
String sayHello(@WebParam(name = "name") String name);
}
package com.example.webservice;
import jakarta.jws.WebService;
import org.springframework.stereotype.Service;
// 实现 WebService 接口
@Service
@WebService(
endpointInterface = "com.example.webservice.HelloService",
targetNamespace = "http://example.com/ws",
serviceName = "HelloService",
portName = "HelloServicePort"
)
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name + "! Welcome to CXF WebService.";
}
}
package com.example.webservice.config;
import com.example.webservice.HelloService;
import jakarta.xml.ws.Endpoint;
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;
@Configuration
public class CxfConfig {
private final HelloService helloService;
public CxfConfig(HelloService helloService) {
this.helloService = helloService;
}
// 配置 CXF 总线
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
// 注册 WebService 端点
@Bean
public Endpoint helloServiceEndpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), helloService);
endpoint.publish("/hello"); // 访问地址:http://localhost:8080/services/hello?wsdl
return endpoint;
}
}
使用 Maven 生成 WebService 客户端代码
<build>
<plugins>
<!-- CXF Codegen Plugin for wsdl2java -->
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>4.0.2</version> <!-- 版本可以根据实际情况调整 -->
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>wsdl2java</goal>
</goals>
<configuration>
<wsdlOptions>
<wsdlOption>
<!-- 这里替换成你的 WSDL 地址 -->
<wsdl>http://localhost:8080/services/hello?wsdl</wsdl>
<packageName>com.example.client</packageName>
</wsdlOption>
</wsdlOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
启动应用访问:http://localhost:8080/services/hello?wsdl
执行maven命令
mvn clean generate-sources
代码生成到target/generated-sources/cxf/com/example/client路径,例如:
HelloService.java(WebService 客户端接口)
HelloService_Service.java(服务工厂类)
ObjectFactory.java(辅助类)
其他 JAXB 相关的 XML 绑定类(用于数据转换)
客户端调用
package com.example.client;
import com.example.webservice.HelloService;
import com.example.webservice.HelloService_Service;
public class WebServiceClient {
public static void main(String[] args) {
// 1. 创建 WebService 访问工厂类
HelloService_Service serviceFactory = new HelloService_Service();
// 2. 获取 WebService 代理
HelloService helloService = serviceFactory.getHelloServicePort();
// 3. 调用 WebService 方法
String response = helloService.sayHello("Alice");
// 4. 输出结果
System.out.println("WebService 响应: " + response);
}
}