Java 模板引擎 ~ FreeMarker。

Java 模板引擎 ~ FreeMarker。



数据模型 + 模板 = 输出(HTML)。

https://freemarker.apache.org/

FreeMarker 是一款模板引擎:即一种基于模板和要改变的数据,并用来生成输出文本(HTML 网页,电子邮件,配置文件,源代码等)的通用工具。ta 不是面向最终用户的,而是一个 Java 类库,是一款程序员可以嵌入他们所开发产品的组件。



异步。

package com.geek.springbootdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync
public class SpringbootdemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootdemoApplication.class, args);
    }

}

package com.geek.springbootdemo.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncService {

    // 耗时操作,在一个子线程中执行。
    @Async
    public void show() {
        System.out.println(2);
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(3);
    }

}

package com.geek.springbootdemo.controller;

import com.geek.springbootdemo.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AsyncController {

    @Autowired
    private AsyncService asyncService;

    @RequestMapping("/async")
    public String testAsync() {

        System.out.println(1);

        asyncService.show();// 由主线程执行,开启了一个子线程。

        System.out.println(4);

        return "success";
    }

}

1
4
2
3


多环境开发。

application-dev.properties

application-prod.properties

application-test.properties

application.properties(Spring Boot 默认加载)。

spring.profiles.active=test


Spring Boot 整合 jsp。

  • 必须是 web 工程。

  • 不能使用 Spring Boot 的 tomcat。

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

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

报 404 问题,不知为啥。

但使用 ↓ ↓ ↓ 可以解决。

spring-boot:run



Maven 构建 FreeMarker。

jsp 动态页面,加载慢。

FreeMarker 不需要 tomcat 等 Servlet。最终商将页面转为 html。

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
  • first.ftl。

根据这个模板生成 html 文件。

${name}
package com.geek.freemarker;

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

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class Demo00 {

    public static void main(String[] args) throws IOException, TemplateException {
        // 创建模板文件 first.ftl。
        // 创建配置对象。
        Configuration configuration = new Configuration();

        // 配置模板文件的路径。
        configuration.setDirectoryForTemplateLoading(new File("G:\\lyfGeek\\IdeaProjects\\freemarker_geek\\freeemarkerdemo\\src\\main\\webapp\\WEB-INF\\ftl"));

        // 模板使用的编码。
        configuration.setDefaultEncoding("utf-8");

        // 得到模板文件 Template 对象。
        Template template = configuration.getTemplate("first.ftl");

        // 构建模板使用的数据。
        Map map = new HashMap();
        map.put("name", "zhangsan");

        // 设置最终生成的静态页面的路径和名称。
        FileWriter fileWriter = new FileWriter("./first.html");
        // 生成。
        template.process(map, fileWriter);

        fileWriter.close();
    }

}



FreeMarker 取值实体类。
package com.geek.freemarker;

public class Student {

    private int id;
    private String name;
    private int age;
    private String address;

    public Student() {
    }

    public Student(int id, String name, int age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

}

  • 生成。
package com.geek.freemarker;


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

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class Demo01 {

    public static void main(String[] args) throws IOException, TemplateException {
        Configuration configuration = new Configuration();
        configuration.setDirectoryForTemplateLoading(new File("G:\\lyfGeek\\IdeaProjects\\freemarker_geek\\freeemarkerdemo\\src\\main\\webapp\\WEB-INF\\ftl"));
        configuration.setDefaultEncoding("UTF-8");
        Template template = configuration.getTemplate("second.ftl");
        // 构建数据模型。
        Student student = new Student();
        student.setId(11);
        student.setName("李四");
        student.setAge(25);
        student.setAddress("武汉");
        Map map = new HashMap();
        map.put("stu", student);

        FileWriter fileWriter = new FileWriter("./second.html");
        template.process(map, fileWriter);

        fileWriter.close();
    }

}

  • 模板文件。
<html>
<head>

</head>

<body>

学号:${stu.id}
姓名:${stu.name}
年龄:${stu.age}
住址:${stu.address}


</body>

</html>

  • 生成的 html 文件。
<html>
<head>

</head>

<body>

学号:11
姓名:李四
年龄:25
住址:武汉


</body>

</html>



FreeMarker 取值 List。
<html>
<head></head>

<body>
<table border="1" cellspacing="0" cellpadding="0">
    <tr>
        <td>编号</td>
        <td>学号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>住址</td>
    </tr>

    <#list stulist as stu>
        <tr>
            <td>${stu_index}</td>
            <td>${stu.id}</td>
            <td>${stu.name}</td>
            <td>${stu.name}</td>
            <td>${stu.address}</td>
        </tr>
    </#list>
</table>
</body>

</html>

package com.geek.freemarker;

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

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Demo02 {

    public static void main(String[] args) throws IOException, TemplateException {
        Configuration configuration = new Configuration();
        configuration.setDirectoryForTemplateLoading(new File("G:\\lyfGeek\\IdeaProjects\\freemarker_geek\\freeemarkerdemo\\src\\main\\webapp\\WEB-INF\\ftl"));
        configuration.setDefaultEncoding("utf-8");
        Template template = configuration.getTemplate("third.ftl");
        List<Student> list = new ArrayList<>();
        Student student = new Student(11, "王五", 25, "武汉");
        Student student2 = new Student(22, "王五2", 25, "上海");
        Student student3 = new Student(33, "王五3", 25, "北京");
        list.add(student);
        list.add(student2);
        list.add(student3);
        Map map = new HashMap();
        map.put("stulist", list);
        FileWriter fileWriter = new FileWriter("./third.html");
        template.process(map, fileWriter);
        fileWriter.close();
    }

}

<html>
<head></head>

<body>
<table border="1" cellspacing="0" cellpadding="0">
    <tr>
        <td>编号</td>
        <td>学号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>住址</td>
    </tr>

