大家好,我是烤鸭:
分享一下本地和线上利用freemarker生成静态页面。
说一下为什么要生成静态页面,以及使用的业务场景。
不是太长时间变更的数据可以用静态页面装填,用户访问的速度会大大提高,敏感的数据会从后台请求。
比如京东的商品页面,就是用的这个技术,价格库存信息就会从后台获取。
比如用于代码生成的时候生成页面(.jsp或者.html),现在很多代码生成工具都可以生成页面了。
环境:
freemarker 2.3.23
1. 本地测试
先创建一个模板文件,${}变量就是要替换的内容。其他的不变。
test.ftl
<html>
<head>
<title>freemarker Test</title>
</head>
<body>
<h1>Hello,${name}</h1>
</body>
</html>
GenerateHtml.java
package cxxx.xxxx.freemaker;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* 使用Freemarker生成html文件
*
* @author lg
*
*/
public class GenerateHtml {
/**
* 把模板读入到String中,然后根据String构造FreeMarker模板
*/
public static void createHtmlFromString() {
BufferedInputStream in = null;
FileWriter out = null;
String inFilePath = "E:\\my\\博客\\freemaker\\ftl\\test.ftl";
String ftlFilePath = "E:\\my\\博客\\freemaker\\html\\";
String fileName = "test.html";
try {
// 模板文件
File file = new File(inFilePath);
// 构造输入流
in = new BufferedInputStream(new FileInputStream(file));
int len;
byte[] bytes = new byte[1024];
// 模板内容
StringBuilder content = new StringBuilder();
while ((len = in.read(bytes)) != -1) {
content.append(new String(bytes, 0, len, "utf-8"));
}
// 构造Configuration
Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
// 构造StringTemplateLoader
StringTemplateLoader loader = new StringTemplateLoader();
// 添加String模板
loader.putTemplate("test", content.toString());
// 把StringTemplateLoader添加到Configuration中
configuration.setTemplateLoader(loader);
// 获取模板
Template template = configuration.getTemplate("test");
String name = "测试测试";
HashMap<Object, Object> names = new HashMap<>();
names.put("name", name);
// 构造输出路
out = new FileWriter(ftlFilePath+fileName);
// 生成HTML
template.process(names, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
createHtmlFromString();
}
}
inFilePath 是模板文件路径
ftlFilePath
生成文件的目录
fileName
生成文件的名称
执行后,结果如图:
2. 项目测试
和本地的方法确实是类似的,静态页模板(.ftl)可以是在项目中的。生成的文件应该是不在项目中的。否则tomcat重新启动后会重新加载war包,文件就没了。应该生成到静态资源目录,简单方式是用nginx完成映射。
方法和上面的类似,就是读取test.ftl的时候会从项目中读取。
/**
* 把模板读入到String中,然后根据String构造FreeMarker模板
*/
public void createHtmlFromRequest(HttpServletRequest request) {
BufferedInputStream in = null;
FileWriter out = null;
// 项目的resources目录
String root = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ request.getContextPath() + "/";
// 生产的静态资源目录
String outPath = "";
// 文件名称,生成的
String outFileName = ""; //.html后缀
File html = new File(outPath+outFileName);// html文件
try {
// 模板文件
File file = new File(root + File.separator + "test.ftl");
// 构造输入流
in = new BufferedInputStream(new FileInputStream(root + File.separator + "test.ftl"));
int len;
byte[] bytes = new byte[1024];
// 模板内容
StringBuilder content = new StringBuilder();
while ((len = in.read(bytes)) != -1) {
content.append(new String(bytes, 0, len, "utf-8"));
}
// 构造Configuration
Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
// 构造StringTemplateLoader
StringTemplateLoader loader = new StringTemplateLoader();
// 添加String模板
loader.putTemplate("test", content.toString());
// 把StringTemplateLoader添加到Configuration中
configuration.setTemplateLoader(loader);
// 获取模板
Template template = configuration.getTemplate("test");
String name = "aaaaaaa";
HashMap<Object, Object> names = new HashMap<>();
names.put("name", name);
// 构造输出路
out = new FileWriter(html);
// 生成HTML
template.process(names, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
之前有想过的使用场景是注册账号绑定邮箱的时候,每个人邮箱收到的是一个专门为这个账号生成的页面,在有限时间内访问有效,完成绑定。
还有就是为每个用户生成二维码发送到个人的邮箱,完成后续操作,如果超时,二维码失效。
上述场景实用性不强,不如发送ajax请求获取数据。只是一些想法,暂时还没具体使用场景。