【SpringBoot】FreeMarker视图渲染
作者:mmseoamin日期:2023-12-18

目录

一、FreeMarker 简介

1.1 什么是FreeMarker?

1.2 Freemarker模板组成部分

1.3 为什么要使用FreeMarker

二、Springboot集成FreeMarker

2.1 配置

2.2 数据类型

2.2.1 字符串

2.2.2 数值

2.2.3 布尔值

2.2.4 日期

2.3 常见指令  

2.3.2 assign

2.3.3 include

...

三、常见指令实现增删改查(综合案例)⭐

3.1 后端

3.2 前端

3.3 效果展示

3.3.1 新增功能

3.3.2 修改功能

3.3.3 查询功能

3.3.4 删除功能


一、FreeMarker 简介

1.1 什么是FreeMarker?

       FreeMarker是一款 模板引擎 ,它允许开发人员使用模板和数据来生成输出文本,如HTML网页、电子邮件、配置文件和源代码等。它是一个Java类库,可以被嵌入到开发人员所创建的产品中。开发人员可以使用FreeMarker来动态生成和渲染视图,以便将数据呈现给最终用户

官方手册【SpringBoot】FreeMarker视图渲染,icon-default.png?t=N7T8,第1张https://freemarker.apache.org/

下面是一些关键点:

  1. 模板引擎: FreeMarker是一种模板引擎,允许开发者定义模板文件,其中包含要动态填充的占位符或表达式。这些模板文件可以包含HTML、XML、文本等。

  2. 动态内容生成: FreeMarker的主要用途是根据模板和数据生成最终的输出内容。模板中的占位符将被实际的数据替代,从而生成动态的、个性化的输出。

  3. 嵌入式组件: FreeMarker是一个Java类库,可以轻松地集成到Java应用程序中。这使得开发人员可以在他们的Java应用中使用FreeMarker来处理视图层的动态内容生成。

  4. 面向程序员: FreeMarker通常被程序员用于构建动态的用户界面或生成其他类型的文本输出。它不直接面向最终用户,而是提供给开发人员一个工具,使他们能够以更灵活和动态的方式生成内容。

1.2 Freemarker模板组成部分

