FreeMarker学习笔记
文章目录
⼀、概述
FreeMarker是⼀款模板引擎:即⼀种基于模板和要改变的数据,并⽤来⽣成输出⽂本(HTML⽹⻚,电⼦邮件,配置⽂件,源代码等)的通⽤⼯具。它不是⾯向最终⽤户的,⽽是⼀个Java类库,是⼀款程序员可以嵌⼊他们所开发产品的组件。
模板编写为 FTL (FreeMarker Template Language)。
设计思想:模板 + 数据 —> ⽂本输出
官网:https://freemarker.apache.org/
FreeMarker可以用于实现页面静态化。
页面静态化:即将页面的内容以静态文件的方式进行展示输出。
静态页面(如:.html,.js,.css文件);直接响应给浏览器
动态页面:(如:.jsp文件)。运行机制:.jsp–>.java–>.class—>响应浏览器
静态页面的访问速度最快。
⼆、第⼀个Freemarker程序
Maven依赖jar
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
创建模板
创建一个FreeMarker的模板index.ftl(后缀名也可以是.html,官方推荐.ftl后缀)
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<h1>您好:${name}</h1>
</body>
</html>
注:${name} 是freemarker的取值表达式
准备数据 并根据模板⽣成静态⻚
package com.demo.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 FreemarkerTest {
public static void main(String[] args) throws IOException, TemplateException {
// 1. 准备数据
Map<String,Object> dataMap = new HashMap<String, Object>();
dataMap.put("name","张三");
// 2. 设置Freemarker的版本
Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
// 3. 设置模板目录
configuration.setDirectoryForTemplateLoading(new File("E:\\Java\\3_Framework\\ideaCode\\freemarker_demo\\src\\main\\webapp\\WEB-INF\\template"));
// 4. 设置编码方式
configuration.setDefaultEncoding("UTF-8");
// 5. 读取模板
Template template = configuration.getTemplate("index.ftl");
// 6. 输出静态页面
template.process(dataMap,new FileWriter("E:\\index.html"));
}
}
三、FTL语法
1. 语法类型
- Interpolation 插值 ${ key名 }
- FTL tags 标签 <# 标签名></#标签名>
- Comments 注释 <#-- 注释内容 —> ; Freemarker的注释不会显示在生成的源文件中,而jsp的注释会显示在源代码中。
- <@>:宏(略),⾃定义标签
2. 具体示例
1. 取值
# =========================================================
Map<String,Object> dataMap = new HashMap<String, Object>();
# =========================================================
# ---------- 普通类型 ------------
<h1>您好:${name}</h1>
# ------------------------------------
// 数据封装
dataMap.put("name","张三");
# -------------- 对象类型 -------------
<h1>您好:${user.name}</h1>
# ------------------------------------
// 对象类型 数据封装
User user = new User();
user.setId(1);
user.setName("⼩红");
dataMap.put("user",user);
# ------------ 数字类型 ---------------
# ------------------------------------
# assign ⽤以声明当前模板临时变量
<#assign answer=42>
# --------------取值--------------------
# 与 ${answer} 作用相同,获取字符串类型
${answer?string}
# 获取数字类型
${answer?string.number}
# 获取货币类型:¥ 23
${answer?string.currency}
# 获取百分制类型: 25%
${answer?string.percent}
# ------------------------------------
# ------ ⽇期类型 ------
# 获取日期:2012-09-09
${date?date}
# 获取时间:11:12:12
${date?time}
# 获取日期与时间:2012-09-09 11:12:12
${date?datetime}
# ------------------------------------
# ⾃定义⽇期格式
${date?string("yyyy年MM⽉dd⽇")}
或
${date?string("yyyy年MM⽉dd⽇ hh:mm:dd")}
# ------------------------------------
# -------------- 布尔值处理 --------------
# 获取字面值(实际值 true | false)b:表示key;c:表示value字面值
${b?c}
# 根据boolean值获取值:值为true时表达式值为yes;值为false时表达式值为no
${b?string('yes', 'no')}
# ----------------------------------------
2. list | set | 数组
# =================== 语法 ===================
<#list 集合名 as 别名>
${别名}
</#list>
# ============================================
// 集合类型数据
ArrayList<String> list = new ArrayList<String>();
list.add("apple");
list.add("banana");
list.add("orange");
dataMap.put("fruit",list);
3. map集合
# =================== 语法 ===================
<#list map?keys as 别名>
key:${别名} ---> value: ${map[别名]}
<br>
</#list>
# ============================================
// map集合
Map<String,Object> map = new HashMap<String,Object>();
map.put("beijing","北京");
map.put("天津","天津");
dataMap.put("map",map);
4. 分支语句 if-elseif-else
<#if 条件>
// true内容
<#elseif 条件>
//elseif true内容
<#else>
// false内容
</#if>
5. 空值处理
Freemarker不允许value出现空值,若有空值则必须进行处理
# ==========方式一:通过设置默认值,当为空值时,显示默认值==============
${ key名 ! "默认值"}
# ==========方式二:通过 if 分支语句进行判断==============
<#if key名??>
值存在
<#else>
不存在
</#if>
6. 包含页面,导⼊ftl或者html⻚⾯
# =============== 语法 ===============
<#include“TemplateFiles/example.ftl”>
# =============== 例子 ===============
<#include "test.html">
# =============== test.html ===============
<center> © www.baybay.com </center>
7. 自定义标签—宏
# ============= 声明一个标签 =================
<#macro demo>
Hello Freemarker
</#macro>
# ============ 使用自定义标签 =================
<@demo></@demo>
深入学习可查看官网
四、Freemarker与SpringMVC集成
1. 创建springmvc项目,并导入依赖jar
<!-- freemarker的依赖jar -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
2. 编写web.xml文件
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- spring工厂全局加载 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-core.xml</param-value>
</context-param>
<!-- springmvc核心serlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置编码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3. 编写springMVC配置文件spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 开启控制器注解扫描 -->
<context:component-scan base-package="com.demo.controller"></context:component-scan>
<!-- 开启springmvc注解扫描驱动 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 过滤静态资源,静态资源不做处理 -->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!-- 定义基于freemarker的试图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".ftl"></property>
<property name="contentType" value="text/html;charset=UTF-8"></property>
</bean>
<!-- 指定freemarker的配置对象 -->
<bean id="configurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 指定模板的加载目录 -->
<property name="templateLoaderPath" value="WEB-INF/templates/"></property>
</bean>
</beans>
4. 创建index.ftl
在/WEB-INF/templates/目录下创建index.ftl文件
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>您好:${name}</h1>
</body>
</html>
5. 创建controller
package com.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class FreeMarkerController {
// produces = "application/json;charset=UTF-8" 设置编码方式
@RequestMapping(value = "/hello",produces = "application/json;charset=UTF-8")
public ModelAndView hello(ModelAndView modelAndView){
modelAndView.setViewName("index");
modelAndView.addObject("name","张三");
return modelAndView;
}
}
6. 测试
五、Freemarker与Spring Boot集成
1. 创建springboot项目,引入依赖jar
<?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 http://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.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>freemarker_springboot_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>freemarker_springboot_demo</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>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. 配置application.properties文件
server.port=8585
spring.freemarker.prefix=/
spring.freemarker.suffix=.ftl
3. 准备模板index.ftl
index.ftl可放在src\main\resources\templates目录下
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>您好:${name}</h1>
</body>
</html>
4. 编写controller
package com.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class FreeMarkerController {
@RequestMapping(value = "/hello",produces = "application/json;charset=UTF-8")
public ModelAndView hello(ModelAndView modelAndView){
modelAndView.setViewName("index");
modelAndView.addObject("name","张三");
return modelAndView;
}
}
5. 测试
六、动静分离
系统架构方案:
- 数据库方面:主从复制(数据的冗余备份),读写分离(在主从复制基础上构建):减轻单台数据库的读写压力。
- 服务器方面:反向代理(统一请求入口,通过反向代理应用服务器集群,将用户的请求转发给应用服务器),负载均衡(服务器集群分担请求压力),动静分离(将静态资源与动态资源分别管理,静态资源由nginx管理,动态资源由tomcat服务器管理)
搭建读写分离系统
1. 准备资源
准备一台虚拟机,tomcat安装包,java的JDK安装包,nginx安装包
下载资源:
tomcat8 :链接:https://pan.baidu.com/s/1KzlZQ7Egd1G322P0rfhupQ 提取码:skm4
JDK :链接:https://pan.baidu.com/s/1U75a0CKeQ0V0txMcfOtArQ 提取码:6t5z
nginx :链接:https://pan.baidu.com/s/1zV91KPHO9edKua8uQpub_A 提取码:yelo
2. 安装JDK
[root@rwsplit ~]# rpm -ivh jdk-8u161-linux-x64.rpm
3. 配置java环境
[root@rwsplit ~]# vim /etc/profile
# 在文件末尾添加
export JAVA_HOME=/usr/java/latest
export CLASSPATH=.
export PATH=$PATH:$JAVA_HOME/bin
4. 配置文件生效
[root@rwsplit ~]# source /etc/profile
5. 安装tomcat
[root@rwsplit ~]# tar -zxvf apache-tomcat-8.5.37.tar.gz -C /usr
6. 启动tomcat服务
[root@rwsplit ~]# cd /usr/apache-tomcat-8.5.37/
[root@rwsplit apache-tomcat-8.5.37]# bin/startup.sh
6. 安装nginx
安装步骤参考:https://blog.csdn.net/qq_43225978/article/details/86323281
7. 修改nginx配置文件-配置静态资源的匹配规则
# ============修改==============
...
35 server {
36 listen 80;
37 server_name localhost;
38
39 #charset koi8-r;
40
41 #access_log logs/host.access.log main;
42
43 location / {
44 root html;
45 index index.html index.htm;
46 }
47 # =============添加以下内容=================
48 location ~ .*\.(js|css|htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ {
49 root staticResource;
50 }
51 #============================================
52 #error_page 404 /404.html;
...
8. 在nginx安装目录下创建一个staticResource目录
[root@rwsplit nginx]# mkdir staticResource
9. 上传一个静态页面index.html到该目录
10. 修改nginx配置文件-配置动态资源的匹配规则
# =============== 修改 =================
...
33 #gzip on;
34 # =====修改以下内容:访问动态资源时,接收转发并指定IP与端口======
35 upstream tomcat{
36 server 192.168.114.150:8080;
37 }
38 #============================================
39 server {
40 listen 80;
41 server_name localhost;
42
43 #charset koi8-r;
44
45 #access_log logs/host.access.log main;
46 # =========修改以下内容:访问动态资源时,转发请求 =========
47 location / {
48 proxy_pass http://tomcat;
49 }
50 #============================================
51 location ~ .*\.(js|css|htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ {
52 root staticResource;
53 }
54
55 #error_page 404 /404.html;
...
11. 启动nginx服务
[root@rwsplit nginx]# sbin/nginx -c conf/nginx.conf
12. 远程访问测试
- 访问静态资源:
- 访问动态资源: