1 goodsList代码实现
1.1 前端
goodsList.html
http://localhost:8080/goods/toList
点【详情】,跳转到商品详情页面
http://localhost:8080/goodsDetail.htm?goodsId=2
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>商品列表</title>
<script type="text/javascript" src="/js/jquery.min.js" ></script>
<script type="text/javascript" src="/js/common.js"></script>
</head>
<body>
<table>
<tr>
<td>序号</td>
<td>商品编号</td>
<td>商品名称</td>
<td>商品价格</td>
<td>商品库存</td>
<td>商品图片</td>
<td></td>
</tr>
<tr th:each="goods,stat : ${goodsList}">
<td th:text="${stat.index}+1"></td>
<td th:text="${goods.id}"></td>
<td th:text="${goods.goodsName}"></td>
<td th:text="${goods.seckillPrice}"></td>
<td th:text="${goods.stockCount}"></td>
<td>
<img th:src="@{${goods.goodsImg}}" width="120px" height="120px" />
</td>
<td>
<!--
<button type="button" th:attr="data-id=${goods.id}" οnclick="buy(this);">详情</button>
<a th:href="'/goods/toDetail/'+${goods.id}">详情</a>
-->
<a th:href="'/goodsDetail.htm?goodsId='+${goods.id}">详情</a>
</td>
</tr>
</table>
<button id="exitBtn" type="button" onclick="exitLogin()">退出登录</button>
</body>
<script>
console.log("goodsList");
function buy(btn){
var id=$(btn).data("id");
alert(id);
window.location.href="/goods/toDetail?id="+id;
}
function exitLogin(){
$.ajax({
url:"/login/exitLogin",
type:"post",
data:{
},
success:function (data){
if(data.code==200){
alert("退出成功");
window.location.href="/login/toLogin"
}else{
alert(data.message);
}
},
error:function (data){
alert("登录出现问题");
}
})
}
</script>
</html>
1.2 后端
GoodsController 中关于商品列表的功能
package com.example.miaosha.controller;
import com.example.miaosha.mapper.GoodsMapper;
import com.example.miaosha.pojo.Goods;
import com.example.miaosha.pojo.Order;
import com.example.miaosha.pojo.User;
import com.example.miaosha.rabbitmq.MQSender;
import com.example.miaosha.service.IGoodsService;
import com.example.miaosha.vo.GoodsDetailVo;
import com.example.miaosha.vo.GoodsVo;
import com.example.miaosha.vo.RespBean;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* <p>
* 前端控制器
* </p>
*
* @author cch
* @since 2021-11-17
*/
@Controller
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private IGoodsService goodsService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private ThymeleafViewResolver thymeleafViewResolver;
private String templateGoodsList="goodsList";
private String templateGoods="goods:";
private String templateGoodsDetail="goodsDetail:";
//商品列表展示tolist
// 商品详情
@RequestMapping(value = "/toList",produces = "text/html;charset=utf-8")
@ResponseBody
public String tolist(Model model, User user, HttpServletRequest request, HttpServletResponse response){
//if(null==user){ return "login"; }
//Redis 中获取页面,如果不为空,直接返回html
ValueOperations valueOperations = redisTemplate.opsForValue();
String html = (String) valueOperations.get(templateGoodsList);
if(!StringUtils.isEmpty(html)){
return html;
}
model.addAttribute("user", user);
List<GoodsVo> list=goodsService.findGoodsVo();
model.addAttribute("goodsList", list);
//如果为空,手动渲染,并且存入redis
WebContext webContext = new WebContext(request, response, request.getServletContext(),request.getLocale(), model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("goodsList",
webContext);
if(!StringUtils.isEmpty(html)){
valueOperations.set(templateGoodsList,html,60, TimeUnit.SECONDS);
}
return html;
}
@RequestMapping(value = "/toList0")
public String tolist0(Model model, User user){
//if(null==user){ return "login"; }
//如果为空,手动渲染,并且存入redis
model.addAttribute("user", user);
List<GoodsVo> list=goodsService.findGoodsVo();
model.addAttribute("goodsList", list);
return "goodsList";
}
}
IGoodsService findGoodsVo
package com.example.miaosha.service;
import com.example.miaosha.pojo.Goods;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.miaosha.vo.GoodsVo;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author cch
* @since 2021-11-17
*/
public interface IGoodsService extends IService<Goods> {
List<Goods> getAll();
List<GoodsVo> findGoodsVo();
GoodsVo findGoodsVoById(Long goodsId);
}
GoodsServiceImpl
package com.example.miaosha.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.miaosha.pojo.Goods;
import com.example.miaosha.mapper.GoodsMapper;
import com.example.miaosha.service.IGoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.miaosha.vo.GoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* <p>
* 服务实现类
* </p>
*
* @author cch
* @since 2021-11-17
*/
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements IGoodsService {
@Autowired
private GoodsMapper goodsMapper;
@Override
public List<Goods> getAll() {
QueryWrapper<Goods> queryWrapper= new QueryWrapper<>();
queryWrapper.apply("1=1");
List<Goods> list = goodsMapper.selectList(queryWrapper);
return list;
}
@Override
public List<GoodsVo> findGoodsVo() {
return goodsMapper.findGoodsVo();
}
@Override
public GoodsVo findGoodsVoById(Long goodsId) {
return goodsMapper.findGoodsVoById(goodsId);
}
}
GoodsMapper
package com.example.miaosha.mapper;
import com.example.miaosha.pojo.Goods;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.miaosha.vo.GoodsVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author cch
* @since 2021-11-17
*/
@Mapper
public interface GoodsMapper extends BaseMapper<Goods> {
List<GoodsVo> findGoodsVo();
GoodsVo findGoodsVoById(Long goodsId);
}
GoodsMapper.xml
<select id="findGoodsVo" resultType="com.example.miaosha.vo.GoodsVo">
select
g.id,
g.goods_name,
g.goods_title,
g.goods_detail,
g.goods_img,
g.goods_price,
g.goods_stock,
sg.seckill_price,
sg.stock_count,
sg.start_date,
sg.end_date
from
t_goods g ,t_seckill_goods sg
where g.id = sg.goods_id
</select>
tolist0()直接通过thymeleaf模板引擎,把List<GoodsVo>放在model中,返回前台
tolist() 把商品页面先放在redis缓存中,
访问时,先去redis缓存中查找,有页面缓存的情况下,直接返回;
如果没有页面缓存,从数据库查找之后,手动渲染页面,把渲染之后的html存入redis
redis中,goodsList 过期时间为1分钟
GoodsVo
package com.example.miaosha.vo;
import com.example.miaosha.pojo.Goods;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GoodsVo extends Goods {
private BigDecimal seckillPrice;
private Integer stockCount;
private Date startDate;
private Date endDate;
}
2.优化方面
2.1 页面缓存
把商品列表通过thymeleaf模板引擎,手动渲染,放在redis缓存,设置过期时间为1分钟
实际过程中,因为商品类别,还有商品列表分页,可以把热度最高的前几页放在缓存中