spring boot使用cxf快速开发webservice
jdk版本:1.8
spring boot版本:2.3.4.RELEASE
cxf版本:3.3.1
cxf-codegen-plugin插件版本:3.3.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>
- 创建服务提供方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包,否则启动会报错,暂时未研究原因。
- 创建服务调用方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工程代码
-
编写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); }
-
-
编写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; } }
-
-
编写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工程代码
-
获取service1接口,在service2工程中创建wsdl文件
本文放到resources目录wsdl文件夹下,这个文件路径定义由service2工程pom文件中cxf-codegen-plugin插件决定
-
打开terminal,输入
mvn generate-sources命令,根据wsdl文件生成java代码,如下
-
编写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 -
编写调用控制器
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全部内容,本文只关注于快速开发,相关术语请自行查阅资料。