spring boot使用cxf快速开发webservice

660 阅读3分钟

spring boot使用cxf快速开发webservice

jdk版本:1.8

spring boot版本:2.3.4.RELEASE

cxf版本:3.3.1

cxf-codegen-plugin插件版本:3.3.1

准备工作

创建工程结构

  1. 创建maven父工程

pom文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.3.4.RELEASE</version>
   </parent>
   <groupId>com.yezi</groupId>
   <artifactId>parent</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>parent</name>
   <description>Demo project for Spring Boot</description>
   <packaging>pom</packaging>

   <modules>
       <module>service1</module>
       <module>service2</module>
   </modules>

   <properties>
       <java.version>1.8</java.version>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-devtools</artifactId>
           <scope>runtime</scope>
           <optional>true</optional>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
           <exclusions>
               <exclusion>
                   <groupId>org.junit.vintage</groupId>
                   <artifactId>junit-vintage-engine</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>

</project>

  1. 创建服务提供方service1
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
       <groupId>com.yezi</groupId>
       <artifactId>parent</artifactId>
       <version>0.0.1-SNAPSHOT</version>
   </parent>
   <groupId>com.yezi</groupId>
   <artifactId>service1</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>service1</name>
   <description>Demo project for Spring Boot</description>
   <packaging>jar</packaging>


   <properties>
       <java.version>1.8</java.version>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter</artifactId>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
           <exclusions>
               <exclusion>
                   <groupId>org.junit.vintage</groupId>
                   <artifactId>junit-vintage-engine</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <!--cxf依赖 -->
       <dependency>
           <groupId>org.apache.cxf</groupId>
           <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
           <version>3.3.1</version>
       </dependency>
       <dependency>
           <groupId>org.hibernate</groupId>
           <artifactId>hibernate-validator</artifactId>
           <version>5.2.4.Final</version>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>

</project>

这里注意引入hibernate-validator包,否则启动会报错,暂时未研究原因。

  1. 创建服务调用方service2
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
       <groupId>com.yezi</groupId>
       <artifactId>parent</artifactId>
       <version>0.0.1-SNAPSHOT</version>
   </parent>
   <groupId>com.yezi</groupId>
   <artifactId>service2</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>service2</name>
   <description>Demo project for Spring Boot</description>
   <packaging>jar</packaging>

   <properties>
       <java.version>1.8</java.version>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter</artifactId>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
           <exclusions>
               <exclusion>
                   <groupId>org.junit.vintage</groupId>
                   <artifactId>junit-vintage-engine</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <!--cxf依赖 -->
       <dependency>
           <groupId>org.apache.cxf</groupId>
           <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
           <version>3.3.1</version>
       </dependency>
       <dependency>
           <groupId>org.hibernate</groupId>
           <artifactId>hibernate-validator</artifactId>
           <version>5.2.4.Final</version>
       </dependency>
       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>fastjson</artifactId>
           <version>RELEASE</version>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
           <!-- cxf-codegen-plugin -->
           <plugin>
               <groupId>org.apache.cxf</groupId>
               <artifactId>cxf-codegen-plugin</artifactId>
               <version>3.3.1</version>
               <executions>
                   <execution>
                       <id>generate-sources</id>
                       <phase>generate-sources</phase>
                       <configuration>
                           		    <sourceRoot>${project.basedir}/src/main/java</sourceRoot>
                           <wsdlOptions>
                               <wsdlOption>
                                   <wsdl>src/main/resources/wsdl/pay.wsdl</wsdl>
                                   <wsdlLocation>classpath:wsdl/pay.wsdl</wsdlLocation>
                               </wsdlOption>
                           </wsdlOptions>
                       </configuration>
                       <goals>
                           <goal>wsdl2java</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
       </plugins>
   </build>

</project>

service2工程pom文件主要关注cxf-codegen-plugin,我们使用此插件来根据wsdl文件生成相关java代码。

编写代码

