使用Apache CXF和Apache Axis2实现Web Services客户端

2023-10-29

记录: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 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
      "<data>\n" +
      "  <row>\n" +
      "   <column Name=\"code\">" + rtnCode + "</column>\n" +
      "   <column Name=\"message\">" + rtnMsg + "</column>\n" +
      "   <column Name=\"randomUUID\">" + uuid + "</column>\n" +
      "  </row>\n" +
      "</data>";
    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<CXFServlet> configCXFServlet() {
      return new ServletRegistrationBean<CXFServlet>(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 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
       "<data>\n" +
       "  <row>\n" +
       "   <column Name=\"ProvinceName\">浙江</column>\n" +
       "   <column Name=\"ProvinceNo\">330000</column>\n" +
       "  </row>\n" +
       "</data>";
    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 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
      "<data>\n" +
      "  <row>\n" +
      "   <column Name=\"ProvinceName\">浙江</column>\n" +
      "   <column Name=\"ProvinceNo\">330000</column>\n" +
      "  </row>\n" +
      "</data>";
    return xmlStr;
  }
}

1.2在main函数验证

直接右键,main函数调用即可。

四、小结

使用Apache CXF实现的客户端,代码简洁,手动设置参数少。

使用Apache Axis2实现的客户端,需要仔细比对客户端和服务端,对应参数需要确认一致。

以上,感谢。

2022年11月13日

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Apache CXF和Apache Axis2实现Web Services客户端 的相关文章

随机推荐

  • 一个数组实现两个栈(共享栈)

    题目 一个数组实现两个栈 方法1 下标为0的位置为栈1的栈底 下标为1的位置为栈2的栈底 栈1的元素存放在下标为偶数的位置上 栈2的元素放在下标为奇数的位置上 如上图所示的数组 若栈1有一个元素 2 栈2有6个元素 1 2 3 4 5 6
  • UnityShader _Object2World与UNITY_MATRIX_MVP被替换

    1 Object2World 模型空间转世界空间 Unity5 5版本中 Object2World已经变成unity ObjectToWorld World2Object也变成了unity WorldToObject 但由于Unity的向下
  • Macos安装brew攻略

    Brew Macos的apt get和软件安装快捷方式 Brew install offiical site https brew sh install instruction bin bash c curl fsSL https raw
  • java批量插入数据库之写绑定变量

    最近查到关于sql批量写入和绑定变量的问题 看到了很多好的帖子 再次进行总结 数据库在执行SQL语句时会首先解析SQL语句 解析又分为硬解析与软解析 说到硬解析和软解析 就不能不说一下Oracle对sql的处理过程 当你发出一条sql语句交
  • Linux C 多线程

    为什么会有线程 gt gt gt gt 进程实现多任务的缺点 进程间切换的计算机资源开销很大 切换效率非常低 进程间数据共享的开销也很大 线程和进程的关系 线程是进程的一个执行单元 是进程内的调度实体 比进程更小的独立运行的基本单位 线程也
  • In-Doubt Transactions

    In Doubt Transactions The two phase commit mechanism ensures that all nodes either commit or perform a rollback together
  • 常用的PHP命令执行函数及利用方式

    PHP命令执行函数常配合代码执行漏洞使用 利用命令执行函数执行操作系统命令 从而发起攻击 接下来就简单分享几个常用的PHP命令执行函数 system system 函数可以执行系统命令 并将命令执行的结果直接输出到界面中 使用时直接在参数中
  • 初窥Linux神秘面纱(叁):基本指令讲解(下)及疑难解惑(精)

    目录 date指令 cal指令 find指令 grep指令 alias指令 wc指令 whereis指令 zip unzip指令 tar指令 date指令 date 指定格式显示时间 date Y m d date 用法 date OPTI
  • Linux驱动入门(6.2)按键驱动和LED驱动 --- 将逻辑电平与物理电平分离

    前言 1 在学习完Linux驱动入门 6 LED驱动 设备树之后 我们发现一个问题 设备树明明的gpios信息明明有三个元素gpios lt gpio5 3 GPIO ACTIVE LOW gt gpio5 3 用来确定控制那个引脚 而GP
  • [4G&5G专题-127]:5G培训部署篇-4-基站项目的安装与验收过程

    作者主页 https blog csdn net HiWangWenBing 本文网址 https blog csdn net HiWangWenBing article details 118456868 目录 第1部分 基站项目的安装与
  • 快排函数

    C 语言中排序的算法有很多 系统也提供一个函数qsort 可以实现快速排序 它包含在
  • 水浊度传感器( ADC 代码详解)

    水浊度传感器 最后代码已上传 代码文章链接 github 代码链接在该文章最后 文章目录 硬件使用 软件使用 实现说明 水浊度原理 具体操作代码说明 配置通道规则 开启软件转换 判断转换完成 读取 ADC 值 计算水浊度 通过串口发送到串口
  • spring-cloud - 部署

    一 jenkins git部署 1 1 jenkins git安装 1 2 jenkins项目配置 1 3 git配置触发器 二 docker部署 2 1 打包 根据项目pom中配置利用mvn package 进行打包生成jar docke
  • 教你如何用命令行装逼,做一个有逼格的程序员

    教你如何用命令行装逼 做一个有逼格的程序员 事先声明 如果你不知道打开windows的命令行工具 我是绝对不会告诉你是用 windows R 然后键入 cmd 打开的 windows 自带的命令行工具很强大 毕竟计算机一开始都是以键入命令的
  • python爬虫八:多任务线程

    1 多线程 举例 有很多的场景中的事情是同时进行的 比如开车的时候 手和脚共同来驾驶汽车 再比如唱歌跳舞也是同时进行的 定义 线程是进程的一个实体 是CPU调度和分派的基本单位 它是比进程更小的能独立运行的基本单位 线程自己基本上不拥有系统
  • 基于PTB数据集实现RNN-LSTM循环神经网络(智能填词)

    本篇直入主题 做一篇学习的记录 在学习RNN的时候 跟着教程敲了一个案例 分为处理方法文件 神经网络模型文件 训练方法文件 测试文件 所有的操作和重要内容都在代码中作了详细的注释 一 目标神经网络模型 二 数据集 PTB数据集下载地址 ht
  • series选取值_Series和DataFrame的数据取值与选择

    数据取值与选择 NumPy数据取值的方法 包括取值操作 如arr 2 1 切片操作 如arr 1 5 掩码操作 如arr arr gt 0 花哨的索引操作 如arr 0 1 5 以及组合操作 如arr 1 5 在NumPy的二维数组里 da
  • qt触摸屏调试(tslib1.21 + qt5.12.9)

    过程是痛苦的 因为之前没调试过qt 也没啥总结的 可能换个设备还是慢慢摸索调试 前文已介绍了如果编译 tslib和qt 且非常详细 那个步骤现在看没有问题 我在调试qt的时候 翻看了好多遍前文编译的库 看编译过程是否有问题 我这不叫写文章
  • excel文件无法打印提示内存不足_打开Excel时,提示“Excel词典(XLLEX.DLL)文件丢失或损坏”...

    使用的是OFFICE2007完整版 一直都是正常的 突然打开Excel时 提示 Excel词典 XLLEX DLL 文件丢失或损坏 怎么办 打开Excel时 提示 Excel词典 XLLEX DLL 文件丢失或损坏 答 出现这种情况 是因为
  • 使用Apache CXF和Apache Axis2实现Web Services客户端

    记录 314 场景 在Spring Boot微应用上 使用Apache CXF框架实现Web Services客户端 调用Web Services服务端 使用Apache Axis2框架实现Web Services客户端 调用Web Ser