一、Freemarker引入
二、环境搭建和测试
pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>FMDemo01</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>FMDemo01 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!--加入FreeMarker依赖坐标,FreeMarker模版引擎就是这里提供的(FreemarkerServlet)-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
<!--加入servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>FMDemo01</finalName>
</build>
</project>
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>freemarker</servlet-name>
<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
<init-param>
<!--模版路径-->
<param-name>TemplatePath</param-name>
<!--默认在webapp目录下查找对应的模版文件,我们会将模版文件放在webapp下-->
<param-value>/</param-value>
</init-param>
<init-param>
<!--默认编码格式:UTF-8-->
<param-name>default_encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>freemarker</servlet-name>
<url-pattern>*.ftl</url-pattern>
</servlet-mapping>
</web-app>
freemarker
<#--freemarker注释,隐式注释,浏览器中看不到-->
<!-- html注释 -->
<h2>${msg}</h2>
controller
package com.itheima.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Description:
* date: 2023/7/12 20:51
*
* @since JDK 11
*/
@WebServlet("/fm01")
public class FMServlet01 extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("msg","hello world!");
request.getRequestDispatcher("f01.ftl").forward(request,response);
}
}
三、数据类型
1、布尔型
controller
package com.itheima.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/fm02")
public class FMServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("bool",true);
req.getRequestDispatcher("f02.ftl").forward(req,resp);
}
}
f02.ftl
<#--是错误的,freemarker中不允许输出布尔类型的值,会报错
<h2>${bool}</h2>-->
<h1>布尔类型的转换</h1>
<#--方式一:?c-->
<h2>${bool?c}</h2>
<#--方式二:?string 弃用-->
<h2>${bool?string}</h2>
<#--${bool?string("bool为true时返回这个","bool为false时返回这个")-->
<h2>${bool?string("yes","false")}</h2>
<#--方式三:?then("true时返回这个","false时返回这个")-->
<h2>${bool?then("then_true","then_false")}</h2>
2、日期型

controller
package com.itheima.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/fm02")
public class FMServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//布尔类型
req.setAttribute("bool",true);
//日期类型
req.setAttribute("date",new Date());
req.getRequestDispatcher("f02.ftl").forward(req,resp);
}
}
f02.ftl
<#--freemarker注释,隐式注释,浏览器中看不到-->
<!-- html注释 -->
<#--是错误的,freemarker中不允许输出布尔类型的值,会报错
<h2>${bool}</h2>-->
<h1>布尔类型的转换</h1>
<#--方式一:?c-->
<h2>${bool?c}</h2>
<#--方式二:?string 弃用-->
<h2>${bool?string}</h2>
<#--${bool?string("bool为true时返回这个","bool为false时返回这个")-->
<h2>${bool?string("yes","false")}</h2>
<#--方式三:?then("true时返回这个","false时返回这个")-->
<h2>${bool?then("then_true","then_false")}</h2>
<hr><br/>
<h1>日期类型</h1>
<#--在freemarker中,日期类型也不支持直接输出如果要输出,先转换成日期型或字符串-->
<h3>${date?date}</h3>
<h3>${date?time}</h3>
<h3>${date?datetime}</h3>
<h3>${date?string("yyyy-MM-dd,HH:mm:ss")}</h3>
3、数值类型

package com.itheima.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/fm02")
public class FMServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//布尔类型
req.setAttribute("bool",true);
//日期类型
req.setAttribute("date",new Date());
// 数值类型
req.setAttribute("age",18);
req.setAttribute("salary",16800);
req.setAttribute("double",0.5485);
// 请求转发到模版2
req.getRequestDispatcher("f02.ftl").forward(req,resp);
}
}
<#--freemarker注释,隐式注释,浏览器中看不到-->
<!-- html注释 -->
<#--是错误的,freemarker中不允许输出布尔类型的值,会报错
<h2>${bool}</h2>-->
<h1>布尔类型的转换</h1>
<#--方式一:?c-->
<h2>${bool?c}</h2>
<#--方式二:?string 弃用-->
<h2>${bool?string}</h2>
<#--${bool?string("bool为true时返回这个","bool为false时返回这个")-->
<h2>${bool?string("yes","false")}</h2>
<#--方式三:?then("true时返回这个","false时返回这个")-->
<h2>${bool?then("then_true","then_false")}</h2>
<hr><br/>
<h1>日期类型</h1>
<#--在freemarker中,日期类型也不支持直接输出如果要输出,先转换成日期型或字符串-->
<h3>${date?date}</h3>
<h3>${date?time}</h3>
<h3>${date?datetime}</h3>
<h3>${date?string("yyyy-MM-dd,HH:mm:ss")}</h3>
<hr><br/>
<h1>数值类型,可以直接表示</h1>
${age?c}<br>
${salary?string.currency}<br>
${double?string.percent},自动四舍五入<br>
${double?string["0.##"]},自动四舍五入<br>
4、字符串类型