FreeMarker模板文件主要由如下4个部分组成:

  • 文本:直接输出的部分

  • 注释:使用 <#-- ... --> 格式做注释,里面内容不会输出

  • 插值:即 ${...} 或 #{...} 格式的部分,类似于占位符,将使用数据模型中的部分替代输出

  • FTL指令:即FreeMarker指令,全称是:FreeMarker Template Language,和HTML标记类似,但名字前加#予以区分,不会输出

    1.3 为什么要使用FreeMarker

    FreeMarker在Spring Boot中被广泛使用的原因与其特性和与Spring Boot的集成有关。

    1. 轻量级: FreeMarker相对轻量,不引入过多的依赖,易于集成和使用。

    2. 与Spring框架整合良好: FreeMarker与Spring框架集成良好,通过Spring Boot的自动配置,可以很容易地配置FreeMarker作为模板引擎。

    3. Spring Boot 默认支持: Spring Boot对多个模板引擎提供了自动配置支持,包括FreeMarker。因此,Spring Boot项目中使用FreeMarker非常方便,只需在依赖中引入相应的starter即可。

    4. 开箱即用: FreeMarker可以作为Spring Boot的一部分,无需额外的配置。这使得开发者能够快速启动项目并使用FreeMarker构建视图。

    5. 简化模板文件的构建: FreeMarker的模板语法相对简洁,可以更容易地与后端Java代码交互。在Spring Boot项目中,Java对象的数据可以直接在FreeMarker模板中使用。

           FreeMarker的诞生是为了取代JSP。虽然JSP功能强大,可以写Java代码实现复杂的逻辑处理,但是页面会有大量业务逻辑,不利于维护和阅读,更不利于前后台分工,容易破坏MVC结构,所以舍弃JSP,选择使用FreeMarker是大势所趋。

    二、Springboot集成FreeMarker

    2.1 配置

    1、配置pom.xml,引入依赖:

    
        org.springframework.boot
        spring-boot-starter-freemarker
    

     

    2、添加application.yml配置:

      freemarker:
        # 设置模板后缀名
        suffix: .ftl
        # 设置文档类型
        content-type: text/html
        # 设置页面编码格式
        charset: UTF-8
        # 设置页面缓存
        cache: false
        # 设置ftl文件路径
        template-loader-path: classpath:/templates
        # 设置静态文件路径,js,css等
        mvc:
          static-path-pattern: /static/**

    3、新建模板文件(.ftl)

    在resources/templates目录新建一个.ftl文件

    第一创建是没有这个文件类型的选项的,所以我们要定义个.ftl格式的文件:

    settings --> Editor --> File and Code Templates 

    【SpringBoot】FreeMarker视图渲染,第2张

    该内容模板于html差不多的,最后在创建文件的时候就有个一个.ftl格式的文件选项

    【SpringBoot】FreeMarker视图渲染,第3张

    index.ftl:

    
    
    
        
        Freemarker
    
    
    

    Hello FreeMarker!!!

    Controller:

    package com.ycxw.boot.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    /**
     * @author 云村小威
     * @create 2023-12-13 18:57
     */
    @Controller
    public class IndexController {
        @RequestMapping("/")
        public String home(){
            return "index";
        }
    }
    

    一个基本的数据显示就成功了

    【SpringBoot】FreeMarker视图渲染,第4张

    2.2 数据类型

    2.2.1 字符串

            在文本中确定字符串值的方法是看双引号,比如: "some text",或单引号,比如: 'some text'。这两种形式是等同的。 如果文本自身包含用于字符引用的引号 ( " 或 ')或反斜杠时, 应该在它们的前面再加一个反斜杠;这就是转义。 转义允许直接在文本中输入任何字符, 也包括换行。

    ${"It's \"quoted\" and this is a backslash: \\"}

    字符串类型处理:

    方法含义
    ?substring(start,end)截取字符串(左闭右开)
    ?uncap_first首字母小写输出
    ?cap_first首字母大写输出
    ?lower_case字母转小写输出
    ?upper_case字母转大写输出
    ?length获取字符串长度
    ?starts_with("xx")?string是否以指定字符开头(boolean类型)
    ?ends_with("xx")?string是否以指定字符结尾(boolean类型)
    ?index_of("xx")获取指定字符的索引
    ?trim去除字符串前后空格
    ?replace("xx","xx")替换指定字符串

    字符串空值情况处理:

    FreeMarker 的变量必须赋值,否则就会抛出异常。而对于 FreeMarker 来说,null 值和不存在的变量是完全一样的,因为 FreeMarker 无法理解 null 值。

    <#-- 如果值不存在,直接输出会报错 -->
    <#--${str}-->
    <#-- 使用!,当值不存在时,默认显示空字符串 -->
    ${str!}
    <#-- 使用!"xx",当值不存在时,默认显示指定字符串 --> ${str!"这是一个默认值"}
    <#-- 使用??,判断字符串是否为空;返回布尔类型。如果想要输出,需要将布尔类型转换成字符串 --> ${(str??)?string}

    【SpringBoot】FreeMarker视图渲染,第5张

    注意事项:

    使用??或?starts_with("xx"),判断字符串是否为空或指定字符开头;返回布尔类型。如果想要输出,需要将布尔类型转换成字符串在后面添加 ?c or ?string

    例如:

    ${"嗨害嗨"?starts_with("我")}
    ${str??}

    不进行转换则会报错

    2.2.2 数值

    输入不带引号的数字就可以直接指定一个数字, 必须使用点作为小数的分隔符而不能是其他的分组分隔符。

    ${0.45}
    ${18}
    <#-- 将数值转换成字符串输出 --> ${1000?c}
    <#-- 将数值转换成货币类型的字符串输出 --> ${1000?string.currency}
    <#-- 将数值转换成百分比类型的字符串输出 --> ${0.45?string.percent}
    <#-- 将浮点型数值保留指定小数位输出 (##表示保留两位小数) --> ${0.45723123?string["0.##"]}

    2.2.3 布尔值

    直接写 true 或者 false 就表示一个布尔值了,不需使用引号。

    在freemarker中布尔类型不能直接输出;如果输出要先转成字符串

    ${flag?c}
    ${flag?string}
    ${flag?string("yes","no")}

     

    2.2.4 日期

    日期变量可以存储和日期/时间相关的数据。

    在freemarker中日期类型不能直接输出;如果输出要先转成日期型或字符串

    日期格式输出:

    输出方式说明
    ?date年月日
    ?time时分秒
    ?datetime年月日时分秒
    ?string("自定义格式")指定格式
    <#-- 输出日期格式 -->
    ${createDate?date} 
    <#-- 输出时间格式 --> ${createDate?time}
    <#-- 输出日期时间格式 --> ${createDate?datetime}
    <#-- 输出格式化日期格式 --> ${createDate?string("yyyy年MM月dd日 HH时mm分ss秒")}

    注意事项:

    在.ftl文件中不能直接创建时间需要通过后端传入时间进行显示(替换掉createDate)

    2.3 常见指令  

    2.3.2 assign

    使用该指令你可以创建一个新的变量, 或者替换一个已经存在的变量。

    案例演示:

    <#-- 创建一个str的变量 -->
    <#assign str="hello">
    <#-- 输出str -->
    ${str} 
    <#-- 一次创建多个变量 --> <#assign num=1 names=["嗨","害","嗨"] > ${num} and ${names?join(",")}

    【SpringBoot】FreeMarker视图渲染,第6张

     

    2.3.3 include

    可以使用它在你的模板中插入另外一个 FreeMarker 模板文件 (由 path 参数指定)

    该标签主要用于引入其他资源,简化数据

    首先创建一个公共页面定义一个变量存储本地访问路径

    【SpringBoot】FreeMarker视图渲染,第7张 在index.ftl中进行引入调用src数值

    <#-- 引入公共页面 -->
    <#include "common.ftl">
    

    ...

    还有如:if/elseif/else、list指令在下面的综合案例中进行演示👇

    三、常见指令实现增删改查(综合案例)⭐

    3.1 后端

    BookMapper.xml

        

    在此添加了模糊查询的方法,其他的增删改都是自动生成。

    BookMapper.java

    package com.ycxw.boot.mapper;
    import com.ycxw.boot.entity.Book;
    import org.apache.ibatis.annotations.Param;
    import org.springframework.stereotype.Repository;
    import java.util.List;
    /**
    * @author 云村小威
    * @description 针对表【t_book(书本信息表)】的数据库操作Mapper
    * @createDate 2023-12-12 14:50:45
    * @Entity com.ycxw.boot.entity.Book
    */
    @Repository
    public interface BookMapper {
        List list(@Param("bookname")String bookname);
        ...其他方法
    }
    

    BookService.java

    package com.ycxw.boot.service;
    import com.ycxw.boot.entity.Book;
    import org.apache.ibatis.annotations.Param;
    import java.util.List;
    /**
     * @author 云村小威
     * @create 2023-12-12 15:11
     */
    public interface BookService {
        List list(@Param("bookname")String bookname);
        int insert(Book record);
        int deleteByPrimaryKey(Long id);
        int updateByPrimaryKey(Book record);
    }
    

    BookServiceImpl.java

    package com.ycxw.boot.service.impl;
    import com.ycxw.boot.entity.Book;
    import com.ycxw.boot.mapper.BookMapper;
    import com.ycxw.boot.service.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import java.util.List;
    /**
     * @author 云村小威
     * @create 2023-12-12 15:12
     */
    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        private BookMapper bookMapper;
        @Override
        public List list(String bookname) {
            return bookMapper.list(bookname);
        }
        @Override
        public int insert(Book record) {
            return bookMapper.insert(record);
        }
        @Override
        public int deleteByPrimaryKey(Long id) {
            return bookMapper.deleteByPrimaryKey(id);
        }
        @Override
        public int updateByPrimaryKey(Book record) {
            return bookMapper.updateByPrimaryKey(record);
        }
    }
    

    IndexController.java

    package com.ycxw.boot.controller;
    import com.ycxw.boot.entity.Book;
    import com.ycxw.boot.service.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.*;
    import java.util.List;
    /**
     * @author 云村小威
     * @create 2023-12-13 18:57
     */
    @Controller
    public class IndexController {
        @Autowired
        private BookService bookService;
        /**
         * 查询所有
         *
         * @param model
         * @return
         */
        @RequestMapping("/")
        public String home(Model model) {
            List list = bookService.list(null);
            model.addAttribute("book", list);
            return "index";
        }
        /**
         * 新增
         *
         * @param book
         * @return
         */
        @PostMapping("/add")
        public String add(@RequestBody Book book) {
            bookService.insert(book);
            return "redirect:/";
        }
        /**
         * 删除
         *
         * @param book
         * @return
         */
        @RequestMapping("/del")
        public String del(Book book) {
            bookService.deleteByPrimaryKey(book.getId().longValue());
            return "redirect:/";
        }
        /**
         * 修改
         *
         * @param book
         * @return
         */
        @PutMapping("/edit")
        public String edit(@RequestBody Book book) {
            bookService.updateByPrimaryKey(book);
            return "redirect:/";
        }
        /**
         * 模糊查询
         *
         * @param bookname
         * @param model
         * @return
         */
        @RequestMapping(value = "/search", method = RequestMethod.POST)
        public String search(@RequestParam("bookname") String bookname, Model model) {
            // 在这里使用 bookname 进行相关的处理
            List list = bookService.list(bookname);
            model.addAttribute("book", list);
            return "index"; // 返回搜索结果页面
        }
    }
    

    3.2 前端

    common.ftl (公共资源)

    <#--引入当前项目的运行路径-->
    <#assign src="${springMacroRequestContext.contextPath}">
    <#--引入样式与脚本-->
    
    

    index.ftl(自定义引擎模版)

    
    
    
        
        FreeMarker
        <#--引入公共模块-->
        <#include "common.ftl">
    
    
        
            
                
            
            
                
                
            
        
        
            
                <#if book??>
                    <#list book as b>
                        
    序号 书籍名称 价格 类型 操作
    ${b.id} ${b.bookname} ${b.price} ${b.booktype} 删除 修改
    新增书籍
    修改书籍

    3.3 效果展示

    3.3.1 新增功能

    【SpringBoot】FreeMarker视图渲染,第8张

    3.3.2 修改功能

    【SpringBoot】FreeMarker视图渲染,第9张

    3.3.3 查询功能

    【SpringBoot】FreeMarker视图渲染,第10张

    3.3.4 删除功能

    【SpringBoot】FreeMarker视图渲染,第11张