• SpringBoot调用WebService的实践


    作者所在公司的系统间的信息交互是通过webservice完成。如:MES与SAP的交互,MES与WMS的交换,MES与SRM的交互,MES与IOT的交互等。

    MES是用.NET VS2008 C#写的,调用webservice很简单,这里不再赘述。如有想了解的,可以私信作者。

    此篇文章主要介绍IOT平台的怎么调用webservice。

    作者所在公司的IOT平台是基于SpringBoot框架开发的。

    环境要求(仅参考,可能别的版本也行,只是作者本次用的是以下版本):

    工具版本
    Java-jdk

    java version "1.8.0_161"

    Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
    ideaIntelliJ IDEA 2019.2以上
    git2.30及以上
    Mavenapache-maven-3.6.3

    SpringBoot框架不再赘述了,作者另一篇文章有做入门介绍,本篇文章主要写java的SpringBoot架构如果调用webservice(XML)

    SpringBoot学习笔记-CSDN博客

    1.先决条件

    依赖引用:


    org.springframework.boot
    spring-boot-starter-web-services

    2.结构创建

    Bean类中创建与soapui中结构相同的请求类和返回类。

    注意:如果XML中的字段名称与Java类中的字段名称不同,要用到以下几个注解。

    @XmlRootElement(name = "XML根节点名称")

    @XmlElementWrapper(name = "XML中LIst节点名称")
    @XmlElement(name = "XML中普通节点名称")

    这些注解可以帮助SpringBoot结构将XML中的字段反射到Java类中的字段。

    3.写Controller

    Controller层没什么特别的,正常写就行,因为传入参数是json,所以用PostMapping的方法

    4.写Service层

    Service层的接口,也正常写就行,返回一个MESResponse类型的对象

    重点是Service的实现层

    整体思路:通过xml调用MES系统提供的服务,将MES系统返回的信息流先转换成字符串,再反射到java的对象中。

    下面贴上实现层的代码供大家参考:

    1. package com.zjtc.qmsquality.FPYData.service;
    2. import com.google.common.io.CharStreams;
    3. import com.zjtc.qmsquality.FPYData.Util.EntityUtil;
    4. import com.zjtc.qmsquality.FPYData.bean.MESRequest;
    5. import com.zjtc.qmsquality.FPYData.bean.MESRsp;
    6. import org.springframework.stereotype.Service;
    7. import java.io.InputStreamReader;
    8. import java.io.OutputStreamWriter;
    9. import java.net.HttpURLConnection;
    10. import java.net.URL;
    11. @Service
    12. public class FPYDataServiceImpl implements FPYDataService{
    13. public static final String targetUrl = "http://172.18.3.67:8020/MesFrameWork.asmx?wsdl"; //测试
    14. @Override
    15. public MESRsp getFPYData(String no){
    16. //调用MES接口查询数据
    17. MESRsp mesResponse = new MESRsp();
    18. try {
    19. MESRequest mesRequest = new MESRequest();
    20. mesRequest.setNo(no);
    21. mesResponse = sendMessage(no);
    22. } catch (Exception e) {
    23. mesResponse.setResult("NG");
    24. mesResponse.setMessage(e.toString());
    25. }
    26. return mesResponse;
    27. }
    28. public static String getDataFromMESSystem(String no,int rflag) {
    29. // 根据上面的XSDL文档封装请求参数
    30. String strParameter = "1.0\" encoding=\"UTF-8\"?>\n" +
    31. "http://schemas.xmlsoap.org/soap/envelope/\" xmlns:dev=\"http://device.service.moresoft.com/\">\n" +
    32. "\n" +
    33. " \n" +
    34. " \n" +
    35. "\n" +
    36. ""+rflag+"\n" +
    37. " " + no + "\n\n" +
    38. " \n" +
    39. " \n" +
    40. "\n" +
    41. "";
    42. System.out.println("strParameter : " + strParameter);
    43. return strParameter;
    44. }
    45. public static MESRsp sendMessage(String no) throws Exception {
    46. try {
    47. URL url = new URL(targetUrl);
    48. OutputStreamWriter wr = null;
    49. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    50. String data = getDataFromMESSystem(no,2);
    51. System.out.println("data : " + data);
    52. conn.setRequestProperty("Content-Length", String.valueOf(data.getBytes().length));
    53. conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
    54. conn.setDoOutput(true);
    55. conn.setConnectTimeout(1000 * 20);
    56. conn.setReadTimeout(1000 * 20);
    57. if(data!=null && data.toString().trim().length()>0){
    58. wr = new OutputStreamWriter(conn.getOutputStream(),"UTF-8");
    59. wr.write(data);
    60. wr.flush();
    61. }
    62. String result = CharStreams.toString(new InputStreamReader(conn.getInputStream(), "utf-8"));
    63. System.out.println("result : " + result);
    64. String xml=analyzeResult(result);
    65. System.out.println("xml : " + xml);
    66. MESRsp mesResponse= EntityUtil.xml2Entity(xml,MESRsp.class);
    67. System.out.println("mesResponse.result : " + mesResponse.getResult());
    68. System.out.println("mesResponse.Message : " + mesResponse.getMessage());
    69. System.out.println("getFpyDataList : " + mesResponse.getFpyDataList());
    70. return mesResponse;
    71. } catch (Exception ex) {
    72. MESRsp mesResponse=new MESRsp();
    73. mesResponse.setResult("NG");
    74. mesResponse.setMessage(ex.toString());
    75. if(mesResponse.getMessage()!=null&&mesResponse.getMessage().startsWith("java.net.SocketTimeout")){
    76. mesResponse.setMessage("接口超时");
    77. }
    78. return mesResponse;
    79. }
    80. }
    81. public static String analyzeResult(String result) throws Exception {
    82. int fromStr=result.indexOf("");
    83. int toStr=result.indexOf("",fromStr);
    84. String xml=result.substring(fromStr,toStr);
    85. return xml;
    86. }
    87. }

    对了,关于这段XSDL的文档,参考soapui中的自动生成的xml文档。(直接复制粘贴上去就行,要什么参数,就填什么参数)

    5.建字符串反射到java类的方法

    按步骤写完第四步的朋友,应该会发现EntityUtil类不存在的报错【狗头保命】,不要紧,接下来咱们来贴上这个类的代码就好了。作者也是抄的,不过这个类不错,以后就是大家的了。

    1. package com.zjtc.qmsquality.FPYData.Util;
    2. import javax.xml.bind.JAXBContext;
    3. import javax.xml.bind.JAXBException;
    4. import javax.xml.bind.Marshaller;
    5. import javax.xml.bind.Unmarshaller;
    6. import java.io.StringReader;
    7. import java.io.StringWriter;
    8. import java.lang.reflect.Field;
    9. import java.lang.reflect.InvocationTargetException;
    10. import java.lang.reflect.Method;
    11. import java.sql.ResultSet;
    12. import java.sql.ResultSetMetaData;
    13. import java.sql.SQLException;
    14. import java.util.ArrayList;
    15. import java.util.List;
    16. public class EntityUtil {
    17. public static String entity2Xml(Object entity) throws JAXBException {
    18. JAXBContext context = JAXBContext.newInstance(new Class[]{entity.getClass()});
    19. Marshaller marshaller = context.createMarshaller();
    20. marshaller.setProperty("jaxb.formatted.output", true);
    21. marshaller.setProperty("jaxb.fragment", true);
    22. StringWriter sw = new StringWriter();
    23. marshaller.marshal(entity, sw);
    24. String xml = sw.toString();
    25. return xml;
    26. }
    27. public static <T> T xml2Entity(String xml, Class<T> c) throws JAXBException {
    28. T t = null;
    29. JAXBContext context = JAXBContext.newInstance(c);
    30. Unmarshaller unmarshaller = context.createUnmarshaller();
    31. t = (T) unmarshaller.unmarshal(new StringReader(xml));
    32. // System.out.println("12312312a: " + t.toString());
    33. return t;
    34. }
    35. public static <T> List<T> resultToList(ResultSet resultSet, Class<T> clazz) throws IllegalAccessException, InstantiationException, SQLException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
    36. //创建一个 T 类型的数组
    37. List<T> list = new ArrayList<>();
    38. try {
    39. //通过反射获取对象的实例
    40. T t = clazz.getConstructor().newInstance();
    41. //获取resultSet 的列的信息
    42. ResultSetMetaData metaData = resultSet.getMetaData();
    43. //遍历resultSet
    44. while (resultSet.next()) {
    45. //遍历每一列
    46. for (int i = 0; i < metaData.getColumnCount(); i++) {
    47. //获取列的名字
    48. String fName = metaData.getColumnLabel(i + 1);
    49. //因为列的名字和我们EMP中的属性名是一样的,所以通过列的名字获得其EMP中属性
    50. Field field = clazz.getDeclaredField(fName.toLowerCase());
    51. //因为属性是私有的,所有获得其对应的set 方法。set+属性名首字母大写+其他小写
    52. String setName = "set" + fName.toUpperCase().substring(0, 1) + fName.substring(1).toLowerCase();
    53. //因为属性的类型和set方法的参数类型一致,所以可以获得set方法
    54. Method setMethod = clazz.getMethod(setName, field.getType());
    55. //执行set方法,把resultSet中的值传入emp中, 再继续循环传值
    56. setMethod.invoke(t, resultSet.getObject(fName));
    57. }
    58. //把赋值后的对象 加入到list集合中
    59. list.add(t);
    60. }
    61. } catch (Exception e) {
    62. e.printStackTrace();
    63. throw e;
    64. }
    65. // 返回list
    66. return list;
    67. }
    68. public static <T> List<T> convertObjectToList(Object object, Class<T> clazz) {
    69. Field[] fields = object.getClass().getDeclaredFields();
    70. List<T> list = new ArrayList<>();
    71. try {
    72. for (Field field : fields) {
    73. field.setAccessible(true);
    74. Object fieldValue = field.get(object);
    75. if (fieldValue instanceof List<?>) {
    76. list.addAll((List<T>) fieldValue);
    77. }
    78. }
    79. } catch (IllegalAccessException e) {
    80. e.printStackTrace();
    81. }
    82. return list;
    83. }
    84. }

    这个类笔者是作为公共类单独建了个Util软件包专门放的,大家可以参考。

    6.运行项目,测试结果。

    到这里,代码就基本完成了,可以运行一下代码,测试一下有没有其他问题,遇到问题解决问题就是了。

    ps:作者一开始遇到了获取xml成功,但是反射成java类死活不成功的问题,原因是没用对注解:XmlElementWrapper(name = "XML中LIst节点名称")

    后面加上这个注解之后就愉快的跑成功了。

    下面附上运行成功和测试成功的截图:

    以下就是SpringBoot中调用Webservice(XML)的一个简单实践。如有疑问,欢迎私信骚扰。

  • 相关阅读:
    Python:实现fibonacci斐波那契算法(附完整源码)
    Java面试题总结(二)
    Spire.Office for .NET 8.10.2 同步更新-Crk
    图数据库:释放关系的力量
    深度学习框架pytorch:tensor.data和tensor.detach()的区别
    【Unity3D】UGUI之Dropdown
    企业门户的必备选择,WorkPlus的定制化解决方案
    Visual Studio 2022+Python3.11实现C++调用python接口
    [LeetCode 687]最长同值路径
    LeetCode高频题88. 合并两个有序数组
  • 原文地址:https://blog.csdn.net/weixin_44730040/article/details/139624372