我正试图为一个拥有数千个页面的大型网站动态生成网站地图。
是的,我已经考虑过离线生成站点地图文件,并简单地静态提供它,我可能最终会这样做。但我认为这是一个普遍有用的问题:
如何从Wicket中的数据库流式传输大数据
我遵循了WicketSEO页面上的说明,并能够使用DataProvider实现动态站点地图。但它不可扩展——当它调用DataProvider的iterator()
方法时,它会耗尽内存,count
参数等于我返回的对象总数,而不是按块迭代它们。
我认为解决方案在WebResource/ResourceStreamingRequestTarget
的某个地方。但这些类期望IResourceStream
,这最终归结为提供InputStream
实现,该实现处理字节,而不是DB记录。在这种情况下,我不知道如何实现length()
方法,因为这需要提前访问每个记录来计算总长度。
来自IResourceStream.length()方法的文档:
/**
* Gets the size of this resource in bytes
*
* TODO 1.5: rename to lengthInBytes() or let it return some sort of size object
*
* @return The size of this resource in the number of bytes, or -1 if unknown
*/
long length();
因此,我认为如果您的IResourceStream实现告诉长度是未知的,并且在从数据库获取记录时直接流式传输数据,这是可以的。
您可以返回-1,表示未知长度,也可以在将结果呈现给客户端之前将其写入内存缓冲区或磁盘。
您也可以将此文件用作缓存,这样您就不需要每次请求此资源时都重新生成它(但请记住,您必须处理并发请求)。还可以考虑专用缓存解决方案(例如memcache、ehcache等)。
它可能比发布静态文件更干净,尽管如果性能至关重要,静态文件可能会更好。
我最终使用了AbsractResourceStreamWriter
子类:
public class SitemapStreamWriter extends AbstractResourceStreamWriter
{
@Override
public void write(OutputStream output)
{
String HEAD = "<?xml version="1.0" encoding="UTF-8"?>n" +
"<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"n" +
" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">n";
try
{
output.write(HEAD.getBytes());
// write out a <loc> entry for each of my pages here
output.write("</urlset>n".getBytes());
}
catch (IOException e)
{
throw new RuntimeException(e.getMessage(), e);
}
}
}