Modelos FreeMarker

O Apache FreeMarker é um mecanismo de modelo: uma biblioteca Java para gerar saída de texto (páginas HTML, xml, arquivos de configuração, código fonte etc.). Um modelo é enviado para a entrada, por exemplo, html no qual existem expressões especiais, os dados correspondentes a essa expressão são preparados, e o Freemarker insere dinamicamente esses dados e você obtém um documento preenchido dinamicamente.

imagem

No artigo FreeMarker
Bota de mola
Macros
API REST

I.e. uma expressão simples no freemarker é, por exemplo, $ {name}, cálculos, operações de comparação, condições, loops, listas, funções internas, macros e muitas outras suportadas na expressão.Exemplo de html com a expressão $ {name} (template test.ftl):

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

Se você agora cria um modelo de dados em 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); 

então obtemos um documento html com o nome preenchido.

Se você precisar processar a lista, a construção #list será usada, por exemplo, para uma lista html:

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

Em java, você pode listar o modelo de dados da seguinte maneira

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

Vamos para a primavera


A inicialização do Spring tem suporte ao Freemarker. No site SPRING INITIALIZR, você pode obter o arquivo do projeto pom.

arquivo 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> 


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


O Spring possui um componente de configuração pré-configurado para o freemarker. Para um exemplo de aplicativo de console, utilizarei a interface spring para processar a linha de comando (CommandLineRunner) e prepararei o modelo de dados para o seguinte modelo de ftl (hello_test.ftl):

Modelo 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> 


Código Java para o modelo de dados do modelo hello_test.ftl:

Classe CommandLine e modelo de dados
 @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(); } } } 


Após o processamento, obtemos um documento html:

Html de saída
 <!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> 


Macros


O Freemarker possui suporte a macro, é muito conveniente e forte, e é absolutamente necessário usá-lo.

Um exemplo simples:

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

Essa é uma macro com o nome textInput e a ID dos parâmetros (é obrigatório) e o valor (não é necessário, porque possui um valor padrão). Em seguida é o seu corpo e o uso de parâmetros de entrada. No modelo, o arquivo de macro está conectado da seguinte maneira:

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

No modelo, a macro é chamada assim:

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

Onde ui é o alias que foi especificado durante a conexão, $ {name} é uma variável no modelo e, por meio do alias, nos referimos ao nome da macro textInput e especificamos seus parâmetros, pelo menos obrigatórios. Vou preparar macros simples para entrada e tabela html:

arquivo de macro 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} é o suporte de índice interno para o item da lista; existem muitas funções internas semelhantes. Se agora alterarmos o modelo principal anterior e substituirmos a entrada e a tabela por macros, obteremos o seguinte documento:

Hello.ftl template
 <#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> 


REST


Obviamente, esse modelo é conveniente para uso em um aplicativo da web. Eu conecto a dependência no pom:

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

Adicione o controlador 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"; } } 


Repositório de serviços para indivíduos:

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; } } 


Classe de rosto:

Person.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; } } 


Modelo de macro:

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> 


O modelo principal:

persons.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> 


Estrutura do projeto:

imagem

O aplicativo processará dois comandos "salvar" e "pesquisar" da face (consulte o controlador). Todo o trabalho de processamento (mapeamento) de parâmetros de entrada é realizado pelo Spring.

Algumas explicações para o modelo.

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

verifica se o parâmetro está definido e, em seguida, exibe a frase "Search for: .."; caso contrário, nada:

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

aqui também foi verificado que a lista de pessoas está presente, caso contrário está vazia. Essas verificações são importantes quando você abre a página, caso contrário, você teria que inicializá-las no controlador index ().

Trabalho de aplicação

imagem

Materiais:

Manual do Apache FreeMarker

Source: https://habr.com/ru/post/pt420549/


All Articles