FreeMarker模板

Apache FreeMarker是一个模板引擎:一个用于生成文本输出(HTML页面,xml,配置文件,源代码等)的Java库。将模板发送到输入,例如html,其中包含特殊表达式,并准备了与此表达式对应的数据, Freemarker会动态插入此数据,您会得到一个动态填充的文档。

图片

在FreeMarker文章中
春季靴
巨集
REST API

即 freemarker上的一个简单表达式是例如$ {name},表达式中支持计算,比较操作,条件,循环,列表,内置函数,宏和许多其他表达式。带有$ {name}表达式的html示例(模板test.ftl):

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>${name}!</title> </head> <body> <h2>Hello ${name}!</h2> </body> </html> 

如果现在在Java中创建数据模型:

 import freemarker.template.Configuration; import freemarker.template.Template; ... //  Configuration cfg = new Configuration(Configuration.VERSION_2_3_27); //   Map<String, Object> root = new HashMap<>(); root.put("name", "Freemarker"); //  Template temp = cfg.getTemplate("test.ftl"); //      Writer out = new OutputStreamWriter(System.out); //    temp.process(root, out); 

然后我们得到一个带有填充名称的html文档。

如果需要处理列表,则使用#list构造,例如html列表:

 <ul> <#list father as item> <li>${item}</li> </#list> </ul> 

在Java中,您可以列出数据模型,如下所示

 Map<String, Object> root = new HashMap<>(); .... root.put("father", Arrays.asList("Alexander", "Petrov", 47)); 

让我们继续春天


春季启动具有Freemarker支持。 在站点SPRING INITIALIZR上,您可以获取pom项目文件。

pom文件
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demoFreeMarker</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demoFreeMarker</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 


类DemoFreeMarkerApplication
 @SpringBootApplication public class DemoFreeMarkerApplication { public static void main(String[] args) { SpringApplication.run(DemoFreeMarkerApplication.class, args); } } 


Spring为freemarker预先配置了配置组件。 对于示例控制台应用程序,我将使用spring界面来处理命令行(CommandLineRunner),并为以下ftl模板(hello_test.ftl)准备数据模型:

Hello_test.ftl模板
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello ${name}!</title> </head> <body> <input type="text" placeholder="${name}"> <table> <#list persons as row> <tr> <#list row as field> <td>${field}</td> </#list> </tr> </#list> </table> </body> </html> 


hello_test.ftl模板数据模型的Java代码:

