Java调用SOAP Web Service时XML响应乱码的解决方法
解决SOAP Web Service调用乱码问题
问题描述
我需要调用SOAP Web Service获取担保列表,Java代码如下,但调用后返回乱码内容。该调用方式在其他Web Service上正常,且服务在SOAP-UI中测试正常。
private List<Guaranty> getGuarantyList(String nationalId, String centerBankCode) throws IOException{ try { fixHttpsHandler(); } catch (Exception ex) { System.out.println(ex.getMessage()); } // Code to make a webservice HTTP request String responseString = ""; String outputString = ""; String wsEndPoint = "http://192.168.5.202/services/out.asmx"; URL url = new URL(wsEndPoint); URLConnection connection = url.openConnection(); HttpURLConnection httpConn = (HttpURLConnection) connection; ByteArrayOutputStream bout = new ByteArrayOutputStream(); String xmlInput = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:pos=\"http://postbank.ir/\">\r\n" + " <soapenv:Header>\r\n" + " <pos:PostbankAuth>\r\n" + " <!--Optional:-->\r\n" + " <pos:UserName>ebank</pos:UserName>\r\n" + " <!--Optional:-->\r\n" + " <pos:Password>qwer@123</pos:Password>\r\n" + " </pos:PostbankAuth>\r\n" + " </soapenv:Header>\r\n" + " <soapenv:Body>\r\n" + " <pos:getGuaranty>\r\n" + " <!--Optional:-->\r\n" + " <pos:nationalCode>" + nationalId + "</pos:nationalCode>\r\n" + " <!--Optional:-->\r\n" + " <pos:centerBankCode>" + centerBankCode + "</pos:centerBankCode>\r\n" + " <!--Optional:-->\r\n" + " <pos:length>10</pos:length>\r\n" + " <pos:offset>0</pos:offset>\r\n" + " </pos:getGuaranty>\r\n" + " </soapenv:Body>\r\n" + "</soapenv:Envelope>"; byte[] buffer = new byte[xmlInput.length()]; buffer = xmlInput.getBytes(); bout.write(buffer); byte[] b = bout.toByteArray(); String SOAPAction = "http://postbank.ir/getGuaranty"; httpConn.setRequestProperty("Accept-Encoding", "gzip,deflate"); httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8"); httpConn.setRequestProperty("SOAPAction", SOAPAction); httpConn.setRequestProperty("Content-Length", String.valueOf(b.length)); httpConn.setRequestProperty("Host", "192.168.5.202"); httpConn.setRequestProperty("Connection", "Keep-Alive"); httpConn.setRequestProperty("User-Agent", "Apache-HttpClient/4.5.5 (Java/16.0.1)"); httpConn.setRequestMethod("POST"); httpConn.setDoOutput(true); httpConn.setDoInput(true); OutputStream out = httpConn.getOutputStream(); // Write the content of the request to the outputstream of the HTTP // Connection. out.write(b); out.close(); // Ready with sending the request. // Read the response. InputStreamReader isr = new InputStreamReader(httpConn.getInputStream(), Charset.forName("UTF-8")); BufferedReader in = new BufferedReader(isr); // Write the SOAP message response to a String. while ((responseString = in.readLine()) != null) { outputString = outputString + responseString; } String formattedSOAPResponse = formatXML(outputString); return formattedSOAPResponse ; }
问题原因与解决方法
乱码的核心原因是你请求了gzip/deflate压缩响应,但没有对返回的压缩数据进行解压,直接用UTF-8读取压缩字节流必然会出现乱码。
具体修复方案
方案一:禁用压缩请求(最简单)
直接删除Accept-Encoding请求头,让服务返回未压缩的明文XML:
// 移除这一行 // httpConn.setRequestProperty("Accept-Encoding", "gzip,deflate");
方案二:保留压缩并添加解压逻辑
如果需要压缩提升传输效率,在读取响应时先判断并解压数据流:
// 读取响应部分替换为以下代码 InputStream inputStream = httpConn.getInputStream(); // 检查响应是否被压缩 String contentEncoding = httpConn.getContentEncoding(); if (contentEncoding != null && contentEncoding.contains("gzip")) { inputStream = new GZIPInputStream(inputStream); } else if (contentEncoding != null && contentEncoding.contains("deflate")) { inputStream = new InflaterInputStream(inputStream); } // 用UTF-8读取解压后的流 InputStreamReader isr = new InputStreamReader(inputStream, StandardCharsets.UTF_8); BufferedReader in = new BufferedReader(isr); String responseString; // 用StringBuilder替代String拼接,提升性能 StringBuilder outputString = new StringBuilder(); while ((responseString = in.readLine()) != null) { outputString.append(responseString); } String formattedSOAPResponse = formatXML(outputString.toString()); // 注意:方法声明返回List<Guaranty>,此处需补充XML解析逻辑将字符串转换为目标对象 // List<Guaranty> guarantyList = parseXmlToGuarantyList(formattedSOAPResponse); // return guarantyList;
额外注意点
代码中存在返回值类型不匹配问题:方法声明返回List<Guaranty>,但当前最后返回的是String,需要后续添加XML解析逻辑,将格式化后的SOAP响应转换为List<Guaranty>对象。
内容的提问来源于stack exchange,提问作者Ahmad Yazdi
相关产品推荐
相关产品推荐

