###前言

通过代码片段分别介绍服务端渲染、客户端渲染、对象缓存三种方式的写法。

代码片段仅供参考,具体实现需要根据业务场景自行适配,但思想都是一样。

一、服务端渲染方式

####1、接口返回html页面的设置

```java

@Autowired

ThymeleafViewResolver thymeleafViewResolver;

@Autowired

ApplicationContext applicationContext;

@RequestMapping(value="/to_list", produces="text/html")

@ResponseBody

public String goodsList() {

// 业务逻辑

}

####2、先从缓存中取,有就返回。

```java

//取缓存

String html = redisService.get(GoodsKey.getGoodsList, "", String.class);

if(!StringUtils.isEmpty(html)) {

return html;

}

3、缓存中没有,就手动渲染。

springboot1.5.x的写法:

List goodsList = goodsService.listGoodsVo();

model.addAttribute("goodsList", goodsList);

SpringWebContext ctx = new SpringWebContext(request,response, request.getServletContext(),request.getLocale(), model.asMap(), applicationContext );

//手动渲染

html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);

springboot2.x的写法:

WebContext ctx = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());

//手动渲染

html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);

4、最后再将渲染内容加入到redis

if(!StringUtils.isEmpty(html)) {

redisService.set(GoodsKey.getGoodsList, "", html);

}

二、客户端渲染方式(商品详情页)

####1、找到跳转到商品详情页的路径,修改为一个静态html的路径。

在商品列表页,找到跳转到详情页的动态路径,直接修改为一个静态路径,后缀为htm或shtml,总之不要是html即可,因为application.properties中一般会配置后缀为html的都访问templates文件夹下的。

注意代码中详情的链接,指向一个静态页面goods_detail.htm:

```html

秒杀商品列表

商品名称商品图片商品原价秒杀价库存数量详情

```

2、根据1的路径,在static目录下新建一个goods_detail.htm文件,原本动态页面上的模板语言都去掉,换成id=“xx”,然后使用ajax来渲染静态文件中的数据即可。

原始动态页面:

秒杀商品详情

您还没有登录,请登陆后再操作

没有收货地址的提示。。。

商品名称
商品图片
秒杀开始时间

秒杀倒计时:秒

秒杀进行中

秒杀已结束

立即秒杀

商品原价
秒杀价
库存数量

静态化之后的页面:可以看到,动态模板语言都去掉了,直接通过JS来赋值。

秒杀商品详情

您还没有登录,请登陆后再操作

没有收货地址的提示。。。

商品名称
商品图片
秒杀开始时间

立即秒杀

商品原价
秒杀价
库存数量

核心js代码:

$(function(){

getDetail();

});

function getDetail(){

var goodsId = g_getQueryString("goodsId");

$.ajax({

url:"/goods/detail/"+goodsId,

type:"GET",

success:function(data){

if(data.code == 0){

render(data.data);

}else{

layer.msg(data.msg);

}

},

error:function(){

layer.msg("客户端请求有误");

}

});

}

function render(detail){

var miaoshaStatus = detail.miaoshaStatus;

var remainSeconds = detail.remainSeconds;

var goods = detail.goods;

var user = detail.user;

if(user){

$("#userTip").hide();

}

$("#goodsName").text(goods.goodsName);

$("#goodsImg").attr("src", goods.goodsImg);

$("#startTime").text(new Date(goods.startDate).format("yyyy-MM-dd hh:mm:ss"));

$("#remainSeconds").val(remainSeconds);

$("#goodsId").val(goods.id);

$("#goodsPrice").text(goods.goodsPrice);

$("#miaoshaPrice").text(goods.miaoshaPrice);

$("#stockCount").text(goods.stockCount);

countDown(); // 判断秒杀开始状态

}

// 判断秒杀开始状态

