页面的优化技术分为:缓存和,页面静态化,静态资源优化,CDN优化等
其中缓存分为: 页面缓存+url缓存+对象缓存
也没缓存的时间比较短的。比如10秒钟的缓存时间失效
思路: 获取页面缓存,没有的时候重新获取页面然后进行渲染,然后返回
使用 Thymeleaf 的话,Springboot中有ThymeleafViewResolver可以帮助我们获取到页面的模板
这个方法可以得到一个模板的引擎,这个类的父类 TemplateEngine,其中的process方法是关键
其中的IContext这个类的参数,可以通过 SpringWebContext
SpringWebContext ctx = new SpringWebContext(request,response,
request.getServletContext(),request.getLocale(), model.asMap(), applicationContext );
html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);
重新我们之前的GoosController的商品列表
此时这个Controller方法返回的是一个页面,因此需要 @ResponseBody进行标记
/**
* 使用页面缓存技术
* @param model
* @param user
* @return
* @throws Exception
*/
@RequestMapping(value="/toListCache", produces="text/html")
@ResponseBody
public String toListWithPageCache(HttpServletRequest request, HttpServletResponse response,Model model , User user) throws Exception {
if(user == null) {
return "login";
}
model.addAttribute("user", user);
//获取页面缓存
RedisServiceProxy proxy = new RedisServiceProxy(GoodsKey.GOODS_LIST,redisService);
String html = proxy.getBean("", String.class);
if(!StringUtils.isEmpty(html)) {
return html;
}
//查询商品信息
List goodsList = goodsService.listGoods();
model.addAttribute("goodsList", goodsList);
//页面缓存的核心东西,渲染页面
SpringWebContext ctx = new SpringWebContext(request,response,
request.getServletContext(),request.getLocale(), model.asMap(), applicationContext );
//手动渲染
html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);
if(!StringUtils.isEmpty(html)) {
proxy.setBean("", html);
}
return html;
}
页面的缓存呢其实呢是user不一样而已,其他的对大部分用户来说是一样的。
但是呢如果是一个详情页面,那么就有问题了。
因此这也就是url缓存的概念了
也就是将用户在url中的参数作为页面缓存key的一部分。
这样不同的用户看到的详情页是不一样的
这个是对页面缓存的进一步利用,参数作为key的一部分。
比如我们的商品详情页面,url中有一个参数 商品id
/**
* 使用缓存的例子
* @param model
* @param user
* @param goodsId
* @return
* @throws Exception
*/
@RequestMapping(value="/to_detailCache/{goodsId}",produces="text/html")
@ResponseBody
public String detailWithCache(HttpServletRequest request, HttpServletResponse response, Model model,User user,
@PathVariable("goodsId")Long goodsId) throws Exception {
model.addAttribute("user", user);
//获取页面缓存
RedisServiceProxy proxy = new RedisServiceProxy(GoodsKey.GOODS_DETAIL,redisService);
String html = proxy.getBean(""+goodsId, String.class);
if(!StringUtils.isEmpty(html)) {
return html;
}
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
model.addAttribute("goods", goods);
long startAt = goods.getStartDate().getTime();
long endAt = goods.getEndDate().getTime();
long now = System.currentTimeMillis();
int miaoshaStatus = 0;
int remainSeconds = 0;
if(now < startAt ) {//秒杀还没开始,倒计时
miaoshaStatus = 0;
//单位是毫秒
remainSeconds = (int)((startAt - now )/1000);
}else if(now > endAt){//秒杀已经结束
miaoshaStatus = 2;
remainSeconds = -1;
}else {//秒杀进行中
miaoshaStatus = 1;
remainSeconds = 0;
}
model.addAttribute("miaoshaStatus", miaoshaStatus);
model.addAttribute("remainSeconds", remainSeconds);
SpringWebContext ctx = new SpringWebContext(request,response,
request.getServletContext(),request.getLocale(), model.asMap(), applicationContext );
html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", ctx);
if(!StringUtils.isEmpty(html)) {
proxy.setBean(""+goodsId, html);
}
return html;
}
将对象化成json然后存入到redis中再从redis中获取到就是对象缓存。
缓存中没有的时候才会查询数据库.
之前的User对象的获取就是这种形式的
因此对于页面上的一些表示对象可以进行缓存。
但是呢如果遇到了更新的话,我们更新完数据库之后,要处理缓存的。
先更新数据库,然后更新缓存,保证缓存的一致性。
注意一定要更新数据库,之后再进行缓存的更新。
因为如果调用顺序之后呢,就会先加载缓存,然后更新,数据库的数据被更新了,是最新的,造成了数据不一致
service中可能是使用了缓存的,直接使用dao就可能造成这个缓存的不一致。
减少对数据库的访问。
基本上保证在60秒内可以不访问 mysql数据库,直接从redis中获取的。
这样系统的负载就只体现在 java 和redis进程上面。
消灭掉mysql的负载