本例应用场景:要做一个webService测试功能,不局限于任何一种固定格式的webService,所以像axis,cxf等框架就不好用了。只有深入到webService的原理,通过发收soap报文,来调用服务返回结果。
发送请求:
/** * 通过httpClient发送soap报文 * @param requestSoap 请求报文 * @param serviceAddress 请求地址 * @param charSet 字符集 * @param contentType 返回的contentType * @return 响应报文 * @throws WebServiceModuleRuntimeException */ public String sendRequestSoap(String requestSoap, String serviceAddress, String charSet, String contentType) throws WebServiceModuleRuntimeException { String resultSoap = ""; PostMethod postMethod = new PostMethod(serviceAddress); byte[] b = new byte[0]; try { b = requestSoap.getBytes(charSet); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } InputStream is = new ByteArrayInputStream(b, 0, b.length); RequestEntity re = new InputStreamRequestEntity(is, b.length, contentType); postMethod.setRequestEntity(re); HttpClient httpClient = new HttpClient(); int statusCode = 0; try { statusCode = httpClient.executeMethod(postMethod); System.out.println("statusCode = " + statusCode); } catch (IOException e) { throw new WebServiceModuleRuntimeException("执行http请求失败", e); } if (statusCode == 200) { try { resultSoap = postMethod.getResponseBodyAsString(); } catch (IOException e) { throw new WebServiceModuleRuntimeException("获取请求返回报文失败", e); } } else { throw new WebServiceModuleRuntimeException("请求失败:" + statusCode); } return resultSoap; }
//调用请求方法,发送报文 String responseSoap = ""; try{ responseSoap = webServiceService.sendRequestSoap(requestSoap,struct.getWebAddress(),"utf-8","text/xml; charset=utf-8"); }catch (WebServiceModuleRuntimeException ex){ throw new ModuleException("发动请求失败",ex); }
解析返回报文:
因没有固定格式,所以无法通过jaxb工具来xml转bean,更没有客户端代码可以用。所以只有解析返回报文中,可以标识返回结果的值,比如成功、success、ok等。
此处考虑两种情况:第一种状态码放在标签的属性值中,第二种状态作为标签的内容:
<result ResultCode="0" ResultCodeDesc="成功"> <result_code>0</result_code>
System.out.println(parseResponseSoap("result_code", "", responseSoap)); /** * 解析返回报文 * @param node 标记所在节点 * @param attr 标记所在属性 * @param soap 报文 * @return 标记值 * @throws WebServiceModuleRuntimeException */ public static String parseResponseSoap(String node, String attr, String soap) throws WebServiceModuleRuntimeException { //然后用SOAPMessage 和 SOAPBody Document personDoc; try { personDoc = new SAXReader().read(new StringReader(soap)); Element rootElt = personDoc.getRootElement(); // 获取根节点 Iterator body = rootElt.elementIterator("Body"); while (body.hasNext()) { Element recordEless = (Element) body.next(); return nextSubElement(node,attr,recordEless); } } catch (DocumentException e) { throw new WebServiceModuleRuntimeException("解析返回报文失败", e); } return ""; }
/** * 递归方法,查找本节点是否有标记信息,如果没有就查找下一层, * 在下一层里同样查找本层节点,只要找到值,就层层返回。 * @param node 节点标签名 * @param attr 节点属性值 * @param el 当前节点对象 * @return 目标值 */ public static String nextSubElement(String node, String attr, Element el) { if (el.getName().equals(node)) { //说明 找到了目标节点 //属性值为空说明取标签内容 if (attr.equals("")) { Iterator sub2 = el.elementIterator(); //有子节点说明标签内容不是单一值,需要拿到查询结果 if (sub2.hasNext()) { while (sub2.hasNext()) { Element s2 = (Element) sub2.next(); //如果返回的不是单一的标记值,而是查询结果,有些麻烦, //查询结果应当是list<map>格式,但是map的key值不好确定,是标签名作为key还是属性值作为key //todo } } else { return el.getText(); } } else { Attribute attrbute = el.attribute(attr); return attrbute.getText(); } } else { Iterator sub2 = el.elementIterator(); while (sub2.hasNext()) { Element sub = (Element) sub2.next(); return nextSubElement(node, attr, sub); } } return ""; }
后记:本篇代码满足我自己的需求,但是看官的需求各异,本篇仅提供部分参考。