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.先决条件

依赖引用:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>

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的对象中。

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

package com.zjtc.qmsquality.FPYData.service;

import com.google.common.io.CharStreams;
import com.zjtc.qmsquality.FPYData.Util.EntityUtil;
import com.zjtc.qmsquality.FPYData.bean.MESRequest;
import com.zjtc.qmsquality.FPYData.bean.MESRsp;
import org.springframework.stereotype.Service;

import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;

@Service
public class FPYDataServiceImpl implements FPYDataService{
    public static final String targetUrl = "http://172.18.3.67:8020/MesFrameWork.asmx?wsdl"; //测试
    @Override
    public MESRsp getFPYData(String no){
        //调用MES接口查询数据
        MESRsp mesResponse = new MESRsp();
        try {
            MESRequest mesRequest = new MESRequest();
            mesRequest.setNo(no);
            mesResponse = sendMessage(no);

        } catch (Exception e) {
            mesResponse.setResult("NG");
            mesResponse.setMessage(e.toString());
        }
        return mesResponse;
    }

    public static String getDataFromMESSystem(String no,int rflag)  {
        // 根据上面的XSDL文档封装请求参数
        String strParameter = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:dev=\"http://device.service.moresoft.com/\">\n" +
                "<soapenv:Header/>\n" +
                " <soapenv:Body>\n" +
                " <dev:IOTTOMES>\n" +
                "<dev:resBody>\n" +
                "<dev:rFlag>"+rflag+"</dev:rFlag>\n" +
                "  <dev:NO>" + no + "</dev:NO>\n\n" +
                " </dev:resBody>\n" +
                " </dev:IOTTOMES>\n" +
                "</soapenv:Body>\n" +
                "</soapenv:Envelope>";
        System.out.println("strParameter : " + strParameter);
        return strParameter;
    }
    public static MESRsp sendMessage(String no) throws Exception {
        try {

            URL url = new URL(targetUrl);
            OutputStreamWriter wr = null;
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            String data = getDataFromMESSystem(no,2);
            System.out.println("data : " + data);
            conn.setRequestProperty("Content-Length", String.valueOf(data.getBytes().length));
            conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
            conn.setDoOutput(true);
            conn.setConnectTimeout(1000 * 20);
            conn.setReadTimeout(1000 * 20);
            if(data!=null && data.toString().trim().length()>0){
                wr = new OutputStreamWriter(conn.getOutputStream(),"UTF-8");
                wr.write(data);
                wr.flush();
            }
            String result = CharStreams.toString(new InputStreamReader(conn.getInputStream(), "utf-8"));
            System.out.println("result : " + result);

            String xml=analyzeResult(result);
            System.out.println("xml : " + xml);
            MESRsp mesResponse= EntityUtil.xml2Entity(xml,MESRsp.class);
            System.out.println("mesResponse.result : " + mesResponse.getResult());
            System.out.println("mesResponse.Message : " + mesResponse.getMessage());
            System.out.println("getFpyDataList : " + mesResponse.getFpyDataList());
            return mesResponse;
        } catch (Exception ex) {
            MESRsp mesResponse=new MESRsp();
            mesResponse.setResult("NG");
            mesResponse.setMessage(ex.toString());
            if(mesResponse.getMessage()!=null&&mesResponse.getMessage().startsWith("java.net.SocketTimeout")){
                mesResponse.setMessage("接口超时");
            }
            return  mesResponse;
        }
    }

    public static String analyzeResult(String result) throws Exception {
        int fromStr=result.indexOf("<IOTTOMESResult>");
        int toStr=result.indexOf("</IOTTOMESResponse>",fromStr);
        String xml=result.substring(fromStr,toStr);
        return  xml;
    }

}

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

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

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

package com.zjtc.qmsquality.FPYData.Util;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class EntityUtil {
    public static String entity2Xml(Object entity) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(new Class[]{entity.getClass()});
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty("jaxb.formatted.output", true);
        marshaller.setProperty("jaxb.fragment", true);
        StringWriter sw = new StringWriter();
        marshaller.marshal(entity, sw);
        String xml = sw.toString();
        return xml;
    }
    public static <T> T xml2Entity(String xml, Class<T> c) throws JAXBException {
        T t = null;
        JAXBContext context = JAXBContext.newInstance(c);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        t = (T) unmarshaller.unmarshal(new StringReader(xml));
//        System.out.println("12312312a: " + t.toString());
        return t;
    }
    public static <T> List<T> resultToList(ResultSet resultSet, Class<T> clazz) throws IllegalAccessException, InstantiationException, SQLException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //创建一个 T 类型的数组
        List<T> list = new ArrayList<>();
        try {
            //通过反射获取对象的实例
            T t = clazz.getConstructor().newInstance();
            //获取resultSet 的列的信息
            ResultSetMetaData metaData = resultSet.getMetaData();
            //遍历resultSet
            while (resultSet.next()) {
                //遍历每一列
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    //获取列的名字
                    String fName = metaData.getColumnLabel(i + 1);
                    //因为列的名字和我们EMP中的属性名是一样的,所以通过列的名字获得其EMP中属性
                    Field field = clazz.getDeclaredField(fName.toLowerCase());
                    //因为属性是私有的,所有获得其对应的set 方法。set+属性名首字母大写+其他小写
                    String setName = "set" + fName.toUpperCase().substring(0, 1) + fName.substring(1).toLowerCase();
                    //因为属性的类型和set方法的参数类型一致,所以可以获得set方法
                    Method setMethod = clazz.getMethod(setName, field.getType());
                    //执行set方法,把resultSet中的值传入emp中,  再继续循环传值
                    setMethod.invoke(t, resultSet.getObject(fName));
                }
                //把赋值后的对象 加入到list集合中
                list.add(t);
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        // 返回list
        return list;
    }


    public static <T> List<T> convertObjectToList(Object object, Class<T> clazz) {
        Field[] fields = object.getClass().getDeclaredFields();
        List<T> list = new ArrayList<>();

        try {
            for (Field field : fields) {
                field.setAccessible(true);
                Object fieldValue = field.get(object);
                if (fieldValue instanceof List<?>) {
                    list.addAll((List<T>) fieldValue);
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return list;
    }
}

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

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

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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/702695.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PGFed: Personalize Each Client’s Global Objective for Federated Learning

ICCV-2023, 文章提出显式隐式的概念,作者通过实验发现显式比隐式的效果好,显式方式通过直接与多个客户的经验风险互动来更新模型,并用泰勒展开式降为 O ( N ) O(N) O(N)通讯成本。 文章地址:arxiv code: 作者开源 贡献 1.我们发现个性化 FL 算法的显式性赋予了其更强的…

LeetCode1268搜索推荐系统

题目描述 给你一个产品数组 products 和一个字符串 searchWord &#xff0c;products 数组中每个产品都是一个字符串。请你设计一个推荐系统&#xff0c;在依次输入单词 searchWord 的每一个字母后&#xff0c;推荐 products 数组中前缀与 searchWord 相同的最多三个产品。如果…

【网络编程】套接字类型与协议设置

协议&#xff1a;计算机对话的通信规则&#xff0c;简而言之是为了完成数据交换而定好的约定。 #include<sys/socket.h> int socket(int domain, int type,int protocol); //domian使用的协议族信息&#xff0c;type传输类型&#xff0c;protocol计算机间通信使用的协议…

Xinstall:解决App安装跳转难题,让你的用户流畅体验不再受阻

在互联网流量红利逐渐衰退的今天&#xff0c;App推广和运营面临着前所未有的挑战。如何确保在多变的互联网环境下&#xff0c;迅速搭建起能时刻满足用户需求的运营体系&#xff0c;已经成为众多企业急待解决的问题。今天&#xff0c;我们就来探讨一下如何通过Xinstall的安装跳转…

在仓库新建分支之后,Vscode里面看不到

问题描述 在仓库新建了分支 但是在Vscode里面看不到这个新建的分支 解决 参考文章&#xff1a;http://t.csdnimg.cn/V92a3 在终端输入&#xff1a;git remote update origin --prune 命令解释 git remote update origin --prune 是一个 Git 命令&#xff0c;用于更新远程…

单目标应用:基于红嘴蓝鹊优化器RBMO的微电网优化(MATLAB代码)

一、微电网模型介绍 微电网多目标优化调度模型简介_vmgpqv-CSDN博客 参考文献&#xff1a; [1]李兴莘,张靖,何宇,等.基于改进粒子群算法的微电网多目标优化调度[J].电力科学与工程, 2021, 37(3):7 二、红嘴蓝鹊优化器求解微电网 2.1算法简介 红嘴蓝鹊优化器&#xff08;R…

本地生活进入下半场,美团的“低价”牌怎么打?

文 | 螳螂观察 作者 | 易不二 近日&#xff0c;美团交出了一份营收利润双增长的一季报。 财报显示&#xff0c;2024年第一季度&#xff0c;美团实现营收733亿&#xff0c;同比增长25%&#xff1b;净利润54亿元&#xff0c;同比增长59.9%&#xff1b;调整后净利润为74.88亿元…

【日记】分墨器大道至简,还挺好用(342 字)

正文 今天没见到任何客户&#xff0c;在柜台坐着玩手机玩了一天。倒是看了许多书&#xff0c;虽说也没看多少就是了。此外给植物换了水&#xff0c;同步了下文章&#xff0c;整理了一下数据什么的。 因为钢笔都没墨水了&#xff0c;去拿新墨水时忽然看见商家送的分墨套装&#…

MySQL-----JOIN语句之左连接、右连接

接着上文我们将基于学生&#xff0c;课程&#xff0c;考试信息三个表对内连接的总结&#xff0c;我们再来对左右连接进行一个总结&#xff0c;三个表结构以及表内数据如下图所示&#xff1a; 左连接 为了便于展示左右连接的区别&#xff0c;我们在student表里插入了一位成员…

大一学生分享哈希表

数据结构与算法&#xff0c;众妙之门&#xff0c;魅力无穷 ---同行者联盟 哈希表 哈希表使用场景与详细介绍 需求&#xff1a; “三分钟内&#xff0c;我要那个女生的全部资料”&#xff0c;这是我们在霸道总裁爱上我的电视剧中常听到的话…

CUDA、CUDNN、Torch的配置

文章目录 一、 配置CUDA1.CUDA下载2.CUDA安装3.CUDA配置环境4.CUDA是否配置成功 三、 配置CUDNN四、配置torch1.创建Python 3.8环境并激活2.下载torch-GPU版本 一、 配置CUDA WinR打开命令行&#xff0c;输入cmd&#xff0c;在终端输入&#xff1a;nvidia-smi。 查看本机的GPU…

海洋CMS /js/player/dmplayer/dmku/ SQL注入漏洞复现(CVE-2024-29275)

0x01 产品简介 海洋CMS是一套专为不同需求的站长而设计的内容管理系统&#xff0c;灵活、方便、人性化设计、简单易用是最大的特色&#xff0c;可快速建立一个海量内容的专业网站。海洋CMS基于PHPMySql技术开发&#xff0c;完全开源免费 、无任何加密代码。 0x02 漏洞概述 海…

CTF-AWD入门手册

引文 AWD赛制是一种网络安全竞赛的赛制。AWD赛制由安全竞赛专家及行业专家凭借十多年实战经验&#xff0c;将真实网络安全防护设备设施加入抽象的网络环境中&#xff0c;模拟政府、企业、院校等单位的典型网络结构和配置&#xff0c;开展的一种人人对抗的竞赛方式&#xff0c;…

使用itextPDF实现PDF电子公章工具类

一、制作公章 在线网站&#xff1a;印章生成器 - Kalvin在线工具 (kalvinbg.cn) 然后对公章进行下载保存 盖章图片&#xff1a; 二、生成数字签名 2.1&#xff1a; java工具keytool生成p12数字证书文件 Keytool是用于管理和证书的工具&#xff0c;位于%JAVA_HOME%/bin目录。…

深入理解Qt多线程编程(QThreadPool)

多线程编程在现代软件开发中变得越来越重要&#xff0c;它能够提高应用程序的响应速度和处理性能。在Qt框架中&#xff0c;QThreadPool作为线程池管理工具&#xff0c;被频繁的使用。 目录 概述 接口介绍 底层原理解析 使用方法 概述 QThreadPool是Qt提供的一个线程池实现&a…

计算机视觉全系列实战教程:(八)图像变换-点运算、灰度变换、直方图变换

图像变换&#xff1a;点运算、灰度变换、直方图变换 1.点运算(1)What(2)Why 2.灰度变换(1)What(2)Why(作用)(3)Which(有哪些灰度变换&#xff09; 3.直方图修正(1)直方图均衡化 1.点运算 (1)What 通过点运算&#xff0c;输出图像的每个像素的灰度值仅仅取决于输入图像中相对应…

eNSP学习——PPP的认证

目录 主要命令 原理概述 实验目的 实验内容 实验拓扑 实验编址 实验步骤 1、基本配置 2、搭建OSPF网络 3、配置PPP的PAP认证 4、配置PPP的CHAP认证 主要命令 //设置本端的PPP协议对对端设备的认证方式为 PAP&#xff0c;认证采用的域名为huawei [R3]int s4/0/0 [R…

C语言 RTC时间(年月日时分秒) 和 时间戳 互相转换

一、介绍 在C语言中&#xff0c;将年月日时分秒转换为时间戳&#xff08;Unix时间戳&#xff0c;即从1970年1月1日00:00:00 UTC到现在的秒数&#xff09;通常需要使用struct tm结构体和timegm或mktime函数。&#xff08;注意&#xff0c;mktime函数假设struct tm是本地时间&…

面试题分享之JVM篇

注意&#xff1a;文章若有错误的地方&#xff0c;欢迎评论区里面指正 &#x1f36d; 系列文章目录 面试题分享之Java并发篇面试题分享之Java集合篇&#xff08;二&#xff09; 前言 学过Java的小伙伴肯定对JVM&#xff08;Java虚拟机&#xff09;多多少少了解一点&#xff0c…

工程项目管理系统:高效、专业的工程管理软件

在当今快速发展的工程行业&#xff0c;有效的项目管理是确保项目成功的关键。鸿鹄工程项目管理系统&#xff0c;基于Spring Cloud、Spring Boot、Mybatis、Vue和ElementUI技术栈&#xff0c;提供了一个全面、高效的解决方案&#xff0c;以应对复杂的工程项目管理挑战。 项目背景…