<h1>字符串类型的展示</h1>
<h4>${str1?substring(1,3)}截取字符串,左闭右开</h4>
<h4>${str1?uncap_first}首字符小写</h4>
<h4>${str1?cap_first}首字符大写</h4>
<h4>${str1?lower_case}全部小写</h4>
<h4>${str1?substring(1,3)}</h4>
<h4>${str1?upper_case}全部大写</h4>
package com.itheima.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/fm02")
public class FMServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//布尔类型
req.setAttribute("bool",true);
//日期类型
req.setAttribute("date",new Date());
// 数值类型
req.setAttribute("age",18);
req.setAttribute("salary",16800);
req.setAttribute("double",0.5485);
// 字符串类型的展示
req.setAttribute("str1","WWW.ee");
// 请求转发到模版2
req.getRequestDispatcher("f02.ftl").forward(req,resp);
}
}
5、字符串空值类型的处理

package com.itheima.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/fm02")
public class FMServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 空字符串的处理
req.setAttribute("a",null);
req.setAttribute("b","");
// 请求转发到模版2
req.getRequestDispatcher("f02.ftl").forward(req,resp);
}
}
<#--freemarker注释,隐式注释,浏览器中看不到-->
<!-- html注释 -->
<#--是错误的,freemarker中不允许输出布尔类型的值,会报错
<h2>${bool}</h2>-->
<h1>布尔类型的转换</h1>
<#--方式一:?c-->
<h2>${bool?c}</h2>
<#--方式二:?string 弃用-->
<h2>${bool?string}</h2>
<#--${bool?string("bool为true时返回这个","bool为false时返回这个")-->
<h2>${bool?string("yes","false")}</h2>
<#--方式三:?then("true时返回这个","false时返回这个")-->
<h2>${bool?then("then_true","then_false")}</h2>
<hr><br/>
<h1>日期类型</h1>
<#--在freemarker中,日期类型也不支持直接输出如果要输出,先转换成日期型或字符串-->
<h3>${date?date}</h3>
<h3>${date?time}</h3>
<h3>${date?datetime}</h3>
<h3>${date?string("yyyy-MM-dd,HH:mm:ss")}</h3>
<hr><br/>
<h1>数值类型,可以直接表示</h1>
${age?c}<br>
${salary?string.currency}<br>
${double?string.percent},自动四舍五入<br>
${double?string["0.##"]},自动四舍五入<br>
<hr><br/>
<h1>字符串类型的展示</h1>
<h4>${str1?substring(1,3)}截取字符串,左闭右开</h4>
<h4>${str1?uncap_first}首字符小写</h4>
<h4>${str1?cap_first}首字符大写</h4>
<h4>${str1?lower_case}全部小写</h4>
<h4>${str1?substring(1,3)}</h4>
<h4>${str1?upper_case}全部大写</h4>
<hr><br/>
<h1>空值情况的处理:</h1>
<h2>freemarker中对null和未定义的变量输出时都会报错,但是对空字符串不会报错</h2>
${a!}<br>
${b}<br>
${c!}<br>
${c???c} ?c转为字符串类型
6、序列类型
package com.itheima.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/fm02")
public class FMServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 存储数组在request作用域中
String[] arr = new String[]{"alili","clili","blili","dlili"};
req.setAttribute("arr",arr);
// 请求转发到模版2
req.getRequestDispatcher("f02.ftl").forward(req,resp);
}
}
存储集合
package com.itheima.controller;
import com.itheima.pojo.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/fm02")
public class FMServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 存储数组在request作用域中
String[] arr = new String[]{"alili","clili","blili","dlili"};
req.setAttribute("arr",arr);
// 存储map在request作用域中
User user1 = new User("xx1",18);
User user2 = new User("xx2",20);
User user3 = new User("xx3",22);
List<User> list = Arrays.asList(user1,user2,user3);
req.setAttribute("list",list);
// 请求转发到模版2
req.getRequestDispatcher("f02.ftl").forward(req,resp);
}
}
<hr><br>
<h1>序列类型</h1>
<#list arr as el>
${el}----${el?index}<br>
</#list>
<hr>
获取数组的大小:${arr?size}<br/><hr>
获取数组的第一个元素:${arr?first}<br/><hr>
获取数组的最后一个元素:${arr?last}<br/><hr>
使数组反转输出<br>
<#list arr?reverse as el>
${el}----${el?index}<br>
</#list>
<hr>
使数组升序输出<br>
<#list arr?sort as el>
${el}----${el?index}<br/>
</#list>
<hr>
使数组降序输出<br>
<#list arr?sort?reverse as el>
${el}----${el?index}<br/>
</#list>
<hr><br>
<h1>存储集合</h1>
<#list list as el>
${el.name} and ${el.age}<br>
</#list>

