现在的位置: 首页 > 综合 > 正文

通过网站将大量数据导出为XML

2018年05月09日 ⁄ 综合 ⁄ 共 2706字 ⁄ 字号 评论关闭

         由于客户的需要,WEB应用程序中有一项功能是要将数据库中的一张表导出成XML文件下载。最初采用的方案是一次将表中的所有数据读出,然后在内存中通过DOM完整地组织XML文档,完成以后通过转换将其输出到页面的响应流中。在数据量小时,这样的方案没有什么问题,但是当数据库中的数据比较多时,程序运行就产生了异常,查看Tomcat的日志,发现是内存溢出了。如何解决这个问题呢?

        要从根本上解决这个问题,就要想办法降低内存的占用。显然这个方案中有两处占用了大量内存,一是将表中的数据全部读出保存于内存之中;二是在内存中将XML组织完整以后才向客户端输出。第一点很容易解决,采取每次读取一批数据分多次读取即可解决,而第二点,可以通过Java的stax解决。

        以下是一段实现将大量数据形成XML文件并发送到客户端浏览器下载的例程,为了简明起见,数据是直接通过代码生成的而不是从数据库中读取的。该代码生成的XML约1G大小,经测试,未再发生内存溢出的错误。

package net.yanzhijun.edu;

import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

/**
* Servlet implementation class ExportXml
*/
public class ExportXml extends HttpServlet {
private static final long serialVersionUID = 1L;

    /**
     * Default constructor.
     */
    public ExportXml() {
        // TODO Auto-generated constructor stub
    }

/**
  * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
  */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  sample(request, response);
}

/**
  * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
  */
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  sample(request, response);
}

private void sample(HttpServletRequest request, HttpServletResponse response)
{
  response.setContentType(“application/octet-stream”);
        response.setHeader(“Content-Disposition”, “attachment; filename=\”sample.xml\”;”);
        response.setHeader(“Content-Transfer-Encoding”,”binary”); 
        response.setHeader(“Cache-Control”, “must-revalidate, post-check=0, pre-check=0″);      

        response.setHeader(“Pragma”, “public”);

  try
  {
   XMLOutputFactory outputFactory=XMLOutputFactory.newInstance();
   OutputStreamWriter output = new OutputStreamWriter(response.getOutputStream(), “UTF-8″);
   XMLStreamWriter xml=outputFactory.createXMLStreamWriter(output);
   xml.writeStartDocument(“UTF-8″, “1.0″);
   // 根结点
   xml.writeStartElement(“root”);
  
   for(int i = 1; i < 10000000; i++)
   {
    //子结点开始
    xml.writeStartElement(“list”);
    xml.writeAttribute(“id”, “ID” + i);
    xml.writeAttribute(“attr1″, “ATTR1_” + i);
    xml.writeAttribute(“attr2″, “ATTR2_” + i);
    xml.writeAttribute(“attr3″, “ATTR3_” + i);
    xml.writeAttribute(“attr4″, “ATTR4_” + i);
    // 子结点结束
    xml.writeEndElement();
   }
  
   // 根结点结束
   xml.writeEndElement();
  
   xml.flush();
   xml.close();
 
  }
  catch(IOException e)
  {
   e.printStackTrace();
  }
  catch( XMLStreamException e)
  {
   e.printStackTrace();
  }
}

}

欢迎访问梦断酒醒的博客http://www.yanzhijun.net

抱歉!评论已关闭.