SpringBoot项目使用CXF框架开发Soap通信接口
物料准备:
1.引入cxf官方提供的SpringBootStarter依赖
2.定义需要暴雷给外部调用的java接口以及接口的实现类
3.配置CxfConfig类,把你定义的java接口注册为webservice的Endpoint
引入cxf-spring-boot-starter-jaxws依赖
这里因为我用的springboot版本是2.4.2的,所以这里选择引入的是3.2.4版本的cxf框架,不建议引入更高的版本。
<!-- CXF webservice -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.2.4</version>
</dependency>
定义需要暴雷给外部调用的java接口以及接口的实现类
接口类
package cn.ath.knowwikibackend.cxf;
import cn.ath.knowwikibackend.cxf.bean.UserInfo;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import java.util.List;
//声明这个接口是一个WebService接口,必须指定targetNamespace命名空间
@WebService(targetNamespace = "http://cxf.knowwikibackend.ath.cn/")
public interface UserService {
//WebMethod注解配置的是接口的方法名
//如果方法有参数,必须配置WebParam注解里的name参数名和targetNamespace命名空间
@WebMethod(operationName = "getHello")
String getHello(@WebParam(name = "name",targetNamespace = "http://cxf.knowwikibackend.ath.cn/") String name);
@WebMethod(operationName = "get123")
List<String> get123();
@WebMethod(operationName = "getUserInfo")
UserInfo getUserInfo();
@WebMethod(operationName = "getUserList")
List<UserInfo> getUserList();
@WebMethod(operationName = "execTest1")
void execTest1();
@WebMethod(operationName = "execTest2")
void execTest2(@WebParam(name = "action",targetNamespace = "http://cxf.knowwikibackend.ath.cn/") String action);
}
实现类
package cn.ath.knowwikibackend.cxf;
import cn.ath.knowwikibackend.cxf.bean.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class UserServiceImpl implements UserService{
@Override
public String getHello(String name) {
return "hello "+name;
}
@Override
public List<String> get123() {
List<String> aee = new ArrayList<>();
aee.add("wer21r");
aee.add("regft23tf");
aee.add("retg23t");
return aee;
}
@Override
public UserInfo getUserInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setAge(24);
userInfo.setName("tear23ewr");
userInfo.setUid(10003L);
return userInfo;
}
@Override
public List<UserInfo> getUserList() {
List<UserInfo> list = new ArrayList<>();
UserInfo userInfo = new UserInfo();
userInfo.setAge(24);
userInfo.setName("tear23ewr");
userInfo.setUid(10003L);
list.add(userInfo);
UserInfo user2 = new UserInfo();
user2.setAge(27);
user2.setName("grfw34tgf");
user2.setUid(10002L);
list.add(user2);
return list;
}
@Override
public void execTest1() {
log.info("execTest1 is exec ok !");
}
@Override
public void execTest2(String action) {
log.info("action:{} is exec ok !",action);
}
}
配置CxfConfig类
package cn.ath.knowwikibackend.cxf;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;
@Configuration
public class CxfConfig {
@Autowired
private Bus bus;
@Autowired
private UserService userService;
@Bean
public ServletRegistrationBean servletRegistrationBean(){
return new ServletRegistrationBean(
new CXFServlet(),
"/soap/*"
);
}
@Bean
public Endpoint userEndpoint(){
EndpointImpl endpoint = new EndpointImpl(bus,userService);
endpoint.publish("/user");
return endpoint;
}
}
测试访问webService效果
浏览器访问暴露出的soap接口
查看你的springboot项目暴露出的soap 接口清单,可以用浏览器访问
http://ip:port/webContext/soap/
webContext是你的项目的 server.servlet.context-path
/soap/ 是你在CxfConfig里配置的soap 接口的前缀
直接用浏览器访问
http://ip:port/webContext/soap/user?wsdl
也可以看到 user端点(Endpoint)的wsdl信息,如上图所示。
这个URL里的/user 是你在CxfConfig里配置的soap接口的Endpoint端点
使用hutool里提供的SoapClient调用这些soap接口
import cn.hutool.core.lang.Console;
import cn.hutool.http.webservice.SoapClient;
@Test
void test23607(){
SoapClient client1 = SoapClient.create("http://localhost:8080/kwb/soap/user?wsdl");
// soap xml请求报文 --- 请求 getHello方法
Console.log(client1.setMethod("web:getHello","http://cxf.knowwikibackend.ath.cn/")
.setParam("name","zhangsan")
.getMsgStr(true));
//soap xml响应报文
Console.log(client1.send(true));
//重置 SoapClient
client1.reset();
// soap xml请求报文 --- 请求 get123方法
Console.log(client1.setMethod("web:get123","http://cxf.knowwikibackend.ath.cn/")
.getMsgStr(true));
//soap xml响应报文
Console.log(client1.send(true));
//重置 SoapClient
client1.reset();
Console.log(client1.setMethod("web:getUserInfo","http://cxf.knowwikibackend.ath.cn/")
.getMsgStr(true));
Console.log(client1.send(true));
client1.reset();
Console.log(client1.setMethod("web:getUserList","http://cxf.knowwikibackend.ath.cn/")
.getMsgStr(true));
Console.log(client1.send(true));
client1.reset();
Console.log(client1.setMethod("web:execTest1","http://cxf.knowwikibackend.ath.cn/")
.getMsgStr(true));
Console.log(client1.send(true));
}
soap接口通信的xml日志如下
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<web:getHello xmlns:web="http://cxf.knowwikibackend.ath.cn/">
<web:name>zhangsan</web:name>
</web:getHello>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getHelloResponse xmlns:ns2="http://cxf.knowwikibackend.ath.cn/">
<return>hello zhangsan</return>
</ns2:getHelloResponse>
</soap:Body>
</soap:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<web:get123 xmlns:web="http://cxf.knowwikibackend.ath.cn/"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:get123Response xmlns:ns2="http://cxf.knowwikibackend.ath.cn/">
<return>wer21r</return>
<return>regft23tf</return>
<return>retg23t</return>
</ns2:get123Response>
</soap:Body>
</soap:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<web:getUserInfo xmlns:web="http://cxf.knowwikibackend.ath.cn/"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getUserInfoResponse xmlns:ns2="http://cxf.knowwikibackend.ath.cn/">
<return>
<age>24</age>
<name>tear23ewr</name>
<uid>10003</uid>
</return>
</ns2:getUserInfoResponse>
</soap:Body>
</soap:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<web:getUserList xmlns:web="http://cxf.knowwikibackend.ath.cn/"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getUserListResponse xmlns:ns2="http://cxf.knowwikibackend.ath.cn/">
<return>
<age>24</age>
<name>tear23ewr</name>
<uid>10003</uid>
</return>
<return>
<age>27</age>
<name>grfw34tgf</name>
<uid>10002</uid>
</return>
</ns2:getUserListResponse>
</soap:Body>
</soap:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<web:execTest1 xmlns:web="http://cxf.knowwikibackend.ath.cn/"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:execTest1Response xmlns:ns2="http://cxf.knowwikibackend.ath.cn/"/>
</soap:Body>
</soap:Envelope>
使用Postman测试工具来测试soap接口
使用cxf自带的工具请求webservice接口
@Test
void test232323(){
String address = "http://localhost:8080/kwb/soap/user?wsdl";
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
jaxWsProxyFactoryBean.setAddress(address);
jaxWsProxyFactoryBean.setServiceClass(UserService.class);
UserService userService = (UserService) jaxWsProxyFactoryBean.create();
String name = "lisi";
String res = userService.getHello(name);
System.err.println(res);
List<UserInfo> userList = userService.getUserList();
System.err.println(userList);
userService.execTest1();
userService.execTest2("bak-sql");
}
执行效果如下
消费者端打印日志
hello lisi
[UserInfo(uid=10003, name=tear23ewr, age=24), UserInfo(uid=10002, name=grfw34tgf, age=27)]
//生产者端打印日志
2023-06-07 19:53:21,038 INFO [http-nio-8080-exec-1] [] c.a.k.c.UserServiceImpl [UserServiceImpl.java : 14] getHello--req name:lisi
2023-06-07 19:53:21,182 INFO [http-nio-8080-exec-2] [] c.a.k.c.UserServiceImpl [UserServiceImpl.java : 39] 访问了getUserList方法
2023-06-07 19:54:01,253 INFO [http-nio-8080-exec-4] [] c.a.k.c.UserServiceImpl [UserServiceImpl.java : 57] execTest1 is exec ok !
2023-06-07 19:54:01,264 INFO [http-nio-8080-exec-5] [] c.a.k.c.UserServiceImpl [UserServiceImpl.java : 63] action:bak-sql is exec ok !