function countDown(){

var remainSeconds = $("#remainSeconds").val();

var timeout;

if(remainSeconds > 0){//秒杀还没开始,倒计时

$("#buyButton").attr("disabled", true);

$("#miaoshaTip").html("秒杀倒计时:"+remainSeconds+"秒");

timeout = setTimeout(function(){

$("#countDown").text(remainSeconds - 1);

$("#remainSeconds").val(remainSeconds - 1);

countDown();

},1000);

}else if(remainSeconds == 0){//秒杀进行中

$("#buyButton").attr("disabled", false);

if(timeout){

clearTimeout(timeout);

}

$("#miaoshaTip").html("秒杀进行中");

$("#verifyCodeImg").attr("src", "/miaosha/verifyCode?goodsId="+$("#goodsId").val());

$("#verifyCodeImg").show();

$("#verifyCode").show();

}else{//秒杀已经结束

$("#buyButton").attr("disabled", true);

$("#miaoshaTip").html("秒杀已经结束");

$("#verifyCodeImg").hide();

$("#verifyCode").hide();

}

}

3、记得服务端返回json格式数据,给静态页面做数据绑定。

三、客户端渲染方式(秒杀接口)

和第二点的操作基本一样,也是去除动态模板语言,改为ajax渲染。

不同的地方:

1)、多了一些springboot的配置;

2)、GET和POST的区别,这里一定要用POST,有一些场景比如删除操作,如果用了GET比如delete?id=XX这样的写法,那么搜索引擎扫描到会自动帮你删除了,所以一定要写清楚类型。

1、springboot-1.5.x的配置

spring.resources.add-mappings=true #是否启用默认资源处理

spring.resources.cache-period= 3600 #缓存时间

spring.resources.chain.cache=true #是否在资源链中启用缓存

spring.resources.chain.enabled=true #是否启用Spring资源处理链。默认情况下,禁用,除非至少启用了一个策略。

spring.resources.chain.gzipped=true #是否对缓存压缩

spring.resources.chain.html-application-cache=true #是否启用HTML5应用程序缓存清单重写

spring.resources.static-locations=classpath:/static/ #静态资源的位置

####2、springboot2.1.1的官方配置

```properties

spring.resources.add-mappings=true # 是否启用默认资源处理

spring.resources.cache.cachecontrol.cache-private= # 表示响应消息是针对单个用户的,不能由共享缓存存储。

spring.resources.cache.cachecontrol.cache-public= # 表示任何缓存都可以存储响应

spring.resources.cache.cachecontrol.max-age= # 响应被缓存的最大时间,如果没有指定持续时间后缀,以秒为单位。

spring.resources.cache.cachecontrol.must-revalidate= # 表明,一旦缓存过期,在未与服务器重新验证之前,缓存不能使用响应。

spring.resources.cache.cachecontrol.no-cache= # 表示缓存的响应只有在服务器重新验证时才能重用

spring.resources.cache.cachecontrol.no-store= # 表示在任何情况下都不缓存响应

spring.resources.cache.cachecontrol.no-transform= # 指示中介(缓存和其他)它们不应该转换响应内容

spring.resources.cache.cachecontrol.proxy-revalidate= # 与“must-revalidate”指令的含义相同,只是它不适用于私有缓存。

spring.resources.cache.cachecontrol.s-max-age= # 响应被共享缓存缓存的最大时间,如果没有指定持续时间后缀,以秒为单位。

spring.resources.cache.cachecontrol.stale-if-error= # 当遇到错误时,响应可能使用的最大时间,如果没有指定持续时间后缀,以秒为单位。

spring.resources.cache.cachecontrol.stale-while-revalidate= # 如果没有指定持续时间后缀,则响应在过期后可以提供的最长时间(以秒为单位)。

spring.resources.cache.period= # 资源处理程序提供的资源的缓存周期。如果没有指定持续时间后缀,将使用秒。

spring.resources.chain.cache=true # 是否在资源链中启用缓存。

spring.resources.chain.compressed=false # 是否启用已压缩资源(gzip, brotli)的解析。

spring.resources.chain.enabled= # 是否启用Spring资源处理链。默认情况下,禁用,除非至少启用了一个策略。

spring.resources.chain.html-application-cache=false # 是否启用HTML5应用缓存清单重写。

spring.resources.chain.strategy.content.enabled=false # 是否启用内容版本策略。

spring.resources.chain.strategy.content.paths=/** # 应用于内容版本策略的以逗号分隔的模式列表。

spring.resources.chain.strategy.fixed.enabled=false # 是否启用固定版本策略。

spring.resources.chain.strategy.fixed.paths=/** # 用于固定版本策略的以逗号分隔的模式列表。

spring.resources.chain.strategy.fixed.version= # 用于固定版本策略的版本字符串。

spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ # 静态资源的位置。

```

