spring boot整合cxf发布和调用webservice-程序员宅基地

一.前言
说起web service最近几年restful大行其道,大有取代传统soap web service的趋势,但是一些特有或相对老旧的系统依然使用了传统的soap web service,例如银行、航空公司的机票查询接口等。本博客主要讲解得是spring boot整合cxf发布webservice服务和spring boot整合cxf客户端调用webservice服务
本案例使用maven方式
二.编码
核心文件清单
1.pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.leftso</groupId>
<artifactId>demo-webservice-cxf</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>demo-webservice-cxf</name>
<description>Demo project for Spring Boot security</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.5.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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-web</artifactId>
</dependency>

<!-- CXF webservice -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.1.7</version>
</dependency>
<!-- CXF webservice -->

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

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

</project>

2.CommonService.java 服务接口

package com.leftso.webservice;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

/**
* 接口
* 
* @author leftso
*
*/
@WebService(name = "CommonService", // 暴露服务名称
targetNamespace = "http://webservice.leftso.com/"// 命名空间,一般是接口的包名倒序
)
public interface CommonService {
@WebMethod
@WebResult(name = "String", targetNamespace = "")
public String sayHello(@WebParam(name = "userName") String name);

}

3.接口实现
package com.leftso.webservice;

import javax.jws.WebService;

import org.springframework.stereotype.Component;

/**
* 接口实现
* 
* @author leftso
*
*/
@WebService(serviceName = "CommonService", // 与接口中指定的name一致
targetNamespace = "http://webservice.leftso.com/", // 与接口中的命名空间一致,一般是接口的包名倒
endpointInterface = "com.leftso.webservice.CommonService"// 接口地址
)
@Component
public class CommonServiceImp implements CommonService {

@Override
public String sayHello(String name) {

return "Hello ," + name;
}

}

4.配置cxf服务发布,默认服务在Host:port/services/***路径下
package com.leftso.config;

import javax.xml.ws.Endpoint;

import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.leftso.webservice.CommonService;

@Configuration
public class CxfConfig {
@Autowired
private Bus bus;

@Autowired
CommonService commonService;

/** JAX-WS **/
@Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, commonService);
endpoint.publish("/CommonService");
return endpoint;
}
}

  

这里相当于把Commonservice接口发布在了路径/services/CommonService下,wsdl文档路径为http://localhost:8080/services/CommonService?wsdl

创建基于cxf的客服端调用webservice接口(非使用wsdl文档生成java类)

package com.leftso.client;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

import com.leftso.webservice.CommonService;

public class CxfClient {
public static void main(String[] args) {
cl1();
}

/**
* 方式1.代理类工厂的方式,需要拿到对方的接口
*/
public static void cl1() {
try {
// 接口地址
String address = "http://localhost:8080/services/CommonService?wsdl";
// 代理工厂
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
// 设置代理地址
jaxWsProxyFactoryBean.setAddress(address);
// 设置接口类型
jaxWsProxyFactoryBean.setServiceClass(CommonService.class);
// 创建一个代理接口实现
CommonService cs = (CommonService) jaxWsProxyFactoryBean.create();
// 数据准备
String userName = "Leftso";
// 调用代理接口的方法调用并返回结果
String result = cs.sayHello(userName);
System.out.println("返回结果:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 动态调用方式
*/
public static void cl2() {
// 创建动态客户端
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("http://localhost:8080/services/CommonService?wsdl");
// 需要密码的情况需要加上用户名和密码
// client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME,
// PASS_WORD));
Object[] objects = new Object[0];
try {
// invoke("方法名",参数1,参数2,参数3....);
objects = client.invoke("sayHello", "Leftso");
System.out.println("返回数据:" + objects[0]);
} catch (java.lang.Exception e) {
e.printStackTrace();
}
}
}

调用后返回结果输出为
Hello,Leftso

三.问题Q&A
3.1已知问题1
将上面例子的Spring Boot版本升级至1.5.x。启动项目报错:

java.lang.NoClassDefFoundError: org/springframework/boot/context/embedded/ServletRegistrationBean
at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_40]
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[na:1.8.0_40]
at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[na:1.8.0_40]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:613) ~[spring-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:524) ~[spring-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:510) ~[spring-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:570) ~[spring-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:697) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:640) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:609) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1484) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:425) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:395) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at com.leftso.Application.main(Application.java:10) [classes/:na]
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.embedded.ServletRegistrationBean
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_40]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_40]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_40]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_40]
... 23 common frames omitted

