前言

最近因为系统需要接入了一个新的支付通道,一般来说都是使用RestApi 来接入,但是本次接入的支付通道为境外支付,使用的WebService,对于WS我们在实际业务中基本上不会用到,所以查阅了一些资料,记录一下自己项目中使用的WS。

WebService概述

  • 什么是WebService
    Web Service技术,能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。
    简单来说WebService就是一种跨编程语言和跨操作系统平台的远程调用技术。
  • WebServcie技术支持
    主要是了解XML和XSDSOAPWSDLUDDI,详细内容请参阅百度百科: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实例

接下来,我们以一个简单的示例来演示下,如何发布服务及如何进行服务调用。

服务端构建

  1. 创建工程spring-boot-cxf-service
  2. 引入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>
    
  3. 创建所需的实体
    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

  4. 创建启动类,同时启动应用
@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启动!
  1. 测试
    访问http://localhost:8080/NBA/player?wsdl 验证:

客户端构建

  1. 创建工程spring-boot-cxf-client
  2. 引入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>
    
  3. 创建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也是可以的

  4. 创建配置类、访问类等
  • 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();}
    }
    
  1. 创建启动类,测试

    @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服务相关推荐

  1. Eclipse+Maven+Spring+CXF 构建webservice 服务

    一.   软件准备 Eclipse 4.2.1 Maven 2.2.1 Spring 3.2.6 CXF 3.0.2 软件下载和Eclipse 安装 maven插件等请參考其它文章. 二.   步骤 ...

  2. cxf开发webservice服务端怎么返回固定的报文格式_Spring boot webservice怎么玩? 第277篇...

    相关历史文章(阅读本文之前,您可能需要先看下之前的系列?) WebService SOAP概述 - 第275篇 WSDL是什么"Lese" - 第276篇 一.前言 当官不为民做主 ...

  3. java cxf服务端代码_【JAVA】 cxf 生成 webservice 服务端代码

    CXF Apache CXF = Celtix + XFire.CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding . ...

  4. 基于jws发布webservice服务

    基于jws发布webservice服务 用途 用于验证基于jws搭建的webservice服务端与客户端. WebService服务端 1.目录结构 D:. │ pom.xml # maven配置 │ ...

  5. CXF创建WebService服务配置说明

    使用CXF创建WebService服务 1.描述 使用CXF创建WebService服务样例,使用CXF创建的服务不需要安装Tomcat也可以启动. 2.开发环境 Eclipse开发工具,JDK1.7 ...

  6. soapui和cxf的却别_根据wsdl文件用soapUi快速构建webService服务(有图有真相)

    最近公司业务上使用webservice 频繁.由于之前都是自己建立webservice 自己定义提供帮对方服务,现在则相反需求都是根据人家提供的wsdl 文件来生成 我们系统必须提供的接口.刚起初不知 ...

  7. 使用CXF发布WebService服务简单实例

    一.说明: 前面介绍了使用axis2来发布Webservice服务,现在介绍一种更popular,更高效的Webservice服务发布技术:CXF Apache CXF = Celtix + XFir ...

  8. DA LAO:SpringBoot讲述 快速构建微服务体系。

    在当今互联网时代,技术圈最火的名词大概就是微服务了.国内外的互联网技术会议上,但凡分享题目中包含"MicroService",不论内容质量如何,一定人山人海.摩肩接踵. 而今天分享 ...

  9. 如何基于DDD构建微服务架构

    微服务构建本质上是软件构建过程中长期演进积累的一系列理念.架构原则.工具和最佳实践. 领域驱动设计的软件思想体系和方法论可以用于指导微服务建模.微服务划分.微服务架构设计等相关工作,它可以促使技术人员 ...

最新文章

  1. Python IDLE或shell中切换路径
  2. 5G NGC — NEF Traffic Influence Service
  3. 1.Python算法之枚举算法
  4. 利用类定义一个指针会调用默认构造函数吗_C++的拷贝构造函数
  5. 解决vue中axios同步的问题
  6. Fredholm第二类积分方程的MATLAB代码实现(1)
  7. CSS 字体 font-family属性
  8. 关于过程改进和能力提升
  9. python视频教程哪个好-Python教学视频哪个好?老男孩Python培训
  10. git 中文文件名乱码
  11. TIA Openness开发入门(1)
  12. html调用如何使用jeecms库,JEECMS标签使用实例教程-序
  13. 《女生宿舍第二部》(1-46上) 转贴
  14. mysqlpump备份工具简单使用
  15. 腾讯视频 Node.js 服务是如何支撑国庆阅兵直播高并发的?
  16. 水果店怎样开业吸引人流量,水果店怎样开业吸引人
  17. chrom浏览器flash_谷歌浏览器怎么打开flash_最新版chrome怎么开启flash-win7之家
  18. Leetcode 1905. Count Sub Islands
  19. 高新技术企业申报流程
  20. 智力题库软件测试,最新软件测试笔试题网友回忆版

热门文章

  1. Java面试题中高级,nasdocker有啥好玩的
  2. Git下载代码--git clone命令
  3. jquery给按钮赋值_jQuery给div,Span, a ,button, radio 赋值与取值
  4. 七巧板复原之剩余区域的计算-多边形的加减法计算
  5. 两张(多张)图片合成一张图片
  6. 小程序开发:完整发布上线流程
  7. 为什么使用dojo?dojo与jquery有什么不同?dojo适合什么开发场景?
  8. mysql 查询 唯一_Mysql中如何查询所有唯一记录
  9. 一些值得一看的博友文章地址
  10. SetWinEventHook 事件钩子