命令行类和数据模型
 @Component public class CommandLine implements CommandLineRunner { @Autowired private Configuration configuration; public void run(String... args) { Map<String, Object> root = new HashMap<>(); //  ${name} root.put("name", "Fremarker"); //  <#list persons List<List> persons = new ArrayList<>(); persons.add(Arrays.asList("Alexander", "Petrov", 47)); persons.add(Arrays.asList("Slava", "Petrov", 13)); root.put("persons", persons); try { Template template = configuration.getTemplate("hello_test.ftl"); Writer out = new OutputStreamWriter(System.out); try { template.process(root, out); } catch (TemplateException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } } 


处理后,我们得到一个html文档:

输出HTML
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello Fremarker!</title> </head> <body> <input type="text" placeholder="Fremarker"> <table> <tr> <td>Alexander</td> <td>Petrov</td> <td>47</td> </tr> <tr> <td>Slava</td> <td>Petrov</td> <td>13</td> </tr> </table> </body> 


巨集


Freemarker具有宏支持,它非常​​方便且强大,并且绝对有必要使用它。

一个简单的例子:

 <#macro textInput id value=""> <input type="text" id="${id}" value="${value}"> </#macro> 

这是一个宏,名称为textInput,参数为id(必填),value为值(非必需,因为它具有默认值)。 接下来是他的身体和输入参数的使用。 在模板中,宏文件的连接方式如下:

 <#import "ui.ftl" as ui/> 

在模板中,宏的调用方式如下:

 <@ui.textInput id="name" value="${name}"/> 

其中ui是连接时指定的别名,$ {name}是模型中的变量,然后通过别名,我们引用宏名称textInput并指定其参数,至少是必需的。 我将为html Input和Table准备简单的宏:

ui.ftl宏文件
 <#-- textInput macro for html input --> <#macro textInput id placeholder="" value=""> <input type="text" id="${id}" placeholder="${placeholder}" value="${value}"> </#macro> <#-- table macro for html table --> <#macro table id rows> <table id="${id}"> <#list rows as row> <tr> <td>${row?index + 1}</td> <#list row as field> <td>${field}</td> </#list> </tr> </#list> </table> </#macro> 


$ {row?index + 1}是列表项的内置索引支持,有很多类似的内置函数。 如果现在更改以前的主模板,并用宏替换其中的输入和表,则会得到以下文档:

Hello.ftl模板
 <#import "ui.ftl" as ui/> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello ${name}!</title> </head> <body> <@ui.textInput id="name" placeholder="Enter name" value="${name}"/> <@ui.table id="table1" rows=persons/> </body> </html> 


休息


当然,这种模型很方便在Web应用程序中使用。 我在pom中连接依赖项:

  <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 

添加REST控制器:

DemoController.java
 @Controller public class DemoController { @Autowired private RepositoryService repositoryService; @GetMapping("/") public String index() { return "persons"; } @RequestMapping(value = "/search", method = RequestMethod.POST) public String hello(Model model, @RequestParam(defaultValue = "") String searchName) { List<List<String>> persons = repositoryService.getRepository(); List<List<String>> filterList = persons.stream() .filter(p -> p.get(0).contains(searchName)) .collect(Collectors.toList()); model.addAttribute("persons", filterList); model.addAttribute("lastSearch", searchName); return "persons"; } @RequestMapping(value = "/save", method = RequestMethod.POST) public String save(Model model, @ModelAttribute("person") Person person) { List<List<String>> persons = repositoryService.addPerson(person); model.addAttribute("persons", persons); return "persons"; } } 


个人服务库:

RepositoryService.java
 @Service public class RepositoryService { private static List<List<String>> repository = new ArrayList<>(); public List<List<String>> getRepository() { return repository; } public List<List<String>> addPerson(Person person) { repository.add(Arrays.asList(person.getFirstName(), person.getAge().toString())); return repository; } } 


面类:

人.java
 public class Person { public Person(String firstName, Integer age) { this.firstName = firstName; this.age = age; } private String firstName; private Integer age; public String getFirstName() { return firstName; } public Integer getAge() { return age; } } 


宏模板:

ui.ftl
 <#macro formInput id name label type="text" value=""> <label for="${id}">${label}</label> <input type="${type}" id="${id}" name="${name}" value="${value}"> </#macro> <#macro table id rows> <table id="${id}" border="1px" cellspacing="2" border="1" cellpadding="5"> <#list rows as row> <tr> <td>${row?index + 1}</td> <#list row as field> <td>${field}</td> </#list> </tr> </#list> </table> </#macro> 


主要模板:

人员.ftl
 <#import "ui.ftl" as ui/> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Person</title> <link href="style/my.css" rel="stylesheet"> </head> <body> <div> <fieldset> <legend> </legend> <form name="person" action="save" method="POST"> <@ui.formInput id="t1" name="firstName" label=""/> <br/> <@ui.formInput id="t2" name="age" label=""/> <br/> <input type="submit" value="Save" /> </form> </fieldset> </div> <div> <fieldset> <legend></legend> <form name="searchForm" action="search" method="POST"> <@ui.formInput id="t3" name="searchName" label=""/> <br/> <input type="submit" value="Search" /> </form> </fieldset> </div> <p><#if lastSearch??> : ${lastSearch}<#else></#if></p> <@ui.table id="table1" rows=persons![]/> </body> </html> 


项目结构:

图片

该应用程序将处理两个“保存”和“搜索”面部命令(请参阅控制器)。 Spring负责所有处理(映射)输入参数的工作。

模板的一些说明。

 <#if lastSearch??> : ${lastSearch}<#else></#if> 

它检查是否设置了参数,然后显示短语“ Search for:..”,否则不显示任何内容:

 <@ui.table id="table1" rows=persons![]/> 

这里也检查了人员列表是否存在,否则为空。 当您第一次打开页面时,这些检查很重要,否则您将必须在index()控制器中对其进行初始化。

申请工作

图片

材料:

Apache FreeMarker手册

Source: https://habr.com/ru/post/zh-CN420549/


All Articles