1.页面缓存
1.1页面缓存(商品列表页面)
1.2 URL缓存(商品详情)
1.3 对象缓存
2.页面静态化
2.1前后端分离
2.2浏览器缓存
3.静态资源优化
综述
我们在优化之前,接口返回的大多是页面名称,或响应数据,在这里我们对页面进行缓存处理,接口将返回静态页面的代码。
步骤:1 取缓存;2 手动渲染模板;3 输出结果
经过取缓存、手动渲染模板、输出结果三个步骤完善商品列表页、商品详细。
@RequestMapping(value="/to_list", produces="text/html")
@ResponseBody
public String list(Model model, MiaoshaUser user, HttpServletRequest request, HttpServletResponse response){
// System.out.println(user);
model.addAttribute("user",user);
//取缓存
String html = redisService.get(GoodsKey.getGoodsList, "", String.class);
if(!StringUtils.isEmpty(html)) {
return html;
}
//取数据库
List goodsList = goodsService.listGoodsVo();
model.addAttribute("goodsList",goodsList);
//return "goods_list";
//手动渲染
//https://blog.csdn.net/ouzhuangzhuang/article/details/84839266
IWebContext ctx =new WebContext(request,response, request.getServletContext(),request.getLocale(),model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);
if(!StringUtils.isEmpty(html)) {
redisService.set(GoodsKey.getGoodsList, "", html);
}
return html;
}
public class GoodsKey extends BasePrefix{
private GoodsKey(int expireSeconds, String prefix) {
super(expireSeconds, prefix);
}
public static GoodsKey getGoodsList = new GoodsKey(60, "gl");
public static GoodsKey getGoodsDetail = new GoodsKey(60, "gd");
}
@RequestMapping(value="/to_detail2/{goodsId}",produces="text/html")
@ResponseBody
public String detai2(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user,
@PathVariable("goodsId")long goodsId){
model.addAttribute("user",user);
//取缓存
String html = redisService.get(GoodsKey.getGoodsDetail, ""+goodsId, String.class);
if(!StringUtils.isEmpty(html)) {
return html;
}
//手动渲染
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
//System.out.println(goods.toString());
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);
//return "goods_detail";
//手动渲染
IWebContext ctx =new WebContext(request,response,
request.getServletContext(),request.getLocale(),model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", ctx);
if(!StringUtils.isEmpty(html)) {
redisService.set(GoodsKey.getGoodsDetail, ""+goodsId, html);
}
return html;
}
使用对象缓存重写MaioshaService里面的getById方法,使得不直接访问数据库,同时也要重写updatePassword方法。
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;
}
页面优化使用前后端分离,具体的在该项目中在商品列表跳转到商品详情可以体现,在静态页面初始化的时候,调用后端接口,获取商品详情,实现页面静态化
@RequestMapping(value="/detail/{goodsId}")
@ResponseBody
public Result detail(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user,
@PathVariable("goodsId")long goodsId) {
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
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;
}
GoodsDetailVo vo = new GoodsDetailVo();
vo.setGoods(goods);
vo.setUser(user);
vo.setRemainSeconds(remainSeconds);
vo.setMiaoshaStatus(miaoshaStatus);
return Result.success(vo);
}
//列表页
详情
//goods_detail.htm
商品详情
秒杀商品详情
您还没有登录,请登陆后再操作
没有收货地址的提示。。。
商品名称
商品图片
秒杀开始时间
商品原价
秒杀价
库存数量
添加配置
#static
#启用静态资源处理
spring.resources.add-mappings=true
#客户端缓存时间
spring.resources.cache.period=3600
spring.resources.chain.cache=true
spring.resources.chain.enabled=true
#启用html5的application-cache
spring.resources.chain.html-application-cache=true
spring.resources.static-locations=classpath:/static/
下面我们来了一下静态资源优化常用的手段
1 JS/CSS压缩,减少流量
2 多个JS/CSS组合,减少连接数
3 CDN就近访问
工具有
Tengine:http://tengine.taobao.org/
webback
CDN
优化完成后,我们可以再次用JMeter进行性能测试,看看QPS是否变大了