7、***hash类型->map重点
package com.itheima.controller;
import com.itheima.pojo.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/fm02")
public class FMServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 存储map在request作用域中
Map<String,String> city = new HashMap<String, String>();
city.put("beijing","北京");
city.put("shanghai","上海");
city.put("jinan","济南");
req.setAttribute("city",city);
// 请求转发到模版2
req.getRequestDispatcher("f02.ftl").forward(req,resp);
}
}
<hr><br/>
<h1>map</h1>
<h2>map循环</h2>
<#list city?keys as key>
${key}----${city[key]}----${key_index}--
<#--key_index返回索引坐标-->
<#--key_has_next 返回布尔值,判断是否还有下一个元素-->
<#if key_has_next>
还有下一个---hello
</#if>
<br>
</#list>
<hr>
<#list city?values as v>
${v}<br/>
</#list>
<h2>可以直接对map进行value的输出</h2>
${city["beijing"]!"xx"}<br>
${city["jinan"]!"xx"}<br>
${city["1234"]!"xx"}<br>

四、freemarker常见指令
1、定义变量
<#--定义变量-->
<#assign name="xxx" age=12 array=[1,"xxx"]>
${name} and ${age}<br>
${array[0]}<br>
${array[1]}<br>
<h2>对array进行拼接</h2>
${array?join("___")}
package com.itheima.controller;
import com.itheima.pojo.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/fm03")
public class FMServlet03 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//定义变量
req.getRequestDispatcher("f03.ftl").forward(req,resp);
}
}

2、***ifelse



3、list指令

五、模版复用
后端
package com.itheima.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/index1")
public class FMServlet04 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Map<String,String> city = new HashMap<String, String>();
city.put("0","北京");
city.put("1","上海");
city.put("2","济南");
req.setAttribute("map",city);
req.getRequestDispatcher("index.ftl").forward(req,resp);
}
}
前端
1、共用select、option
index.ftl
<#import "optionmodel.ftl" as op>
<@op.optionfun map></@op.optionfun>
optionmodel.ftl
<#macro optionfun map>
<select>
<#list map?keys as key>
<option value="${key}">${map[key]}</option>
</#list>
</select>
</#macro>
六、小笔记
package com.itheima.controller;
import com.itheima.pojo.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Description:
* date: 2023/7/12 21:08
*
* @since JDK 11
*/
@WebServlet("/index1")
public class FMServlet04 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User user1 = new User();
user1.setFlag(true);
User user2 = new User();
user2.setFlag(false);
User user3 = new User();
user3.setFlag(true);
User user4 = new User();
// 添加list集合
List<User> users = Arrays.asList(user1,user2,user3,user4);
req.setAttribute("users",users);
User user5 = new User("xiaoshiguang",11,false);
req.setAttribute("obj",user5);
System.out.println(req.getParameter("save").getClass()+"---------");
String flag = req.getParameter("save");
User user6 = new User();
user6.setFlag(Boolean.valueOf(flag));
System.out.println(user6.getFlag());
req.getRequestDispatcher("index.ftl").forward(req,resp);
}
}
<#import "optionmodel.ftl" as op>
<@op.optionfun map></@op.optionfun>
${bool?then("hello","false")}
<hr>
<#list users as user>
<#if user.flag??>true</#if>
<br>
</#list>
<br><br>
<hr>
<#list users as user>
<#if user.flag?has_content>
<#if user.flag == true>
hello<br>
</#if>
</#if>
</#list>
<br><br>
<hr>
<#--判断true或false最好的还是这个方法-->
<#list users as user>
<#if user.flag??>
${user.flag?then("true","false")}
</#if>
</#list>
<hr>
${obj.name!}
<br><br><br>
<#--只设置一个复选框,设置选择为true,不选中为false,value为true的一定要放在第一个-->
<form action="http://localhost:8080/index1">
<input type="checkbox" name="save" value="true">1
<input type="hidden" name="save" value="false">
<input type="submit">
</form>
freemarker—Jersey—jQuery
循环,去除a标签的href换为自定义function,click事件
MyTest.java
package com.itheima.controller;
import org.glassfish.jersey.server.mvc.Viewable;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Path("/hello")
public class MyTest {
@GET
@Path("/redirect")
@Produces(MediaType.TEXT_HTML)
public Response redirectToFreemarker() {
Map<String, Object> model = new HashMap<>();
List<String> strings = new ArrayList<>();
strings.add("Hello from Jersey!");
strings.add("John Doe");
strings.add("nihao");
model.put("data", strings);
model.put("flag", true);
Viewable viewable = new Viewable("/index.ftl",model); // 指定 Freemarker 模板路径
return Response.ok(viewable).build();
}
}
index.ftl
<!DOCTYPE html>
<html>
<head>
<title>Jersey to Freemarker</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
</body>
</html>
<hr>
<#list data as key>
<a class="clearhref" href="https://www.baidu.com">${key}</a>
<#if key_has_next><br></#if>
</#list>
<script type="text/javascript">
$(function (){
$('.clearhref').click(function (event){
event.preventDefault();
if(${flag!?c} === false){
//自定义函数
myfun();
} else {
// 执行原始的跳转
window.location.href = $(this).attr('href');
}
})
function myfun(){
alert("hello");
}
})
</script>
