前面章节中我们介绍了如何基于标准JavaEE和Wildfly应用服务器使用CXF框架实现JAX-WS和JAX-RS服务,这篇笔记我们继续介绍如何在SpringBoot中集成CXF进行JAX-WS开发。对于JAX-RS,实际上我们可能更倾向于使用SpringMVC框架,因此我们这里仅介绍如何使用CXF实现JAX-WS服务。
这篇笔记我们使用SpringBoot2.7.18和JDK8为例进行介绍。
CXF提供了SpringBoot的起步依赖,我们直接引入即可。
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.2.1</version>
</dependency>
注意CXF框架额外依赖Hibernate Validation,目前实测3.2.1版本如果不引入会在启动阶段报错,因此我们还需要保证工程中存在如下依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
我们的SpringBoot工程目录结构如下。
|_ src/main
|_ java
|_ com.gacfox.demo.demows
|_ config
|_ WsConfig.java
|_ model
|_ Weather.java
|_ service
|_ WeatherService.java
|_ impl
|_ WeatherServiceImpl.java
|_ DemowsApplication.java
|_ resources
|_ application.properties
首先我们创建实体类、SEI接口类和实现类,这些代码和之前JAX-WS章节中的完全一致,唯一的区别是对于WebService实现类我们使用了Spring的@Component
注解将其托管到Spring的IoC容器。
package com.gacfox.demo.demows.model;
import lombok.Data;
import java.util.Date;
@Data
public class Weather {
private String city;
private String weather;
private int temperature;
private Date date;
}
package com.gacfox.demo.demows.service;
import com.gacfox.demo.demows.model.Weather;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(name = "WeatherServicePortType",
targetNamespace = "http://service.demows.demo.gacfox.com/")
@SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.LITERAL)
public interface WeatherService {
@WebMethod(operationName = "queryWeather")
@WebResult(name = "weather")
Weather queryWeather(@WebParam(name = "city") String city);
}
package com.gacfox.demo.demows.service.impl;
import com.gacfox.demo.demows.model.Weather;
import org.springframework.stereotype.Component;
import com.gacfox.demo.demows.service.WeatherService;
import javax.jws.WebService;
import java.util.Date;
@Component("weatherService")
@WebService(endpointInterface = "com.gacfox.demo.demows.service.WeatherService",
targetNamespace = "http://service.demows.demo.gacfox.com/",
serviceName = "WeatherService",
portName = "WeatherServicePort")
public class WeatherServiceImpl implements WeatherService {
@Override
public Weather queryWeather(String city) {
// ... 具体业务逻辑
return weather;
}
}
然后我们在配置类WsConfig
中手动注册JAX-WS接口。
package com.gacfox.demo.demows.config;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.gacfox.demo.demows.service.WeatherService;
import javax.xml.ws.Endpoint;
@Configuration
public class WsConfig {
@Bean
public Endpoint endpoint(Bus bus, WeatherService weatherService) {
Endpoint endpoint = new EndpointImpl(bus, weatherService);
endpoint.publish("/WeatherService");
return endpoint;
}
}
代码中,我们依赖注入了WebService实例和一个Bus实例,这个Bus是CXF框架的核心类,其中包含了CXF的运行时环境等信息,我们在EndPointImpl
的构造函数参数中传入这些对象并将这个接口注册到/WeatherService
路径上。
最后,我们在SpringBoot工程的application.properties
配置文件中添加如下配置。
cxf.path=/ws
该配置用于指定CXF框架处理的基础路径。我们前面介绍过CXF框架本身也是基于Servlet实现的,其实这个配置就是用在CXF的核心Servlet上。
正常启动工程后,按照我们之前注册的CXF基础路径和WebService接口路径,我们使用浏览器访问http://localhost:8080/ws/WeatherService?wsdl
即可看到WSDL文档。