【Java】页面静态化

article/2025/10/29 18:27:06

1.页面静态化介绍

2.Freemarker介绍

3.Freemarker入门案例

3.1环境搭建

创建maven工程并导入Freemarker的maven坐标

<dependency><groupId>freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version>
</dependency>

 3.2创建模板文件

模板文件中有四种元素:

  1. 文本,直接输出的部分
  2. 注释,即<#-- ... -->格式不会输出
  3. 插值(interpolation):即${..}部分,将使用数据模型中的部分替代输出
  4. FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出

FreeMarker的模板文件后缀可以任意,一般建议为ftl。

在D盘创建ftl目录,在ftl目录中创建称为test.ftl的模板文件,内容如下:

<!-- 模板文件以 .ftl结尾 -->
<html>
<head><meta charset="utf-8"><title>Freemarker入门DEMO </title>
</head>
<body><#--我是一个注释,我不会有任何输出  -->${name},你好。${message}<#-- FTL指令,引入文件 --><#include "foot.ftl">
</body>
</html>

3.3生成文件

使用步骤:

  • 第一步:创建一个Configuration对象,直接new一个对象。构造方法的参数就是freemarket的版本号。
  • 第二步:设置模板文件所在的路径。
  • 第三步:设置模板文件使用的字符集。一般是utf-8.
  • 第四步:加载一个模板,创建一个模板对象。
  • 第五步:创建一个模板使用的数据集,可以是pojo也可以是map。一般是Map。
  • 第六步:创建一个Writer对象,一般创建FileWriter对象,指定生成的文件名。
  • 第七步:调用模板对象的process方法输出文件。
  • 第八步:关闭流。
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;public class FreeMarkerTest{public static void main(String[] args) throws Exception {//1.创建配置类,传入自身版本号Configuration configuration=new Configuration(Configuration.getVersion());//2.设置模板所在的目录 configuration.setDirectoryForTemplateLoading(new File("D:/freemarkerDemo/src/main/resources/"));//3.设置字符集configuration.setDefaultEncoding("utf-8");//4.加载模板Template template = configuration.getTemplate("test.ftl");//5.创建数据模型,准备模板文件中所需要的数据,通常是通过map构造Map map=new HashMap();map.put("name", "小明");map.put("message", "欢迎光临!");//6.创建Writer对象,准备输出流对象用于输出静态文件(格式也可以是.xml或.jsp)Writer out =new FileWriter(new File("d:\\freemarkerDemo\\src\\main\\resources\\test.html"));//7.输出template.process(map, out);//8.关闭Writer对象out.close();}
}

4.Freemarker指令

4.1 assign指令

在模板文件中定义一个变量

(1)定义简单类型

<#assign linkman="周先生">
联系人:${linkman}

(2)定义对象类型

<#assign info={"mobile":"13301231212",'address':'北京市昌平区王府街'} >
电话:${info.mobile}  地址:${info.address}

4.2 include指令

include指令用于模板文件的嵌套,在模板文件中包含另外一个文件,多用于抽取。

(1)创建模板文件head.ftl

<h1>XXX</h1>

(2)修改入门案例中的test.ftl,在模板文件中使用include指令引入上面建立的模板文件

<#include "header.ftl">

4.3 if指令

if 指令用于判断,控制输出语句

(1)在模板文件中使用if指令进行判断(需要闭合<#if></#if>)

<#-- 可以通过assign属性为变量赋值 -->
<#assign success=false>
<#if success=true>你已通过实名认证
<#else>  你未通过实名认证
</#if>

(2)在java代码中为变量success赋值

map.put("success", true);

Java代码和assign为同一个变量赋值,结果以assign为准。

在freemarker的判断中,可以使用= 也可以使用==

 4.4 list指令

list 指令用于遍历

(1)在模板文件中使用list指令进行遍历

语法:#list 集合 as 存储遍历出的项

<#list goodsList as goods>商品名称:${goods.name} 价格:${goods.price}<br>
</#list>

(2)在java代码中为goodsList赋值

List goodsList=new ArrayList();Map goods1=new HashMap();
goods1.put("name", "苹果");
goods1.put("price", 5.8);Map goods2=new HashMap();
goods2.put("name", "香蕉");
goods2.put("price", 2.5);Map goods3=new HashMap();
goods3.put("name", "橘子");
goods3.put("price", 3.2);goodsList.add(goods1);
goodsList.add(goods2);
goodsList.add(goods3);
map.put("goodsList", goodsList);

如果想在循环中得到索引,使用循环变量+_index就可以得到。

5.生成移动端静态页面

前面我们已经学习了Freemarker的基本使用方法,下面我们就可以将Freemarker应用到项目中,帮我们生成移动端套餐列表静态页面和套餐详情静态页面。接下来我们需要思考几个问题:

(1)什么时候生成静态页面比较合适呢?

(2)将静态页面生成到什么位置呢?

(3)应该生成几个静态页面呢?

对于第一个问题,应该是当套餐数据发生改变时,需要生成静态页面,即我们通过后台系统修改套餐数据(包括新增、删除、编辑)时。

对于第二个问题,如果是在开发阶段可以将文件生成到项目工程中,如果上线后可以将文件生成到移动端系统运行的tomcat中。

对于第三个问题,套餐列表只需要一个页面就可以了,在这个页面中展示所有的套餐列表数据即可。套餐详情页面需要有多个,即一个套餐应该对应一个静态页面。

NGINX服务器,反向代理服务器

nginx(80) + tomcat(后端服务) 形式部署

静态文件(js,html,css):nginx可以直接配置静态文件所在的文件夹路径,nginx 直接配置访问

5.1环境搭建

在项目父工程的pom文件中导入framework的maven坐标

<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-web</artifactId><version>2.3.23</version>
</dependency>

5.2创建模板文件

在health_service_provider工程的WEB-INF目录中创建ftl目录,在ftl目录中创建模板文件mobile_setmeal.ftl和mobile_setmeal_detail.ftl文件,前者是用于生成套餐列表页面的模板文件,后者是生成套餐详情页面的模板文件。

(1)mobile_setmeal.ftl

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no,minimal-ui"><meta name="description" content=""><meta name="author" content=""><link rel="icon" href="../img/asset-favico.ico"><title>预约</title><link rel="stylesheet" href="../css/page-health-order.css" />
</head>
<body data-spy="scroll" data-target="#myNavbar" data-offset="150">
<div class="app" id="app"><!-- 页面头部 --><div class="top-header"><span class="f-left"><i class="icon-back" onclick="history.go(-1)"></i></span><span class="center">传智健康</span><span class="f-right"><i class="icon-more"></i></span></div><!-- 页面内容 --><div class="contentBox"><div class="list-column1"><ul class="list"><#-- 与动态页面 li class="list-item" v-for="setmeal in setmealList" 类似,但是setmealList取值在Ajax取,静态页面在java代码中取 --><#list setmealList as setmeal><li class="list-item"><a class="link-page" href="setmeal_detail_${setmeal.id}.html"><img class="img-object f-left" src="http://puco9aur6.bkt.clouddn.com/${setmeal.img}" alt=""><div class="item-body"><h4 class="ellipsis item-title">${setmeal.name}</h4><p class="ellipsis-more item-desc">${setmeal.remark}</p><p class="item-keywords"><span><#if setmeal.sex == '0'>性别不限<#else><#if setmeal.sex == '1'>男<#else>女</#if></#if></span><span>${setmeal.age}</span></p></div></a></li></#list></ul></div></div>
</div>
<!-- 页面 css js -->
<script src="../plugins/vue/vue.js"></script>
<script src="../plugins/vue/axios-0.18.0.js"></script>
</body>

注意上面模板文件中每个套餐对应的超链接如下:

<#-- 对应动态页面 a class="link-page" :href="'setmeal_detail.html?id='+setmeal.id" -->
<a class="link-page" href="setmeal_detail_${setmeal.id}.html">

可以看到,链接的地址是动态构成的,如果套餐的id为1,则对应的超链接地址为setmeal_detail_1.html;如果套餐的id为5,则对应的超链接地址为setmeal_detail_5.html。所以我们需要为每个套餐生成一个套餐详情静态页面。

(2)mobile_setmeal_detail.ftl

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no,minimal-ui"><meta name="description" content=""><meta name="author" content=""><link rel="icon" href="../img/asset-favico.ico"><title>预约详情</title><link rel="stylesheet" href="../css/page-health-orderDetail.css" /><script src="../plugins/vue/vue.js"></script><script src="../plugins/vue/axios-0.18.0.js"></script><script src="../plugins/healthmobile.js"></script>
</head>
<body data-spy="scroll" data-target="#myNavbar" data-offset="150">
<div id="app" class="app"><!-- 页面头部 --><div class="top-header"><span class="f-left"><i class="icon-back" onclick="history.go(-1)"></i></span><span class="center">传智健康</span><span class="f-right"><i class="icon-more"></i></span></div><!-- 页面内容 --><div class="contentBox"><div class="card"><div class="project-img"><img src="http://puco9aur6.bkt.clouddn.com/${setmeal.img}" width="100%" height="100%" /></div><div class="project-text"><h4 class="tit">${setmeal.name}</h4><p class="subtit">${setmeal.remark}</p><p class="keywords"><span><#if setmeal.sex == '0'>性别不限<#else><#if setmeal.sex == '1'>男<#else>女</#if></#if></span><span>${setmeal.age}</span></p></div></div><div class="table-listbox"><div class="box-title"><i class="icon-zhen"><span class="path1"></span><span class="path2"></span></i><span>套餐详情</span></div><div class="box-table"><div class="table-title"><div class="tit-item flex2">项目名称</div><div class="tit-item  flex3">项目内容</div><div class="tit-item  flex3">项目解读</div></div><div class="table-content"><ul class="table-list"><#list setmeal.checkGroups as checkgroup><li class="table-item"><div class="item flex2">${checkgroup.name}</div><div class="item flex3"><#list checkgroup.checkItems as checkitem><label>${checkitem.name}</label></#list></div><div class="item flex3">${checkgroup.remark}</div></li></#list></ul></div><div class="box-button"><a @click="toOrderInfo()" class="order-btn">立即预约</a></div></div></div></div>
</div>
<script>var vue = new Vue({el:'#app',methods:{toOrderInfo(){window.location.href = "orderInfo.html?id=${setmeal.id}";}}});
</script>
</body>

5.3 配置文件

(1)在health_service_provider工程中创建属性文件freemarker.properties

与health_mobile跨项目(同一个服务器不同的tomcat),所以写绝对路径,可以dubbo远程调用,但不能访问里面的文件

out_put_path=D:/ideaProjects/health_parent/health_mobile/src/main/webapp/pages

通过上面的配置可以指定将静态HTML页面生成的目录位置,让其被访问到。

真正的生产环境下,不同于开发环境,直接生成在工程(health_parent)对应的tomcat下。

(2)在health_service_provider工程的Spring配置文件中配置

freemarker既可以单独使用也可以整合在spring中使用,对象由spring框架创建

<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"><!--指定模板文件所在目录--><property name="templateLoaderPath" value="/WEB-INF/ftl/" /><!--指定字符集--><property name="defaultEncoding" value="UTF-8" />
</bean><!--加载属性文件,后期在java代码中会使用到属性文件中定义的key和value-->
<context:property-placeholder location="classpath:freemarker.properties"/>

5.4 生成静态页面

修改health_service_provider工程中的SetmealServiceImpl类的add方法,加入生成静态页面的逻辑。

  1. 取出套餐所有的数据
  2. freemarkerConfig 得到模板
  3. 注入数据(套餐列表模板,套餐详情的模板)
  4. 生成文件
@Service(interfaceClass = SetmealService.class)
@Transactional
public class SetmealServiceImpl implements SetmealService {@Autowiredprivate FreeMarkerConfigurer freemarkerConfig;@Autowiredprivate SetmealDao setmealDao;@Autowiredprivate JedisPool jedisPool;@Value("${out_put_path}")//从属性文件读取要生成的html对应目录的路径private String outputpath ;//新增套餐,同时关联检查组public void add(Setmeal setmeal, Integer[] checkgroupIds) {setmealDao.add(setmeal);Integer setmealId = setmeal.getId();//获取套餐idthis.setSetmealAndCheckGroup(setmealId,checkgroupIds);//完成数据库操作后需要将图片名称保存到redisjedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_DB_RESOURCES,setmeal.getImg());//新增套餐后需要重新生成静态页面generateMobileStaticHtml();}//生成静态页面public void generateMobileStaticHtml() {//准备模板文件中所需的数据List<Setmeal> setmealList = this.findAll();//生成套餐列表静态页面generateMobileSetmealListHtml(setmealList);//生成套餐详情静态页面(多个)generateMobileSetmealDetailHtml(setmealList);}//生成套餐列表静态页面public void generateMobileSetmealListHtml(List<Setmeal> setmealList) {Map<String, Object> dataMap = new HashMap<String, Object>();dataMap.put("setmealList", setmealList);this.generateHtml("mobile_setmeal.ftl","m_setmeal.html",dataMap);}//生成套餐详情静态页面(多个)public void generateMobileSetmealDetailHtml(List<Setmeal> setmealList) {for (Setmeal setmeal : setmealList) {Map<String, Object> dataMap = new HashMap<String, Object>();dataMap.put("setmeal", this.findById(setmeal.getId()));this.generateHtml("mobile_setmeal_detail.ftl","setmeal_detail_"+setmeal.getId()+".html",dataMap);}}//通用的方法:用于生成静态页面(具体生成的静态文件,用哪个模板文件生成,模板文件中需要填充的数据)public void generateHtml(String templateName,String htmlPageName,Map<String, Object> dataMap){//获得spring注入的配置对象Configuration configuration = freeMarkerConfigurer.getConfiguration();Writer out = null;try {// 加载模版文件Template template = configuration.getTemplate(templateName);// 生成数据File docFile = new File(outputpath + "\\" + htmlPageName);out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));// 输出文件template.process(dataMap, out);} catch (Exception e) {e.printStackTrace();} finally {try {if (null != out) {out.flush();}} catch (Exception e2) {e2.printStackTrace();}}}
}

通过上面代码可以看到,我们生成的套餐列表页面名称为m_setmeal.html,为了能够在移动端访问到此页面,需要将移动端工程中的/pages/index.html页面的超链接地址进行修改:

<a href="/pages/m_setmeal.html" class="link-page"><div class="type-title"><h3>体检预约</h3><p>实时预约</p></div><div class="type-icon"><i class="icon-zhen"><span class="path1"></span><span class="path2"></span></i></div>
</a>

6.FreeMarker小结

6.1网页静态化技术

随着用户量以及数据量的增大,网页静态化技术方案如今越来越流行。

简单地说,网页静态化技术就是将网页以纯静态方式的形式展现(不需要Ajax实时发送请求)。

6.2网页静态化技术与缓存技术的比较

共同点:都可以减小数据库的访问压力。

区别:

(1)缓存技术适用于小规模的数据。以及一些经常变动的数据。

(2)网页静态化技术适用于大规模但是变化不太频繁的数据。

6.3网页静态化技术的应用场景

(1)新闻门户网站的文章类型频道一般都用到了网页静态化技术。点击新闻直接会跳转静态化的页面。

(2)电商网站的商品详情页也十分常用,在存储商品的时候会生成静态化页面,点击商品详情会直接跳到生成的商品详情的静态化页面。

(3)网页静态化技术可以结合Nignx这种高性能的web服务器来提高并发访问量。(开发时生成的静态页面在本地目录,而项目部署到tomcat运行,tomcat作为容器加载动态servlet内容,处理静态页面能力不如nignx,一般将生成的静态页面生成在nignx服务下)

6.4 什么是FreeMarker

FreeMarket是一款用Java语言编写的模板引擎,用它可以通过模板和要改变的数据来生成输出文本(例如HTML网页,配置文件,源代码等),作为用来实现网页静态化技术的一种手段。FreeMarket的使用率大大超过其他一些技术。对于系统中频繁使用数据库进行查询但是内容更新很小的应用,都可以用FreeMarket将网页静态化,这样就避免了大量的数据库访问请求,从而提高网站的性能。

 

 


http://chatgpt.dhexx.cn/article/0Jl3P452.shtml

相关文章

网站优化---页面静态化技术

一&#xff1a; 首先先区分一下动态页面和静态页面的区别 动态文件&#xff1a;PHP脚本、Java脚本等 动态文件的执行过程&#xff1a;词法、语法分析 -> 编译 -> 渲染输出 静态文件&#xff1a;HTML文件 从加载速度上可以看出&#xff0c;静态文件明显比动态文件速度…

openresty 页面静态化及多级缓存

openresty 页面静态化及多级缓存 多级缓存&#xff1a; 数据缓存的好处不用介绍了吧&#xff01;&#xff0c; 所谓多级缓存&#xff0c;即在整个系统架构的不同系统层级进行数据缓存&#xff0c;以提升访问效率&#xff0c;这也是应用最广的方案之一。而 nginx 是可以缓存数据…

java网站页面静态化方案

要生活得漂亮&#xff0c;需要付出极大的忍耐&#xff0c;一不抱怨&#xff0c;二不解释&#xff0c;绝对是个人才。——《变形记》 1、概述 在大型网站中&#xff0c;如京东和当当商品详情界面&#xff0c;看到的页面基本上是静态页面。为什么都要把页面静态化呢&#xff1f;…

freemarker 页面静态化技术

文章目录 一.背景二.页面静态化技术freemarker三.Freemarker基本操作1.引入依赖&#xff1a;2.创建模板文件&#xff1a;3.FTL指令&#xff1a; 四.freemarker整合spring五.总结&#xff1a;1.什么是网页静态化技术2.网页静态化技术与缓存技术的比较3.网页静态化技术的应用场景…

springboot 页面静态化

springboot 页面静态化 页面静态化&#xff1a;将动态渲染的页面保存为静态页面&#xff08;一般存储在nginx&#xff09;&#xff0c;提高访问速度 说明&#xff1a;页面静态化适用于数据不常变更的场景&#xff0c;如果数据频繁变更&#xff0c;宜使用其他方案提高访问性能 …

PHP 页面静态化

前言 随着网站的内容的增多和用户访问量的增多&#xff0c;网站加载会越来越慢&#xff0c;受限于带宽和服务器同一时间的请求次数的限制&#xff0c;我们往往需要在此时对我们的网站进行代码优化和服务器配置的优化。 一、页面静态化概念 静态化定义 静态化就是指把原本的动态…

页面静态化

前言 我们在使用购物网站的时候&#xff0c;会选择相应的商品点击查看详情&#xff0c;其实会发现每件商品的商品详情页面都是差不多的&#xff0c;除了一些数据外&#xff0c;其余结构布局都是一模一样的&#xff0c;那么是为每件商品都写一个详情页面吗&#xff1f;很显然这…

img标签图片自适应的样式

问题&#xff1a; img标签宽高固定的情况下&#xff0c;上传的图片尺寸不一致&#xff0c;会导致图片被拉伸变形&#xff0c;影响页面美观。 解决方法&#xff1a; 用css3的object-fit 属性、object-position 属性可以解决&#xff0c;代码如下&#xff1a; <!DOCTYPE htm…

图片自适应屏幕大小

有时候美工给过来的图片不规范&#xff0c;用户手机屏幕大小不一样。可能导致在不同的用户手机上显示效果不一样&#xff0c;这时候需要对图片的显示做自适应。 一把来说自适应可以根据需求&#xff0c;做成宽高固定显示屏幕大小。但对于一些长图可能出现图片被压缩在一个屏幕…

响应式图像--图片自适应大小

Foreword 做项目的过程中遇到了一个图片拉伸的问题&#xff0c;做的是手机端的页面&#xff0c;当让其以电脑端页面显示的时候&#xff0c;图片被拉伸的有那么点丑&#xff01;所以改改它&#xff01; Why 为什么会出现这样的情况呢&#xff1f; 1、因为图片是放在盒子…

HTML网页图片背景以及图片自适应设置

关于HTML网页图片背景以及图片自适应设置 Test 1 背景图片需要用到标签中的background属性 图片背景需要显示的位置是网页的身体部分即在body中显示&#xff0c;因此background属性应该放在body标签内 本次使用图片的大小为4808*2704像素&#xff0c;这是图片原来的样子 这是…

html图片自动适应,css如何让图片自适应?

要使图片能够自适应显示&#xff0c;我们一般可以通过设置CSS样式&#xff0c;让图片作为父元素的背景图片&#xff0c;再设置相关属性来实现。下面我们来看一下使用css设置图片自适应的方法。 css设置图片自适应示例&#xff1a; HTML代码&#xff1a;title css代码&#xff1…

【前端】js实现图片自适应

前言&#xff1a; 前几天写第一版代码的时候&#xff0c;测试跟我说&#xff0c;你这用户上传图片显示有问题啊&#xff0c;图像不是被拉宽就是被拉长了&#xff0c;不行啊。因为我给el-image设计的是固定长宽&#xff0c;如果图片不是这个比例&#xff0c;那直接就会变形了&am…

谈一下图片的自适应

在工作中经常遇到要求图片自适应的需求&#xff0c;下面就谈一下我在工作中经常使用的一些方法 单独使用img标签的情况 单独使用img的时候&#xff0c;可以只设置width就可以了&#xff0c;height不用设置&#xff0c;因为img不设置height&#xff0c;它会自动根据图片的比例…

浅谈图片宽度自适应解决方案

在网页设计中&#xff0c;随着响应式设计的到来&#xff0c;各种响应式设计方案层出不穷。对于图片响应式的问题也有很多前端开发人员在进行研究。比较好的图片响应式设想便是在不同的屏幕分辨率下使用不同实际尺寸的图片&#xff0c;而达到在高速网络环境中使用大或超大高清图…

浅谈图片展示、图片自适应解决方案

文章目录 导读CSS 解决方案background-size&#x1f437;background-size: contain&#xff1b;&#x1f437;background-size&#xff1a;100%&#xff1b;&#x1f437;background-size:cover; object-fit&#x1f437;object-fit: contain&#xff1b;&#x1f437;object-f…

实时即未来,大数据项目车联网之项目基石与前瞻【一】

文章目录 写在前面车联网项目全新升级 车联网行业背景介绍车联网技术汽车行业新能源汽车 车联网行业技术车辆网行业产业链与国内知名企业 车联网项目车联网技术架构和技术选型车联网项目的架构搭建 写在前面 车联网项目全新升级 更全 8-》21篇 更细 -》 图文并茂、部分代码首…

开发一个大数据项目的架构与流程

如果我们想做一个数据分析项目&#xff0c;我们就应该清楚数据的处理流程。 我们大致可以分为: 数据采集——数据存储——数据清洗——数据分析——数据可视化和数据挖掘、二次分析 在以上流程处理完成之后&#xff0c;会进入调度阶段&#xff1a;将数据采集、清洗、分析、导出…

大数据项目大致流程

1、提出需求-需要和多个部门负责人进行协商&#xff1a;关于项目的可行性分析 2、需求分析-进行需求调研&#xff08;研究竞品&#xff09;、市场调研&#xff0c;如果是给甲方做产品&#xff0c;需要和甲方协商需求细则 3、技术选型-需要多个开发部门的人员参与协商 考虑的…