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)的一个简单实践。如有疑问,欢迎私信骚扰。

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

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

相关文章

kotlin数组

1、kotlin中的数组与java数组比较&#xff1a; 2、创建 fun main() {// 值创建val a intArrayOf(1,2,3)// 表达式创建val b IntArray(3){println("it: ${it}")it1}println("a数组&#xff1a;${a.contentToString()}, 长度&#xff1a;${a.size}")prin…

重生之 SpringBoot3 入门保姆级学习(22、场景整合 Swagger 接口文档)

重生之 SpringBoot3 入门保姆级学习&#xff08;22、场景整合 Swagger 接口文档&#xff09; 6.2 Swagger 接口文档 6.2 Swagger 接口文档 1、将 starter 导入 Maven 官网 https://springdoc.org/<dependency><groupId>org.springdoc</groupId><artifact…

电路分析期末总结笔记下

对称三相电路的线电流和相电流&#xff0c;线电压和相电压关系 相电压与线电压的关系 线电压定义&#xff1a;任意两相之间的电压称为线电压&#xff0c;常用符号V_L表示。 相电压定义&#xff1a;一相绕组两端的电压称为相电压&#xff0c;常用符号V_P表示。 关系&#xff1…

2024年6月22日(星期六)骑行谷仓坝

2024年6月22日 (星期六) 骑行谷仓坝&#xff0c;早8:00到8:30&#xff0c; 龙泉小学门口(北京路尽头&#xff0c;高架桥下&#xff09;&#xff0c;9:00准时出发 【因迟到者&#xff0c;骑行速度快者&#xff0c;可自行追赶偶遇。】 偶遇地点:集合 &#xff0c;家住东&#xf…

ESP8266+STM32+阿里云保姆级教程(AT指令+MQTT)

前言&#xff1a;在开发过程中&#xff0c;几乎踩便了所有大坑小坑总结出的文章&#xff0c;我是把坑踩满了&#xff0c;帮助更过小白快速上手&#xff0c;如有错误之处&#xff0c;还麻烦各位大佬帮忙指正、 目录 一、ESP-01s介绍 1、ESP-01s管脚功能&#xff1a; 模组启动模…

无监督医学图像翻译与对抗扩散模型| 文献速递-深度学习结合医疗影像疾病诊断与病灶分割

Title 题目 Unsupervised Medical Image Translation With Adversarial Diffusion Models 无监督医学图像翻译与对抗扩散模型 01 文献速递介绍 多模态成像对于全面评估人体解剖结构和功能至关重要[1]。通过各自模态捕获的互补组织信息&#xff0c;有助于提高诊断准确性并改…

换位置(C++)

问题描述 体育课上&#xff0c;有一个班级的同学站成了一队&#xff0c;体育老师请最高的和最矮的两位同学调换一下位置&#xff0c;其余的同学不要动&#xff0c;请编程实现&#xff01;&#xff08;假设所有人的高矮都是不一样的&#xff09; 输入 第一行有一个整数 &…

NSSCTF-Web题目10

目录 [强网杯 2019]随便注 1、题目 2、知识点 3、思路 [GXYCTF 2019]BabyUpload 1、题目 2、知识点 3、思路 [强网杯 2019]随便注 1、题目 2、知识点 数据库注入&#xff0c;堆叠注入&#xff0c;更改表名 3、思路 正常提交查询&#xff0c;看看数据回显 加入单引号…

api-ms-win-crt-runtime-l1-1-0.dll文件丢失的情况要怎么处理?比较靠谱的多种修复方法分享

遇到api-ms-win-crt-runtime-l1-1-0.dll文件丢失的情况实际上是一个常见问题&#xff0c;解决此类问题存在多种方法。首先我们先来了解一下api-ms-win-crt-runtime-l1-1-0.dll文件吧&#xff0c;只有了解了我们才知道怎么去解决这个api-ms-win-crt-runtime-l1-1-0.dll文件丢失的…

flutter 打包 exe

采用官方的MSIX打包 原文链接 https://blog.csdn.net/weixin_44786530/article/details/135308360 第一步&#xff1a;安装依赖 在项目根目录&#xff0c;执行命令&#xff1a; flutter pub add --dev msix 等待安装完成&#xff0c;就好了 第二步&#xff1a;打包编译 当m…

LVGL开发教程-img图片

系列文章目录 知不足而奋进 望远山而前行 目录 系列文章目录 文章目录 前言 1. 显示静态图像 2. 显示动态图像gif 3. 文件系统使用 总结 前言 在嵌入式系统中&#xff0c;使用LVGL&#xff08;Light and Versatile Graphics Library&#xff09;显示静态和动态图像是一…

索引与书架、新华字典的爱恨情仇

在MySQL的索引世界中&#xff0c;性能优化一直是开发者们关注的焦点。而索引&#xff0c;作为提升查询速度的关键技术之一&#xff0c;是非常重要的。索引根据存储类型可以分为聚簇索引(聚集)与非聚簇索引(非聚集)&#xff0c;它们决定了数据在磁盘上的存储方式和查询时的访问路…

HANA 自动生成年月维度,指定起始即可生成

官方指导文档&#xff1a;SERIES_GENERATE Function (Series Data) | SAP Help Portal select * from SERIES_GENERATE_DATE(INTERVAL 1 MONTH, 2024-01-01, 2024-12-01) 以下示例生成范围从1999-01-01到1999-01-02的一系列时间戳&#xff0c;该时间戳以30秒的间隔递增&#…

重生之 SpringBoot3 入门保姆级学习(24、场景整合 kafka 消息发送服务)

重生之 SpringBoot3 入门保姆级学习&#xff08;24、场景整合 kafka 消息发送服务&#xff09; 6.4 消息发送服务 6.4 消息发送服务 访问 kafka-ui &#xff08;注意这里需要换成你自己的服务器或者虚拟机的 IP 地址&#xff0c;虚拟机可以用局域网 192.168.xxx.xxx 的地址&…

引领未来建筑潮流:轻空间设计团队打造“淄博珍珠”

作为国内单体最大的气膜会展场馆&#xff0c;“淄博珍珠”自四年前启用以来&#xff0c;已成为淄博市的重要地标和经济引擎。该场馆首次亮相于第二十届中国&#xff08;淄博&#xff09;国际陶瓷博览会&#xff0c;凭借其独特的设计和先进的建筑理念&#xff0c;吸引了社会各界…

机器人、人工智能相关领域 news/events (专栏目录)

Some Insights 一些机器人、人工智能或相关领域的news、events等 专栏直达链接 1. 智能制造 - 你需要了解的 10 个基本要素 2. 现实世界中的人工智能&#xff1a;工业制造的 4 个成功案例研究 3. 企业使用人工智能情况调查 4. 未来工厂中的人工智能&#xff1a;人工智能加…

A comprehensive review of machine learning-based models for fake news detection

Abstract 互联网在假新闻传播中的作用使其成为一个严重的问题&#xff0c;需要复杂的技术来自动检测。为了应对 Facebook、Twitter、Instagram 和 WhatsApp 等社交媒体网站上误导性材料的快速传播&#xff0c;本研究探索了深度学习方法和各种分类策略领域。该研究特别调查了基…

Linux安装kvm虚拟机

kvm是基于内核的虚拟机&#xff0c;为什么要用kvm不用vmware、virtual box… 只有一个原因&#xff0c;它非常快&#xff01;本机使用linux开发也是因为它快&#xff01;linux在老电脑上都能流畅运行&#xff0c;更别说现代电脑&#xff0c;如果你觉得装Linux并没有比win快多少…

一文带你搞定Linux开发环境配置

Linux开发必备 万事先更新 sudo apt update && sudo apt upgrade安装gcc工具链 sudo apt install build-essential像mysql、nacos等等建议装docker里&#xff0c;数据挂载到宿主机&#xff0c;日志别挂&#xff0c;直接装本机哪天日志塞满了就要开始重装系统了 以下…

SpringCloud Alibaba Sentinel基础入门与安装

GitHub地址&#xff1a;https://github.com/alibaba/Sentinel 中文文档&#xff1a;https://sentinelguard.io/zh-cn/docs/introduction.html 下载地址&#xff1a;https://github.com/alibaba/Sentinel/releases Spring Cloud Alibaba 官方说明文档&#xff1a;Spring Clou…