【电商项目实战】商品详情显示与Redis存储购物车信息

news2024/11/28 5:37:32

🎉🎉欢迎来到我的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>数量&nbsp;&nbsp;库存<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">继续购物&gt;</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>合计:&nbsp;<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,然后调用redisServiceloadUser方法根据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);
    }

}

请添加图片描述

到这里我的分享就结束了,欢迎到评论区探讨交流!!

💖如果觉得有用的话还请点个赞吧 💖

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1349033.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第9章 继承和派生习题(详解)

一、选择题 1&#xff0e;下列表示引用的方法中&#xff0c; &#xff08;&#xff09; 是正确的。已知&#xff1a;int m10&#xff1a; A&#xff0e;int &xm&#xff1b; B&#xff0e;int &y10&#xff1b; C&#xff0e;int &z&#xff1b; D&#xff0e;fl…

[CISCN 2019华东南]Web11

[CISCN 2019华东南]Web11 wp 信息搜集 页面内容如下&#xff1a; 右上角显示的是我的当前 IP 。 在最下角提示&#xff1a;Build With Smarty ! Smarty 是 PHP 的一个模板引擎&#xff0c;那么这道题应该是 Smarty 模板注入。 Smarty 模板注入 可以参考博客&#xff1a;Sm…

4年微博热搜数据,一次拿走

又是新的一年了&#xff0c;从2020年开始&#xff0c;就养成了定时备份各大平台热搜数据的习惯&#xff0c;微博&#xff0c;知乎都在备份&#xff0c;今天给大家看一下从2020年到2023年的微博热搜数据情况 这是2022年的备份数据&#xff0c;每天的热搜数据一个文件&#xff0c…

[蓝桥杯基础题型] 图论题目

遍历 添加路障 首先答案只能是0 1 2 &#xff0c;原因&#xff1a;把出发点堵住只需要两个路障 路障为0&#xff1a;不能找到一条从出发点到终点的路 路障为1&#xff1a;能找到一条从出发点到终点的路&#xff0c;但是只有一条 路障为2&#xff1a;能找到一条从出发点到终…

Origin 2021软件安装包下载及安装教程

Origin 2021下载链接&#xff1a;https://docs.qq.com/doc/DUnJNb3p4VWJtUUhP 1.选中下载的压缩包&#xff0c;然后鼠标右键选择解压到"Origin 2021"文件夹 2.双击打开“Setup”文件夹 3.选中“Setup.exe”鼠标右键点击“以管理员身份运行” 4.点击“下一步" 5…

SELinux 安全模型——MLS

首发公号&#xff1a;Rand_cs BLP 模型&#xff1a;于1973年被提出&#xff0c;是一种模拟军事安全策略的计算机访问控制模型&#xff0c;它是最早也是最常用的一种多级访问控制模型&#xff0c;主要用于保证系统信息的机密性&#xff0c;是第一个严格形式化的安全模型 暂时无…

SQL性能优化-索引

1.性能下降sql慢执行时间长等待时间长常见原因 1&#xff09;索引失效 索引分为单索、复合索引。 四种创建索引方式 create index index_name on user (name); create index index_name_2 on user(id,name,email); 2&#xff09;查询语句较烂 3&#xff09;关联查询太多join&a…

Embedding模型在大语言模型中的重要性

引言 随着大型语言模型的发展&#xff0c;以ChatGPT为首&#xff0c;涌现了诸如ChatPDF、BingGPT、NotionAI等多种多样的应用。公众大量地将目光聚焦于生成模型的进展之快&#xff0c;却少有关注支撑许多大型语言模型应用落地的必不可少的Embedding模型。本文将主要介绍为什么…

【SpringCloud Alibaba笔记】(2)Nacos服务注册与配置中心

Nacos Nacos简介与下载 是什么&#xff1f; 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos&#xff08;Dynamic Naming and Configuration Service&#xff09;就是注册中心&#xff0b;配置中心的组合 Nacos Eureka Config Bus 替代Eureka…

初识HTTP协议

Web服务器可以接收浏览器的请求&#xff0c;并将服务器中的web项目资源响应给浏览器&#xff0c;浏览器与服务器之间进行网络通信遵循HTTP协议。 一、什么是HTTP协议 超文本传输协议&#xff08;HTTP&#xff0c;HyperText Transfer Protocol&#xff09;(浏览器---->web服务…

27 UVM queue

uvm_queue类构建一个动态队列&#xff0c;该队列将按需分配并通过引用传递。 uvm_queue类声明&#xff1a; class uvm_queue #( type T int ) extends uvm_object 1 uvm_queue class hierarchy 2 uvm_queue class Methods 3 UVM Queue Example 在下面的示例中&#xff0c;…

基于深度卷积神经网络的垃圾分类识别系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 本文详细介绍了一基于深度卷积神经网络的垃圾分类识别系统。采用TensorFlow和Keras框架&#xff0c;通过卷积神经网络&#xff08;CNN&#xff09;进行模型训练和预测。引入迁移学习中的VGG16模型…

Linux:apache优化(7)—— 日志分割|日志合并

作用&#xff1a;随着网站访问量的增加&#xff0c;访问日志中的信息会越来越多&#xff0c; Apache 默认访问日志access_log单个文件会越来越大&#xff0c;日志文件体积越大&#xff0c;信息都在一个文件中&#xff0c;查看及分析信息会及不方便。 分割 实现方式&#xff1a…

『JavaScript』JavaScript事件类型详解:全面解析各类用户交互行为

&#x1f4e3;读完这篇文章里你能收获到 理解事件驱动编程的基本概念和工作原理掌握JavaScript中常见的事件类型及其应用场合学习如何使用DOM API添加和移除事件监听器探讨事件冒泡、事件捕获和事件委托等高级事件处理技术 文章目录 一、事件处理程序1. HTML事件处理HTML事件处…

单片机键盘程序设计举例

1、键盘与的连接 图3键盘连接 图4单片机与键盘接口图 2、通过1/0口连接。将每个按钮的一端接到单片机的I/O口&#xff0c;另一端接地&#xff0c;这是最简单的办法&#xff0c;如图3所示是实验板上按钮的接法&#xff0c;四个按钮分别接到P3.2 、P3.3、P3.4和P3.5。对于这种键…

HttpClient入门

HttpClient入门 简介 HttpClient 是 Apache HttpComponents 项目中的一个开源的 Java HTTP 客户端库&#xff0c;用于发送 HTTP 请求和处理 HTTP 响应。它提供了一组强大而灵活的 API&#xff0c;使得在 Java 程序中执行 HTTP 请求变得相对简单 maven依赖 org.apache.httpco…

72内网安全-域横向CSMSF联动及应急响应知识

拿到才行&#xff0c;拿不到就是多余的 案例一MSF&CobaltStrike 联动 Shell 有一些功能可能cs或者msf强大一些&#xff0c;他们两个可以相互调用&#xff0c;在真实情况下也是可以cs和msf同时启动的&#xff0c; cs移交给msf .创建Foreign监听器 “Listeners”“Add”…

[NAND Flash 4.2] Flash 原理 | NOR Flash 和 NAND Flash 闪存详解

依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< 前言 智能手机有一个可用的存储空间(如苹果128G),电脑里有一个固态硬盘空间(如联想512G), 这个空间是啥呢? 这个存储空间就是闪存设备,我们都统称为…

ILI9481 TFT3.5寸屏STM32F446ZEXX FMC驱动方式详解

图片来源于网络&#xff0c;如若侵权请联系博主删除 文章目录 1. 背景2. 基础知识2.1 TFT-LCD2.2 硬件接线2.3 FMC2.4 ILI9481 3. 软件抽象 1. 背景 最近做项目需要&#xff0c;博主在某宝上买了一块3.5寸的TFT屏&#xff0c;店家虽然发了资料&#xff0c;但是往产品上移植驱动…

动画墙纸:将视频、网页、游戏、模拟器变成windows墙纸——Lively Wallpaper

文章目录 前言下载github地址&#xff1a;网盘 关于VideoWebpagesYoutube和流媒体ShadersGIFs游戏和应用程序& more:Performance:多监视器支持&#xff1a;完结 前言 Lively Wallpaper是一款开源的视频壁纸桌面软件&#xff0c;类似 Wallpaper Engine&#xff0c;兼容 Wal…