编写service1工程代码
  1. 编写service1工程webservice接口

    • package com.yezi.service1.webservice.service;
      
      import javax.jws.WebMethod;
      import javax.jws.WebService;
      
      /**
       * @Description:
       * @Author: yezi
       * @Date: 2020/9/23 16:03
       */
      @WebService
      public interface DemoSrevice1 {
      
      
          @WebMethod
          String getInfo(String msg);
      
      }
      
      
  2. 编写service1工程webservice实现

    • package com.yezi.service1.webservice.service;
      
      
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.stereotype.Service;
      
      import javax.jws.WebService;
      
      /**
      * @Description:
      * @Author: yezi
      * @Date: 2020/9/23 16:07
      */
      @Slf4j
      @WebService
      @Service
      public class DemoService1Impl implements DemoSrevice1 {
      
      
         @Override
         public String getInfo(String msg) {
             log.info("请求参数:" + msg);
             return "service1收到请求,原样返回入参:" + msg;
         }
      }
      
      
  3. 编写webservice配置类发布服务

    • package com.yezi.service1.config;
      
      import com.yezi.service1.webservice.service.DemoSrevice1;
      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;
      
      /**
      * @Description:
      * @Author: yezi
      * @Date: 2020/9/23 16:00
      */
      @Configuration
      public class WebServiceConfig {
      
      
         @Autowired
         private SpringBus springBus;
      
         @Autowired
         private DemoSrevice1 demoSrevice1;
      
      
         @Bean("cxfServletRegistration")
         public ServletRegistrationBean cXFServlet() {
             return new ServletRegistrationBean(new CXFServlet(), "/service1/*");
         }
      
      
         /**
          * 发布endpoint
          */
         @Bean
         public Endpoint endpoint() {
             EndpointImpl endpoint = new EndpointImpl(springBus, demoSrevice1);
             //发布地址
             endpoint.publish("/info");
             return endpoint;
         }
      
      }
      
启动service1工程

启动service1工程,注意修改工程端口号。启动后结果如下

验证webservice发布结果

浏览器访问http://localhost:9001/service1/info?wsdl 得到如下结果:

服务发布成功

编写service2工程代码
  1. 获取service1接口,在service2工程中创建wsdl文件

    本文放到resources目录wsdl文件夹下,这个文件路径定义由service2工程pom文件中cxf-codegen-plugin插件决定

  2. 打开terminal,输入mvn generate-sources 命令,根据wsdl文件生成java代码,如下

  1. 编写service2工程webservice配置类

    package com.yezi.service2.config;
    
    
    import com.yezi.service1.webservice.service.DemoSrevice1;
    import com.yezi.service2.constant.WsConst;
    import org.apache.cxf.endpoint.Client;
    import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
    import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
    * @Description:
    * @Author: yezi
    * @Date: 2020/9/23 16:00
    */
    @Configuration
    public class WebServiceConfig {
    
       /**
        * 采用代理方式
        *
        * @return NBAPlayerSoap
        */
       @Bean
       public DemoSrevice1 createAuthorPortTypeProxy() {
           JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
           jaxWsProxyFactoryBean.setServiceClass(DemoSrevice1.class);
           jaxWsProxyFactoryBean.setAddress(WsConst.SERVICE_ADDRESS);
           return (DemoSrevice1) jaxWsProxyFactoryBean.create();
       }
    
       /**
        * 采用动态工厂方式 不需要指定服务接口
        */
       @Bean
       public Client createDynamicClient() {
           JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
           Client client = dcf.createClient(WsConst.SERVICE_ADDRESS);
           return client;
       }
    
    
    }
    
    

    其中WsConst.SERVICE_ADDRESS为service1工程所发布的webservice地址,也就是前面获取wsdl的地址:

    WsConst.SERVICE_ADDRESS = http://localhost:9001/service1/info?wsdl

  2. 编写调用控制器

    package com.yezi.service2.controller;
    
    import com.yezi.service1.webservice.service.DemoSrevice1;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
    * @Description:
    * @Author: yezi
    * @Date: 2020/9/23 15:56
    */
    @Slf4j
    @RestController
    public class HomeController {
    
       @Autowired
       private DemoSrevice1 demoSrevice1;
    
    
       @GetMapping("/home")
       public String home() {
    
           return demoSrevice1.getInfo("service2调用service1");
       }
    
    }
    
    

    可以看到,使用cxf-codegen-plugin插件生成的代码,可以像调用本地服务一样,直接注入使用

启动service2工程并验证调用结果

在浏览器输入 http://localhost:9002/home 得到如下结果:

以上为spring boot使用cxf快速开发webservice全部内容,本文只关注于快速开发,相关术语请自行查阅资料。