在上篇博客中说到我采用第二种方案实现静态化,也就是通过扩展FreeMarker的FreeMarkerView类(参考【我的博客】)。上次说到这种方式更加优雅,节省不少的工作量,而且降低了后期的维护成本。这篇博客将指出这种方案的一个缺点,以及解决方案。
该静态化方案中,FreeMarker渲染页面的工作发生在Controller层return之后,如下形式:
@RequestMapping(value = "detail")
@NeedNavigation
public String detail(HttpServletRequest request, Model model, Integer id, String createHtml){
……页面数据处理逻辑略……
//页面静态化
if (createHtml != null && "true".equals(createHtml)) {
StaticSupportInfo staticSupportInfo = new StaticSupportInfo();
//设置静态化文件名
staticSupportInfo.setTargetHtml("detail_" + id + ".html");
//将静态化信息支持对象放到Attribute中,注意key值不要写错
request.setAttribute("staticSupportInfo", staticSupportInfo);
}
return "web/blog/detail";
}
我们向上层容器返回了模板页的路径,也就是web/home/index.ftl,然后渲染页面以及向客户端返回结果的工作就交给了FreeMarker,然后其他的事就不由我们管了。那么批量静态化怎么办呢?这是一个问题,因为我们没法通过循环向一个方法传递不同的参数让其静态化这一批页面,无论我们怎么循环,上层的FreeMarker都只是处理我们return给它的那一个模板页。
其实解决办法很简单,在一次访问的内部循环不行,那我们就在外部循环嘛,让每一次循环都是一次完整的http访问。代码如下:
@RequestMapping("static_all")
public void staticAll(HttpServletRequest request, HttpServletResponse response) throws IOException {
……业务逻辑略……
for (Integer id : ids) { //ids获取的具体业务逻辑略
String urlString = "www.test.com/web/blog/detail.htm?id=" + id + "&createHtml=true";
try {
UrlResource urlResource = new UrlResource(urlString);
EncodedResource encodedResource = new EncodedResource(urlResource,"utf-8");
String result = FileCopyUtils.copyToString(encodedResource.getReader());
} catch (Exception e) {
e.printStackTrace();
continue;
}
}
……response中返回处理结果的逻辑略……
}
注:这里UrlResource是spring对java接口的封装,用java的URL和HttpURLConnection也可以。
url中用的是域名,服务器要记得配置host。
如此,我们就解决了批量静态化的问题,从理论上讲,相比于静态化方案一(参考【我的博客】),这种方式效率较低,因为每一次循环都是一次完整的http访问。静态化功能本来就是提供给公司内部的,因此不用在这个问题上纠结。在效率要求不高的前提下这种方案不失为一种简单的解决方案。