服务器端有xml流过来,为了解析,最初使用的方法是构建一个StringBuilder,在onMessage方法中不断append,最终形成一个完成的xml文件字符串(其中包含多个xml).最后使用DocumentBuilder来解析。这种做法在数据量小的时候可以维持,当一次传来大量xml,便会出现OOM。
改良后的方法使用边接收数据,边解析的异步方式,这样解析过的部分就可以丢掉而不继续占用内存。
准备工作,需要熟悉的API,
com.sun.jersey.api.client.Client : 用来构建提交Restful请求的客户端,可以通过其来设置请求的参数,比如是否异步调用,请求的header信息等等。
java.util.concurrent.Future<InputStream>: 接收异步请求返回的结果,可以用future.isDone(), future.isCancelled()来判断“是否返回”或“是否取消”等执行状态。
1 Future<InputStream> future = future = Client.create() 2 .asyncResource(requestBean.getUrl()) 3 .entity(requestBean.getRequestBody(), "application/json") 4 .post(InputStream.class);
com.google.common.base.Function<Node,Void> :自定义callback方法,用来处理当一个返回完成时所得到的数据。Node是xml的基本元素,Void表示所定义的回掉无返回值。
1 Function<Node, Void> callback = new Function<Node, Void>() { 2 public Void apply(Node tradeNode) { 3 //Process node and customized logic etc. 4 5 };
javax.xml.stream.XMLOutputFactory: 构建工厂类来实例化XMLEventWriters 和 XMLStreamWriters。
javax.xml.parsers.DocumentBuilder: 创建DOM来解析XML数据源,这些数据源可以是InputStreams, Files, URLs, 以及SAX InputSources。
javax.xml.stream.XMLEventReader: 此类是用于解析 XML 事件的顶层接口。它提供查看下一个事件和返回属性接口中的配置信息的功能。可以通过一个while(event.hasNext())便利xml数据。
javax.xml.stream.XMLEventWriter: 生成XML文件的接口,此接口并不对xml的格式的合法性进行校验
javax.xml.namespace.QName.QName(String namespaceURI, String localPart): 构建一个xml 节点
1 public void handleResponseStream(InputStream stream, Function<Node, Void> callback) throws Exception{ 2 3 XMLOutputFactory outfac = XMLOutputFactory.newInstance(); 4 DocumentBuilder dombuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 5 XMLEventReader r = XMLInputFactory.newInstance().createXMLEventReader(stream); 6 XMLEventWriter xew = null; 7 DOMResult domresult = null; 8 QName root = new QName("http://www.namespace.com", "tagstart"); 9 10 while(r.hasNext() ) { 11 XMLEvent e = r.nextEvent(); 12 if(e.isStartElement() && root.equals(((StartElement)e).getName())) { 13 domresult = new DOMResult(dombuilder.newDocument()); 14 xew = outfac.createXMLEventWriter(domresult); 15 } 16 if(xew != null) { 17 xew.add(e); 18 } 19 if(e.isEndElement() && root.equals(((EndElement)e).getName())) { 20 xew.close(); 21 callback.apply(domresult.getNode().getFirstChild()); 22 xew = null; 23 } 24 } 25 }