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


    记录:314

    场景:在Spring Boot微应用上,使用Apache CXF框架实现Web Services客户端,调用Web Services服务端;使用Apache Axis2框架实现Web Services客户端,调用Web Services服务端。

    版本:

    1. JDK 1.8
    2. Spring Boot 2.6.3
    3. Apache CXF 3.5.1
    4. 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接口类

    1. package com.hub.example.webservice;
    2. import javax.jws.WebParam;
    3. import javax.jws.WebService;
    4. /**
    5. * 发布WebService服务的接口
    6. * 使用@WebService标记,并指定命名空间.
    7. * 本例指定: http://www.pro.com
    8. * 不指定则默认: webservice.example.hub.com
    9. * 实际就是包名倒序.
    10. * @date: 2022-11-13 16:55
    11. */
    12. @WebService(targetNamespace = "http://www.pro.com")
    13. public interface IProvinceInfo {
    14. /**
    15. * 入参: XML格式字符串
    16. * 返回: XML格式字符串
    17. */
    18. String getProvince(@WebParam(name = "xmlStr",targetNamespace = "http://www.pro.com")String xmlStr);
    19. }

    1.2实现类

    1. package com.hub.example.webservice.impl;
    2. import com.hub.example.webservice.IProvinceInfo;
    3. import lombok.extern.slf4j.Slf4j;
    4. import org.springframework.stereotype.Component;
    5. import javax.jws.WebParam;
    6. import javax.jws.WebService;
    7. import java.util.UUID;
    8. @Slf4j
    9. @WebService(targetNamespace = "http://www.pro.com")
    10. @Component
    11. public class ProvinceInfoImpl implements IProvinceInfo {
    12. /**
    13. * 接口实现类
    14. * */
    15. @Override
    16. public String getProvince(@WebParam(name = "xmlStr",targetNamespace = "http://www.pro.com")String xmlStr) {
    17. String result = "";
    18. log.info("WebService的getProvince方法,接收入参,xmlStr:" + xmlStr);
    19. String uuid = UUID.randomUUID().toString().toUpperCase().replace("-", "");
    20. result = buildXml("1", "执行成功",uuid);
    21. log.info("WebService的getProvince方法,返回,result:" + result);
    22. return result;
    23. }
    24. /**
    25. * 辅助方法,组装xml格式字符串
    26. * */
    27. private String buildXml(String rtnCode, String rtnMsg,String uuid) {
    28. String xml = "\n" +
    29. "\n" +
    30. " \n" +
    31. " " + rtnCode + "\n" +
    32. " " + rtnMsg + "\n" +
    33. " " + uuid + "\n" +
    34. " \n" +
    35. "";
    36. return xml;
    37. }
    38. }

    2.发布Web Services服务的配置类

    1. @Configuration
    2. public class CxfConfiguration {
    3. @Autowired
    4. private Bus bus;
    5. /**
    6. * 注入对外提供服务的实现类
    7. */
    8. @Autowired
    9. private ProvinceInfoImpl provinceInfoImpl;
    10. /**
    11. * 配置CXFServlet,拦截/WebServices请求
    12. * 注意: /WebServices作为http请求url前缀专门给CXFServlet使用
    13. **/
    14. @Bean
    15. public ServletRegistrationBean configCXFServlet() {
    16. return new ServletRegistrationBean(new CXFServlet(), "/WebServices/*");
    17. }
    18. /**
    19. * 发布CXF服务,使用org.apache.cxf.jaxws包的EndpointImpl发布
    20. */
    21. @Bean
    22. public Endpoint endpointProvinceInfo() {
    23. EndpointImpl endpoint = new EndpointImpl(bus, provinceInfoImpl);
    24. endpoint.publish("/provinceInfoWS");
    25. return endpoint;
    26. }
    27. }

    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客户端代码

    1. package com.hub.example.cxf;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.apache.cxf.endpoint.Client;
    4. import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
    5. import org.apache.cxf.transport.http.HTTPConduit;
    6. import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
    7. @Slf4j
    8. public class CxfClientUtils {
    9. public static void main(String[] args) {
    10. // 1.服务端地址
    11. String wsdlAddr = "http://127.0.0.1:18080/example-cxf/WebServices/provinceInfoWS?wsdl";
    12. // 2.服务端发布的方法
    13. String methodName = "getProvince";
    14. // 3.服务端发布的方法的入参的参数值
    15. String xmlStr = getXmlStr();
    16. Object[] para = new Object[]{xmlStr};
    17. // 4.客户端发起调用
    18. invokeWs(wsdlAddr, methodName, para);
    19. }
    20. /**
    21. * wsdlAddr: 服务端发布的地址
    22. * methodName: 服务端发布的方法名称
    23. * params: 服务端发布的方法的参数值
    24. */
    25. public static Object[] invokeWs(String wsdlAddr, String methodName, Object[] para) {
    26. // 设置90秒接收超时
    27. long receiveTimeout = 1000 * 90;
    28. // 设置90秒连接超时
    29. long connectionTimeout = 1000 * 90;
    30. // 以动态方式创建客户端以及设置相关参数
    31. JaxWsDynamicClientFactory jwdcf = JaxWsDynamicClientFactory.newInstance();
    32. Client cli = jwdcf.createClient(wsdlAddr);
    33. Object[] obj = null;
    34. HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
    35. HTTPConduit conduit = (HTTPConduit) cli.getConduit();
    36. httpClientPolicy.setConnectionTimeout(connectionTimeout);
    37. httpClientPolicy.setReceiveTimeout(receiveTimeout);
    38. conduit.setClient(httpClientPolicy);
    39. try {
    40. obj = cli.invoke(methodName, para);
    41. log.info("cxf客户端接收到服务端返回值:" + obj[0].toString());
    42. } catch (Exception e) {
    43. e.printStackTrace();
    44. }
    45. return obj;
    46. }
    47. public static String getXmlStr() {
    48. String xmlStr = "\n" +
    49. "\n" +
    50. " \n" +
    51. " 浙江\n" +
    52. " 330000\n" +
    53. " \n" +
    54. "";
    55. return xmlStr;
    56. }
    57. }

    1.2在main函数验证

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

    三、使用Apache Axis2框架实现Web Services客户端

    使用Apache Axis2框架实现客户端方式有很多,开发者按需选择。

    1.客户端一个

    1.1客户端代码

    1. package com.hub.example.axis2;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.apache.axiom.om.OMAbstractFactory;
    4. import org.apache.axiom.om.OMElement;
    5. import org.apache.axiom.om.OMFactory;
    6. import org.apache.axiom.om.OMNamespace;
    7. import org.apache.axis2.AxisFault;
    8. import org.apache.axis2.addressing.EndpointReference;
    9. import org.apache.axis2.client.Options;
    10. import org.apache.axis2.client.ServiceClient;
    11. @Slf4j
    12. public class Axis2ClientUtils {
    13. public static void main(String[] args) {
    14. // 1.服务端地址
    15. String wsdlAddr = "http://127.0.0.1:18080/example-cxf/WebServices/provinceInfoWS?wsdl";
    16. // 2.服务端的命名空间
    17. String targetNamespace = "http://www.pro.com";
    18. // 3.服务端发布的方法
    19. String methodName = "getProvince";
    20. // 4.服务端发布的方法的入参的参数名称
    21. String paramName = "xmlStr";
    22. // 5.服务端发布的方法的入参的参数值
    23. String paramValue = getXmlStr();
    24. try {
    25. String result = Axis2ClientUtils.invokeWs(wsdlAddr, targetNamespace,
    26. methodName, paramName, paramValue);
    27. log.info("Axis2客户端接收到服务端返回值:" + result.toString());
    28. } catch (Exception e) {
    29. e.printStackTrace();
    30. }
    31. }
    32. /**
    33. * wsdlAddr: 服务端发布的地址
    34. * targetNamespace: 服务端发布的命名空间
    35. * methodName: 服务端发布的方法名称
    36. * params: 服务端发布的方法的参数名称和参数值
    37. */
    38. public static String invokeWs(String wsdlAddr, String targetNamespace, String methodName, Object... params) {
    39. String result = "";
    40. try {
    41. ServiceClient serviceClient = new ServiceClient();
    42. Options options = serviceClient.getOptions();
    43. EndpointReference endpointReference = new EndpointReference(wsdlAddr);
    44. options.setTo(endpointReference);
    45. // 服务端没有指定soapAction,则直接设置为空
    46. options.setAction("");
    47. OMFactory omFactory = OMAbstractFactory.getOMFactory();
    48. OMNamespace omNamespace = omFactory.createOMNamespace(targetNamespace, "");
    49. // 服务端发布的方法,客户端会用一个OMElement对象去对应
    50. OMElement methodOMElement = omFactory.createOMElement(methodName, omNamespace);
    51. // 服务端方法的形式参数名称和实参的值是一对的且传入一个OMElement
    52. // 如果服务端方法有多个参数,则就会构造多个OMElement
    53. for (int i = 0; i < params.length; i = i + 2) {
    54. // 参数名称
    55. OMElement paraOMElement = omFactory.createOMElement(String.valueOf(params[i]), omNamespace);
    56. // 参数值
    57. paraOMElement.setText(String.valueOf(params[i + 1]));
    58. // 把设置参数的OMElement加入到方法的OMElement中
    59. methodOMElement.addChild(paraOMElement);
    60. }
    61. methodOMElement.build();
    62. // 返回结果有一个OMElement对象去对应
    63. OMElement resultOMElement = serviceClient.sendReceive(methodOMElement);
    64. result = resultOMElement.getFirstElement().toString();
    65. } catch (Exception e) {
    66. e.printStackTrace();
    67. }
    68. return result;
    69. }
    70. public static String getXmlStr() {
    71. String xmlStr = "\n" +
    72. "\n" +
    73. " \n" +
    74. " 浙江\n" +
    75. " 330000\n" +
    76. " \n" +
    77. "";
    78. return xmlStr;
    79. }
    80. }

    1.2在main函数验证

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

    四、小结

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

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

    以上,感谢。

    2022年11月13日

  • 相关阅读:
    PHP GET,POST请求file_get_contents拼接header
    吃鸡专家教你战无不胜,分享顶级干货!
    【面试题】智力题
    【哈希】关于哈希的实现、冲突的解决、扩容等
    触摸屏实验
    如何解决跨域问题
    SpringBean生命周期
    [分布式算法] 理论基础
    短视频解析易语言代码
    Windows搭建青龙面板并且可以外网登录教程
  • 原文地址:https://blog.csdn.net/zhangbeizhen18/article/details/127835722