zoukankan      html  css  js  c++  java
  • 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示例,代码中的注释很重要,请仔细参考,否则启动程序会报错。

  • 相关阅读:
    java线程间的协作
    java线程间的共享
    java多线程基础API
    java并发编程基础概念
    如何设计一套规则引擎系统
    Stream—一个早产的婴儿
    Java函数式编程的前生今世
    关于微服务划分的一些思考
    如何更优雅的给控制器 “减负”
    PHP简洁之道
  • 原文地址:https://www.cnblogs.com/elnimo/p/15756177.html
Copyright © 2011-2022 走看看