欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Freemarker生成商品详情静态页面

程序员文章站 2022-05-31 14:16:03
...

    Freemarker 模板引擎技术,是一种基于模板和数据生成可用的文本的工具。例如,我们可以通过定义 JavaBean 对象的格式,从数据库提取字段名称、类型,生成 JavaBean 对象。我们还可以用它生成静态的 html 页面,提供访问效率,例如电商网站商品详情页面,布局格式相同,只是内容不一样。
    下面我会介绍 Freemarker 在电商网站生成商品详情页面的具体使用方法。

1.引入 jar 包

<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.23</version>
</dependency>

2.创建 service 接口和实现

package com.p7.framework.service;
import java.util.Map;
public interface StaticPageService {
    void createGoodsStaticHtml(Map<String, Object> root, String id);
}
package com.p7.framework.service.impl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import com.p7.framework.service.StaticPageService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class StaticPageServiceImpl implements StaticPageService, ServletContextAware {
    private static final Logger logger = Logger.getLogger(StaticPageServiceImpl.class);
    private ServletContext servletContext;
    private Configuration conf;
    /**
     * 注入 SpringMVC 的 FreeMarkerConfigurer 启动配置类
     */
    public void setFreeMarkerConfigurer(FreeMarkerConfigurer freeMarkerConfigurer) {
        this.conf = freeMarkerConfigurer.getConfiguration();
    }
    /**
     * 注入 ServletContext ,获取路径
     */
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }
    /**
     * 
     * @param root
     *            商品信息
     * @param id
     *            商品 id
     */
    public void createGoodsStaticHtml(Map<String, Object> root, String id) {
        // 获取到路径
        String path = servletContext.getRealPath("/html/goods/detail/" + id + ".html");
        // 创建文件
        File f = new File(path);
        // 判断父文件夹存在不存在
        if (!f.getParentFile().exists()) {
            f.getParentFile().mkdirs();
        }
        // 输出流
        Writer out = null;
        // 创建输出流并指定编码UTF-8,此处的编码与
        try {
            out = new OutputStreamWriter(new FileOutputStream(f), "UTF-8");
            // 指定模板 返回模板对象 读UTF-8
            Template template = conf.getTemplate("freemarker.html");

            template.process(root, out);
        } catch (UnsupportedEncodingException e) {
            logger.error("UnsupportedEncodingException: " + e.getMessage());
        } catch (FileNotFoundException e) {
            logger.error("FileNotFoundException: " + e.getMessage());
        } catch (IOException e) {
            logger.error("IOException: " + e.getMessage());
        } catch (TemplateException e) {
            logger.error("TemplateException: " + e.getMessage());
        }
    }
}

3.在 SpringMVC 配置文件中配置 FreeMarkerConfigurer

// 在 Freemarker 入门程序中创建的 Configuration ,用来设置模板的加载目录,这个路径必须写成绝对路径。
// Configuration conf = new Configuration();
// conf.setDirectoryForTemplateLoading(new File("E:/ws/framework/demo/ftl/"));
// 但是在实际的项目开发中,我们不可能使用这样一个路径,
// 因此,我们需要借助其他方法,例如 SpringMVC 中有 FreeMarkerConfigurer 这样的一个类
<!-- Freemarker 配置 -->
<bean id="staticPageService" class="com.p7.framework.service.impl.StaticPageServiceImpl">
    <!-- 注入FreeMarkerConfigurer -->
    <property name="freeMarkerConfigurer">
        <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
            <!-- 采用相对路径来设置模板目录 -->
            <property name="templateLoaderPath" value="/WEB-INF/ftl/"/>
        </bean>
    </property>
</bean>

<!-- 配置静态资源访问 -->
<mvc:resources mapping="/resources/**" location="/" />

Freemarker生成商品详情静态页面

4.controller 层
    由于是测试,直接访问该接口,弄一些测试数据。

package com.p7.framework.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.p7.framework.service.StaticPageService;
@Controller
@RequestMapping("/freemarker")
public class FreemarkerController {
    @Autowired
    private StaticPageService staticPageService;
    @GetMapping()
    public void createGoodsStaticHtml() {
        String id = "7758521";
        Map<String, Object> root = new HashMap<String, Object>();
        List<String> sizes = new ArrayList<String>();
        sizes.add("s");
        sizes.add("xl");
        sizes.add("xxl");
        root.put("goodsName", "苍**同款ww");
        root.put("goodsPrice", new BigDecimal("100.00"));
        root.put("crowd", "you just can't keep it in your pants!");
        root.put("imgSrc", "xxoo");
        root.put("sizes", sizes);
        staticPageService.createGoodsStaticHtml(root, id);
    }
}

5.项目结构
Freemarker生成商品详情静态页面

6.模板内容
    因为只是测试,所以模板内容只是简单的一些文本输出。实际的应用中,模板内容是包含了引入的 js、css 等等的文件。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    商品名称:${goodsName} 
    商品价格:${goodsPrice}
    适合人群:${crowd}
    商品尺码:
            <#list sizes as size> 
                ${size} 
            </#list>
    商品图片:<img src="${imgSrc}">
</body>
</html>

7.测试

    测试通过模板和数据生成静态页面。

# resources 是映射的静态路径的相对跟路径,也就是在配置文件中配置的
# <mvc:resources mapping="/resources/**" location="/" />
http://localhost:8080/项目名/freemarker
http://localhost:8080/项目名/resources/html/goods/detail/7758521.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    商品名称:苍**同款ww 
    商品价格:100
    适合人群:you just can't keep it in your pants!
    商品尺码:
                s 
                xl 
                xxl 
    商品图片:<img src="xxoo">
</body>
</html>

8.说明
    在实际的电商应用中,一般情况下,静态的商品详情页在点击商品上架时,生成静态页面,也就是说,在上架的接口中获取到商品的信息,调用 StaticPageService 的方法生成静态页面。
    在访问电商主页或者查询商品时,我们也需要对静态页面的 url 作一些处理

<a href="javascript:void(0)" onclick="window.open('http://localhost:8080/resources/html/goods/detail/${goods.id}.html')"