解决办法:
出现这个问题的第一时间,我以为是常规的maven管理jar包依赖问题。后面群里有小伙伴多次尝试证明了不是maven的依赖包问题。而是spring boot的版本和cxf的版本不兼容问题。
已知兼容版本:
Spring boot 1.4.x ------>cxf-spring-boot-starter-jaxws 3.1.x
Spring boot 1.5.x------->cxf-spring-boot-starter-jaxws 3.2.x
所以出现上面问题,且用了spring boot 1.5.x的小伙伴请将cxf-spring-boot-starter-jaxws 版本升级到3.2.1即可解决。

3.2修改spring boot cxf整合后默认的/services路径
在spring boot的application配置文件中配置
cxf.path=/yourpath

本文转自:http://www.leftso.com/blog/144.html

转载于:https://www.cnblogs.com/JThinking/p/9487047.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30832983/article/details/99130895

智能推荐

bzoj3578: GTY的人类基因组计划2-程序员宅基地

文章浏览阅读60次。STL即玄学。。一看过去就觉得要hash一下吧,顺便瞄了一眼hint那我就想mp记录hash值咯然而修改不好搞啊。。。暴力重算肯定挂啊。。%了一下发现原来可以用异或来离散化(感觉这个很看脸的样子)把没有重复插入set,这样就不用穷举区间啦~边查找边删除不好弄啊。。这个RE了很久,s.end()!=it这个判法还是很迷。。。#include<cstdio>..._p2075 gty的人类基因组计划

计算机网络面临的威胁_计算机网络系统面临的威胁-程序员宅基地

文章浏览阅读3.1k次。计算机网络面临的威胁多种多样,概括起来主要有以下几类:   (1)内部泄密和破坏    内部人员可能对信息网络形成的威胁包括:内部泄密人员有意或无意泄密、更改记录信息;内部非授权人员有意偷窃机密信息、更改记录信息;内部人员破坏信息系统等。   (2)截收    网络攻击者可能通过搭线或在电磁波辐射范围内安装截收装置等方式,截获机密信息,或通过对信息流量和流向、通信频度和长度等参_计算机网络系统面临的威胁

通用mapper(tk.mybatis) 使用Enum枚举类型字段的注意事项_mapper结果可以用枚举返回值-程序员宅基地

文章浏览阅读1.3k次。我的实体类问题我的实体类中定义了一个枚举类型的字段,发现插入数据和查询数据时,都会忽略该字段;插入时的实体传参有值,数据库中为null;手动在数据库设置值,然后查询出来的数据该字段也为null;排查关于这块的资料都比较少,所以只好自己来debug源码找问题了;为什么这个字段会被参数处理器与结果处理器都忽略掉呢?源码:tk.mybatis.mapper.mapperhelper.EntityHelper#initEntityNameMaptk.mybatis.mapper.mappe_mapper结果可以用枚举返回值

强化学习入门 : 一文入门强化学习 (Sarsa、Q learning、Monte-carlo learning、Deep-Q-Network等)_monte carlo deep learning-程序员宅基地

文章浏览阅读1.1w次,点赞7次,收藏37次。最近博主在看强化学习的资料,找到这两个觉得特别适合入门,一个是“一文入门深度学习”,一个是”莫烦PYTHON”。建议:看资料的时候可以多种资料一起参考,一边调代码一边看资料学算法,有事半功倍的疗效,还有就是别看一半就放弃,要坚持治疗。转自:(原贴)http://geek.csdn.net/news/detail/201928?utm_source=tuicool&u_monte carlo deep learning