####3、第二点在点击按钮时调用的JS方法getMiaoshaPath()如下

```javascript

```

四、对象缓存

最基本最常用的缓存处理逻辑:

失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。

命中:应用程序从cache中取数据,取到后返回。

更新:先把数据存到数据库中,成功后,再让缓存失效。

参考代码:

// 先查缓存,再查数据库。

public MiaoshaUser getById(long id) {

//取缓存

MiaoshaUser user = redisService.get(MiaoshaUserKey.getById, ""+id, MiaoshaUser.class);

if(user != null) {

return user;

}

//取数据库

user = miaoshaUserDao.getById(id);

if(user != null) {

redisService.set(MiaoshaUserKey.getById, ""+id, user);

}

return user;

}

// 更新数据库后,缓存也要做同步更新。

public boolean updatePassword(String token, long id, String formPass) {

//取user

MiaoshaUser user = getById(id);

if(user == null) {

throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);

}

//更新数据库

MiaoshaUser toBeUpdate = new MiaoshaUser();

toBeUpdate.setId(id);

toBeUpdate.setPassword(MD5Util.formPassToDBPass(formPass, user.getSalt()));

miaoshaUserDao.update(toBeUpdate);

//处理缓存

redisService.delete(MiaoshaUserKey.getById, ""+id);

user.setPassword(toBeUpdate.getPassword());

redisService.set(MiaoshaUserKey.token, token, user);

return true;

}

总结

服务端渲染:利用模板引擎技术生成静态html页面到指定目录或者是redis等缓存中间件中去,页面上的访问路径直接指向到该目录下的静态html,这种方式实际上还是属于服务端渲染的静态化方式。

客户端渲染:将原本的模板语言渲染的html,改变为纯静态的htm/shtml,然后用js/ajax渲染数据,加上spring配置文件的相关配置指定静态文件存放路径,达到利用浏览器缓存页面的方式。推荐使用这种方式,这种属于前后端分离的客户端渲染方式,性能更好。

对象缓存:对象级缓存主要是在service中对一些对象的缓存处理,要按照合理的步骤,先取缓存,再取数据库,缓存中有就返回缓存对象,没有就返回数据库数据,最后将数据库数据再放入缓存中。

如果对缓存处理逻辑感兴趣,可以参考这篇博客:http://blog.csdn.net/tTU1EvLDeLFq5btqiK/article/details/78693323

