这是我参与更文挑战的第 3 天,活动详情查看: 更文挑战
日积月累,水滴石穿 😄
在工作当中经常需要与第三方对接,某些第三方提供的接口是 WebService
类型的,所以需要集成 WebService
由于 SpringBoot
提供了 WebService
的 starter
组件,所以集成 WebService
相当的简单
加入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
服务端
创建WebService接口
package com.gongj.webservice_server.service;
import com.gongj.webservice_server.DTO.UserDTO;
import javax.jws.WebService;
public interface IUserServer {
UserDTO getUser(Long str);
}
创建实体类
@Data
public class UserDTO {
private Long id;
private String name;
private Integer age;
private String address;
}
创建WebService接口的实现类
package com.gongj.webservice_server.service.impl;
import com.gongj.webservice_server.DTO.UserDTO;
import com.gongj.webservice_server.service.IUserServer;
import org.springframework.stereotype.Service;
import javax.jws.WebService;
@Service
@WebService
public class UserServerImpl implements IUserServer {
@Override
public UserDTO getUser(Long id) {
UserDTO user = new UserDTO();
user.setId(id);
user.setAddress("上海市浦东新区");
user.setAge(25);
user.setName("gongj");
return user;
}
}
这里用到了一个注解@WebService
,我这就只在实现类上使用了。这里介绍一下,先来看下它的定义:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface WebService {
String name() default "";
String targetNamespace() default "";
String serviceName() default "";
String portName() default "";
String wsdlLocation() default "";
String endpointInterface() default "";
}
- name:对应
wsdl:portType
标签,默认值为 Java 类或接口的名称 - targetNamespace:命名空间,一般写为接口的包名倒序,默认值也是接口的包名倒序。对应
wsdl:definitions:targetNamespace
标签, - serviceName:
WebService
的服务名称,对应wsdl:service
,默认值为WebService
接口实现类的名称+ “Service”,示例:UserServerImplService
- portName:对应
wsdl:port
标签,默认值为:WebService
接口实现类的名称 + "Port",示例:UserServerImplPort
- wsdlLocation:指定用于定义
WebService
的 WSDL 文档的地址 - endpointInterface:
WebService
接口全路径
创建 WebService 配置类
package com.gongj.webservice_server.config;
import com.gongj.webservice_server.service.IUserServer;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;
@Configuration
public class CxfConfig {
@Autowired
private IUserServer userServer;
/**
* 注入Servlet 注意beanName不能为dispatcherServlet
* @return
*/
@Bean
public ServletRegistrationBean cxfServlet() {
return new ServletRegistrationBean(new CXFServlet(),"/webservice/*");
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
@Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), userServer);
endpoint.publish("/api");
return endpoint;
}
}
启动服务,进行访问:http://localhost:8080/webservice
点击链接跳转,我们会看到一个页面,这是 wsdl 服务描述文档。对于这个文档也需要简单的了解一下,也许某次对接第三方系统直接给你一个 wsdl 文档让你自己看去,注意:wsdl 文档是从下往上看的。
wsdl 文档
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://impl.service.webservice_server.gongj.com/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="UserServerImplService"
targetNamespace="http://impl.service.webservice_server.gongj.com/">
<!-- web service 使用的数据类型 -->
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://impl.service.webservice_server.gongj.com/" elementFormDefault="unqualified" targetNamespace="http://impl.service.webservice_server.gongj.com/" version="1.0">
<xs:element name="getUser" type="tns:getUser"/>
<xs:element name="getUserResponse" type="tns:getUserResponse"/>
<!-- getUser 方法的请求参数类型 -->
<xs:complexType name="getUser">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:long"/>
</xs:sequence>
</xs:complexType>
<!-- getUser 方法的响应参数类型 -->
<xs:complexType name="getUserResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="tns:userDTO"/>
</xs:sequence>
</xs:complexType>
<!-- getUser 方法的响应参数的具体类型 -->
<xs:complexType name="userDTO">
<xs:sequence>
<xs:element minOccurs="0" name="address" type="xs:string"/>
<xs:element minOccurs="0" name="age" type="xs:int"/>
<xs:element minOccurs="0" name="id" type="xs:long"/>
<xs:element minOccurs="0" name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<!--
message:用来定义soap消息结构
part:引用上面 types 中的约束格式
-->
<wsdl:message name="getUser">
<wsdl:part element="tns:getUser" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getUserResponse">
<wsdl:part element="tns:getUserResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<!--
portType:用来指定服务器端的接口
operation:接口中定义的方法
input:方法getUser的输入
output:方法getUser的输出
输入输出引用的是上面message的定义
-->
<wsdl:portType name="UserServerImpl">
<wsdl:operation name="getUser">
<wsdl:input message="tns:getUser" name="getUser">
</wsdl:input>
<wsdl:output message="tns:getUserResponse" name="getUserResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<!--
type属性:引用<portType>的定义
<soap:binding style="document">:表示传输的一个document (xml)
<input><output>方法的输入、输出
<soap:body use="literal" />:表示body传输采用文本即xml格式的文本
-->
<wsdl:binding name="UserServerImplServiceSoapBinding" type="tns:UserServerImpl">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getUser">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="getUser">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getUserResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<!--
name:用于指定客户端的容器类/工厂类
binding:引用上面的 binding 标签
port name:容器通过这个方法获得实现类,自动生成会出现这个类,可以不用管
address:客户端真正用于请求的地址
-->
<wsdl:service name="UserServerImplService">
<wsdl:port binding="tns:UserServerImplServiceSoapBinding" name="UserServerImplPort">
<soap:address location="http://localhost:8080/webservice/api"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
客户端
加入依赖
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.3.4</version>
</dependency>
调用
public static void main(String[] args) {
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("http://localhost:8080/webservice/api?wsdl");
ObjectMapper mapper = new ObjectMapper();
try {
// invoke("方法名",参数1,参数2,参数3....);
Object[] objects = client.invoke("getUser", 99L);
System.out.println(mapper.writeValueAsString(objects[0]));
} catch (java.lang.Exception e) {
e.printStackTrace();
}
}
输出结果:
{"address":"上海市浦东新区","age":25,"id":99,"name":"gongj"}
- 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。