记录:314
场景:在Spring Boot微应用上,使用Apache CXF框架实现Web Services客户端,调用Web Services服务端;使用Apache Axis2框架实现Web Services客户端,调用Web Services服务端。
版本:
- JDK 1.8
- Spring Boot 2.6.3
- Apache CXF 3.5.1
- Apache Axis2 1.8.2
一、Web Services服务端
本例是基于基于Spring Boot使用Apache CXF发布Web Services服务,作为服务端,用来验证客户端。
集成方式具体细节可以参考如下博文,本例只列出关键部分。
名称:基于Spring Boot应用Apache CXF发布Web Services服务
地址:https://blog.csdn.net/zhangbeizhen18/article/details/127417394
1.发布Web Services服务的接口类和实现类
1.1接口类
- package com.hub.example.webservice;
- import javax.jws.WebParam;
- import javax.jws.WebService;
- /**
- * 发布WebService服务的接口
- * 使用@WebService标记,并指定命名空间.
- * 本例指定: http://www.pro.com
- * 不指定则默认: webservice.example.hub.com
- * 实际就是包名倒序.
- * @date: 2022-11-13 16:55
- */
- @WebService(targetNamespace = "http://www.pro.com")
- public interface IProvinceInfo {
- /**
- * 入参: XML格式字符串
- * 返回: XML格式字符串
- */
- String getProvince(@WebParam(name = "xmlStr",targetNamespace = "http://www.pro.com")String xmlStr);
- }
1.2实现类
- package com.hub.example.webservice.impl;
- import com.hub.example.webservice.IProvinceInfo;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Component;
- import javax.jws.WebParam;
- import javax.jws.WebService;
- import java.util.UUID;
- @Slf4j
- @WebService(targetNamespace = "http://www.pro.com")
- @Component
- public class ProvinceInfoImpl implements IProvinceInfo {
- /**
- * 接口实现类
- * */
- @Override
- public String getProvince(@WebParam(name = "xmlStr",targetNamespace = "http://www.pro.com")String xmlStr) {
- String result = "";
- log.info("WebService的getProvince方法,接收入参,xmlStr:" + xmlStr);
- String uuid = UUID.randomUUID().toString().toUpperCase().replace("-", "");
- result = buildXml("1", "执行成功",uuid);
- log.info("WebService的getProvince方法,返回,result:" + result);
- return result;
- }
- /**
- * 辅助方法,组装xml格式字符串
- * */
- private String buildXml(String rtnCode, String rtnMsg,String uuid) {
- String xml = "\n" +
- "\n" +
- "
\n"
+ - "
" + rtnCode + "\n" + - "
" + rtnMsg + "\n" + - "
" + uuid + "\n" + - " \n" +
- "";
- return xml;
- }
- }
2.发布Web Services服务的配置类
- @Configuration
- public class CxfConfiguration {
- @Autowired
- private Bus bus;
- /**
- * 注入对外提供服务的实现类
- */
- @Autowired
- private ProvinceInfoImpl provinceInfoImpl;
-
- /**
- * 配置CXFServlet,拦截/WebServices请求
- * 注意: /WebServices作为http请求url前缀专门给CXFServlet使用
- **/
- @Bean
- public ServletRegistrationBean
configCXFServlet() { - return new ServletRegistrationBean
(new CXFServlet(), "/WebServices/*"); - }
- /**
- * 发布CXF服务,使用org.apache.cxf.jaxws包的EndpointImpl发布
- */
- @Bean
- public Endpoint endpointProvinceInfo() {
- EndpointImpl endpoint = new EndpointImpl(bus, provinceInfoImpl);
- endpoint.publish("/provinceInfoWS");
- return endpoint;
- }
- }
3.发布Web Services地址
本例发布服务地址,根据配置类中信息可以组装完成。
地址:http://127.0.0.1:18080/example-cxf/WebServices/provinceInfoWS?wsdl
解析:example-cxf,是微服务名称;WebServices,专门给CXFServlet使用,用来确认请求是WebServices的请求;provinceInfoWS,是Web Services发布的地址;wsdl,是Web Services约定的标识符。
二、使用Apache CXF框架实现Web Services客户端
使用Apache CXF框架实现客户端方式有很多,开发者按需选择。
1.客户端一
1.1客户端代码
- package com.hub.example.cxf;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.cxf.endpoint.Client;
- import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
- import org.apache.cxf.transport.http.HTTPConduit;
- import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
- @Slf4j
- public class CxfClientUtils {
- public static void main(String[] args) {
- // 1.服务端地址
- String wsdlAddr = "http://127.0.0.1:18080/example-cxf/WebServices/provinceInfoWS?wsdl";
- // 2.服务端发布的方法
- String methodName = "getProvince";
- // 3.服务端发布的方法的入参的参数值
- String xmlStr = getXmlStr();
- Object[] para = new Object[]{xmlStr};
- // 4.客户端发起调用
- invokeWs(wsdlAddr, methodName, para);
- }
- /**
- * wsdlAddr: 服务端发布的地址
- * methodName: 服务端发布的方法名称
- * params: 服务端发布的方法的参数值
- */
- public static Object[] invokeWs(String wsdlAddr, String methodName, Object[] para) {
- // 设置90秒接收超时
- long receiveTimeout = 1000 * 90;
- // 设置90秒连接超时
- long connectionTimeout = 1000 * 90;
- // 以动态方式创建客户端以及设置相关参数
- JaxWsDynamicClientFactory jwdcf = JaxWsDynamicClientFactory.newInstance();
- Client cli = jwdcf.createClient(wsdlAddr);
- Object[] obj = null;
- HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
- HTTPConduit conduit = (HTTPConduit) cli.getConduit();
- httpClientPolicy.setConnectionTimeout(connectionTimeout);
- httpClientPolicy.setReceiveTimeout(receiveTimeout);
- conduit.setClient(httpClientPolicy);
- try {
- obj = cli.invoke(methodName, para);
- log.info("cxf客户端接收到服务端返回值:" + obj[0].toString());
- } catch (Exception e) {
- e.printStackTrace();
- }
- return obj;
- }
- public static String getXmlStr() {
- String xmlStr = "\n" +
- "\n" +
- "
\n"
+ - "
浙江 \n" + - "
330000 \n" + - " \n" +
- "";
- return xmlStr;
- }
- }
1.2在main函数验证
直接右键,main函数调用即可。
三、使用Apache Axis2框架实现Web Services客户端
使用Apache Axis2框架实现客户端方式有很多,开发者按需选择。
1.客户端一个
1.1客户端代码
- package com.hub.example.axis2;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.axiom.om.OMAbstractFactory;
- import org.apache.axiom.om.OMElement;
- import org.apache.axiom.om.OMFactory;
- import org.apache.axiom.om.OMNamespace;
- import org.apache.axis2.AxisFault;
- import org.apache.axis2.addressing.EndpointReference;
- import org.apache.axis2.client.Options;
- import org.apache.axis2.client.ServiceClient;
- @Slf4j
- public class Axis2ClientUtils {
- public static void main(String[] args) {
- // 1.服务端地址
- String wsdlAddr = "http://127.0.0.1:18080/example-cxf/WebServices/provinceInfoWS?wsdl";
- // 2.服务端的命名空间
- String targetNamespace = "http://www.pro.com";
- // 3.服务端发布的方法
- String methodName = "getProvince";
- // 4.服务端发布的方法的入参的参数名称
- String paramName = "xmlStr";
- // 5.服务端发布的方法的入参的参数值
- String paramValue = getXmlStr();
- try {
- String result = Axis2ClientUtils.invokeWs(wsdlAddr, targetNamespace,
- methodName, paramName, paramValue);
- log.info("Axis2客户端接收到服务端返回值:" + result.toString());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * wsdlAddr: 服务端发布的地址
- * targetNamespace: 服务端发布的命名空间
- * methodName: 服务端发布的方法名称
- * params: 服务端发布的方法的参数名称和参数值
- */
- public static String invokeWs(String wsdlAddr, String targetNamespace, String methodName, Object... params) {
- String result = "";
- try {
- ServiceClient serviceClient = new ServiceClient();
- Options options = serviceClient.getOptions();
- EndpointReference endpointReference = new EndpointReference(wsdlAddr);
- options.setTo(endpointReference);
- // 服务端没有指定soapAction,则直接设置为空
- options.setAction("");
- OMFactory omFactory = OMAbstractFactory.getOMFactory();
- OMNamespace omNamespace = omFactory.createOMNamespace(targetNamespace, "");
- // 服务端发布的方法,客户端会用一个OMElement对象去对应
- OMElement methodOMElement = omFactory.createOMElement(methodName, omNamespace);
- // 服务端方法的形式参数名称和实参的值是一对的且传入一个OMElement
- // 如果服务端方法有多个参数,则就会构造多个OMElement
- for (int i = 0; i < params.length; i = i + 2) {
- // 参数名称
- OMElement paraOMElement = omFactory.createOMElement(String.valueOf(params[i]), omNamespace);
- // 参数值
- paraOMElement.setText(String.valueOf(params[i + 1]));
- // 把设置参数的OMElement加入到方法的OMElement中
- methodOMElement.addChild(paraOMElement);
- }
- methodOMElement.build();
- // 返回结果有一个OMElement对象去对应
- OMElement resultOMElement = serviceClient.sendReceive(methodOMElement);
- result = resultOMElement.getFirstElement().toString();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return result;
- }
- public static String getXmlStr() {
- String xmlStr = "\n" +
- "\n" +
- "
\n"
+ - "
浙江 \n" + - "
330000 \n" + - " \n" +
- "";
- return xmlStr;
- }
- }
1.2在main函数验证
直接右键,main函数调用即可。
四、小结
使用Apache CXF实现的客户端,代码简洁,手动设置参数少。
使用Apache Axis2实现的客户端,需要仔细比对客户端和服务端,对应参数需要确认一致。
以上,感谢。
2022年11月13日