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

时间: 2024-10-05 10:35:16

spring boot整合cxf发布和调用webservice的相关文章

使用CXF发布和调用webservice之HelloWorld入门

依赖的JAR     cxf-2.2.10.jar     jetty-6.1.21.jar     jetty-util-6.1.21.jar     servlet-2_5-api.jar     wsdl4j-1.6.2.jar     XmlSchema-1.4.5.jar 创建一个普通的Java工程即可 创建webservice接口 package com.cxf.interfaces; import javax.jws.WebParam; import javax.jws.WebSe

webService总结(一)——使用CXF发布和调用webService(不使用Spring)

CXF和Axis2是两个比较流行的webService框架,接下来我会写几篇博客简单介绍如何使用这两种框架.首先,先简单介绍一下CXF的使用. CXF发布webService有多种方法,这里我介绍三种: 1.不使用Spring,CXF自动发布webService 2.不使用Spring,CXF手动发布webService 3.使用Spring + CXF发布webService 这篇博客以实例介绍第一种方法--不使用Spring,CXF自动发布webService. 服务端: 目录结构如下: I

Spring Boot用Cxf的jax-ws开发WebService

首先上项目的pom.xml: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apa

Spring Boot (十三): Spring Boot 整合 RabbitMQ

1. 前言 RabbitMQ 是一个消息队列,说到消息队列,大家可能多多少少有听过,它主要的功能是用来实现应用服务的异步与解耦,同时也能起到削峰填谷.消息分发的作用. 消息队列在比较主要的一个作用是用来做应用服务的解耦,消息从消息的生产者传递到消息队列,消费者从消息队列中获取消息并进行消费,生产者不需要管是谁在消费消息,消费者也无需关注消息是由谁来生产的.在分布式的系统中,消息队列也会被用在其他地方,比如分布式事务的支持,代表如阿里开源的 RocketMQ . 当然,我们本篇文章的主角还是 Ra

spring boot 整合 quartz 集群环境 实现 动态定时任务配置【原】

最近做了一个spring boot 整合 quartz  实现 动态定时任务配置,在集群环境下运行的 任务.能够对定时任务,动态的进行增删改查,界面效果图如下: 1. 在项目中引入jar 2. 将需要的表导入数据库 官网上有不同数据库的脚本,找到对应的,导入即可 3. java 代码 将quartz 的相关配置文件,配置为暴露bean,方便后期引用. 有一处关键的地方,就是注入spring 上下文,也可以算是一个坑.如果,不注入spring 上下文,那么新添加的定时任务job,是新new 的一个

webService总结(四)——使用axis2发布和调用webService

准备工作 Axis2 官网 http://axis.apache.org/  下载axis2相关资料 其中 axis2-1.6.2-bin.zip文件中包含了Axis2中所有的jar文件, axis2-1.6.2-war.zip文件用于将WebService发布到Web容器中.最后两个是axis2在eclipse中的插件. 大概说说这几个文件如何使用. 1.解压axis2-1.6.2-bin.zip到任意目录.然后在eclipse中按下图配置. 2.将axis2-1.6.2-war.zip文件解

activeMQ入门+spring boot整合activeMQ

最近想要学习MOM(消息中间件:Message Oriented Middleware),就从比较基础的activeMQ学起,rabbitMQ.zeroMQ.rocketMQ.Kafka等后续再去学习. 上面说activeMQ是一种消息中间件,可是为什么要使用activeMQ? 在没有使用JMS的时候,很多应用会出现同步通信(客户端发起请求后需要等待服务端返回结果才能继续执行).客户端服务端耦合.单一点对点(P2P)通信的问题,JMS可以通过面向消息中间件的方式很好的解决了上面的问题. JMS规

Spring Boot 整合JDBC 实现后端项目开发

一.前言 前后端分离开发是将项目开发工作前后端交互工作拆分,使前端开发人员能够专注于页面开发或APP 开发,后端开发人员专注与接口开发.业务逻辑开发. 此处开发后端项目,给前端或者APP 端提供接口.不涉及复杂的业务逻辑,通过简单的增删改查来演示后端开发项目. 环境介绍: 开发工具:IDEA JDK: 1.7 及以上 Spring Boot: 2.0 及以上 Maven: 3.0 及以上 二.新建Spring Boot 项目 通过功能菜单File - New - Project 新建Spring

Spring Boot 整合 Dubbo和Zookeeper

Spring Boot 整合 Dubbo和Zookeeper Spring Boot 整合 Dubbo和Zookeeper 环境介绍 Zookeeper 安装 启动 Dubbo admin 搭建 创建主maven项目 创建子spring boot项目 环境介绍 zookeeper 安装 dubbo-admin 查看管理注册中心服务提供者和消费者 Zookeeper 安装 http://zookeeper.apache.org/releases.html 下载最新安装包,文件格式是tar.gz,可