简介
FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件
官网手册:链接
JavaEE中的两种开发方式
前后端不分离
要求程序员要掌握js,为了简化页面开发,引入页面模板,页面模板整体上来说又可以分为两大类
前端模板
前端模板就是后缀为html的模板,代表就是Thymeleaf,这种模板有一个好处就是不需要服务端解析就能直接在浏览器中打开。
后端模板
必须经过服务端解析才能被浏览器展示出来的模板
- JSP
- Freemarker
- velocity
前后端分离
前后端分离的时候,后端纯粹只是接口,没有任何页面。所有的页面由前端完成,前端会使用相关的模板。
- Vue
- AngularJS
- React
HelloWorld案例
创建一个maven项目
整合spring和SpringMVC
Spring整合SpringMVC:链接
引入freemarker
1.引入freemarker依赖
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<!-- freemarker中必须依赖spring-context-support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.21.RELEASE</version>
</dependency>
2.配置视图解析器
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 开启注解 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 开启扫描 -->
<context:component-scan base-package="com.i.controller">
<!-- 只扫描指定路径下的controller注解 -->
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- 配置freemarker -->
<!-- 1.引入freemarker属性文件 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- <property name="locations">
<list>
<value>classpath:freemarker-var.properties</value>
</list>
</property> -->
</bean>
<!-- 2.定义模板属性 -->
<bean
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<!-- 定义模板位置 -->
<property name="templateLoaderPath" value="/WEB-INF/ftl/" />
<!-- 编码方式 -->
<property name="defaultEncoding" value="utf-8" />
<!-- 设置键值对 -->
<!-- <property name="freemarkerVariables">
<map>
<entry key="root" value="${root}"></entry>
</map>
</property> -->
<!--设置属性值 -->
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">10</prop>
<prop key="locale">zh_CN</prop>
<prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
<prop key="date_format">yyyy-MM-dd</prop>
<prop key="time_format">HH:mm:ss</prop>
<prop key="number_format">#.####</prop>
</props>
</property>
</bean>
<!-- 3.配置视图解析器 -->
<bean
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<!-- 生成view的类 -->
<property name="viewClass"
value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
<!-- 配置后缀 -->
<property name="suffix" value=".ftl" />
<!-- 支持request覆盖model -->
<property name="allowRequestOverride" value="true" />
<property name="allowSessionOverride" value="true" />
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<property name="contentType" value="text/html;charset=utf-8" />
</bean>
</beans>
3.测试
在WEB-INF下创建 hello.ftl
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190906153226442.png
controller跳转到index.ftl页面
@Controller
public class UserController {
@RequestMapping("/hello")
public String hello(Model m){
return "/hello";
}
}
插值规则
通用插值
字符串,数字,Boolean型,Date类型
@Controller
public class UserController {
@RequestMapping("/hello")
public String hello(Model m){
m.addAttribute("name","张三");
m.addAttribute("age",18);
m.addAttribute("flag",true);
m.addAttribute("birth",new Date());
return "/hello";
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>hello giao....</h1>
<h2>name:${name}</h2>
<h2>age:${age}</h2>
<!-- 转换规则 通过内置的函数对Boolean变量做转换 -->
<h2>flag:${flag?string("true","false")}</h2>
<h2>birth:${birth?string("yyyy-MM-dd")}</h2>
</body>
</html>
显示结果:
数字格式化插入
数字格式化插值可采用#{expr;format}形式来格式化数字,其中format可以是:
mX:小数部分最小X位
MX:小数部分最大X位
<h1>数字格式化:</h1>
<!-- 声明变量 -->
<#assign x=2.456>
<#assign y=99>
#{x;m2}<br>
#{x;M2}<br>
#{y;m2}<br>
#{y;M2}<br>
显示结果:
eclipse安装Freemarker插件
增加代码提示
表达式
直接指定值
直接显示字符串
显示集合
<!-- 字符串 -->
${'hello freemark!'}<br>
<!-- 集合 -->
List:<br>
<#list ["aa","bb","cc"] as c> <!-- 循环取出,赋值给c -->
${c}<br>
</#list>
输出变量
集合
@RequestMapping("/hello3")
public String hello3(Model m){
m.addAttribute("list",Arrays.asList("1","2","3"));
return "/hello3";
}
<h1>输出变量..</h1>
<#list list as i>
${i}<br>
</#list>
显示结果:
Map
@RequestMapping("/hello3")
public String hello3(Model m){
HashMap<Object, Object> map = new HashMap<>();
map.put("id", 1);
map.put("name", "i");
map.put("address", "深圳");
map.put("users", new User(1,"张三",18));
m.addAttribute("user",map);
return "/hello3";
}
<!-- 两种写法 -->
${user.id}<br>
${user['name']}<br>
${user.address}<br>
${user.users}<br>
${user['users'].id}<br>
${user['users']['name']}<br>
显示结果:
字符串操作
1.字符串拼接
m.addAttribute("hello"," freemarker");
<#-- 字符串拼接 -->
<#-- 1.直接拼接 -->
hello${hello}<br>
<#-- 2. + -->
${"hello"+hello}<br>
<#-- 3. ""中通过${}取值 -->
${"hello${hello}"}<br>
显示结果:
字符串截取
<#-- 字符串截取 -->
${hello}<br>
${hello[1]}<br>
${hello[3]}<br>
${hello[1..3]}<br>
${hello[2..4]}<br>
${hello[4..5]}<br>
${hello[2..]}<br>
显示结果:
集合连接
提前定义两个集合,在遍历时做集合的拼接运算
@RequestMapping("/hello3")
public String hello3(Model m){
m.addAttribute("list",Arrays.asList("1","2","3"));
m.addAttribute("list2",Arrays.asList("6","7","8"));
return "/hello3";
}
<#list list+list2 as l>
${l}<br>
</#list>
显示结果:
算数运算
算数运算包含基本的四则运算和求模运算,运算符有:
加法: +
减法: -
乘法: *
除法: /
求模 (求余): %
${100 - 1 * 3}
${6 / 3}
${10 % 2}
显示结果:
结果转换为整数
<#assign x=5>
${(x/2)?int}<br>
${1.4?int}<br>
${1.5999?int}<br>
${-1.9?int}<br>
${-1.9999?int}<br>
显示结果:
比较运算符
比较运算符 | 替代 |
---|---|
== | == |
!= | != |
>= | gte |
> | gt |
< | lt |
<= | lte |
逻辑操作
常用的逻辑操作符:
与: &&
或: ||
非: !
逻辑操作符仅仅在布尔值之间有效,若用在其他类型将会产生错误导致模板执行中止
内置函数
内建函数就像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 | 日期和时间都在 |
@RequestMapping("/hello4")
public String hello4(Model m){
m.addAttribute("hello"," freemarker");
m.addAttribute("mypage"," <h1> hello freemarker </h1>");
m.addAttribute("now",new Date());
m.addAttribute("list",Arrays.asList("1","2","3"));
return "/hello4";
}
${mypage}<br>
${mypage?html}<br>
${hello?upper_case}<br>
${hello?lower_case}<br>
${hello?cap_first}<br>
${list?size}<br>
<hr>
<#assign x=now>
${x?date}<br>
${x?time}<br>
${x?datetime}<br>
显示结果:
常用指令
if
和java中的用法一样
<#-- 定义变量 -->
<#assign i=123>
<#if i==1234>
1
<#elseif i gt 12>
2
<#else>
0
</#if>
switch
和java中的switch语句一样
<#assign i=123>
<#switch i>
<#case 12>
1
<#break>
<#case 123>
2
<#break>
<#default>
</#switch>
list+break
跳出循环的用法
<#list list as i>
<#if i=="2">
<#break><#--终止循环-->
<#else>
${i}<br>
</#if>
</#list>
空值处理
处理不存在的值
!的使用
<#-- 如果a为空就显示 123 否则显示a对应的值 -->
${a!"123"}<br>
${hello!"123"}<br>
显示结果:
??的使用
不存在值检测操作符,这个操作符告诉我们一个值是否存在。
基于这种情况, 结果是 true 或 false, ??判断变量是否为空
<#if hello??>
1
<#else>
0
</#if>
<#if aaa??>
1
<#else>
0
</#if>
显示结果为: 1 0