SpringBoot整合WebService加入依赖

这是我参与更文挑战的第 3 天,活动详情查看: 更文挑战

日积月累,水滴石穿 😄

在工作当中经常需要与第三方对接,某些第三方提供的接口是 WebService 类型的,所以需要集成 WebService
由于 SpringBoot提供了 WebServicestarter 组件,所以集成 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

image.png
点击链接跳转,我们会看到一个页面,这是 wsdl 服务描述文档。对于这个文档也需要简单的了解一下,也许某次对接第三方系统直接给你一个 wsdl 文档让你自己看去,注意:wsdl 文档是从下往上看的

image.png

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"}
复制代码
  • 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。