欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【电商网站 005】页面静态化(项目实践:商品详情页,页面静态化)

程序员文章站 2023-12-23 18:57:27
...

一、前言

二、简介

2.1 问题分析

一般流程:前端页面是通过Thymeleaf模板引擎渲染后返回到浏览器,在后台需要大量的数据查询,而后渲染得到HTML页面
问题:第一,后台大量数据查询,对数据库造成压力;第二,响应慢,请求的响应时间过长,并发能力不高
方案1:缓存技术,比如Redis。但是,Redis适合数据规模比较小的情况。假如数据量比较大,例如我们的商品详情页。每个页面如果10kb,100万商品,就是10GB空间,对内存占用比较大。此时就给缓存系统带来极大压力,如果缓存崩溃,接下来倒霉的就是数据库了。

2.2 what 什么是静态化

定义:将动态生成的HTML页面变为静态内容保存在Nginx服务器上,以后用户的请求到来,直接访问静态页面,不再经过服务的渲染。
小结:静态的HTML页面可以部署在nginx中,从而大大提高并发能力,减小tomcat压力。
理由1:web服务器和web应用服务器
web服务器的优点并发量大,缺点是只能处理静态资源,nginx并发量50000但是只能处理静态页面
web应用服务器的缺点是并发量小,优点是可以处理动态页面,tomcat并发量200但是可以处理动态页面
理由2:Nginx和Redis:
页面静态化,将商品详情页是访问频率大、数据量大而且包含各种图片,干脆将商品详情页整个html变为静态页面,存放在Nginx上,下次直接从Nginx上面拿(redis只能存放访问频率大的热点数据,key-value键值对,不能存放页面)
ps:页面静态化是将整个html页面静态化存放到Nginx上,不是数据和图片一点点存放

2.3 how 如何实现静态化

第一,静态化页面都是通过模板引擎来生成,
第二,生成的静态化页面保存到nginx服务器来部署。
一句话小结:模板引擎整个html页面生成静态化页面nginx服务器将生成的静态化页面存储起来,需要的时候取出。

常用的模板引擎比如:Freemarker、Velocity、Thymeleaf
对于Thymeleaf,我们之前就使用的Thymeleaf,来渲染html返回给用户。Thymeleaf除了可以把渲染结果写入Response,也可以写到本地文件,从而实现静态化。
一句话小结:Thymeleaf可以把渲染结果写入Response返回给前端;也可以将渲染结果写到本地文件得到静态页面存放到Nginx服务器,从而实现静态化。

三、Thymeleaf实现静态化(将渲染结果写到本地文件得到静态页面存放到Nginx服务器)

3.1 Thymeleaf中的几个概念

先说下Thymeleaf中的几个概念:
Context:运行上下文
TemplateResolver:模板解析器
TemplateEngine:模板引擎

Context
定义:上下文,用来保存模型数据,保存的模型数据有什么用呢?当模板引擎TemplateEngine渲染时,可以从Context上下文中获取数据用于渲染。
与SpringBoot结合使用:当与SpringBoot结合使用时,放入Model的数据就自动会被处理到Context,作为模板渲染的数据使用。

TemplateResolver
定义:模板解析器,用来读取模板相关的配置,例如:模板存放的位置信息,模板文件名称,模板文件的类型等等。
与SpringBoot结合使用:当与SpringBoot结合时,TemplateResolver已经由其创建完成,并且各种配置也都有默认值,比如模板存放位置,其默认值就是:templates。比如模板文件类型,其默认值就是html。

TemplateEngine(Thymeleaf就是一个模板引擎)
定义:模板引擎,用来解析模板的引擎,需要使用到上下文、模板解析器。分别从上下文Context、模板解析器TemplateResolver中获取模板中需要的数据(即模板文件)。然后利用内置的语法规则解析,从而输出解析后的文件。来看下模板引擎进行处理的函数:
templateEngine.process(“模板名”, context, writer);
三个参数:
(1)模板名称
(2)上下文对象:里面包含模型数据 //
(3)writer:输出目的地的流 //该参数作用:在输出时,我们可以指定输出的目的地,如果目的地是Response的流,那就是网络响应。如果目的地是本地文件,那就实现静态化了。
ps:在SpringBoot中已经自动配置了模板引擎,我们做静态化,就是把输出的目的地改成本地文件即可!

3.2 实践:SpringBoot项目中,Thymeleaf实现静态化

【电商网站 005】页面静态化(项目实践:商品详情页,页面静态化)

Service代码:

@Service
public class GoodsHtmlService {   // 商品详情页面Html页面

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private TemplateEngine templateEngine;  // 模板引擎

