SpringBoot调用WebService的实践

news2024/12/28 19:00:08

作者所在公司的系统间的信息交互是通过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)的一个简单实践。如有疑问,欢迎私信骚扰。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI 定位!只需一张图片就能找到你,锁定具体位置!精确到经纬度

你能猜到这张自拍的拍摄地点吗?别小瞧了AI的能力,答案可能会让你吓一跳。 这事交给现在的AI来处理&#xff0c;它只需要“看”一眼&#xff0c;就能把照片里的“底裤都给扒出来”&#xff1a; 美国&#xff0c;加利福尼亚州&#xff0c;旧金山机场洗手间&#xff0c;93号登机口…

【数据结构】第十五弹---C语言实现直接插入排序

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、排序的概念及其运用 1.1、排序的概念与分类 1.2、排序运用 1.3、常见的排序算法 1.4、常见的排序算法性能测试 2、常见排序算法的实现 2…

JAVA小知识16:JAVA常用的API

一、Math 方法名说明public static int abs(int a)获取参数绝对值public static double ceil(double a)向上取整public static double floor(double a)向下取整public static int round(float a)四舍五入public static int max(int a,int b)获取两个int值中的较大值public s…

AI绘画Stable Diffusion 3 正式开源,AI生图格局迎来巨变!(附模型下载)

大家好&#xff0c;我是向阳 就在刚刚&#xff0c;Stable Diffusion 3 Medium 如约而至。 几天前&#xff0c;Stability AI 在社交平台 X 上官宣&#xff0c;SD3 Medium 将在 6 月 12 日正式开源。 这一次&#xff0c;没有跳票&#xff0c;它是真的来了。 20 亿参数大小&…

python数据分析-房价数据集聚类分析

一、研究背景和意义 随着房地产市场的快速发展&#xff0c;房价数据成为了人们关注的焦点。了解房价的分布特征、影响因素以及不同区域之间的差异对于购房者、房地产开发商、政府部门等都具有重要的意义。通过对房价数据的聚类分析&#xff0c;可以深入了解房价的内在结构和规…

C语言 | 文件操作(上)【必收藏】

文件操作&#xff08;上&#xff09; 1、使用文件的原因2、什么是文件3、二进制文件和文本文件4、 流的打开与关闭4.1 流和标准流4.1.1 流4.1.2 标准流 4.2 文件指针4.3 文件的打开和关闭 5、文件的顺序读写5.1 顺序读写函数介绍5.1.1 fputc与fgetc 1、使用文件的原因 首先来看…

据阿谱尔统计显示,2023年全球凹版印刷机市场销售额约为9.1亿美元

根据阿谱尔 (APO Research&#xff09;的统计及预测&#xff0c;2023年全球凹版印刷机市场销售额约为9.1亿美元&#xff0c;预计在2024-2030年预测期内将以超过2.54%的CAGR&#xff08;年复合增长率&#xff09;增长。 由于对软包装和印刷包装的需求不断增长&#xff0c;全球凹…

Qt绘图项目 - 简易表盘

发话少说&#xff0c;放码过来 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();prot…

3-哈希表-81-四数之和-LeetCode18

3-哈希表-81-四数之和-LeetCode18 参考&#xff1a;代码随想录 LeetCode: 题目序号18 更多内容欢迎关注我&#xff08;持续更新中&#xff0c;欢迎Star✨&#xff09; Github&#xff1a;CodeZeng1998/Java-Developer-Work-Note 技术公众号&#xff1a;CodeZeng1998&#xff…

C#发送邮件

C#发送邮件代码&#xff0c;亲测可用。 using System; using System.Net; using System.Net.Mail;namespace MailSend {class Program{static void Main(string[] args){try{MailAddress receiver new MailAddress("666666666qq.com");//666666666qq.com 换成收件人…

告别混乱!7步打造精益管理模式,让企业效率翻倍

当下&#xff0c;企业要想立于不败之地&#xff0c;就必须注重管理效率的提升。然而&#xff0c;很多企业在追求高效运营的过程中&#xff0c;却常常陷入混乱和无效的努力中。那么&#xff0c;如何才能真正实现精益管理呢&#xff1f;深圳天行健精益管理咨询公司分享步骤如下&a…

【投稿优惠】2024年计算机科学与软件工程国际会议(ICCSSE 2024)

2024年计算机科学与软件工程国际会议 2024 International Conference on Computer Science and Software Engineering 会议简介 2024年计算机科学与软件工程国际会议是一个备受全球瞩目的学术盛会&#xff0c;旨在促进计算机科学和软件工程领域的学术交流与合作。此次会议将汇聚…

Android开发之音乐播放器添加排行需求

Music统计功能需求 1.记录歌曲名称与次数(歌曲播放结束算一次)&#xff0c;根据播放次数制作一个排行列表;&#xff08;开始说要记录歌手&#xff0c;后面debug发现这个字段没有&#xff0c;暂时不记录&#xff09; 2.记录播放歌曲的时长&#xff0c;时间累加&#xff1b;&…

基于安信可串口调试助手软件调试ESP8266串口WIFI模块ESP-01S应用功能

基于安信可串口调试助手软件调试ESP8266串口WIFI模块ESP-01S应用功能 ESP8266_01S引脚功能图ESP8266_01S原理图ESP8266_01S尺寸图检验工作1、USB-TTL串口工具(推荐使用搭载CP2102芯片的安信可USB-T1串口)与ESP8266_01S WiFi模块(推荐使用安信可ESP8266系列模组)接线(注意当…

使用谷歌 Gemini API 构建自己的 ChatGPT(一)

AI领域一直由OpenAI和微软等公司主导&#xff0c;而Gemini则崭露头角&#xff0c;以更大的规模和多样性脱颖而出。它被设计用于无缝处理文本、图像、音频和视频&#xff1b;这些基础模型重新定义了人工智能交互的边界。随着谷歌在人工智能领域强势回归&#xff0c;了解Gemini如…

HMI(人机交互)应用的15大领域,欢迎补充。

HMI&#xff08;Human-Machine Interface&#xff0c;人机界面&#xff09;可以应用于许多不同的场景和行业&#xff0c;包括但不限于以下几个方面&#xff1a; 工业控制系统&#xff1a;HMI在工业生产中广泛应用&#xff0c;用于监控和控制生产过程。例如&#xff0c;工厂中的…

数据库学霸笔记

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

前端问题整理

Vue vue mvvm&#xff08;Model-View-ViewModel&#xff09;架构模式原理 Model 是数据层&#xff0c;即 vue 实例中的数据View 是视图层&#xff0c; 即 domViewModel&#xff0c;即连接Model和Vue的中间层&#xff0c;Vue实例就是ViewModelViewModel 负责将 Model 的变化反映…

构建企业核心竞争力:拥有自主大模型,引领行业未来

前言 随着人工智能技术的飞速发展&#xff0c;大模型技术已经成为推动行业进步的重要力量。在这个变革的时代&#xff0c;作为一位具有前瞻性的企业家&#xff0c;您深知拥有自主大模型对于提升公司竞争力、引领行业未来的重要性。本文将为您详细介绍大模型的市场现状以及企业…

【机器学习】通用大模型VS垂直大模型,你更加青睐哪一方?

目录 前言AI大模型的战场&#xff1a;通用与垂直的分化通用大模型&#xff1a;广泛适用的利器垂直大模型&#xff1a;深入领域的利器谁能够形成绝对优势&#xff1f;结语通用大模型文章推荐 前言 AI大模型的战场正在分化&#xff1a; 通用大模型在落地场景更广泛毋庸置疑&…