FreeMarker学习笔记

FreeMarker学习笔记

⼀、概述

FreeMarker是⼀款模板引擎:即⼀种基于模板和要改变的数据,并⽤来⽣成输出⽂本(HTML⽹⻚,电⼦邮件,配置⽂件,源代码等)的通⽤⼯具。它不是⾯向最终⽤户的,⽽是⼀个Java类库,是⼀款程序员可以嵌⼊他们所开发产品的组件。
模板编写为 FTL (FreeMarker Template Language)。
设计思想:模板 + 数据 —> ⽂本输出

官网:https://freemarker.apache.org/
freemarker架构描述
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> &copy; 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. 测试

freemarker访问测试

六、动静分离

系统架构方案:

  • 数据库方面:主从复制(数据的冗余备份),读写分离(在主从复制基础上构建):减轻单台数据库的读写压力。
  • 服务器方面:反向代理(统一请求入口,通过反向代理应用服务器集群,将用户的请求转发给应用服务器),负载均衡(服务器集群分担请求压力),动静分离(将静态资源与动态资源分别管理,静态资源由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. 远程访问测试

  1. 访问静态资源:
    访问静态资源
  2. 访问动态资源:
    在这里插入图片描述

版权声明:本文为qq_43225978原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。