🎉🎉欢迎来到我的CSDN主页!🎉🎉
🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚
🌟推荐给大家我的专栏《电商项目实战》。🎯🎯
👉点击这里,就可以查看我的主页啦!👇👇
Java方文山的个人主页
🎁如果感觉还不错的话请给我点赞吧!🎁🎁
💖期待你的加入,一起学习,一起进步!💖💖
一、商品详情
当我们点击商品的时候需要展示对应的商品详情,首先在首页商品页写入后端的接口
controller代码
@Controller
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private IGoodsService goodsService;
@RequestMapping("/ByIdSelect")
public String ByIdSelect(GoodsVo vo, Model model){
Goods g = goodsService.getById(vo.getGid());
model.addAttribute("g",g);
return "proDetail";
}
}
在对应的页面显示相应的数据
<!DOCTYPE html>
<html>
<head>
<#include "common/head.html">
<link rel="stylesheet" type="text/css" href="css/public.css"/>
<link rel="stylesheet" type="text/css" href="css/proList.css"/>
</head>
<body>
<!------------------------------head------------------------------>
<#include "common/top.html">
<!-----------------address------------------------------->
<div class="address">
<div class="wrapper clearfix">
<a href="${ctx}/">首页</a>
<span>/</span>
<a href="${ctx}/page/flowerDer.html">装饰摆件</a>
<span>/</span>
<a href="${ctx}/page/proList.html">干花花艺</a>
<span>/</span>
<#--
注意:
1)${goods.goodsTitle!}:只能判断goodsTitle属性是否为空,不能判断goods对象是否为空
2)${(goods.goodsTitle)!}:既可以判断goods对象是否为空,也可以判断goodsTitle属性是否为空
-->
<a href="#" class="on">${(g.goodsTitle)!}</a>
</div>
</div>
<!-----------------------Detail------------------------------>
<div class="detCon">
<div class="proDet wrapper">
<div class="proCon clearfix">
<div class="proImg fl">
<img class="det" src="${(g.goodsImg)!}" />
<#--<div class="smallImg clearfix">]
<img src="img/temp/proDet01.jpg" data-src="img/temp/proDet01_big.jpg">
<img src="img/temp/proDet02.jpg" data-src="img/temp/proDet02_big.jpg">
<img src="img/temp/proDet03.jpg" data-src="img/temp/proDet03_big.jpg">
<img src="img/temp/proDet04.jpg" data-src="img/temp/proDet04_big.jpg">
</div>-->
</div>
<div class="fr intro">
<div class="title">
<h4>${(g.goodsTitle)!}</h4>
<p>${(g.goodsName)!}</p>
<span>¥${(g.goodsPrice)!}</span>
</div>
<div class="proIntro">
<p>颜色分类</p>
<div class="smallImg clearfix categ">
<p class="fl"><img src="img/temp/prosmall01.jpg" alt="白瓷花瓶+20支快乐花" data-src="img/temp/proBig01.jpg"></p>
<p class="fl"><img src="img/temp/prosmall02.jpg" alt="白瓷花瓶+20支兔尾巴草" data-src="img/temp/proBig02.jpg"></p>
<p class="fl"><img src="img/temp/prosmall03.jpg" alt="20支快乐花" data-src="img/temp/proBig03.jpg"></p>
<p class="fl"><img src="img/temp/prosmall04.jpg" alt="20支兔尾巴草" data-src="img/temp/proBig04.jpg"></p>
</div>
<p>数量 库存<span>${(g.goodsStock)!}</span>件</p>
<div class="num clearfix">
<img class="fl sub" src="img/temp/sub.jpg">
<span class="fl" contentEditable="true">1</span>
<img class="fl add" src="img/temp/add.jpg">
<p class="please fl">请选择商品属性!</p>
</div>
</div>
<div class="btns clearfix">
<a href="#2"><p class="buy fl">立即购买</p></a>
<a href="javascript:void(0);"><p class="cart fr" data-gid="${(g.gid)!}">加入购物车</p></a>
</div>
</div>
</div>
</div>
</div>
<div class="introMsg wrapper clearfix">
<div class="msgL fl">
<div class="msgTit clearfix">
<a class="on">商品详情</a>
<a>所有评价</a>
</div>
<div class="msgAll">
<div class="msgImgs">
<img src="img/temp/det01.jpg">
<img src="img/temp/det02.jpg">
<img src="img/temp/det03.jpg">
<img src="img/temp/det04.jpg">
<img src="img/temp/det05.jpg">
<img src="img/temp/det06.jpg">
<img src="img/temp/det07.jpg">
</div>
<div class="eva">
<div class="per clearfix">
<img class="fl" src="img/temp/per01.jpg">
<div class="perR fl">
<p>馨***呀</p>
<p>不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分</p>
<div class="clearfix">
<p><img src="img/temp/eva01.jpg"></p>
<p><img src="img/temp/eva02.jpg"></p>
<p><img src="img/temp/eva03.jpg"></p>
<p><img src="img/temp/eva04.jpg"></p>
<p><img src="img/temp/eva05.jpg"></p>
</div>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
<div class="per clearfix">
<img class="fl" src="img/temp/per02.jpg">
<div class="perR fl">
<p>么***周</p>
<p>花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!</p>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
<div class="per clearfix">
<img class="fl" src="img/temp/per01.jpg">
<div class="perR fl">
<p>馨***呀</p>
<p>不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分</p>
<div class="clearfix">
<p><img src="img/temp/eva01.jpg"></p>
<p><img src="img/temp/eva02.jpg"></p>
<p><img src="img/temp/eva03.jpg"></p>
<p><img src="img/temp/eva04.jpg"></p>
<p><img src="img/temp/eva05.jpg"></p>
</div>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
<div class="per clearfix">
<img class="fl" src="img/temp/per02.jpg">
<div class="perR fl">
<p>么***周</p>
<p>花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!</p>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
<div class="per clearfix">
<img class="fl" src="img/temp/per01.jpg">
<div class="perR fl">
<p>馨***呀</p>
<p>不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分</p>
<div class="clearfix">
<p><img src="img/temp/eva01.jpg"></p>
<p><img src="img/temp/eva02.jpg"></p>
<p><img src="img/temp/eva03.jpg"></p>
<p><img src="img/temp/eva04.jpg"></p>
<p><img src="img/temp/eva05.jpg"></p>
</div>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
<div class="per clearfix">
<img class="fl" src="img/temp/per02.jpg">
<div class="perR fl">
<p>么***周</p>
<p>花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!</p>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
<div class="per clearfix">
<img class="fl" src="img/temp/per01.jpg">
<div class="perR fl">
<p>馨***呀</p>
<p>不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分</p>
<div class="clearfix">
<p><img src="img/temp/eva01.jpg"></p>
<p><img src="img/temp/eva02.jpg"></p>
<p><img src="img/temp/eva03.jpg"></p>
<p><img src="img/temp/eva04.jpg"></p>
<p><img src="img/temp/eva05.jpg"></p>
</div>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
<div class="per clearfix">
<img class="fl" src="img/temp/per02.jpg">
<div class="perR fl">
<p>么***周</p>
<p>花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!</p>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
<div class="per clearfix">
<img class="fl" src="img/temp/per01.jpg">
<div class="perR fl">
<p>馨***呀</p>
<p>不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分</p>
<div class="clearfix">
<p><img src="img/temp/eva01.jpg"></p>
<p><img src="img/temp/eva02.jpg"></p>
<p><img src="img/temp/eva03.jpg"></p>
<p><img src="img/temp/eva04.jpg"></p>
<p><img src="img/temp/eva05.jpg"></p>
</div>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
<div class="per clearfix">
<img class="fl" src="img/temp/per02.jpg">
<div class="perR fl">
<p>么***周</p>
<p>花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!</p>
<p><span>2016年12月27日08:31</span><span>颜色分类:大中小三件套(不含花)</span></p>
</div>
</div>
</div>
</div>
</div>
<div class="msgR fr">
<h4>为你推荐</h4>
<div class="seeList">
<a href="#">
<dl>
<dt><img src="img/temp/see01.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="#">
<dl>
<dt><img src="img/temp/see02.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="#">
<dl>
<dt><img src="img/temp/see03.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="#">
<dl>
<dt><img src="img/temp/see04.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
</div>
</div>
</div>
<div class="like">
<h4>猜你喜欢</h4>
<div class="bottom">
<div class="hd">
<span class="prev"><img src="img/temp/prev.png"></span>
<span class="next"><img src="img/temp/next.png"></span>
</div>
<div class="imgCon bd">
<div class="likeList clearfix">
<div>
<a href="${ctx}/page/proDetail.html">
<dl>
<dt><img src="img/temp/like01.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="${ctx}/page/proDetail.html">
<dl>
<dt><img src="img/temp/like02.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="${ctx}/page/proDetail.html">
<dl>
<dt><img src="img/temp/like03.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="${ctx}/page/proDetail.html">
<dl>
<dt><img src="img/temp/like04.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="${ctx}/page/proDetail.html" class="last">
<dl>
<dt><img src="img/temp/like05.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
</div>
<div>
<a href="${ctx}/page/proDetail.html">
<dl>
<dt><img src="img/temp/like01.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="${ctx}/page/proDetail.html">
<dl>
<dt><img src="img/temp/like02.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="${ctx}/page/proDetail.html">
<dl>
<dt><img src="img/temp/like03.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="${ctx}/page/proDetail.html">
<dl>
<dt><img src="img/temp/like04.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
<a href="${ctx}/page/proDetail.html" class="last">
<dl>
<dt><img src="img/temp/like05.jpg"></dt>
<dd>【最家】复古文艺风玻璃花瓶</dd>
<dd>¥193.20</dd>
</dl>
</a>
</div>
</div>
</div>
</div>
</div>
<!--返回顶部-->
<#include "common/footer.html">
<script src="js/jquery.SuperSlide.2.1.1.js" type="text/javascript" charset="utf-8"></script>
<script src="js/public.js" type="text/javascript" charset="utf-8"></script>
<script src="js/nav.js" type="text/javascript" charset="utf-8"></script>
<script src="js/pro.js" type="text/javascript" charset="utf-8"></script>
<script src="js/cart.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
jQuery(".bottom").slide({titCell:".hd ul",mainCell:".bd .likeList",autoPage:true,autoPlay:false,effect:"leftLoop",autoPlay:true,vis:1});
</script>
</body>
</html>
效果展示
二、加入购物车
1.前端方法编写
商品详情页面引入了一个cart.js,里面是有关该所有的点击事件方法
$(function(){
/**************数量加减***************/
$(".num .sub").click(function(){
var num = parseInt($(this).siblings("span").text());
if(num<=1){
$(this).attr("disabled","disabled");
}else{
num--;
$(this).siblings("span").text(num);
//获取除了货币符号以外的数字
var price = $(this).parents(".number").prev().text().substring(1);
//单价和数量相乘并保留两位小数
$(this).parents(".th").find(".sAll").text('¥'+(num*price).toFixed(2));
jisuan();
zg();
}
});
$(".num .add").click(function(){
var num = parseInt($(this).siblings("span").text());
if(num>=5){
confirm("限购5件");
}else{
num++;
$(this).siblings("span").text(num);
var price = $(this).parents(".number").prev().text().substring(1);
$(this).parents(".th").find(".sAll").text('¥'+(num*price).toFixed(2));
jisuan();
zg();
}
});
//计算总价
function jisuan(){
var all=0;
var len =$(".th input[type='checkbox']:checked").length;
if(len==0){
$("#all").text('¥'+parseFloat(0).toFixed(2));
}else{
$(".th input[type='checkbox']:checked").each(function(){
//获取小计里的数值
var sAll = $(this).parents(".pro").siblings('.sAll').text().substring(1);
//累加
all+=parseFloat(sAll);
//赋值
$("#all").text('¥'+all.toFixed(2));
})
}
}
//计算总共几件商品
function zg(){
var zsl = 0;
var index = $(".th input[type='checkbox']:checked").parents(".th").find(".num span");
var len =index.length;
if(len==0){
$("#sl").text(0);
}else{
index.each(function(){
zsl+=parseInt($(this).text());
$("#sl").text(zsl);
})
}
if($("#sl").text()>0){
$(".count").css("background","#c10000");
}else{
$(".count").css("background","#8e8e8e");
}
}
/*****************商品全选***********************/
$("input[type='checkbox']").on('click',function(){
var sf = $(this).is(":checked");
var sc= $(this).hasClass("checkAll");
if(sf){
if(sc){
$("input[type='checkbox']").each(function(){
this.checked=true;
});
zg();
jisuan();
}else{
$(this).checked=true;
var len = $("input[type='checkbox']:checked").length;
var len1 = $("input").length-1;
if(len==len1){
$("input[type='checkbox']").each(function(){
this.checked=true;
});
}
zg();
jisuan();
}
}else{
if(sc){
$("input[type='checkbox']").each(function(){
this.checked=false;
});
zg();
jisuan();
}else{
$(this).checked=false;
var len = $(".th input[type='checkbox']:checked").length;
var len1 = $("input").length-1;
if(len<len1){
$('.checkAll').attr("checked",false);
}
zg();
jisuan();
}
}
});
/****************************proDetail 加入购物车*******************************/
$(".btns .cart").click(function(){
//获取购物车上的商品ID
let gid=this.dataset.gid;
//获取商品数量
let num=$("div span.fl").text;
//发起请求
$.post('/cart/add',{gid},resp=>{
},"json")
});
//删除购物车商品
$('.del').click(function(){
//单个删除
if($(this).parent().parent().hasClass("th")){
$(".mask").show();
$(".tipDel").show();
index = $(this).parents(".th").index()-1;
$('.cer').click(function(){
$(".mask").hide();
$(".tipDel").hide();
$(".th").eq(index).remove();
$('.cer').off('click');
if($(".th").length==0){
$(".table .goOn").show();
}
})
}else{
//选中多个一起删除
if($(".th input[type='checkbox']:checked").length==0){
$(".mask").show();
$(".pleaseC").show();
}
else{
$(".mask").show();
$(".tipDel").show();
$('.cer').click(function(){
$(".th input[type='checkbox']:checked").each(function(j){
index = $(this).parents('.th').index()-1;
$(".th").eq(index).remove();
if($(".th").length==0){
$(".table .goOn").show();
}
})
$(".mask").hide();
$(".tipDel").hide();
zg();
jisuan();
})
}
}
})
$('.cancel').click(function(){
$(".mask").hide();
$(".tipDel").hide();
})
//改变商品规格
// $(".pro dd").hover(function(){
// var html='';
// html='<span class="edit">修改</span>';
// $(this).addClass("on").append(html).parents(".th").siblings(".th").find(".pro dd").removeClass("on").find('.edit').remove();
// $(".edit").each(function(i){
// $(this).attr("id",'edit'+i);
// $("#edit"+i).click(function(){
// $(".proDets").show();
// $(".mask").show();
// $(".changeBtn .buy").attr("data-id",i);
// })
// })
// },function(){
// $(this).removeClass("on");
// })
// $(".changeBtn .buy").click(function(){
// var index = $(this).attr("data-id");
// var result = $(".smallImg .on").find("img").attr("alt");
// $("#edit"+index).prev().text(result);
// $(".proDets").hide();
// $(".mask").hide();
// $("#edit"+index).parent("dd").removeClass("on").find(".edit").remove();
// });
// $(".changeBtn .cart").click(function(){
// $(".proDets").hide();
// $(".mask").hide();
// })
})
2.后端代码编写
我们的用户购物车数据放在数据库太耗费数据库的资源了,我们可以将数据放入redis,进行一个时限判断,如果一周内没有进行数据访问就加入数据库并清除缓存。
我们需要编写新增和查询Redis中购物车数据方法
IRedisService
// 保存用户购物车信息
void saveCart(User user, GoodsVo vo);
// 查询用户购物车信息
List<GoodsVo> loadCart(User user);
IRedisService实现类
@Override
public List<GoodsVo> loadCart(User user) {
HashOperations<String,String,GoodsVo> operations=redisTemplate.opsForHash();
String bigKey=Constants.REDIS_CART_PREFIX + user.getId();
//根据用户Id查询所有的购物车信息
List<GoodsVo> values = operations.values(bigKey);
return values;
}
controller
@RequestMapping("/getCart")
public String getCart(GoodsVo vo, HttpServletRequest request, Model model) {
//根据键获取token
String token = CookieUtils.getCookieValue(request, "userToken");
//根据token获取用户
User user = redisService.loadUser(token);
//获取用户购物车商品信息
List<GoodsVo> goodsVos = redisService.loadCart(user);
//根据商品Id查询对应商品
List<Integer> ids = goodsVos.stream().map(GoodsVo::getGid).collect(Collectors.toList());
List<Goods> goods = goodsService.listByIds(ids);
// 进行遍历筛选合适的数据
for (Goods g : goods) {
//找到对应属性的商品
GoodsVo gv = goodsVos.stream()
.filter(v -> Objects.equals(v.getGid(), g.getGid()))
.findFirst()
.orElse(null);
if (gv != null) {
//将该商品g的属性赋值给GoodsVos
BeanUtils.copyProperties(g, gv);
}
}
System.out.println(goodsVos);
model.addAttribute("item", goodsVos);
return "cart";
}
因为我们redis中只有商品的id所以需要将所有商品的id拿到数据库中查询,将该商品的图片信息标题等查询出来利用BeanUtils将属性加入到goodsVos中,方便前端页面显示
三、优化细节部分
1.购物车显示数据
<!DOCTYPE html>
<html>
<head lang="en">
<#include "common/head.html">
<link rel="stylesheet" type="text/css" href="css/public.css"/>
<link rel="stylesheet" type="text/css" href="css/proList.css" />
</head>
<body>
<!--------------------------------------cart--------------------->
<div class="head ding">
<div class="wrapper clearfix">
<div class="clearfix" id="top">
<h1 class="fl"><a href="${ctx}/"><img src="img/logo.png"/></a></h1>
<div class="fr clearfix" id="top1">
<form action="#" method="get" class="fl">
<input type="text" placeholder="搜索" />
<input type="button" />
</form>
</div>
</div>
</div>
</div>
<div class="cart mt">
<!-----------------logo------------------->
<!--<div class="logo">
<h1 class="wrapper clearfix">
<a href="${ctx}/"><img class="fl" src="img/temp/logo.png"></a>
<img class="top" src="img/temp/cartTop01.png">
</h1>
</div>-->
<!-----------------site------------------->
<div class="site">
<p class=" wrapper clearfix">
<span class="fl">购物车</span>
<img class="top" src="img/temp/cartTop01.png">
<a href="${ctx}/" class="fr">继续购物></a>
</p>
</div>
<!-----------------table------------------->
<div class="table wrapper">
<div class="tr">
<div>商品</div>
<div>单价</div>
<div>数量</div>
<div>小计</div>
<div>操作</div>
</div>
<#--有数据就显示-->
<#if item??>
<#list item as g>
<div class="th">
<div class="pro clearfix">
<label class="fl">
<input type="checkbox"/>
<span></span>
</label>
<a class="fl" href="#">
<dl class="clearfix">
<dt class="fl"><img src="${(g.goodsImg)!}"></dt>
<dd class="fl">
<p>${(g.goodsName)!}</p>
<p>颜色分类:</p>
<p>${(g.goodsType)!}</p>
</dd>
</dl>
</a>
</div>
<div class="price">¥${(g.goodsPrice)!}</div>
<div class="number">
<p class="num clearfix">
<img class="fl sub" src="img/temp/sub.jpg">
<span class="fl">${(g.num)!}</span>
<img class="fl add" src="img/temp/add.jpg">
</p>
</div>
<div class="price sAll">¥20.00</div>
<div class="price"><a class="del" href="#2">删除</a></div>
</div>
</#list>
<#else>
<div class="goOn">空空如也~<a href="${ctx}/">去逛逛</a></div>
</#if>
<div class="tr clearfix">
<label class="fl">
<input class="checkAll" type="checkbox"/>
<span></span>
</label>
<p class="fl">
<a href="javascript:void(0);">全选</a>
<a href="javascript:void(0);" class="del">删除</a>
</p>
<p class="fr">
<span>共<small id="sl">0</small>件商品</span>
<span>合计: <small id="all">¥0.00</small></span>
<a class="count">结算</a>
</p>
</div>
</div>
</div>
<div class="mask"></div>
<div class="tipDel">
<p>确定要删除该商品吗?</p>
<p class="clearfix">
<a class="fl cer" href="javascript:void(0);">确定</a>
<a class="fr cancel" href="javascript:void(0);">取消</a>
</p>
</div>
<!--返回顶部-->
<#include "common/footer.html">
<!----------------mask------------------->
<div class="mask"></div>
<!-------------------mask内容------------------->
<div class="proDets">
<img class="off" src="img/temp/off.jpg" />
<div class="proCon clearfix">
<div class="proImg fr">
<img class="list" src="img/temp/proDet.jpg" />
<div class="smallImg clearfix">
<img src="img/temp/proDet01.jpg" data-src="img/temp/proDet01_big.jpg">
<img src="img/temp/proDet02.jpg" data-src="img/temp/proDet02_big.jpg">
<img src="img/temp/proDet03.jpg" data-src="img/temp/proDet03_big.jpg">
<img src="img/temp/proDet04.jpg" data-src="img/temp/proDet04_big.jpg">
</div>
</div>
<div class="fl">
<div class="proIntro change">
<p>颜色分类</p>
<div class="smallImg clearfix">
<p class="fl on"><img src="img/temp/prosmall01.jpg" alt="白瓷花瓶+20支快乐花" data-src="img/temp/proBig01.jpg"></p>
<p class="fl"><img src="img/temp/prosmall02.jpg" alt="白瓷花瓶+20支兔尾巴草" data-src="img/temp/proBig02.jpg"></p>
<p class="fl"><img src="img/temp/prosmall03.jpg" alt="20支快乐花" data-src="img/temp/proBig03.jpg"></p>
<p class="fl"><img src="img/temp/prosmall04.jpg" alt="20支兔尾巴草" data-src="img/temp/proBig04.jpg"></p>
</div>
</div>
<div class="changeBtn clearfix">
<a href="#2" class="fl"><p class="buy">确认</p></a>
<a href="#2" class="fr"><p class="cart">取消</p></a>
</div>
</div>
</div>
</div>
<div class="pleaseC">
<p>请选择宝贝</p>
<img class="off" src="img/temp/off.jpg" />
</div>
<script src="js/public.js" type="text/javascript" charset="utf-8"></script>
<script src="js/pro.js" type="text/javascript" charset="utf-8"></script>
<script src="js/cart.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
这里直接将我们后端所拿到的数据进行判断遍历展示即可
2.退出登录
首先我们不止需要清除浏览器上的cookie还需要清除redis中保存的用户信息,所以在Redis的service层定义一个删除的方法
// 清除用户数据
void logout(String token);
实现类编写相应代码
@Override
public void logout(String token) {
//根据token删除对应的键
redisTemplate.delete(Constants.REDIS_USER_PREFIX +token);
}
这时候,我们就可以编写退出的controller代码了
@RequestMapping("/logout")
public String login( HttpServletRequest request, HttpServletResponse response){
//清除redis缓存
String token = CookieUtils.getCookieValue(request, "userToken");
redisService.logout(token);
//清除cookie
CookieUtils.deleteCookie(request,response,"userToken");
CookieUtils.deleteCookie(request,response,"nickname");
return "redirect:/";
}
清除浏览器cookie的同时也清除redis中的数据避免资源浪费
3.参数解析器
通过这几天的编写,不知道大家发现没有,我们很多方法中都有获取用户的token信息,可以说这段代码是重复的,我们可以将其优化掉
UserArgumentResolver
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private IRedisService redisService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getGenericParameterType()== User.class;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
//从请求中获取cookie
String token = CookieUtils.getCookieValue(request, "userToken");
User user = redisService.loadUser(token);
return user;
}
}
这个解析器的作用是判断控制器方法的参数是否为User类型,如果是,则会在处理请求之前执行resolveArgument方法。在resolveArgument方法中,它会通过HttpServletRequest获取请求中的cookie,然后调用redisService的loadUser方法根据cookie中的token加载对应的用户信息。最后,返回解析得到的User对象作为控制器方法的参数。
这里还需要一个config配置类,用于加载自定义解析器
WebConfig
@Component
public class WebConfig implements WebMvcConfigurer {
@Autowired
private UserArgumentResolver userArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(userArgumentResolver);
}
}
到这里我的分享就结束了,欢迎到评论区探讨交流!!
💖如果觉得有用的话还请点个赞吧 💖