Java FreeMarker页面静态化实例详解
什么是FreeMarker页面静态化
FreeMarker是一款基于模板技术实现的Java模板引擎,它可以将动态的HTML页面转化成静态的HTML页面,将一个基于模板的数据模型填充到模板中生成完整的HTML页面,并将HTML页面中的占位符等内容替换成相应的数据,将页面的内容动态的生成并输出。FreeMarker页面静态化是指将服务器端渲染的动态网页,由Java程序定时或者触发器方式生成静态化HTML页面,减少服务器直接处理动态页面的消耗,避免网站被大流量打崩。
实现步骤
- 引入FreeMarker依赖
在Maven中可以添加如下的依赖:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
- 构建FreeMarker配置类
构建一个FreeMarker配置类,配置模板和静态页面的存储位置
@Configuration
public class FreeMarkerConfig {
@Value("${spring.freemarker.template-loader-path}")
private String templateLoaderPath;
@Value("${spring.freemarker.static-file-loader-path}")
private String staticFileLoaderPath;
@Bean
public FreeMarkerConfigurationFactoryBean freeMarkerConfigurationFactoryBean() throws IOException {
FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
bean.setTemplateLoaderPath(templateLoaderPath);
// 设置页面名称和路径
Map<String, String> nameMapping = new HashMap<>();
nameMapping.put("test.ftl", "test.html");
bean.setFreemarkerVariables(Collections.singletonMap("nameMapping", nameMapping));
Properties settings = new Properties();
settings.setProperty(freemarker.template.Configuration.TEMPLATE_UPDATE_DELAY_KEY, "5000");
bean.setFreemarkerSettings(settings);
return bean;
}
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer(FreeMarkerConfigurationFactoryBean bean) throws IOException {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setConfiguration(bean.getObject());
configurer.setDefaultEncoding("UTF-8");
configurer.setPreferFileSystemAccess(false);
Map<String, String> mappings = new HashMap<>();
mappings.put("*.ftl", "*.html");
configurer.setFreemarkerMappings(mappings);
configurer.setFreeMarkerVariables(Collections.singletonMap("STATIC_FILE_LOADER",
staticFileLoaderPath));
return configurer;
}
}
- 构建Java模板引擎工具类
构建一个工具类,用于将Java对象转化为Map
@Service
public class FreeMarkerService {
@Autowired
private Configuration configuration;
public void toHtml(String templateName, String staticFileName, Object data) throws Exception {
// 获取模板
Template template = configuration.getTemplate(templateName);
// 设置静态化文件路径
String path = "./static/" + staticFileName;
// 获取输出流
FileWriter fileWriter = new FileWriter(path);
// 渲染模板生成静态文件
template.process(data, fileWriter);
// 关闭输出流
fileWriter.close();
}
public Map<String, Object> objectToMap(Object obj) throws Exception {
if (obj == null) {
return null;
}
Map<String, Object> map = new HashMap<>();
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
if (key.compareToIgnoreCase("class") == 0) {
continue;
}
Method getter = property.getReadMethod();
Object value = getter == null ? null : getter.invoke(obj);
map.put(key, value);
}
return map;
}
public void toHtmlFromObject(String templateName, String staticFileName, Object obj) throws Exception {
Map<String, Object> map = objectToMap(obj);
toHtml(templateName, staticFileName, map);
}
}
- 构建测试类
在测试类中使用方法toHtmlFromObject:将数据模型填充到模板中生成完整的HTML页面,并将HTML页面中的占位符等内容替换成相应的数据。
示例
以模拟网站电商商品详情页面,生成一个符合静态页面的html作为例子,具体步骤如下:
- 引入依赖
在Maven中添加FreeMarker依赖,pom.xml中的配置如下:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
- 配置FreeMarker
配置FreeMarker的模板和静态文件的存储位置,代码如下:
@Configuration
public class FreeMarkerConfig {
@Value("${spring.freemarker.template-loader-path}")
private String templateLoaderPath;
@Value("${spring.freemarker.static-file-loader-path}")
private String staticFileLoaderPath;
// 通过此方法创建FreeMarkerConfigurationFactoryBean,配置FreeMarker
@Bean
public FreeMarkerConfigurationFactoryBean freeMarkerConfigurationFactoryBean() throws IOException {
FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
bean.setTemplateLoaderPath(templateLoaderPath);
// 设置页面名称和路径
Map<String, String> nameMapping = new HashMap<>();
nameMapping.put("goods.ftl", "goods.html");
bean.setFreemarkerVariables(Collections.singletonMap("nameMapping", nameMapping));
Properties settings = new Properties();
settings.setProperty(freemarker.template.Configuration.TEMPLATE_UPDATE_DELAY_KEY, "5000");
// 设置FreeMarker相关设置
bean.setFreemarkerSettings(settings);
return bean;
}
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer(FreeMarkerConfigurationFactoryBean bean) throws IOException {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setConfiguration(bean.getObject());
configurer.setDefaultEncoding("UTF-8");
configurer.setPreferFileSystemAccess(false);
Map<String, String> mappings = new HashMap<>();
mappings.put("*.ftl", "*.html");
configurer.setFreemarkerMappings(mappings);
configurer.setFreeMarkerVariables(Collections.singletonMap("STATIC_FILE_LOADER",
staticFileLoaderPath));
return configurer;
}
}
- 构建Java模板引擎工具类
构建一个工具类,用于将Java对象转化为Map
@Service
public class FreeMarkerService {
@Autowired
private Configuration configuration;
public void toHtml(String templateName, String staticFileName, Object data) throws Exception {
// 获取模板
Template template = configuration.getTemplate(templateName);
// 设置静态化文件路径
String path = "./static/" + staticFileName;
// 获取输出流
FileWriter fileWriter = new FileWriter(path);
// 渲染模板生成静态文件
template.process(data, fileWriter);
// 关闭输出流
fileWriter.close();
}
public Map<String, Object> objectToMap(Object obj) throws Exception {
if (obj == null) {
return null;
}
Map<String, Object> map = new HashMap<>();
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
if (key.compareToIgnoreCase("class") == 0) {
continue;
}
Method getter = property.getReadMethod();
Object value = getter == null ? null : getter.invoke(obj);
map.put(key, value);
}
return map;
}
/**
* 利用对象数据生成静态页面
* @param templateName
* @param staticFileName
* @param obj
* @throws Exception
*/
public void toHtmlFromObject(String templateName, String staticFileName, Object obj) throws Exception {
Map<String, Object> map = objectToMap(obj);
toHtml(templateName, staticFileName, map);
}
}
- 构建测试类
在测试类中使用方法 toHtmlFromObject:将数据模型填充到模板中生成完整的HTML页面,并将HTML 页面中的占位符等内容替换成相应的数据。代码如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class FreeMarkerTest {
@Autowired
private FreeMarkerService freeMarkerService;
/**
* 商品详情页面示例
*/
@Test
public void goodsTest() throws Exception {
Goods goods = new Goods();
goods.setName("iPhone 13");
goods.setDescription("最新款 iPhone");
goods.setPrice(new BigDecimal(9999));
goods.setSales(0);
// 模拟访问详情页,将数据转成静态文件
freeMarkerService.toHtmlFromObject("goods.ftl", "iphone13_detail.html", goods);
}
}
- 代码解析
在以上示例中,离线化实现过程核心是由 FreeMarker 实现模板渲染生成 HTML 页面,然后将生成的页面通过 Java IO 流输出到指定文件。具体代码解析如下:
FreeMarker 配置
FreeMarker 通过 Configuration(配置类)对模板引擎的配置进行初始化操作,将配置类作为参数进行构造,以便 FreeMarker 可以读取配置类中的各项参数进行初始化。示例中配置模板、静态文件存储路径,开启自动检测页面更新功能,将数据模型的变量名映射到文件名称的映射关系保存在 FreeMarker 配置的 freemarkerVariables 属性中,便于其他方法调用使用。
工具类 FreeMarkerService
FreeMarkerService 类是生成静态页面的核心类,它是将数据模型插入到 HTML 页面模板中、渲染对象存放于键值对 Map 中,并将生成的页面保存到指定的文件中。示例中主要通过 toHtml 方法来实现,它接受三个参数:模板名称、存储路径、数据模型,其中模板名称和存储路径的参数类型都是字符串类型。处理过程中,首先通过 Configuration 对模板进行初始化,然后使用 Template 实例加载模板,将渲染后的 HTML 页面生成文件大输出到指定路径, 最后关闭流。
toHtml 方法中,调用了 FreeMarker 的 process 方法,将配置类(即 Configuration)和数据模型传入,生成目标 HTML 页面内容并存入指定的输出流对应的文件中。
objectToMap 将对象转化成 Map
toHtmlFromObject 方法是生成静态页面的主方法,首先将 java 对象转成 Map 格式,然后以转换好的数据模型填充到模板中。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java Freemarker页面静态化实例详解 - Python技术站