需求:过Soap方式调用WebService接口返回的xml字符串,客户要求将返回回来的信息入库,最终在web端展示。
思路:1创建对应的实体类,目的是将返回回来的信息中将有用的信息映射到实体类中,实体类的属性应和xml中有用的信息字段保持一致;2:使用RestTemplate发送请求,设置请求头参数以及对应的WebService接口地址,请求数据;3使用dom4j解析返回回来的xml字符串;4实现入库操作。
具体实现:
1创建实体类
/**
* @Description: saop映射实体类
* @Title: XxVo
* @Package com.example.entity
* @Author: ytsj
* @CreateTime: 2023/1/16 16:43
*/
@Data
public class XxVo{
private String asd;
private String dfd;
private String gfg;
private String hgg;
}
2:使用RestTemplate发送请求获取接口返回的数据,注意请求头的参数和接口需要的参数一致,接口需要哪些参数就传哪些,我这里接口还需要额外传递用户名和密码
@GetMapping("/getXmlData")
public ResultEntity getXmlData() throws Exception {
String url = " ";// WebService接口地址
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType("text/xml;charset=utf-8"); // 设置Content-Type
headers.add("Accept-Encoding", "gzip, deflate, br");//设置Accept-Encoding
// 请求头需要传递用户名和密码
headers.add("password", "");
headers.add("username", "");
//这里是发生请求时body中的raw类型为xml的参数,使用StringBuffer进行拼接
StringBuffer xmlParam = new StringBuffer();
xmlParam.append("");
//请求体
HttpEntity formEntity = new HttpEntity<>(xmlParam.toString(), headers);
//发送数据方法
ResponseEntity forEntity = restTemplate.postForEntity(url, formEntity, String.class);
//得到返回的数据body
String jsonData = forEntity.getBody();
//组织返回的数据
List vos = getChildResult(jsonData);
return ResultEntity.ok(vos);
}
3:解析返回的数据
/**
* @description 通过递归调用组织的数据
* @methodName getChildResult
* @param [jsonData]
* @return java.util.List
* @date: 2023/1/18 11:17
* @author ytsj
*/
public static List getChildResult(String jsonData) throws UnsupportedEncodingException, DocumentException, InstantiationException, IllegalAccessException, NoSuchMethodException {
SAXReader reader = new SAXReader();
Document document = reader.read(new ByteArrayInputStream(jsonData.getBytes("UTF-8")));
XxVo vo = new XxVo();
Element rootElement = document.getRootElement();// 根节点
List arrayList = new ArrayList<>();
List childElement = getChildElement(rootElement, XxVo.class, vo , arrayList);
return childElement;
}
/**
* @param [elem, clazz, t, list]
* @return java.util.List
* @description 递归遍历子节点
* @methodName getChildElement
* @date: 2023/1/18 10:09
* @author ytsj
*/
private static List getChildElement(Element elem, Class clazz, T t, List list) throws InstantiationException, IllegalAccessException, NoSuchMethodException {
List elems = elem.elements();
for (Element ele : elems) {
if (ele.getName().equals("item")) {
List content = ele.content();
t = (T) clazz.newInstance();
for (Element element : content) {
// 通过反射获取该类的所有属性
Field[] fields = clazz.getDeclaredFields();
for (int x = 0; x < fields.length; x++) {
Field field = fields[x]; //获取该类的属性
if (field.getName().equals(element.getName())) {
field.setAccessible(true); // 设置属性可访问的
field.set(t, element.getText());
break;
}
}
list.add(t);
}
}
if (ele.elements().size() > 0) { // 说明还存在子节点,继续遍历
getChildElement(ele, clazz, t, list);
}
}
return list;
}
还有一种方式,是在上面的方法基础上有一丢丢改变,可能理解起来会更好些,我个人也这么认为的。哈哈~
/**
* @return java.util.List
* @description 递归调用
* @methodName getChildResult
* @date: 2023/1/17 16:07
* @author ytsj
*/
public List getChildResult(String xmlStr) {
SAXReader sax = new SAXReader();
List xxVos= new ArrayList<>();
try {
Document doc = sax.read(new ByteArrayInputStream(xmlStr.getBytes(StandardCharsets.UTF_8)));
Element root = doc.getRootElement();
//递归遍历节点
searchDoc(root, xxVos);
return xxVos;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 递归获取xml文件信息
*
* @param elem
* @param
*/
private void searchDoc(Element elem, List vos) {
List elems = elem.elements();
for (Element ele : elems) {
if (ele.getName().equals("item")) {
try {
// 创建一个新类
XxVo vo = new XxVo();
// 获取该类的所有属性
Field[] fields = XxVo.class.getDeclaredFields();
List content = ele.content();
for (Element element : content) {
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (field.getName().equals(element.getName())) {
field.setAccessible(true);
field.set(vo , element.getText());
break;
}
}
}
vos.add(vo);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (ele.elements().size() > 0) {
searchDoc(ele, vos);
}
}
}
解析出来的数据
然后就是将解析出来的数据入库就还好了。入库的操作就就是写一个新增方法,批量insert就好了。
这就是我对这个需求的具体实现,大家有更好的方法欢迎踊跃分享~。
以上描述有误的地方欢迎大家指正,有问题可加v 876942434.