mysql安装 防火墙设置_Linux下安装MySql,防火墙简单设置-程序员宅基地

文章浏览阅读434次。最近在网上找了很多资料,发现大部分都不是很详细,以下是在网上找到的一篇文章,及自己的一些总结。本章介绍使用Mysql-rpm包进行安装,测试结果安装成功,发出来分享给大家,这里大家安装的时候一定要找到mysql安装包对应系统的版本,这一点很多教程上都没有说,导致很多新手怎么安装都是失败。详细内容看教程吧。一、新特性MySQL 5.7可谓是一个令人激动的里程碑,在默认了InnoDB引擎的基础上,新增..._安装mysql怎么改防火墙

Spring使用总结(二):添加缓存管理监控MBean_org.springframework.jmx.support.jmxutils-程序员宅基地

文章浏览阅读1.7k次。首先激活Spring的缓存管理,XML配置如下:

随便推点

手把手教你装系统(UEFI GPT篇)_uefi gpt系统怎么装-程序员宅基地

文章浏览阅读959次。转载自品略图书馆http://www.pinlue.com/article/2020/03/2813/1510060785712.html早上好,昨天有同学问到为什么不用UEFI+GPT来重装系统,那么今天这个教程就是UEFI+GPT的系统教程。首先,操作系统的启动模式有两种:Legacy BIOS和UEFI。Legacy BIOS传统启动模式,在开机时需进行自检,启动过程较..._uefi gpt系统怎么装

机器学习(Machine Learning)&深度学习(Deep Learning)资料-程序员宅基地

文章浏览阅读320次。wepon的专栏目录视图摘要视图订阅赠书 | AI专栏(AI圣经!《深度学习》中文版) 每周荐书:分布式、深度学习算法、iOS(评论送书) 项目管理+代码托管+文档协作,开发更流畅机器学习(Machine Learning)&深度学..._machine learning到deep learning

【OpenPCDet】优化器之adam_oncycle_adam_onecycle-程序员宅基地

文章浏览阅读3.8k次,点赞13次,收藏18次。OpenPCDet到目前版本(v 0.3.0)为止集成的优化器有3种:adam,sgd和adam_onecyel。这个可见代码build_optimizer(model,optim_cfg)函数。def build_optimizer(model, optim_cfg): if optim_cfg.OPTIMIZER == 'adam': optimizer = optim.Adam(model.parameters(), lr=optim_cfg.LR, weight..._adam_onecycle

Python多线程编程——多线程编程中的加锁机制_python 中什么时候该加锁-程序员宅基地

文章浏览阅读417次。如果大家对Python中的多线程编程不是很了解,推荐大家阅读之前的两篇文章:Python多线程编程——多线程基础介绍Python多线程编程——创建线程的两个方法一、什么是加锁首先举一个很生活化的例子,比如我们很多人在排队上公共厕所,一旦前面的小明进去了,那么后面的同学理论上就不能再进去了。但是如果后面的同学不知道小明现在在厕所里面,硬是推门进去了,这样机会显得很尴尬。小明为了不让..._python 中什么时候该加锁

模拟-第十届蓝桥杯省赛C++B组-特别数的和_取得每一位数字模10除10-程序员宅基地

文章浏览阅读308次。模拟-第十届蓝桥杯省赛C++B组-特别数的和题目:小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。请问,在 1 到 n 中,所有这样的数的和是多少?输入格式共一行,包含一个整数 n。输出格式共一行,包含一个整数,表示满足条件的数的和。数据范围1≤n≤..._取得每一位数字模10除10

综合布线6A系统产品集锦(一)-程序员宅基地

文章浏览阅读267次。文┃《智能建筑与城市信息》编辑部整理 1 美国康普国际控股有限公司 (1)GigaSPEED X10D 91系列电缆 GigaSPEED X10D解决方案包括专门设计的4对线UTP和FTP系列线缆(1091/2091/3091 UTP线缆和1291/2291/3291 FTP线缆)。GigaSPEED X10D解决方案旨在提供超..._g10fp和gs10e网线