当前位置: 首页 > news >正文

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"; //测试@Overridepublic 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();//遍历resultSetwhile (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;}// 返回listreturn 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)的一个简单实践。如有疑问,欢迎私信骚扰。

相关文章:

SpringBoot调用WebService的实践

作者所在公司的系统间的信息交互是通过webservice完成。如&#xff1a;MES与SAP的交互&#xff0c;MES与WMS的交换&#xff0c;MES与SRM的交互&#xff0c;MES与IOT的交互等。 MES是用.NET VS2008 C#写的&#xff0c;调用webservice很简单&#xff0c;这里不再赘述。如有想了解…...

源码编译构建LAMP

Apache 起源 源于A Patchy Server&#xff0c;著名的开源Web服务软件1995年时&#xff0c;发布Apache服务程序的1.0版本由Apache软件基金会&#xff08;ASF)负责维护最新的名称为“Apache HTTP Server”官方站点&#xff1a;http://httpd.apache.org/ 主要特点 开发源代码/…...

搜索是门艺术,大神都是这样找资源

以下所有资源均可在星云导航找到&#xff0c;网站地址&#xff1a;https://www.xygalaxy.com/ 浏览器搜索高级用法 1、排除干扰&#xff0c;指定关键词 1.1、排除指定关键字 格式&#xff1a;关键字1 -关键字2比如搜索&#xff1a;星云导航&#xff0c;不想要CSDN的内容 星…...

【设计模式深度剖析】【5】【行为型】【迭代器模式】

&#x1f448;️上一篇:策略模式 | 下一篇:中介者模式&#x1f449;️ 设计模式-专栏&#x1f448;️ 文章目录 迭代器模式定义英文原话直译如何理解呢&#xff1f; 迭代器模式的角色1. Iterator&#xff08;迭代器&#xff09;2. ConcreteIterator&#xff08;具体迭代器…...

怎么更快捷的修改图片大小?压缩图片jpg、png、gif的快捷方法

jpg作为最常用的一种图片格式&#xff0c;在遇到图片太大问题时&#xff0c;该如何操作能够快速在压缩图片jpg的大小呢&#xff1f;图片太大无法上传时目前常见的一个使用问题&#xff0c;只有将图片处理到合适的大小才可以正常在平台上传使用&#xff0c;一般情况下想要快速解…...

Shell脚本 if语句

条件测试&#xff1a; $? 返回码 判断命令或者脚本是否执行成功&#xff08;最近的一条&#xff09; 0 true 为真就是成功 成立 非0 false 失败或者异常 test命令 可以进行条件测试 然后根据的是返回值来判断条件是否成立。 -e 测试目录或者文件是否存在 exist -d 测试…...

集合查询-并(UNION)集运算、交(INTERSECT)集运算、差(EXCEPT)集运算

一、概述 集合查询是对两个SELECT语句的查询结果进行再进行处理的查询 二、条件 1、两个SELECT语句的查询结果必须是属性列数目相同 2、两个SELECT语句的查询结果必须是对应位置上的属性列必须是相同的数据类型 三、并(UNION)运算 1、语法格式&#xff1a; SELECT 语句1…...

常用的bit位操作

//判断某1位是1还是0 #ifndef GET_BIT #define BIT_IS_1(value,bitpos) (((value)&(1<<(bitpos)))>>(bitpos)) #endif //读取指定位置bit位的值 #ifndef GET_BIT #define GET_BIT(value,bitpos) ((value)&(1<<(bitpos))) #endif //取反指定位置bit位…...

自动控制原理【期末复习】(二)

无人机上桨之后可以在调试架上先调试&#xff1a; 1.根轨迹的绘制 /// 前面针对的是时域分析&#xff0c;下面针对频域分析&#xff1a; 2.波特图 3.奈维斯特图绘制 1.奈氏稳定判据 2.对数稳定判据 3.相位裕度和幅值裕度...

机器学习——集成学习和梯度提升决策树