java使用的页面静态化技术_java秒杀系列(2)- 页面静态化技术相关推荐

  1. java中级工程师所需的技能_Java 工程师要具备哪些技能或技术?

    Java开发工程师的必备技能有哪些?从一个软件开发爱好者,到一名合格的符合企业用人需求的Java开发工程师,必须掌握一定的核心技能. 首先,我们来看看市面上用人企业在招聘Java开发工程师时都有哪些要 ...

  2. java ee技术_Java EE 6与Spring Framework:技术决策过程

    java ee技术 在过去的几个月中,我们经历了这个决策过程:为Java平台上的企业开发选择哪种技术堆栈? 有多种选择. 但是,我们深入讨论的是:纯Java EE 6堆栈与带有Java EE的Spri ...

  3. Java文件和文件夹的区别_Java面试系列-webapp文件夹和WebContent文件夹的区别?-kingsoft是什么文件夹...

    我的程序员面试系列 面试题:Java Web Project里我们会遇到下面两种文件夹:webapp和WebContent. 这两个文件夹下都有个字文件夹WEB-INF,里面都有web.xml.为什么 ...

  4. AWS云计算技术架构探索系列之五-网络

    一.前言 当我们有了计算和存储资源,但是要真正把应用程序运行起来并提供互联网服务,那还需要使用AWS的网络,本章节就一起了解AWS的网络及其相关的组件基础知识和架构,其中包括: 区域(Region), ...

  5. AWS云计算技术架构探索系列之一-开篇

    一.前言 1.什么是AWS AWS是亚马逊公司的云计算 品牌,作为全球云计算技术的首创者和领导者,其分布在全球25区域81个可用区的数据中心,提供200多项服务齐全的云服务(2021年12月份数据), ...

  6. AWS云计算技术架构探索系列之二-身份账户体系(IAM)

    一.前言 建立身份账户体系是我们上云的第一步,良好的账户体系设计,会为后续的管理带来极大的便捷性和扩展性,反之,则可能增加管理的复杂,以及账户使用的不安全. AWS设计了一套完备的身份账号体系,主要包 ...

  7. AWS云计算技术架构探索系列之三-计算

    一.前言 计算是最核心的云服务,对于用户来说,取之不尽,用之不竭.按需使用的算力正是云计算的最主要的优势之一. 从云计算架构发展历程看,经历了基于XEN,KVM,VMware和Hyper-V为核心的虚 ...

  8. php技术创新:利用动态404页面实现全站自动静态化

    还就没到这里来了,不知道大家对我还有印象没有?上次来记得是给一个眼角膜脱落的兄弟捐款,那时候我对php还一窍不通呢.经过一年多的刻苦学习,现在我又回来了这次不仅初步掌握了PHP语言,还带来了一篇刚刚发 ...

  9. java反射技术_java反射技术,逆向开发必备技能

    相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了, ...

最新文章

  1. 推荐8个高质量的小众实用APP,解决你的痛点需求
  2. 使用深度学习opencv 进行人脸年龄的实时检测
  3. MySql中常用的内置函数
  4. C++测试题练习题1
  5. Spring Security构建Rest服务-0600-SpringSecurity基本原理
  6. 新房装修有哪些除味小妙招?
  7. 简单的HTML5灰度图查看器 simple PACS DICOM HTML5 viewer
  8. VC 图像处理相关源代码,共28套打包下载.rar 分享
  9. 基本磁盘转换为动态磁盘后快速启动关机变重启,记录一次研究过程
  10. 计算机网络工程师初级,软考计算机网络的初级和中级有啥区别?直接考中级网络工程师好考吗?计算机软考中级费用高吗...
  11. Python办公自动化——批量发送邮件
  12. 华为网络设备-访问控制列表配置实验
  13. DNA甲基化经CTCF和黏连蛋白复合体调节RNA可变剪切
  14. 向你推荐一个五星级云原生DevOps论坛
  15. No provisioned iOS devices are available with a compatible iOS version. Connect an iOS device with a
  16. SPINN: Synergistic Progressive Inferenceof Neural Networks over Device and Cloud
  17. 最新青龙面板安装教程+依赖+拉库合集
  18. 【BSV动态】VXPASS与世卫组织合作为莱索托提供数字疫苗监测服务
  19. php图片处理案例,使用GD、ImageGick与PHP框架的图片处理技术
  20. 陪诊服务系统源码,可以在线预约陪诊师的软件平台

热门文章

  1. DirectX支配游戏!历代GPU架构全解析
  2. 【转载】给程序员的圣诞大礼★★春夏
  3. Linux下查看软件安装路径(whereis)
  4. linux df命令无反馈,Linux-df命令
  5. java mail 已发送_JavaMail获取已发送邮件
  6. [转载] 【Java】将一个字符串的字符排序,按ASCII表的顺序从小到大
  7. [转载] 向集合中添加自定义类型--建议在自定义类型的时候要重写equals方法
  8. Java Hashtable containsValue()方法与示例
  9. 在Python3中将字符串转换为字节的最佳方法
  10. mysql快速批量入库_MySQL-批量入库优化