模板引擎是为了能够更好的将前后端分离,将数据与界面有效解耦。现在较为常用的模板引擎包括JSP、Freemarker、Beetl本节主要介绍FreeMarker。FreeMarker使用FTL(FreeMarker Temple Language)脚本来获取后端的数据,其本身与JS类似是解释型脚本,所以执行效率较差,但开发效率和扩展性较高。

FreeMarker创建

先下载freemarker-2.3.23.jar包并将其导入项目中,并以此创建对象,获取模板对象并将数据输出至模板

package com.freemarker;

import freemarker.core.Configurable;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) throws IOException, TemplateException {
        // 创建核心配置对象
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);

        // 设置加载目录
        configuration.setClassForTemplateLoading(Test.class, "");

        // 获取模板对象
        Template template = configuration.getTemplate("freemarker1.ftl");

        // 创建对象
        Map<String, Object> map = new HashMap<>();

        map.put("description", "百度");
        map.put("url", "http://www.baidu.com/");

        // 向模板输出对象
        template.process(map, new OutputStreamWriter(System.out));
    }
}

创建FreeMarker脚本以ftl后缀名结尾,执行Java程序就可在控制台查看结果。

${description}-${url}

后端调用大模型架构 后端模板引擎有哪些_Computer

FTL数据获取

FreeMarker将数据都保存在Map集合中,在模板获取值时就可以按照key值将value值获取出来,例如:

  • ${key}:获取key所对应的值,若value值为JavaBean对象可以使用“.”加属性名来获取对象的值,若为Map集合可以使用“[key]”来获取值
  • ${key!default}:获取key所对应的值,若该值没有对应的值就获取default默认值
  • ${key?string(...)}:获取key所对应的值,并格式化

示例:
先实现JavaBean类

package com.freemarker.entity;

import java.util.Date;
import java.util.Map;

public class Computer {
    private String sn;      //序列号
    private String model;   //型号
    private int state;      //状态 1-在用 2-闲置 3-报废
    private String user;    //使用人
    private Date dop;       //采购日期
    private Float price;    //购买价格
    private Map info;       //电脑配置信息

	...
	// 省略构造方法和Get/Set方法
}
package com.freemarker;

import com.freemarker.entity.Computer;
import freemarker.core.Configurable;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.*;

public class Test {
    public static void main(String[] args) throws IOException, TemplateException {
        // 创建核心配置对象
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);

        // 设置加载目录
        configuration.setClassForTemplateLoading(Test.class, "");

        // 获取模板对象
        Template template = configuration.getTemplate("freemarker1.ftl");

        // 创建对象
        Map<String, Object> data = new HashMap<>();

       	Map info = new HashMap();
		info.put("cpu", "i5");
		Computer c1 = new Computer("1234567" , "ThinkPad" , 1 , "李四" , new Date() , 12900f , info);
		data.put("computer", c1);

        // 向模板输出对象
        template.process(data, new OutputStreamWriter(System.out));
    }
}

编写FTL文件,对日期格式和金额进行格式化,对于没有值的数据使用默认值

设备序列号:${computer.sn}
型号:${computer.model}
使用状态:${computer.state}
用户:${computer.user}
采购日期:${computer.dop?string("yyyy-MM-dd")}
价格:${computer.price?string("0.00")}
电脑配置信息
--------------------
CPU:${computer.info["cpu"]}
内存:${computer.memory!"暂无信息"}

条件判断

FreeMarker中内置了条件判断标签<#if><#switch>标签,用法上与Java语法类似,示例:

使用<#if>标签判断电脑使用状态,修改FTL文件

设备序列号:${computer.sn}
型号:${computer.model}
使用状态:<#if computer.state == 1>在用<#elseif computer.state == 2>闲置<#elseif computer.state == 3>废弃</#if>
用户:${computer.user}
采购日期:${computer.dop?string("yyyy-MM-dd")}
价格:${computer.price?string("0.00")}
电脑配置信息
--------------------
CPU:${computer.info["cpu"]}
内存:${computer.memory!"暂无信息"}

使用<#switch>标签

设备序列号:${computer.sn}
型号:${computer.model}
使用状态:<#switch computer.state><#case 1>在用<#break ><#case 2>闲置<#break ><#case 3>报废<#break ></#switch>
用户:${computer.user}
采购日期:${computer.dop?string("yyyy-MM-dd")}
价格:${computer.price?string("0.00")}
电脑配置信息
--------------------
CPU:${computer.info["cpu"]}
内存:${computer.memory!"暂无信息"}

