Springboot 项目 调用webservice接口

前言

近期接到个需求,项目中需要集成零几年建设的OA系统。

OA系统使用的接口全部都是webservice接口,在此分享一下webservice接口调用过程中遇到的问题及调用方式。

焦头烂额

笔者也是第一次接触webservice接口,搜索了大量的资料,最后使用如下两种方式进行的交互。

调用方式:

笔者接触到的OA系统,接口参数没有统一
1、有的入参使用XML方式,有的入参是JSON字符串,
2、有的有命名空间,有的没有命名空间
3、有的返回了JSON字符串,有的返回了XML~
em....(@#%¥#@%#¥%),为了适配这个老东西,下面展出两种方式的调用代码,。

1.使用Hutool工具包调用:

   业务流程是web端调用我的HTTP接口,然后HTTP接口去调用OA的webservice接口拿数据。

   但是webservice接口返回的参数是XML形式的,所以需要使用工具转成JSON,返回给web浏览器。

   笔者使用的工具是hutool下的SoapClient工具包(Hutool还是挺强大)调用webservice接口,jdom、fastjson做XML转换JSON。

POM如下

   		<!-- 如下依赖看自己的需求取-->
   		
   		<!-- fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            //版本自己找哈~
        </dependency>
        <!-- hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.20</version>
        </dependency>
        
        <!-- XMLJSON-->
        <dependency>
            <groupId>org.jdom</groupId>
            <artifactId>jdom</artifactId>
            <version>2.0.2</version>
        </dependency>
        
    

Controller忽略不展示了
Service 实现 如下:

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.http.webservice.SoapClient;
import javax.xml.namespace.QName;
import java.util.*;
@Service
@Slf4j
public class OAServiceImpl implements OAService {
 //@Override
 public JSONObject getGWList(OAReqVO reqVO) {
        Map<String, Object> map = new HashMap<>();
        //笔者系统中的业务参数,对方需要用到的json参数
        map.put("参数3-1","1");
        map.put("参数3-2","2");
        map.put("参数3-3","3");
        Map<String, Object> mapReq = new HashMap<>();
        mapReq.put("content",map);
        JSONObject writeContent = new JSONObject(mapReq);
        log.info("接口入参:"+writeContent);
        String result = null;
        try {
        	//对方接口地址
            SoapClient soapClient = SoapClient.create("http://xxx.xxx.xxx/xxxController/init.done")
                    // 对端 提供的方法名,命名空间(如果有命名空间记得找他们要)
                    .setMethod("方法名", "http://xxx.xxx.com.cn")
                    // 设置参数名称及参数值
                    .setParam("token", "token-123123123")
                    .setParam("systemId","系统标识")
                    //上面中的writeContent,对端业务系统使用
                    .setParam("content",writeContent.toString())
                    // 设置超时时间
                    .setConnectionTimeout(15000)
                    .setReadTimeout(15000)
                    .timeout(15000);
            // 还有其他可以配置,根据自己的需求配置
            result = soapClient.send();
            log.info("OA返回信息={}", result);
            // 返回的是xml形式的,所以在此处转一下json
            JSONObject jsonObject = XmlToJsonUtil.xml2Json(result);
            //拿到数据 下面做自己的业务处理,笔者就直接return了。
            log.info("OA返回信息JSON转换={}", jsonObject);
            return jsonObject ;
        }catch (Exception e) {
            log.error("接口调用失败:"+e.getMessage(),e);
             JSONObject jsonObject = new JSONObject();
        	 jsonObject.put("code","1002");
        	 jsonObject.put("mesText","");
       		 jsonObject.put("mesType","0");
        	 jsonObject.put("mes","获取失败");
             return jsonObject;
        }
    }
 }

XmlToJsonUtil:

package cn.com.XXXX.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;

@Component
public class XmlToJsonUtil {

    public static JSONObject xml2Json(String xmlStr) throws JDOMException, IOException {
        if (StringUtils.isBlank(xmlStr)) {
            return null;
        }
        xmlStr = xmlStr.replaceAll("\n", "");
        byte[] xml = xmlStr.getBytes(StandardCharsets.UTF_8);
        JSONObject json = new JSONObject();
        InputStream is = new ByteArrayInputStream(xml);
        SAXBuilder sb = new SAXBuilder();
        Document doc = sb.build(is);
        Element root = doc.getRootElement();
        json.put(root.getName(), iterateElement(root));

        return json;
    }



    private static JSONObject iterateElement(Element element) {
        List<Element> node = element.getChildren();
        JSONObject obj = new JSONObject();
        List list = null;
        for (Element child : node) {
            list = new LinkedList();
            String text = child.getTextTrim();
            if (StringUtils.isBlank(text)) {
                if (child.getChildren().size() == 0) {
                    continue;
                }
                if (obj.containsKey(child.getName())) {
                    list = (List) obj.get(child.getName());
                }
                list.add(iterateElement(child)); //遍历child的子节点
                obj.put(child.getName(), list);
            } else {
                if (obj.containsKey(child.getName())) {
                    Object value = obj.get(child.getName());
                    try {
                        list = (List) value;
                    } catch (ClassCastException e) {
                        list.add(value);
                    }
                }
                if (child.getChildren().size() == 0) { //child无子节点时直接设置text
                    obj.put(child.getName(), text);
                } else {
                    list.add(text);
                    obj.put(child.getName(), list);
                }
            }
        }
        return obj;
    }

}

如此一番操作就能调用了~

2.使用cxf工具包调用:

注:下面这个接口没用使用命名空间

废话不多说,直接上代码
pom依赖:

    <!-- JSONXML-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.9.0</version>
        </dependency>
          <!-- CXF webservice -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.2.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.2.1</version>
        </dependency>

controller忽略
service实现如下:

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
//如需复制,import 与代码 请分开复制~

 @Override
    public String webserviceTest() {
        //封装xml报文体,可以自己拼装例如:
        //请求参数
        String req = 
                "<Root>\n" +
                "  <Session>\n" +
                "    <parm1>123</parm1>\n" +
                "    <parm2>123</parm2>\n" +
                "  </Session>\n" +
                "</Root>";
        //或者编辑好JSON,使用下面的JsonToXml 的工具类进行xml转换
        //创建请求实例
        JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
        try{
            Client client = factory.createClient("http://xxx.xxx.com/sdadsa");
            HTTPConduit conduit = (HTTPConduit) client.getConduit();
            HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
            httpClientPolicy.setConnectionTimeout(10000);  //连接超时
            httpClientPolicy.setAllowChunking(false);    //取消块编码
            httpClientPolicy.setReceiveTimeout(10000);     //响应超时
            conduit.setClient(httpClientPolicy);
            Object[] objects = new Object[0];
            //请求接口
            objects = client.invoke(loginMethod, req);
            log.info("返回数据= {}" , objects[0].toString() );
            //做自己的业务逻辑处理,如果返回的是XML,需要转JSON,可以使用上面的XML转JSON的工具类进行操作。笔者直接return了
  			return objects[0].toString();
        }catch (Exception e){
            log.error("系统交互异常:{}",e.getMessage(),e);
            return "交互异常,请联系管理员";
        }
    }

json转xml工具类:

package cn.com.XXXX.utils;


import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.dom4j.Element;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;

@Component
public class JsonToXml {

    /**
     * 将json字符串转换成xml
     *
     * @param json
     *            json字符串
     * @param parentElement
     *            xml根节点
     * @throws Exception
     */
    public static Element jsonToXml(String json, Element parentElement) throws Exception {
        JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
        Element ee = toXml(jsonObject, parentElement, null);
        return ee;
    }

    /**
     * 将json字符串转换成xml
     *
     * @param jsonElement
     *            待解析json对象元素
     * @param parentElement
     *            上一层xml的dom对象
     * @param name
     *            父节点
     */
    public static Element toXml(JsonElement jsonElement, Element parentElement, String name) {
        if (jsonElement instanceof JsonArray) {
            //是json数据,需继续解析
            JsonArray sonJsonArray = (JsonArray)jsonElement;
            for (int i = 0; i < sonJsonArray.size(); i++) {
                JsonElement arrayElement = sonJsonArray.get(i);
                toXml(arrayElement, parentElement, name);
            }
        }else if (jsonElement instanceof JsonObject) {
            //说明是一个json对象字符串,需要继续解析
            JsonObject sonJsonObject = (JsonObject) jsonElement;
            Element currentElement = null;
            if (name != null) {
                currentElement = parentElement.addElement(name);
            }
            Set<Map.Entry<String, JsonElement>> set = sonJsonObject.entrySet();
            for (Map.Entry<String, JsonElement> s : set) {
                toXml(s.getValue(), currentElement != null ? currentElement : parentElement, s.getKey());
            }
        } else {
            //说明是一个键值对的key,可以作为节点插入了
            addAttribute(parentElement, name, jsonElement.getAsString());
        }
        return parentElement;
    }

    /**
     *
     * @param element   父节点
     * @param name      子节点的名字
     * @param value     子节点的值
     */
    public static void addAttribute(Element element, String name, String value) {
        //增加子节点,并为子节点赋值
        Element el = element.addElement(name);
        el.addText(value);

    }
}

问题及方案

谈谈遇到的问题,
1:跟OA交互时候,传参没有驼峰,OA系统收不到这个没有驼峰的参数
解决方案:给字段进行驼峰。
2:xml转JSON后会有多个层级,取最里层的参数比较麻烦
解决方案:使用JSONPath.read()方法,能快速去除最里层的参数,注意判空。
如:String respDesc = JSONPath.read(SessionHeader, "$.Response[:1].RspDesc[0]").toString();
3:其他问题
  切记 一定要把所有接口交互前想到的问题都问清楚,最好双方能出个文档,评审完文档后进行开发~,
  多沟通才是解决问题的重要方式。

以上就是笔者跟老系统交互的两种方式,欢迎各位讨论交流~

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值