当前位置:首页 » 《我的小黑屋》 » 正文

SpringBoot调用WebService的实践

13 人参与  2024年11月11日 18:41  分类 : 《我的小黑屋》  评论

点击全文阅读


作者所在公司的系统间的信息交互是通过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;@Servicepublic 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://m.zhangshiyu.com/post/184771.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1