一、页面缓存+URL缓存+对象缓存
1.页面缓存
(1)取缓存
在访问页面时,不是系统自动帮我们渲染,而是从缓存里取,如果在缓存里找到了就直接返回客户端。
(2)手动渲染模板存入缓存
通过在手动渲染得到的html页面缓存到redis。
(3)结果输出
@RequestMapping(value = "/to_list",produces ="text/html")
@ApiOperation(value = "显示商品列表",httpMethod = "GET")
@ApiResponses(value ={
@ApiResponse(code = 500216,message = "参数校验异常"),
@ApiResponse(code = 5,message = "服务端异常"),
@ApiResponse(code = 500210,message = "session不存在或已经失效"),
@ApiResponse(code = 0,message = "success"),
})
@ResponseBody
public String list(@ApiParam(value = "存储用户信息,以及将数据返回前端",required = true)HttpServletRequest request,HttpServletResponse response, Model model, MiaoshaUser user) {
model.addAttribute("user", user);
//查询商品列表
List<GoodsVo> goodsList = goodsService.listGoodVo();
model.addAttribute("goodsList", goodsList);
// return "goods_list";
//取缓存
String html = redisSevice.get(GoodsKey.getGoodsList, "", String.class);
if (!StringUtils.isEmpty(html)) {
return html;
}
WebContext ctx=new WebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap());
//手动渲染
html = thymeleafViewResolver.getTemplateEngine().process("goods_list",ctx);
if(StringUtils.isEmpty(html)){
redisSevice.set(GoodsKey.getGoodsList,"",html);
}
return html;
}
2.URL缓存
@RequestMapping(value="/to_detail/{goodsId}",produces="text/html")
@ResponseBody
//@ApiImplicitParam(name = "goodsId", value = "商品ID", paramType = "path", required = true, dataType = "long")
public String detai2(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user,
@PathVariable("goodsId")long goodsId){
//showflake
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;
}
3、对象缓存
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;
}
// http://blog.csdn.net/tTU1EvLDeLFq5btqiK/article/details/78693323
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,动态数据是通过接口从服务端获取,实现前后端分离,静态页面无需连接数据库打开速度较动态页面会有明显提高。
关键代码GoodsDetailVo
public class GoodsDetailVo {
private int miaoshaStatus = 0;
private int remainSeconds = 0;
private GoodsVo goods ;
private MiaoshaUser user;
public int getMiaoshaStatus() {
return miaoshaStatus;
}
public void setMiaoshaStatus(int miaoshaStatus) {
this.miaoshaStatus = miaoshaStatus;
}
public int getRemainSeconds() {
return remainSeconds;
}
public void setRemainSeconds(int remainSeconds) {
this.remainSeconds = remainSeconds;
}
public GoodsVo getGoods() {
return goods;
}
public void setGoods(GoodsVo goods) {
this.goods = goods;
}
public MiaoshaUser getUser() {
return user;
}
public void setUser(MiaoshaUser user) {
this.user = user;
}
}
获取到数据之后返回动态数据
@RequestMapping(value="/detail/{goodsId}")
@ResponseBody
public Result<GoodsDetailVo> 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_list.html的超链接参数改为goods_detail.htm,然后修改修改common.js,修改后的代码如下:
function g_showLoading(){
var idx = layer.msg('处理中...', {icon: 16,shade: [0.5, '#f5f5f5'],scrollbar: false,offset: '0px', time:100000}) ;
return idx;
}
//salt
var g_passsword_salt="1a2b3c4d"
// 获取url参数
function g_getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r != null) return unescape(r[2]);
return null;
};
//设定时间格式化函数,使用new Date().format("yyyyMMddhhmmss");
Date.prototype.format = function (format) {
var args = {
"M+": this.getMonth() + 1,
"d+": this.getDate(),
"h+": this.getHours(),
"m+": this.getMinutes(),
"s+": this.getSeconds(),
};
if (/(y+)/.test(format))
format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var i in args) {
var n = args[i];
if (new RegExp("(" + i + ")").test(format))
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? n : ("00" + n).substr(("" + n).length));
}
return format;
};
三、静态资源优化
MiaoshaController
@RequestMapping(value = "/do_miaosha")
// public String hellowrold(Model model, MiaoshaUser user,
// @RequestParam("goodsId")long goodsId) {
// model.addAttribute("user", user);
// if(user == null) {
// return "login";
// }
// //判断库存
// GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
// int stock = goods.getStockCount();
// if(stock <= 0) {
// model.addAttribute("errmsg", CodeMsg.MIAO_SHA_OVER.getMsg());
// return "miaosha_fail";
// }
// //判断是否已经秒杀到了
// MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
// if(order != null) {
// model.addAttribute("errmsg", CodeMsg.REPEATE_MIAOSHA.getMsg());
// return "miaosha_fail";
// }
// //减库存 下订单 写入秒杀订单
// OrderInfo orderInfo = miaoshaService.miaosha(user, goods);
// model.addAttribute("orderInfo", orderInfo);
// model.addAttribute("goods", goods);
// return "order_detail";
// }
OrderService
@Service
public class OrderService {
@Autowired
OrderDao orderDao;
@Autowired
RedisService redisService;
public MiaoshaOrder getMiaoshaOrderByUserIdGoodsId(long userId, long goodsId) {
//return orderDao.getMiaoshaOrderByUserIdGoodsId(userId, goodsId);
return redisService.get(OrderKey.getMiaoshaOrderByUidGid, ""+userId+"_"+goodsId, MiaoshaOrder.class);
}
public OrderInfo getOrderById(long orderId) {
return orderDao.getOrderById(orderId);
}
@Transactional
public OrderInfo createOrder(MiaoshaUser user, GoodsVo goods) {
OrderInfo orderInfo = new OrderInfo();
orderInfo.setCreateDate(new Date());
orderInfo.setDeliveryAddrId(0L);
orderInfo.setGoodsCount(1);
orderInfo.setGoodsId(goods.getId());
orderInfo.setGoodsName(goods.getGoodsName());
orderInfo.setGoodsPrice(goods.getMiaoshaPrice());
orderInfo.setOrderChannel(1);
orderInfo.setStatus(0);
orderInfo.setUserId(user.getId());
long orderId = orderDao.insert(orderInfo);
MiaoshaOrder miaoshaOrder = new MiaoshaOrder();
miaoshaOrder.setGoodsId(goods.getId());
miaoshaOrder.setOrderId(orderId);
miaoshaOrder.setUserId(user.getId());
orderDao.insertMiaoshaOrder(miaoshaOrder);
redisService.set(OrderKey.getMiaoshaOrderByUidGid, ""+user.getId()+"_"+goods.getId(), miaoshaOrder);
return orderInfo;
}
}
接口静态化:
通过接口名称,直接调用其中的静态方法。
OrderController
@RequestMapping("/detail")
@ResponseBody
public Result<OrderDetailVo> info(Model model, MiaoshaUser user,
@RequestParam("orderId") long orderId) {
if(user == null) {
return Result.error(CodeMsg.SESSION_ERROR);
}
OrderInfo order = orderService.getOrderById(orderId);
if(order == null) {
return Result.error(CodeMsg.ORDER_NOT_EXIST);
}
long goodsId = order.getGoodsId();
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
OrderDetailVo vo = new OrderDetailVo();
vo.setOrder(order);
vo.setGoods(goods);
return Result.success(vo);
}
OrderDetailVo
public class OrderDetailVo {
private GoodsVo goods;
private OrderInfo order;
public GoodsVo getGoods() {
return goods;
}
public void setGoods(GoodsVo goods) {
this.goods = goods;
}
public OrderInfo getOrder() {
return order;
}
public void setOrder(OrderInfo order) {
this.order = order;
}
}