    private static final Logger LOGGER = LoggerFactory.getLogger(GoodsHtmlService.class);

    public void createHtml(Long spuId) {   // 创建html页面
        PrintWriter writer = null;
        try {
            // 第二个参数,创建thymeleaf上下文context对象
            Context context = new Context();
            // 获取页面数据
            Map<String, Object> spuMap = this.goodsService.loadModel(spuId);
            // 把数据放入上下文对象
            context.setVariables(spuMap);

            // 第三个参数,创建输出流  指定输出位置  输出为html文件
            File file = new File("C:\\project\\nginx-1.14.0\\html\\item\\" + spuId + ".html");
            writer = new PrintWriter(file);

            // 执行页面静态化方法
            templateEngine.process("item", context, writer);
        } catch (Exception e) {
            LOGGER.error("页面静态化出错:{},"+ e, spuId);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    /**
     * 新建线程处理页面静态化
     * @param spuId
     */
    public void asyncExcute(Long spuId) {
        ThreadUtils.execute(()->createHtml(spuId));  
        /*ThreadUtils.execute(new Runnable() {
            @Override
            public void run() {
                createHtml(spuId);
            }
        });*/
    }
}

线程工具类:

public class ThreadUtils {

    private static final ExecutorService es = Executors.newFixedThreadPool(10);

    public static void execute(Runnable runnable) {
        es.submit(runnable);
    }
}

3.2.1 什么时候创建静态文件

我们编写好了创建静态文件的service,那么问题来了:什么时候去调用它呢

想想这样的场景:

假如大部分的商品都有了静态页面。那么用户的请求都会被nginx拦截下来,根本不会到达我们的leyou-goods-web服务。只有那些还没有页面的请求,才可能会到达这里。

因此,如果请求到达了这里,我们除了返回页面视图外,还应该创建一个静态页面,那么下次就不会再来麻烦我们了。

所以,我们在GoodsController中添加逻辑,去生成静态html文件:

@GetMapping("{id}.html")
public String toItemPage(@PathVariable("id")Long id, Model model){

    // 原有业务逻辑,加载所需的数据
    Map<String, Object> map = this.goodsService.loadModel(id);
    // 原有业务逻辑,把数据放入数据模型
    model.addAllAttributes(map);

    // 新增业务逻辑,页面静态化
    this.goodsHtmlService.asyncExcute(id);

    return "item";
}

注意:生成html 的代码不能对用户请求产生影响,所以这里我们使用额外的线程进行异步创建。

3.2.2 重启测试:

访问一个商品详情,然后查看nginx目录:

【电商网站 005】页面静态化(项目实践:商品详情页,页面静态化)

3.3 nginx代理静态页面

我们修改nginx,让它对商品请求进行监听,指向本地静态页面,如果本地没找到,才进行反向代理到实际服务器

server {
    listen       80;
    server_name  www.leyou.com;

    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location /item {
        # 先找本地
        root html;
        if (!-f $request_filename) { #请求的文件不存在,就反向代理
            proxy_pass http://127.0.0.1:8084;
            break;
        }
    }

    location / {
        proxy_pass http://127.0.0.1:9002;
        proxy_connect_timeout 600;
        proxy_read_timeout 600;
    }
}

重启测试:

发现请求速度得到了极大提升:

【电商网站 005】页面静态化(项目实践:商品详情页,页面静态化)

四、面试金手指

面试的时候,能够搞懂几个问题:
1、为什么要使用页面静态化?
2、what 什么是静态化?静态化的原理?
3、how 如何实现静态化?
4、Thymeleaf实现静态化(将渲染结果写到本地文件得到静态页面存放到Nginx服务器)
4.1 Thymeleaf中的三个概念
4.2 controller接口什么时候调用静态化service
4.3 nginx配置:修改nginx配置,让它对商品请求进行监听,指向本地静态页面,如果本地没找到,才进行反向代理到实际服务器
ps:原则:生成html 的代码不能对用户请求产生影响,所以这里我们使用额外的线程进行异步创建。
这些记下来,一气呵成,页面静态化这个问题就好了。

4.1 页面静态化基础知识

4.1.1 为什么要使用静态化

一般流程:前端页面是通过Thymeleaf模板引擎渲染后返回到浏览器,在后台需要大量的数据查询,而后渲染得到HTML页面
问题:第一,后台大量数据查询,对数据库造成压力;第二,响应慢,请求的响应时间过长,并发能力不高
方案1:缓存技术,比如Redis。但是,Redis适合数据规模比较小的情况。假如数据量比较大,例如我们的商品详情页。每个页面如果10kb,100万商品,就是10GB空间,对内存占用比较大。此时就给缓存系统带来极大压力,如果缓存崩溃,接下来倒霉的就是数据库了。

4.1.2 what 什么是静态化?静态化的原理?

定义:将动态生成的HTML页面变为静态内容保存在Nginx服务器上,以后用户的请求到来,直接访问静态页面,不再经过服务的渲染。
小结:静态的HTML页面可以部署在nginx中,从而大大提高并发能力,减小tomcat压力。
理由1:web服务器和web应用服务器
web服务器的优点并发量大,缺点是只能处理静态资源,nginx并发量50000但是只能处理静态页面
web应用服务器的缺点是并发量小,优点是可以处理动态页面,tomcat并发量200但是可以处理动态页面
理由2:Nginx和Redis:
页面静态化,将商品详情页是访问频率大、数据量大而且包含各种图片,干脆将商品详情页整个html变为静态页面,存放在Nginx上,下次直接从Nginx上面拿(redis只能存放访问频率大的热点数据,key-value键值对,不能存放页面)
ps:页面静态化是将整个html页面静态化存放到Nginx上,不是数据和图片一点点存放

4.1.3 how 如何实现静态化

第一,静态化页面都是通过模板引擎来生成,
第二,生成的静态化页面保存到nginx服务器来部署。
一句话小结:模板引擎整个html页面生成静态化页面nginx服务器将生成的静态化页面存储起来,需要的时候取出。

常用的模板引擎比如:Freemarker、Velocity、Thymeleaf
对于Thymeleaf,我们之前就使用的Thymeleaf,来渲染html返回给用户。Thymeleaf除了可以把渲染结果写入Response,也可以写到本地文件,从而实现静态化。
一句话小结:Thymeleaf可以把渲染结果写入Response返回给前端;也可以将渲染结果写到本地文件得到静态页面存放到Nginx服务器,从而实现静态化。

4.2 Thymeleaf实现静态化(将渲染结果写到本地文件得到静态页面存放到Nginx服务器)

4.2.1 Thymeleaf中的几个概念

先说下Thymeleaf中的几个概念:
Context:运行上下文
TemplateResolver:模板解析器
TemplateEngine:模板引擎

Context
定义:上下文,用来保存模型数据,保存的模型数据有什么用呢?当模板引擎TemplateEngine渲染时,可以从Context上下文中获取数据用于渲染。
与SpringBoot结合使用:当与SpringBoot结合使用时,放入Model的数据就自动会被处理到Context,作为模板渲染的数据使用。

TemplateResolver
定义:模板解析器,用来读取模板相关的配置,例如:模板存放的位置信息,模板文件名称,模板文件的类型等等。
与SpringBoot结合使用:当与SpringBoot结合时,TemplateResolver已经由其创建完成,并且各种配置也都有默认值,比如模板存放位置,其默认值就是:templates。比如模板文件类型,其默认值就是html。

TemplateEngine(Thymeleaf就是一个模板引擎)
定义:模板引擎,用来解析模板的引擎,需要使用到上下文、模板解析器。分别从上下文Context、模板解析器TemplateResolver中获取模板中需要的数据(即模板文件)。然后利用内置的语法规则解析,从而输出解析后的文件。来看下模板引擎进行处理的函数:
templateEngine.process(“模板名”, context, writer);
三个参数:
(1)模板名称
(2)上下文对象:里面包含模型数据 //
(3)writer:输出目的地的流 //该参数作用:在输出时,我们可以指定输出的目的地,如果目的地是Response的流,那就是网络响应。如果目的地是本地文件,那就实现静态化了。
ps:在SpringBoot中已经自动配置了模板引擎,我们做静态化,就是把输出的目的地改成本地文件即可!

4.2.2 when 什么时候调用静态化页面Service

第一,controller调用静态化页面service
我们编写好了创建静态文件的service,那么问题来了:什么时候去调用它呢
想想这样的场景:
假如大部分的商品都有了静态页面。那么用户的请求都会被nginx拦截下来,根本不会到达我们的leyou-goods-web服务。只有那些还没有页面的请求,才可能会到达这里。
因此,如果请求到达了这里,我们除了返回页面视图外,还应该创建一个静态页面,那么下次就不会再来麻烦我们了。

第二,Nginx配置:修改nginx配置,让它对商品请求进行监听,指向本地静态页面,如果本地没找到,才进行反向代理到实际服务器

注意:生成html 的代码不能对用户请求产生影响,所以这里我们使用额外的线程进行异步创建。

五、小结

页面静态化(项目实践:商品详情页,页面静态化),完成了。

天天打码,天天进步!!!

上一篇:

下一篇: