一、FreeMarker介绍
1.什么是FreeMarker?
FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
模板编写为FreeMarker Template Language (FTL)。它是简单的,专用的语言, 不是 像PHP那样成熟的编程语言。 那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。
二、SpringBoot整合FreeMaker
1.方式一:可以在创建时直接勾选添加
2.方式二:自行添加
2.1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
2.2 配置
我们在属性文件中设置视图解析器的前后缀,可以使在控制器的显示里方便点
spring.freemarker.suffix=.ftl
2.3 创建FreeMaker文件
然后我们在系统的模板文件中创建FreeMaker文件,注意改文件为一个后缀为 .ftl 的文件
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Hello FreeMaker...</h1>
</body>
</html>
2.4 控制器
因为在 template 目录下的文件是没法直接访问的,而且我们也需要现在服务端获取数据绑定数据后再在页面模板文件中呈现,所以请求先到控制器,然后通过模板引擎解析模板文件生成具体的HTML页面响应客户
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/query")
public String query(){
System.out.println("query....");
return "user";
}
}
2.5 测试
三、FreeMaker的基本使用
接下来介绍如何在FreeMaker中绑定数据
1.单个数据
我们在Model中绑定的是单个数据,怎么在ftl文件中绑定呢?
/**
* 基本数据类型
* 自定义数据类型
* 数据容器
* @return
*/
@RequestMapping("/query")
public String query(Model model){
System.out.println("query....");
model.addAttribute("username","biao");
model.addAttribute("age",18);
model.addAttribute("address","广东广州");
model.addAttribute("flag",true);
model.addAttribute("birth",new Date());
return "user";
}
字符串和数字类型我们可以通过EL表达式直接取出来
Boolean不能直接转换为string类型
报错代码
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Hello FreeMaker...</h1>
${username}<br>
${age}<br>
${address}<br>
${flag}<br>
</body>
</html>
这时候我们要通过 内部的转换函数 来处理
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Hello FreeMaker...</h1>
${username}<br>
${age}<br>
${address}<br>
${flag?string("真","假")}<br>
</body>
</html>
时间类型我们也需要去转换
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Hello FreeMaker...</h1>
${username}<br>
${age}<br>
${address}<br>
${flag?string("真","假")}<br>
${birth?string("yyyy-MM-dd")}<br>
</body>
</html>
2.单个数据处理
我们服务端绑定的单个数据,比如字符串或者数字,我们可能需要对这些数据做出调整,比如数字要四舍五入,字符串我们需要截取等操作。
2.1数字处理
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<#-- 注释符 -->
<#assign x=3.1415>
<#assign y=6>
<!--
mN:小数部分最小N位
MN:小数部分最大N位
-->
x=${x}<br>
y=${y}<br>
#{x;M2}<br><!-- 3.14 -->
#{x;m2}<br><!-- 3.14 -->
#{y;M2}<br><!-- 6 -->
#{y;m2}<br><!-- 6.00 -->
</body>
</html>
2.2 字符串处理
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<hr>
<#assign hello="hello freemarker">
<#-- 字符串拼接 -->
HELLO-${hello}<br>
<#-- EL表达式中的常量表示 -->
${'HELLO+'+hello}<br>
<#-- 常量中使用数据 -->
${'HELLO*${hello}'}<br>
${username}----${hello}<br>
${username+'-->' +hello}<br>
</body>
</html>
结果
2.3字符串截取
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
${hello}<br>
<!--截取1下标-->
${hello[1]}<br>
<!--截取4下标-->
${hello[4]}<br>
<!--截取1到6-->
${hello[1..6]}<br>
<!--截取3后面-->
${hello[3..]}<br>
</body>
</html>
结果
3.自定义对象
控制器
@RequestMapping("/query1")
public String query1(Model model){
User user = new User(666,"admin","123456");
model.addAttribute("user",user);
return "user1";
}
ftl文件
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<#-- 自定义对象 -->
${user.id}<br>
${user.userName}<br>
${user['userName']}<br>
${user.password}<br>
</body>
</html>
结果
4.Map集合与List集合
控制器
@RequestMapping("/query1")
public String query1(Model model){
User user = new User(666,"admin","123456");
model.addAttribute("user",user);
Map<String,Object> map = new HashMap<>();
map.put("user",user);
List list = Arrays.asList("张三","李四","王五");
List list1 = Arrays.asList("111","222","333");
model.addAttribute("map",map);
model.addAttribute("list",list);
model.addAttribute("list1",list1);
return "user1";
}
ftl文件
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Map集合</h1><br>
${map.user.id}<br>
${map['user'].userName}<br>
${map['user']['password']}<br>
<hr>
<h1>list集合</h1>
<#--循环输出-->
<#list list as obj>
${obj}<br>
</#list>
<hr>
<#--联合输出-->
<#list list+list1 as obj>
${obj}<br>
</#list>
</body>
</html>
结果
5.算数运算符
运算符名 | 符号 |
---|---|
加法 | + |
减法 | - |
乘法 | * |
除法 | / |
求模(求余) | % |
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<h1>算数运算符:</h1>
${99+100*30}<br>
${99/7}<br>
<#--数据转换-->
${(99/7)?int}<br>
${55%3}<br>
<hr>
</html>
6.比较运算符
比较运算符 | 替代 |
---|---|
== | == |
!= | != |
>= | gte |
> | gt |
< | lt |
<= | lte |
7.逻辑操作
逻辑 或: ||
逻辑 与: &&
逻辑 非: !
逻辑操作符仅仅在布尔值之间有效,若用在其他类型将会产生错误导致模板执行中止
8.内置函数
内建函数就像FreeMarker在对象中添加的方法一样。 要防止和实际方法和其它子变量的命名冲突,则不能使用点 (.),这里使用问号 (?)来和父对象分隔开。 比如,想要保证 path 有起始的 / ,那么可以这么来写: path?ensure_starts_with(’/’)。 path 后的Java对象(通常就是String) 并没有这样的方法,这是FreeMarker添加的。为了简洁,如果方法没有参数, 那么就可以忽略 (),比如想要获取 path 的长度,就可以写作:path?length, 而不是 path?length()
常用内置函数
内置函数 | 说明 |
---|---|
html | 显示标签内容,浏览器不渲染 |
cap_first | 首字母大写 |
upper_case | 转大写 |
lower_case | 转小写 |
size | 集合和数组的元素个数 |
date | 仅日期部分,没有一天当中的时间部分 |
time | 仅一天当中的时间部分,没有日期部分 |
datetime | 日期和时间都在 |
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<h1>内建函数:</h1>
<#assign hello="hello FreeMarker">
<#assign page="<span style='color:red'>HELLO</span>">
${hello}<br>
${page}<br>
${page?html}<br>
${hello?upper_case}<br>
${now?date}<br>
${now?datetime}<br>
${now?time}<br>
</body>
</html>
9.分支与循环
if语句,switch语句以及循环语句,基本的语法格式和我们在Java中使用的是一样的。我们只需要注意下具体的使用格式
<html>
<head>
<title>FreeMaker</title>
<meta charset="UTF-8">
</head>
<body>
<#assign age = 18>
<#if age == 18>
等于18
<#elseif age gt 18>
大于18
<#else >
小于18
</#if>
<br>
null值的判断:
<#-- ?? 检测值是否存在 -->
<#assign mypage="a">
<#if mypage??>
mypage存在
<#else >
mypage不存在
</#if>
<br>
<#--switch语句-->
<#assign i=3>
<#switch i>
<#case 1>
ok
<#break >
<#case 2>
ok2
<#break >
<#case 3>
ok3
<#break >
<#default >
ok4
</#switch>
<br>
<#--循环的使用-->
<#list list as obj>
<#if obj='李四'>
<#break >
</#if>
${obj}<br>
</#list>
<#-- !的使用 -->
<#assign aaa="555">
<#--如果aaa存在就显示aaa本来的值,如果aaa不存在就显示666-->
${aaa!"666"}
</body>
</html>
结果
四、综合案例
主要介绍SpringBoot整合MyBatis,同时结合FreeMaker展现数据
1.创建项目
导入Web和Template
2.添加相关依赖
<!-- 整合mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<!-- 添加mysql的依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 添加连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
3.添加相关的配置文件
application.properties
server.port=8082
# 配置JDBC的相关信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/logistics?characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
# 配置连接池
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 配置MyBatis的package设置 别名
mybatis.type-aliases-package=com.biao.pojo
4.创建实体对象
package com.biao.pojo;
public class User {
private String user_id ;
private String user_name ;
private String real_name ;
private String password ;
private String email ;
private String phone ;
private String u1 ;
private String u2 ;
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getReal_name() {
return real_name;
}
public void setReal_name(String real_name) {
this.real_name = real_name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getU1() {
return u1;
}
public void setU1(String u1) {
this.u1 = u1;
}
public String getU2() {
return u2;
}
public void setU2(String u2) {
this.u2 = u2;
}
}
5.查询用户信息
5.1 创建接口
package com.biao.mapper;
import com.biao.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> query();
}
5.2 创建映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.biao.mapper.UserMapper">
<select id="query" resultType="user">
select * from t_user
</select>
</mapper>
5.3 属性文件中添加Mapper映射文件的路径
5.4 创建Service
5.4.1 创建接口
package com.biao.service;
import com.biao.pojo.User;
import java.util.List;
public interface IUserService {
List<User> query();
}
5.4.2 创建实现
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper mapper;
@Override
public List<User> query() {
return mapper.query();
}
}
5.5 创建Controller
package com.biao.controller;
import com.biao.pojo.User;
import com.biao.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService service;
public String query(Model model){
List<User> list = service.query();
model.addAttribute("list",list);
return "/user";
}
}
5.6 属性文件中配置FreeMaker的后缀
5.7 创建FreeMaker模板文件,并且展示数据
user.ftl
<html>
<head>
<title>用户管理</title>
<meta charset="UTF-8">
</head>
<body>
<h1>用户管理</h1>
<table>
<tr>
<th>编号</th>
<th>账号</th>
<th>姓名</th>
<th>邮箱</th>
<th>电话</th>
<th>操作</th>
</tr>
<#list list as user>
<tr>
<td>${user.user_id}</td>
<td>${user.user_name}</td>
<td>${user.real_name!""}</td>
<td>${user.email!""}</td>
<td>${user.phone!""}</td>
<td>...</td>
</tr>
</#list>
</table>
</body>
</html>
5.8 测试
6.添加用户
6.1 FreeMaker文件
<html>
<head>
<title>用户管理</title>
<meta charset="UTF-8">
</head>
<body>
<h1>用户管理</h1>
<form action="/user/userUpdate" method="post">
<label>账号</label><input type="text" name="user_name"><br>
<label>姓名</label><input type="text" name="real_name"><br>
<label>邮箱</label><input type="text" name="email"><br>
<label>电话</label><input type="text" name="phone"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
6.2 Controller
@RequestMapping("/dispatchUpdate")
public String dispatchUpdate(Model model){
return "/userUpdate";
}
@RequestMapping("/userUpdate")
public String update(User user){
service.insertUser(user);
return "redirect:/user/query";
}
6.3 Service
@Override
public Integer insertUser(User user) {
return mapper.insertUser(user);
}
6.4 UserMapper
6.4.1 Mapper接口
public interface UserMapper {
List<User> query();
Integer insertUser(User user);
}
6.4.2 Mapper映射文件
<insert id="insertUser" parameterType="user">
insert into
t_user(user_name,real_name,email,phone)
values(#{user_name},#{real_name},#{email},#{phone})
</insert>
7.更新用户
7.1 更新链接
7.2 Controller
@RequestMapping("/userUpdate")
public String update(User user){
if (user.getUser_id() != null){
// 更新数据
service.updateUser(user);
}else{
service.insertUser(user);
}
return "redirect:/user/query";
}
@RequestMapping("/deleteUser")
public String deleteUser(Integer id){
service.deleteUser(id);
return "redirect:/user/query";
}
7.3 UserMapper.xml
<select id="queryUserById" resultType="User">
select * from t_user where user_id = #{id}
</select>
<update id="updateUser" parameterType="User">
update t_user set user_name = #{user_name}
,real_name=#{real_name}
,email=#{email}
,phone=#{phone}
where user_id = #{user_id}
</update>
8.删除用户
8.1 链接跳转
8.2 Controller
@RequestMapping("/deleteUser")
public String deleteUser(Integer id){
service.deleteUser(id);
return "redirect:/user/query";
}
8.3 UserMapper.xml
<delete id="deleteUser">
delete from t_user where user_id = #{id}
</delete>