            <tr>
            <td>0</td>
            <td>11</td>
            <td>王五</td>
            <td>王五</td>
            <td>武汉</td>
        </tr>
        <tr>
            <td>1</td>
            <td>22</td>
            <td>王五2</td>
            <td>王五2</td>
            <td>上海</td>
        </tr>
        <tr>
            <td>2</td>
            <td>33</td>
            <td>王五3</td>
            <td>王五3</td>
            <td>北京</td>
        </tr>
</table>
</body>

</html>



日期。
        map.put("date", new Date());
  • ftl。
${date}

会报错。

提示解决方式。

----
Tip: Use ?date, ?time, or ?datetime to tell FreeMarker the exact type.
----
Tip: If you need a particular format only once, use ?string(pattern), like ?string('dd.MM.yyyy HH:mm:ss'), to specify which fields to display. 
----

六月 25, 2020 11:42:15 下午 freemarker.log._JULLoggerFactory$JULLogger error
严重: Error executing FreeMarker template
FreeMarker template error:
Can't convert the date-like value to string because it isn't known if it's a date (no time part), time or date-time value.
The blamed expression:
==> date  [in template "third.ftl" at line 6, column 3]

----
Tip: Use ?date, ?time, or ?datetime to tell FreeMarker the exact type.
----
Tip: If you need a particular format only once, use ?string(pattern), like ?string('dd.MM.yyyy HH:mm:ss'), to specify which fields to display. 
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: ${date}  [in template "third.ftl" at line 6, column 1]
----

Java stack trace (for programmers):
----
freemarker.core._TemplateModelException: [... Exception message was already printed; see it above ...]
	at freemarker.core._MessageUtil.newCantFormatUnknownTypeDateException(_MessageUtil.java:301)
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1660)
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1645)
	at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:380)
	at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:358)
	at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100)
	at freemarker.core.DollarVariable.accept(DollarVariable.java:63)
	at freemarker.core.Environment.visit(Environment.java:330)
	at freemarker.core.Environment.visit(Environment.java:336)
	at freemarker.core.Environment.process(Environment.java:309)
	at freemarker.template.Template.process(Template.java:384)
	at com.geek.freemarker.Demo02.main(Demo02.java:30)
Caused by: freemarker.core.UnknownDateTypeFormattingUnsupportedException: Can't convert the date-like value to string because it isn't known if it's a date (no time part), time or date-time value.
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1722)
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1492)
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1658)
	... 10 more

Exception in thread "main" FreeMarker template error:
Can't convert the date-like value to string because it isn't known if it's a date (no time part), time or date-time value.
The blamed expression:
==> date  [in template "third.ftl" at line 6, column 3]

----
Tip: Use ?date, ?time, or ?datetime to tell FreeMarker the exact type.
----
Tip: If you need a particular format only once, use ?string(pattern), like ?string('dd.MM.yyyy HH:mm:ss'), to specify which fields to display. 
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: ${date}  [in template "third.ftl" at line 6, column 1]
----

Java stack trace (for programmers):
----
freemarker.core._TemplateModelException: [... Exception message was already printed; see it above ...]
	at freemarker.core._MessageUtil.newCantFormatUnknownTypeDateException(_MessageUtil.java:301)
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1660)
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1645)
	at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:380)
	at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:358)
	at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100)
	at freemarker.core.DollarVariable.accept(DollarVariable.java:63)
	at freemarker.core.Environment.visit(Environment.java:330)
	at freemarker.core.Environment.visit(Environment.java:336)
	at freemarker.core.Environment.process(Environment.java:309)
	at freemarker.template.Template.process(Template.java:384)
	at com.geek.freemarker.Demo02.main(Demo02.java:30)
Caused by: freemarker.core.UnknownDateTypeFormattingUnsupportedException: Can't convert the date-like value to string because it isn't known if it's a date (no time part), time or date-time value.
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1722)
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1492)
	at freemarker.core.Environment.getTemplateDateFormat(Environment.java:1658)
	... 10 more

Process finished with exit code 1



Spring Boot 整合 FreeMarker。

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.geek</groupId>
    <artifactId>springboot-freemarker</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-freemarker</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <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-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

  • ftl 模板文件放在 templates/page.ftl。
${address}
  • controller 层。
package com.geek.springbootfreemarker.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

@Controller
public class TestController {

    @RequestMapping("/toPage")
    public String show(Map<String, Object> map) {
        map.put("address", "武汉");
        return "page";
    }

}

  • 访问 http://localhost:8080/toPage。页面会显示

武汉

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lyfGeek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值