简介
本篇文章主要解决了上篇文章中遗留的对象嵌套问题,要想全面解析无限极的对象嵌套需要使用递归去解决
上文链接:
使用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<String,Object> wsdl = getWSDLContent();Client client = (Client) wsdl.get("client");List<MessagePartInfo> partInfos = (List<MessagePartInfo>) 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<Object> 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> 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<DTGMM1020GERP> list = new ArrayList<>();
DTGMM1020GERP entity = new DTGMM1020GERP();
entity = getEntityData(entity);
list.add(entity);