集成学习 不同的算法都可以对解决同一个问题&#xff0c;但是可能准确率不同&#xff0c;集成学习就是不同算法按照某种组合来解决问题&#xff0c;使得准确率提升。 那怎么组合算法呢&#xff1f; 自举聚合算法**&#xff08;bagging&#xff09;** 顾名思义是 自举聚合 自举…...

MYSQL 查看SQL执行计划

一、explain explain select id,db,user,host,command,time,state,info from information_schema.processlist order by time desc; id: 查询的标记&#xff0c;可以查看不同查询的执行顺序。 select_type: 查询的类型&#xff0c;如SIMPLE、SUBQUERY、PRIMARY等。 table: …...

ARM-V9 RME(Realm Management Extension)系统架构之系统安全能力的MPAM

安全之安全(security)博客目录导读 关于RME的MPAM变化的完整定义见在《Arm Architecture Reference Manual Supplement, Memory System Resource Partitioning and Monitoring (MPAM), for A-profile architecture》中详细说明。 实现RME的处理元件(PE)能够生成一个2位的MPAM_…...

cuda 架构设置

import torch torch.cuda.get_device_capability(0) 添加cmake options&#xff1a; -DCMAKE_CUDA_ARCHITECTURES86 -DCMAKE_CUDA_COMPILER/usr/local/cuda-11.8/bin/nvcc cmake工程出现“CMAKE_CUDA_ARCHITECTURES must be non-empty if set.“的解决方法_failed to detec…...

基于 Vue 3 封装一个 ECharts 图表组件

在前端开发中&#xff0c;数据可视化是展示数据的重要方式之一。ECharts 是一个强大的开源可视化库&#xff0c;能够帮助我们轻松地创建各种图表。本文将介绍如何在 Vue 3 项目中使用 ECharts 封装一个图表组件。 代码 <template><div ref"chartRef" styl…...

LeetCode 算法: 旋转图像c++

原题链接&#x1f517;&#xff1a; 旋转图像 难度&#xff1a;中等⭐️⭐️ 题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图…...

Java Android 静态内部类 以及优雅实现单例模式/避免handler内存泄漏

前言 Java 中的静态内部类(Static Nested Class)是定义在另一个类里面的一个静态类。它和普通的内部类有些区别,主要是静态内部类不需要依赖于外部类的实例就可以被创建和访问。这种类的特性使得它非常适合用来作为辅助类,用于支持外部类的功能。 特点以及使用场景 静态内…...

Flink协调器Coordinator及自定义Operator

Flink协调器Coordinator及自定义Operator 最近的项目开发过程中&#xff0c;使用到了Flink中的协调器以及自定义算子相关的内容&#xff0c;本篇文章主要介绍Flink中的协调器是什么&#xff0c;如何用&#xff0c;以及协调器与算子间的交互。 协调器Coordinator Flink中的协调…...

C调用C++中的类

文章目录 测试代码 测试代码 在C语言中调用C类&#xff0c;需要遵循几个步骤&#xff1a; 在C代码中&#xff0c;确保C类的函数是extern “C”&#xff0c;这样可以防止名称修饰&#xff08;name mangling&#xff09;。 使用头文件声明C类的公共接口&#xff0c;并且为这个…...

NFTScan 正式上线 Sei NFTScan 浏览器和 NFT API 数据服务

2024 年 6 月 12 号&#xff0c;NFTScan 团队正式对外发布了 Sei NFTScan 浏览器&#xff0c;将为 Sei 生态的 NFT 开发者和用户提供简洁高效的 NFT 数据搜索查询服务。NFTScan 作为全球领先的 NFT 数据基础设施服务商&#xff0c;Sei 是继 Bitcoin、Ethereum、BNBChain、Polyg…...

2024年高考:计算机相关专业前景分析与选择建议

2024年高考结束&#xff0c;面对计算机专业是否仍具有吸引力的讨论&#xff0c;本文将从行业趋势、就业市场、个人兴趣与能力、专业选择建议等多个角度进行深入分析&#xff0c;以帮助考生和家长做出明智的决策。 文章目录 一、行业趋势与就业市场1. 计算机行业的发展与变革2. …...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...