使用CXF调用WSDL(二)

简介

本篇文章主要解决了上篇文章中遗留的对象嵌套问题,要想全面解析无限极的对象嵌套需要使用递归去解决

 上文链接:

使用CXF调用WSDL(一)

上文回顾

上文使用了单方法“ call() ”解决了List和基本类型(含String)以及对象的解析,但遗留了对象嵌套问题,本文将把 “ call() ” 方法中关于对象解析的部分拆分出独立的方法 “ analysisParam() ”,然后使用递归解决对象的嵌套问题

正文

    /**
     * 调用远程过程
     */
    public Object call(DTGMM1020GERP paramEntity) {
        Object result = null;
        log.info("[PO创建时]入参:{}",JSON.toJSONString(paramEntity,true));
        Map map = JSONObject.parseObject(JSON.toJSONString(paramEntity, SerializerFeature.WriteDateUseDateFormat), Map.class);
        Map wsdl = getWSDLContent();
        Client client = (Client) wsdl.get("client");
        List partInfos = (List) wsdl.get("messagePartInfo");
        QName qName = (QName) wsdl.get("qname");

        String clazzName = partInfos.get(0).getTypeClass().getName(); 
        try {
            Object requestParamObject = Thread.currentThread().getContextClassLoader().loadClass(clazzName).newInstance();
            requestParamObject = analysisParam(requestParamObject,map);
            log.info("请求参数:{}",JSON.toJSON(requestParamObject));
            result = client.invoke(qName, requestParamObject);
            log.info("响应结果:{}",JSON.toJSONString(result,true));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

解说:方法 “ call() ” 接收一个 “ DTGMM1020GERP ” 对象作为入参并返回一个Object对象,该方法主要业务就是将入参对象转换成map对象,而后读取WSDL文件内容,并传入给 “ analysisParam() ” 方法解析,其中requestParamObject是读出的WSDL文件的节点,map是待写入节点的值

private static Object analysisParam(Object req, Map map) throws InstantiationException, IllegalAccessException {
        Field[] fields = req.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            boolean b = field.getGenericType() instanceof ParameterizedType;
            //如果是泛型并且是List类型
            if(b && field.getType() == List.class){
                List cParam = (List) map.get(field.getName());
                log.info("子对象参数:{}",cParam);
                if(CollectionUtils.isEmpty(cParam)){
                    continue;
                }
                Type type = ((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0];
                Class aClass = (Class) type;
                Object cObj = aClass.newInstance();
                log.info("子对象:{}",cObj);

                Field[] cFields = cObj.getClass().getDeclaredFields();
                for (Field cField : cFields) {
                    cField.setAccessible(true);
                    List target = cParam.stream().map(o -> {
                        Map ccParam = JSONObject.parseObject(JSON.toJSONString(o),Map.class);
                        Object strParam = ccParam.get(cField.getName());
                        //如果子对象类型是基本类型或String类型那就直接赋值,负责就递归
                        if(cField.getType().isPrimitive() || cField.getType() == String.class){
                            try {
                                if(null != strParam){
                                    cField.set(cObj,strParam);
                                }
                            } catch (IllegalAccessException e) {
                                throw new RuntimeException(e);
                            }
                        }else{
                            try {
                                Object obj = cField.getType().newInstance();
                                Map objMap = JSONObject.parseObject(JSON.toJSONString(strParam),Map.class);
                                if(!CollectionUtils.isEmpty(objMap)){
                                    analysisParam(obj,objMap);
                                    cField.set(cObj,obj);
                                }
                            } catch (InstantiationException e) {
                                throw new RuntimeException(e);
                            } catch (IllegalAccessException e) {
                                throw new RuntimeException(e);
                            }
                        }
                        return strParam;
                    }).collect(Collectors.toList());
                    /*Object targetResp = target.get(0);
                    cField.set(cObj,targetResp);*/
                }
                List cObjs = new ArrayList<>();
                cObjs.add(cObj);
                //给父对象赋值
                field.set(req,cObjs);
            }else if(field.getType().isPrimitive() || field.getType() == String.class){
                //如果是基本类型或String类型
                field.set(req,map.get(field.getName()));
            }else{
                //按对象处理
                Object o = field.getType().newInstance();
                Map childrenObjMap = (Map) map.get(field.getName());
                if(!CollectionUtils.isEmpty(childrenObjMap)){
                    writeFieldValue(o,childrenObjMap);
                    field.set(req,o);
                }
            }
        }
        return req;
    } 
  

 步骤解析:

一、使用反射获取待解析节点的字段

二、进行第一层 for 循环解析节点,先判断了字段的类型是否为泛型且为List类型,如果不是泛型且不是List类型,再判断是否为基本类型或是String类型,如果也不是,那就当成普通对象处理

三、如果第一层 for 循环中的类型为泛型且为List类型时,则进行第二层 for 循环处理,第二层循环同样判断子对象字段值是否为基本类型或String类型,如果是则直接赋值,如果不是,则说明是一个对象,至于是个什么对象(List?基本类型?String?POJO?),无需理会,直接进行递归解析即可

注意:map的key需和待解析的节点字段名保持一致,因为map.get()是通过field.getName()取值的

本文中引用到的其他方法请从上一篇文章中获取

使用CXF调用WSDL(一)

完成


文末

这是我mock加数据的方法,入参对象可以使用该方法快速生成mock数据(本文中的DTGMM1020GERP )

    public static  T getEntityData(T t) {
        Field[] field = t.getClass().getDeclaredFields();
        for (Field f : field) {
            f.setAccessible(true);
            try {
                Random random = new Random();
                int num = random.nextInt(10);
                f.set(t,""+num);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        return t;
    }

用法

只需要定义好对象的嵌套层级即可 

List list = new ArrayList<>();
DTGMM1020GERP entity = new DTGMM1020GERP();
entity = getEntityData(entity);
list.add(entity);

使用CXF调用WSDL(二)_第1张图片

结束

你可能感兴趣的:(Java,CXF,org.apache.cxf,WebService,CXF调用WebService,CXF解析WSDL)