Springboot 基于CXF构建WebService服务
前言
最近因为系统需要接入了一个新的支付通道,一般来说都是使用RestApi
来接入,但是本次接入的支付通道为境外支付,使用的WebService,对于WS我们在实际业务中基本上不会用到,所以查阅了一些资料,记录一下自己项目中使用的WS。
WebService概述
- 什么是WebService
Web Service技术,能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。
简单来说WebService就是一种跨编程语言和跨操作系统平台的远程调用技术。 - WebServcie技术支持
主要是了解XML和XSD
、SOAP
、WSDL
、UDDI
,详细内容请参阅百度百科:Web Service
Apache-CXF概述
- 什么是Apache-CXF
Apache CXF是一个开源的Services框架,CXF帮助您利用Frontend编程 API 来构建和开发Services,像JAX-WS、JAX-RS。这些Services可以支持多种协议,比如:SOAP、XML/HTTP、RESTful HTTP或者CORBA,并且可以在多种传输协议上运行,比如:HTTP、JMS 或者JBI,
CXF大大简化了 Services 的创建,同时它可以天然地和Spring进行无缝集成。
详细内容请参阅官方:Apache CXF - JAX-WS规范
JAX-WS全称:Java API for XML-Based Web Services。JAX-WS是一种编程模型,它通过支持将基于注释的标准模型用于开发Web Service应用程序和客户机来简化应用程序开发。
JAX-WS是Java程序设计语言一个用来创建Web服务的API。- 在服务器端,用户只需要通过Java语言定义远程调用所需要实现的接口SEI(service endpoint interface),并提供相关的实现,通过调用JAX-WS的服务发布接口就可以将其发布为WebService接口。
- 在客户端,用户可以通过JAX-WS的API创建一个代理(用本地对象来替代远程的服务)来实现对于远程服务器端的调用。当然JAX-WS也提供了一组针对底层消息进行操作的API调用,你可以通过Dispatch直接使用SOAP消息或XML消息发送请求或者使用Provider处理SOAP或XML消息。
- 常用注解参考WebService注解总结
SpringBoot整合CXF实例
接下来,我们以一个简单的示例来演示下,如何发布服务及如何进行服务调用。
服务端构建
- 创建工程
spring-boot-cxf-service
- 引入maven依赖
<dependencies><!--spring-boot-starter--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!--lombok懒人依赖 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--test依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--cxf依赖 --><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-spring-boot-starter-jaxws</artifactId><version>3.2.5</version></dependency><!--commons-lang3 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.4</version><scope>provided</scope></dependency> </dependencies>
- 创建所需的实体
1.NBAPlayer.java
@Data @Builder @AllArgsConstructor @NoArgsConstructor public class NBAPlayer {String name;String team;List<String> teams;String description;Position position;@Overridepublic String toString() {return "NBA现役球员" + name + ",司职" + position.value + "现效力于" + team + ",曾效力球队" + teams.toString();} }
2.
Positon.java
public enum Position {FORWARD("小前锋"),SHOOTING("控球後衛");String value;Position(String value) {this.value = value;}public String value() {return value;}public static Position fromValue(String v) {for (Position c : Position.values()) {if (c.value.equals(v)) {return c;}}throw new IllegalArgumentException(v);} }
3.
NBAPlayerSoapService.java
@WebService(targetNamespace = WsConst.NAMESPACE_URI, name = "NBAPlayerSoap") public interface NBAPlayerSoapService {/*** description 根据姓名获取球员信息* date 2019/10/15** @param NBAPlayerName* @return cn.forward.springboot.cxf.service.entity.NBAPlayer*/@WebMethod(operationName = "getNBAPlayerByName")NBAPlayer getNBAPlayerByName(@WebParam(name = "NBAPlayerName") String NBAPlayerName);/*** description 获取球员列表* date 2019/10/15** @return java.util.List<cn.forward.springboot.cxf.service.entity.NBAPlayer>*/@WebMethodList<NBAPlayer> getNBAPlayerList();}
4.
NBAPlayerSoapImpl.java
@WebService(targetNamespace = WsConst.NAMESPACE_URI, //wsdl命名空间name = "NBAPlayerSoap", //portType名称 客户端生成代码时 为接口名称serviceName = "NBAPlayerSoapService", //服务name名称portName = "NBAPlayerPortName", //port名称endpointInterface = "cn.forward.springboot.cxf.service.service.NBAPlayerSoapService") public class NBAPlayerSoapImpl implements NBAPlayerSoapService {@Overridepublic NBAPlayer getNBAPlayerByName(String name) {List<NBAPlayer> nbaPlayers = getNBAPlayerList();AtomicReference<NBAPlayer> player = new AtomicReference<>(nbaPlayers.get(new Random().nextInt(2)));nbaPlayers.forEach(nbaPlayer -> {if (nbaPlayer.getName().equals(name)) {player.set(nbaPlayer);}});return player.get();}@Overridepublic List<NBAPlayer> getNBAPlayerList() {return generatorList();}public List<NBAPlayer> generatorList() {List<NBAPlayer> resultList = new ArrayList<>();NBAPlayer LBJ = new NBAPlayer();LBJ.setName("勒布朗·詹姆斯");LBJ.setTeam("洛杉矶湖人");LBJ.setTeams(Arrays.asList("克里夫蘭騎士(2003−2010)", "邁阿密熱火(2010−2014)"));LBJ.setPosition(Position.FORWARD);LBJ.setDescription(LBJ.toString());resultList.add(LBJ);NBAPlayer WS = new NBAPlayer();WS.setName("罗素·威斯布鲁克");WS.setTeam("休斯頓火箭");WS.setTeams(Arrays.asList("奧克拉荷馬雷霆 (2008-2019)"));WS.setPosition(Position.SHOOTING);WS.setDescription(WS.toString());resultList.add(WS);return resultList;} }
5.
WsConst.java
public class WsConst {public static final String NAMESPACE_URI = "http://www.lqdev.cn/webservice"; }
6.
CxfWebServiceConfig.java
@Configuration public class CxfWebServiceConfig {//这里需要注意 由于springmvc 的核心类 为DispatcherServlet//此处若不重命名此bean的话 原本的mvc就被覆盖了。可查看配置类:DispatcherServletAutoConfiguration//一种方法是修改方法名称 或者指定bean名称//这里需要注意 若beanName命名不是 cxfServletRegistration 时,会创建两个CXFServlet的。//具体可查看下自动配置类:Declaration org.apache.cxf.spring.boot.autoconfigure.CxfAutoConfiguration//也可以不设置此bean 直接通过配置项 cxf.path 来修改访问路径的@Bean("cxfServletRegistration")public ServletRegistrationBean dispatcherServlet() {//注册servlet 拦截/NBA 开头的请求 不设置 默认为:/services/*return new ServletRegistrationBean(new CXFServlet(), "/NBA/*");}/*** 申明业务处理类 当然也可以直接 在实现类上标注 @Service* @author ShiFan*/@Beanpublic NBAPlayerSoapService authorService() {return new NBAPlayerSoapImpl();}/*** 非必要项*/@Bean(name = Bus.DEFAULT_BUS_ID)public SpringBus springBus() {SpringBus springBus = new SpringBus();return springBus;}/*** 发布endpoint*/@Beanpublic Endpoint endpoint(NBAPlayerSoapService NBAPlayerSoap) {EndpointImpl endpoint = new EndpointImpl(springBus(), NBAPlayerSoap);//发布地址endpoint.publish("/player");return endpoint;} }
注意事项:
配置ServletRegistrationBean时,需要注意设置方法的名称或者bean的名称时,不要和默认的DispatcherServlet类重名了,会导致原先的mvc接口无法使用,因为被覆盖了。
修改访问的路径可以通过设置ServletRegistrationBean来修改,但同时,要注意需要设置bean的名称为cxfServletRegistration,不然会造成注册多个CXFServlet的。具体原因可查看自动配置类:org.apache.cxf.spring.boot.autoconfigure.CxfAutoConfiguration。
所以,修改访问路径还可以通过配置项:cxf.path来设置。其默认的访问url为:/services - 创建启动类,同时启动应用
@SpringBootApplication
@Slf4j
public class SpringBootCxfServiceApplication {public static void main(String[] args) {SpringApplication.run(SpringBootCxfServiceApplication.class, args);log.info("spring-boot-cxf-service启动!");}
}
查看输入日志
2019-10-15 15:49:17.964 INFO 16100 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-10-15 15:49:17.967 INFO 16100 --- [ main] .f.s.c.s.SpringBootCxfServiceApplication : Started SpringBootCxfServiceApplication in 3.35 seconds (JVM running for 4.454)
2019-10-15 15:49:17.969 INFO 16100 --- [ main] .f.s.c.s.SpringBootCxfServiceApplication : spring-boot-cxf-service启动!
- 测试
访问http://localhost:8080/NBA/player?wsdl 验证:
客户端构建
- 创建工程
spring-boot-cxf-client
- 引入maven依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></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></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-spring-boot-starter-jaxws</artifactId><version>3.2.5</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.5.17</version></dependency> </dependencies>
- 创建wsdl文件,同时利用插件:cxf-codegen-plugin创建相关类。
<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.2.5</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/player.wsdl</wsdl><wsdlLocation>classpath:wsdl/player.wsdl</wsdlLocation></wsdlOption></wsdlOptions></configuration><goals><goal>wsdl2java</goal></goals></execution></executions></plugin></plugins> </build>
提示:
将wsdl文件,放入main/resources/wsdl目录下。之后执行:mvn generate-sources命令,就会自动创建相应的类文件了。拷贝相应的类文件至src/java目录下即可。或者直接指定sourceRoot也是可以的 - 创建配置类、访问类等
WsCont.java
public class WsConst {public static final String SERVICE_ADDRESS= "http://localhost:8080/NBA/player?wsdl"; }
CxfClientConfig.java
@Configuration public class CxfClientConfig {/*** 采用代理方式** @return NBAPlayerSoap*/@Beanpublic NBAPlayerSoap createAuthorPortTypeProxy() {JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();jaxWsProxyFactoryBean.setServiceClass(NBAPlayerSoap.class);jaxWsProxyFactoryBean.setAddress(WsConst.SERVICE_ADDRESS);return (NBAPlayerSoap) jaxWsProxyFactoryBean.create();}/*** 采用动态工厂方式 不需要指定服务接口*/@Beanpublic Client createDynamicClient() {JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();Client client = dcf.createClient(WsConst.SERVICE_ADDRESS);return client;} }
NBAPlayerController.java
@RestController @RequestMapping("/nba/player") public class NBAPlayerController {@ResourceNBAPlayerSoap nbaPlayerSoap;/*** description 根据球员名称获取球员信息* date 2019/10/15** @param nbaPlayerName* @return cn.lqdev.webservice.NbaPlayer*/@GetMapping("/getNBAPlayerByName")public NbaPlayer getNBAPlayerByName(@RequestParam("nbaPlayerName") String nbaPlayerName) {return nbaPlayerSoap.getNBAPlayerByName(nbaPlayerName);}/*** description 获取全部球员信息* date 2019/10/15* @return java.util.List<cn.lqdev.webservice.NbaPlayer>*/@GetMapping("/getNBAPlayerList")public List<NbaPlayer> getNBAPlayerList() {return nbaPlayerSoap.getNBAPlayerList();} }
- 创建启动类,测试
@SpringBootApplication @Slf4j public class SpringBootCxfClientApplication {public static void main(String[] args) {SpringApplication.run(SpringBootCxfClientApplication.class, args);log.info("spring-boot-cxf-client启动!");} }
访问:
http://localhost:8081/nba/player/getNBAPlayerByName?nbaPlayerName=%E5%8B%92%E5%B8%83%E6%9C%97%C2%B7%E8%A9%B9%E5%A7%86%E6%96%AF
验证结果:{description: "NBA现役球员勒布朗·詹姆斯,司职小前锋现效力于洛杉矶湖人,曾效力球队[克里夫蘭騎士(2003−2010), 邁阿密熱火(2010−2014)]",name: "勒布朗·詹姆斯",position: "FORWARD",team: "洛杉矶湖人",teams: ["克里夫蘭騎士(2003−2010)","邁阿密熱火(2010−2014)"] }
6.参考文章
- CXF构建WebService服务
- Spring web Servcies集成和使用
总结
本次文章主要是分享了springboot基于CXF构建WebService服务的过程。
Springboot 基于CXF构建WebService服务相关推荐
- Eclipse+Maven+Spring+CXF 构建webservice 服务
一. 软件准备 Eclipse 4.2.1 Maven 2.2.1 Spring 3.2.6 CXF 3.0.2 软件下载和Eclipse 安装 maven插件等请參考其它文章. 二. 步骤 ...
- cxf开发webservice服务端怎么返回固定的报文格式_Spring boot webservice怎么玩? 第277篇...
相关历史文章(阅读本文之前,您可能需要先看下之前的系列?) WebService SOAP概述 - 第275篇 WSDL是什么"Lese" - 第276篇 一.前言 当官不为民做主 ...
- java cxf服务端代码_【JAVA】 cxf 生成 webservice 服务端代码
CXF Apache CXF = Celtix + XFire.CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding . ...
- 基于jws发布webservice服务
基于jws发布webservice服务 用途 用于验证基于jws搭建的webservice服务端与客户端. WebService服务端 1.目录结构 D:. │ pom.xml # maven配置 │ ...
- CXF创建WebService服务配置说明
使用CXF创建WebService服务 1.描述 使用CXF创建WebService服务样例,使用CXF创建的服务不需要安装Tomcat也可以启动. 2.开发环境 Eclipse开发工具,JDK1.7 ...
- soapui和cxf的却别_根据wsdl文件用soapUi快速构建webService服务(有图有真相)
最近公司业务上使用webservice 频繁.由于之前都是自己建立webservice 自己定义提供帮对方服务,现在则相反需求都是根据人家提供的wsdl 文件来生成 我们系统必须提供的接口.刚起初不知 ...
- 使用CXF发布WebService服务简单实例
一.说明: 前面介绍了使用axis2来发布Webservice服务,现在介绍一种更popular,更高效的Webservice服务发布技术:CXF Apache CXF = Celtix + XFir ...
- DA LAO:SpringBoot讲述 快速构建微服务体系。
在当今互联网时代,技术圈最火的名词大概就是微服务了.国内外的互联网技术会议上,但凡分享题目中包含"MicroService",不论内容质量如何,一定人山人海.摩肩接踵. 而今天分享 ...
- 如何基于DDD构建微服务架构
微服务构建本质上是软件构建过程中长期演进积累的一系列理念.架构原则.工具和最佳实践. 领域驱动设计的软件思想体系和方法论可以用于指导微服务建模.微服务划分.微服务架构设计等相关工作,它可以促使技术人员 ...
最新文章
- Python IDLE或shell中切换路径
- 5G NGC — NEF Traffic Influence Service
- 1.Python算法之枚举算法
- 利用类定义一个指针会调用默认构造函数吗_C++的拷贝构造函数
- 解决vue中axios同步的问题
- Fredholm第二类积分方程的MATLAB代码实现(1)
- CSS 字体 font-family属性
- 关于过程改进和能力提升
- python视频教程哪个好-Python教学视频哪个好?老男孩Python培训
- git 中文文件名乱码
- TIA Openness开发入门(1)
- html调用如何使用jeecms库,JEECMS标签使用实例教程-序
- 《女生宿舍第二部》(1-46上) 转贴
- mysqlpump备份工具简单使用
- 腾讯视频 Node.js 服务是如何支撑国庆阅兵直播高并发的?
- 水果店怎样开业吸引人流量,水果店怎样开业吸引人
- chrom浏览器flash_谷歌浏览器怎么打开flash_最新版chrome怎么开启flash-win7之家
- Leetcode 1905. Count Sub Islands
- 高新技术企业申报流程
- 智力题库软件测试,最新软件测试笔试题网友回忆版