SpringBoot 整合 webservice 示例

现在有一些老项目是使用webservice提供远程接口服务的,工作中遇到了,在这里使用Apache CXF 特意做一个示例,供参考!

1.webservice技术特点?

  • webservice接口调用可以跨语言(不管程序是用什么语言开发的,webservice接口都可以相互调用)
  • 也是基于http协议
  • 可以使用xml进行数据传递(使用jaxws协议),也可以使用json进行数据传递(使用jaxrs协议),本示例演示xml进行数据传递

2.构建webservice服务端

1、新建一个SringBoot工程,引入依赖,注意:这里不用引入web依赖,springboot 整合 webservice 依赖中包含web依赖

<!--springboot 整合 webservice 依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<!--cxf 核心依赖-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>3.4.3</version>
</dependency>
<!--jaxws 协议的 cxf webservice依赖 -->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>3.4.4</version>
</dependency>

2、新建一个接口服务

@WebService(targetNamespace = "http://service.winson.com", name = "HelloService")//与接口中的命名空间一致,一般是接口的包名倒(要与实现类定义的值相同,否则利用动态代理创建客户端,无法调用接口方法)
public interface HelloService {
    @WebMethod
    String hello(@WebParam(name = "name") String name);
}

3、接口实现类。注:目标命名空间必须与接口一致

@Service
@WebService(serviceName = "HelloService",// 与接口中指定的name一致
        targetNamespace = "http://service.winson.com",// 与接口中的命名空间一致,一般是接口的包名倒
        endpointInterface = "com.winson.service.HelloService")// 接口地址
public class HelloServiceImpl implements HelloService {
    @Override
    public String hello(String name) {
        return name + ",welcome to china!";
    }
}

4、新建一个配置类,注册服务,暴露服务调用地址

@Configuration
public class WebServiceConfig {

    @Autowired
    private HelloService helloService;

    /**
     * 注入servlet  bean name不能dispatcherServlet 否则会覆盖dispatcherServlet
     *
     * @return
     */
    @Bean
    public ServletRegistrationBean cxfServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/ws/*");//第二个参数:设置CXFServlet注册地址
    }

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        return new SpringBus();
    }

    /**
     * 注册WebService接口到webservice服务
     *
     * @return
     */
    @Bean(name = "helloServiceEndpoint")
    public Endpoint sweptPayEndpoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), helloService);
        endpoint.publish("/webservice");//设置接口注册地址
        return endpoint;
    }
}

5、访问接口服务

WSDL:webservice 描述语言,如何解读不赘述,查看规则是从下到上分析来看

地址:http://localhost:8080/ws/webservice?wsdl

地址格式: (http://ip+端口/cxfServlet注册地址/具体服务接口地址+ ?wsdl)

报文示例:

<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://service.winson.com" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="HelloService" targetNamespace="http://service.winson.com">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.winson.com" elementFormDefault="unqualified" targetNamespace="http://service.winson.com" version="1.0">
<xs:element name="hello" type="tns:hello"/>
<xs:element name="helloResponse" type="tns:helloResponse"/>
<xs:complexType name="hello">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="helloResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="hello">
<wsdl:part element="tns:hello" name="parameters"> </wsdl:part>
</wsdl:message>
<wsdl:message name="helloResponse">
<wsdl:part element="tns:helloResponse" name="parameters"> </wsdl:part>
</wsdl:message>
<wsdl:portType name="HelloService">
<wsdl:operation name="hello">
<wsdl:input message="tns:hello" name="hello"> </wsdl:input>
<wsdl:output message="tns:helloResponse" name="helloResponse"> </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="hello">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="hello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="helloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloService">
<wsdl:port binding="tns:HelloServiceSoapBinding" name="HelloServiceImplPort">
<soap:address location="http://localhost:8080/ws/webservice"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

3.构建webservice客户端

1、构建一个 SpringBoot 工程,引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web-services</artifactId>
    </dependency>
    <!--webservice 依赖-->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>3.4.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>3.4.4</version>
    </dependency>
    <!--测试依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
</dependencies>

有两种方式测试:

  • 方式1:代理类工厂的方式,需要拿到对方的接口

    @Test
    public void testWebserviceServer() {
        try {
            // 接口地址
            String address = "http://localhost:8080/ws/webservice?wsdl";
            // 代理工厂
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            // 设置代理地址
            jaxWsProxyFactoryBean.setAddress(address);
            // 设置接口类型
            jaxWsProxyFactoryBean.setServiceClass(HelloService.class);
            // 创建一个代理接口实现
            HelloService helloService = (HelloService) jaxWsProxyFactoryBean.create();
            // 调用代理接口的方法调用并返回结果
            String res = helloService.hello("winson");
            System.out.println("返回结果:" + res);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  • 方式2:动态调用方式,优点:动态客户端调用,利用反射不需要引入服务端Service类

    @Test
    public void test02() {
        //创建动态客户端
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        try {
            Client client = dcf.createClient("http://localhost:8080/ws/webservice?wsdl");
            // 需要密码的情况需要加上用户名和密码
            // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
            Object[] objects = new Object[0];
            // invoke("方法名",参数1,参数2,参数3....);
            objects = client.invoke("hello", "elnimo");
            System.out.println("返回数据:" + objects[0]);
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }
    }
    

4.启动测试用例,返回结果

返回数据:elnimo,welcome to china!
Disconnected from the target VM, address: '127.0.0.1:51792', transport: 'socket'

Process finished with exit code 0

以上几步就是利用SpringBoot + webservice(jaxws) 实现webservice示例,代码中的注释很重要,请仔细参考,否则启动程序会报错。

posted @ 2022-01-01 21:27  温森  阅读(1424)  评论(1编辑  收藏  举报