后端调用大模型架构 后端模板引擎有哪些_后端调用大模型架构_02

<#if>判断中使用<#if computer.user??>标识是否存在,若存在则为true,不存在则为false
对于字符串的判断可以直接使用==表示相等

循环迭代

FreeMarker中使用两种方法迭代输出集合,一种用于List集合,与Java语法中的循环迭代类似获取每个对象,使用${object_index}表示循环到了第几次

<#list list as object>
	${object_index} - ${object}
</#list>

另一种用于Map集合,获取集合中的key值

<#list Map?keys as key>
	${key} - ${Map[keys]}
</#list>

示例:
JavaBean对象不变,增加数据到List集合和Map集合中

package com.freemarker;

import com.freemarker.entity.Computer;
import freemarker.core.Configurable;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.*;

public class Test {
    public static void main(String[] args) throws IOException, TemplateException {
        // 创建核心配置对象
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);

        // 设置加载目录
        configuration.setClassForTemplateLoading(Test.class, "");

        // 获取模板对象
        Template template = configuration.getTemplate("freemarker1.ftl");

        // 创建对象
        Map<String, Object> data = new HashMap<>();

        List<Computer> computers = new ArrayList<>();
        computers.add(new Computer("1234567" , "ThinkPad X1" , 2 , null , new Date() , 12999f , new HashMap() ));
        computers.add(new Computer("1234568" , "HP XXX" , 1 , "张三" , new Date() , 7500f , new HashMap() ));
        computers.add(new Computer("1234569" , "DELL XXX" , 3 , "李四" , new Date() , 8500f , new HashMap() ));
        computers.add(new Computer("1234570" , "ACER XXX" , 1 , "王五" , new Date() , 6300f , new HashMap() ));
        computers.add(new Computer("1234571" , "MSI XXX" , 1 , "赵六" , new Date() , 9300f , new HashMap() ));
        
        //LinkedHashMap可以保证数据按存放顺序进行提取
        Map<String, Computer> map = new LinkedHashMap<>();
        for(Computer c : computers) {
            map.put(c.getSn(), c);
        }

        data.put("computers", computers);
        data.put("computer_map", map);

        // 向模板输出对象
        template.process(data, new OutputStreamWriter(System.out));
    }
}

修改FTL模板

<#list computers as c>
    序号:${c_index + 1} <#-- 迭代变量_index保存了循环的索引,从0开始 -->
    SN:${c.sn}
    型号:${c.model}
    <#switch c.state>
        <#case 1>
            状态:使用中
            <#break>
        <#case 2>
            状态:闲置
            <#break>
        <#case 3>
            状态:已作废
            <#break>
    </#switch>
    <#if c.user??>
        用户:${c.user}
    </#if>
    采购日期:${c.dop?string("yyyy-MM-dd")}
    采购价格:${c.price?string("0.00")}
    -------------------------------------------
</#list>

==========================================
<#list computer_map?keys as k >
    ${k}-${computer_map[k].model}
    ${computer_map[k].price?string("0.00")}
</#list>

FreeMarker与Servlet的结合开发

freemarker的jar包中包含了对Servlet的支持,所以在使用是可以在web.xml中直接配置该Servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>freemarker</servlet-name>
        <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
        <init-param>
            <param-name>TemplatePath</param-name>
            <param-value>/WEB-INF/ftl</param-value>
        </init-param>
        <init-param>
            <param-name>DefaultEncoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>freemarker</servlet-name>
        <url-pattern>*.ftl</url-pattern>
    </servlet-mapping>
</web-app>

TemplatePath是指向FTL模板的路径,DefaultEncoding描述模板的编码格式这里一定要指定否则中文会乱码。映射地址使用模糊匹配所有的FTL文件。

package com.freemarker.servlet;

import com.freemarker.entity.Employee;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebServlet(urlPatterns = "/list")
public class EmployeeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 创建实体类并将其放在集合中
        List<Employee> list = new ArrayList<>();

        list.add(new Employee(7731,"张三" , "市场部" , "客户代表" , 8000f));
        list.add(new Employee(7731,"张三" , "市场部" , "客户代表" , 8000f));

        // 将list属性放到Request属性中
        req.setAttribute("employees", list);

        // 将请求转发给FTL
        req.getRequestDispatcher("/employee.ftl").forward(req, resp);
    }
}

在访问该Servlet时就会将请求转发给freemarker服务去处理。

FreeMarkerServlet会对Web应用对象根据作用范围依次检索属性,若请求中没有属性会去检索用户会话,若会话中没有会去检索全局对象,所以可以将要返回的信息放在任意一个对象中。