工作第一次遇到对接soap接口,觉得有必要记录一下,毕竟踩了不少坑,网上帖子很多但大都不全,也不可能完全满足自己的需求,于是就有了下面的代码:
除了只是借鉴,
注意事项:1.http://ip:port/xxx/xxx/soap?wsdl有些soap接口,对面是不需要穿?wsdl对接时要问出清
2. httpPost.setHeader("SOAPAction", SOAPAction); SOAPAction也要问下,或者查看接口文件,有些只要传空字符串
3.拼接报文时要注意格式,/n一类的特殊符号不能有
4.xml解析式注意编号,编号可能存在编码来回切换returnDatabase = convertToUTF8(returnDatabase);
package com.ankang.hospital.utils;import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.StringEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException;import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;@Slf4j public class HttpClientUtil {private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);/*** HttpClient 调用 WebService** @param wsUrl webService地址,格式:http://ip:port/xxx/xxx/soap?wsdl* @param StrDate 格式的入参StrDate=2023/08/02* @return*/public static String callServiceHC(String wsUrl, String StrDate) {String xml = createSoapContent(StrDate);String returnDatabase = doPostSoap(wsUrl, xml, "");//urn:hl7-org:v3/ZDYFWTYRK// 强制将返回结果转换为 UTF-8 编码returnDatabase = convertToUTF8(returnDatabase);return returnDatabase;}/*** 强制转换整utp-8* @param input* @return*/public static String convertToUTF8(String input) {try {byte[] utf8Bytes = input.getBytes(StandardCharsets.UTF_8);return new String(utf8Bytes, StandardCharsets.UTF_8);} catch (Exception e) {e.printStackTrace();}return input; // 返回原始字符串,如果转换失败}/*** 根据拼接 xml 字符串** @param StrDate* @return*/public static String createSoapContent(String StrDate) {log.info("开始拼接请求报文");//开始拼接请求报文StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:urn=\"urn:hl7-org:v3\">\n");stringBuilder.append("<soapenv:Header/>");stringBuilder.append("<soapenv:Body>");stringBuilder.append("<urn:ZDYFWTYRK>");stringBuilder.append("<urn:req>");//传参actionstringBuilder.append("<urn:action>");stringBuilder.append("Z1901");stringBuilder.append("</urn:action>");//传参rdnstringBuilder.append("<urn:rdn>");stringBuilder.append("SSXWGYGXT");stringBuilder.append("</urn:rdn>");//传参messagestringBuilder.append("<urn:message><![CDATA[");stringBuilder.append("<Request>");stringBuilder.append("<operDate>");stringBuilder.append(StrDate);stringBuilder.append("</operDate>");stringBuilder.append("<hoscode>");stringBuilder.append("A001");stringBuilder.append("</hoscode>");stringBuilder.append("</Request>");stringBuilder.append("]]></urn:message>");stringBuilder.append("</urn:req>");stringBuilder.append("</urn:ZDYFWTYRK>");stringBuilder.append("</soapenv:Body>");stringBuilder.append("</soapenv:Envelope>");logger.debug("拼接后的参数\n" + stringBuilder.toString());return stringBuilder.toString();}/*** HTTPClient 调用 WebService** @param url* @param soap* @param SOAPAction* @return*/public static String doPostSoap(String url, String soap, String SOAPAction) {//请求体String retStr = "";// 创建HttpClientBuilderHttpClientBuilder httpClientBuilder = HttpClientBuilder.create();// HttpClientCloseableHttpClient closeableHttpClient = httpClientBuilder.build();HttpPost httpPost = new HttpPost(url);try {httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");httpPost.setHeader("SOAPAction", SOAPAction);StringEntity data = new StringEntity(soap, Charset.forName("UTF-8"));httpPost.setEntity(data);CloseableHttpResponse response = closeableHttpClient.execute(httpPost);HttpEntity httpEntity = response.getEntity();if (httpEntity != null) {// 打印响应内容retStr = EntityUtils.toString(httpEntity, "UTF-8");}// 释放资源closeableHttpClient.close();} catch (Exception e) {e.printStackTrace();}return retStr;}public static String analyzeResult(String xmlContent) {try {// 从 xmlContent 字符串解析 XMLDocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();factory.setNamespaceAware(true); // 启用命名空间感知DocumentBuilder builder = factory.newDocumentBuilder();Document doc = builder.parse(new InputSource(new StringReader(xmlContent)));// 获取根元素 (SOAP-ENV:Envelope)Element root = doc.getDocumentElement();// 获取 SOAP-ENV:Body 元素Element body = null;NodeList bodyList = root.getElementsByTagName("SOAP-ENV:Body");if (bodyList.getLength() > 0) {body = (Element) bodyList.item(0);}// 获取带有 'urn:hl7-org:v3' 命名空间的 ZDYFWTYRKResponse 元素Element zdyfwtyrkResponse = (Element) body.getElementsByTagNameNS("urn:hl7-org:v3", "ZDYFWTYRKResponse").item(0);Element zdyfwtyrkResult = (Element) zdyfwtyrkResponse.getElementsByTagNameNS("urn:hl7-org:v3", "ZDYFWTYRKResult").item(0);// 获取 ZDYFWTYRKResult 元素中的 CDATA 内容(实际的结果数据)String cdataContent = zdyfwtyrkResult.getTextContent();// 处理CDATA中的XML内容Document cdataDoc = builder.parse(new InputSource(new StringReader(cdataContent)));// 将Document转换为不带BOM的字符串String cdataXmlString = convertDocumentToStringWithoutBOM(cdataDoc);logger.debug("cdataXmlString结果: " + cdataXmlString);return cdataXmlString;} catch (ParserConfigurationException e) {// 记录异常信息到日志log.error("XML解析器配置错误: " + e.getMessage(), e);} catch (IOException e) {// 记录 IOException 异常信息到日志log.error("发生 IO 异常: " + e.getMessage(), e);} catch (SAXException e) {// 记录 SAXException 异常信息到日志log.error("SAX 解析异常: " + e.getMessage(), e);} catch (TransformerException e) {log.error("XML的转换、解析和转换错误: " + e.getMessage(), e);}return null;}/*** 将 DOM Document 转换为 UTF-8 无 BOM 格式的字符串。** @param doc 要转换的 DOM Document。* @return 不带 BOM 的 UTF-8 字符串表示的文档。*/private static String convertDocumentToStringWithoutBOM(Document doc) throws TransformerException, UnsupportedEncodingException {TransformerFactory transformerFactory = TransformerFactory.newInstance();Transformer transformer = transformerFactory.newTransformer();// 设置编码为 UTF-8 且不带 BOMtransformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); // 省略 XML 声明transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 格式化输出// 创建一个 ByteArrayOutputStream 来保存 XML 内容ByteArrayOutputStream outputStream = new ByteArrayOutputStream();StreamResult result = new StreamResult(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));// 将 Document 转换为不带 BOM 的字符串transformer.transform(new DOMSource(doc), result);// 将 ByteArrayOutputStream 转换为字符串return outputStream.toString("UTF-8");}public static List<Map<String, String>> resultMap1(String soapResponse) {// 从soapResponse中提取JSON部分int startIndex = soapResponse.indexOf("<list>");int endIndex = soapResponse.indexOf("</list>");String jsonPart = soapResponse.substring(startIndex + "<list>".length(), endIndex);// 将JSON转换为MapObjectMapper objectMapper = new ObjectMapper();try {Map<String, Object> resultMap = objectMapper.readValue(soapResponse, new TypeReference<Map<String, Object>>() {});;List<Map<String, Object>> resultJsonList = (List<Map<String, Object>>) resultMap.get("resultJson");// 转换为 List<Map<String, String>>List<Map<String, String>> resultList = new ArrayList();for (Map<String, Object> item : resultJsonList) {Map<String, String> newMap = new HashMap();for (Map.Entry<String, Object> entry : item.entrySet()) {String key = entry.getKey();String value = entry.getValue().toString();newMap.put(key, value);}// 添加resultCode和resultMsg到转换后的结果newMap.put("resultCode", resultMap.get("resultCode").toString());newMap.put("resultMsg", resultMap.get("resultMsg").toString());resultList.add(newMap);}// 输出转换后的结果for (Map<String, String> item : resultList) {System.out.println("resultCode: " + item.get("resultCode"));System.out.println("resultMsg: " + item.get("resultMsg"));System.out.println("patientName: " + item.get("patientName"));System.out.println("opername: " + item.get("opername"));System.out.println("operdate: " + item.get("operdate"));System.out.println("doctor: " + item.get("doctor"));}return resultList;} catch (IOException e) {// 异常处理e.printStackTrace();}return null;}public static List<Map<String, String>> resultMap(String soapResponse) {// 从soapResponse中提取JSON部分int startIndex = soapResponse.indexOf("<list>");int endIndex = soapResponse.indexOf("</list>");String jsonPart = soapResponse.substring(startIndex + "<list>".length(), endIndex);// 将JSON转换为MapObjectMapper objectMapper = new ObjectMapper();try {Map<String, Object> resultMap = objectMapper.readValue(jsonPart, new TypeReference<Map<String, Object>>() {});List<Map<String, Object>> resultJsonList = (List<Map<String, Object>>) resultMap.get("resultJson");// 转换为 List<Map<String, String>>List<Map<String, String>> resultList = new ArrayList();for (Map<String, Object> item : resultJsonList) {Map<String, String> newMap = new HashMap();for (Map.Entry<String, Object> entry : item.entrySet()) {String key = entry.getKey();String value = entry.getValue().toString();newMap.put(key, value);}resultList.add(newMap);}return resultList;} catch (IOException e) {// 异常处理e.printStackTrace();}return null;}}