Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】

点击指定的商品去到指定的商品详情页面:点击加入购物车,会将指定的商品加入该账号的购物车中去:

实现点击指定的商品详情页面:

前台传递商品id

后台接收:

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第1张图片

GoodsController 

package com.lya.lyaspshop.controller;

import com.lya.lyaspshop.pojo.Goods;
import com.lya.lyaspshop.service.impl.GoodsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


/**
 * 

* 商品信息表 前端控制器 *

* * @author lya * @since 2023-12-27 */ @RequestMapping("/goods") @Controller//跳页面 //@RestController//显示数据 public class GoodsController { @Autowired private GoodsServiceImpl goodsService; // 首页商品 @RequestMapping("/list") public Object index() { List g1 = goodsService.list(); return g1; } @RequestMapping("/query") public String query(Goods goods , Model model) { // 前台带一个gid,我们来查询 Goods g = goodsService.getById(goods.getGid()); model.addAttribute("g",g); return "proDetail" ; } }

购物车界面:

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第2张图片



	
		<#include "common/head.html">
		
		
	
	
		
		<#include "common/top.html">
		
		
首页 / 装饰摆件 / 干花花艺 / <#-- 注意: 1)${goods.goodsTitle!}:只能判断goodsTitle属性是否为空,不能判断goods对象是否为空 2)${(goods.goodsTitle)!}:既可以判断goods对象是否为空,也可以判断goodsTitle属性是否为空 --> 【最家】非洲菊仿真花干花
<#--
]
-->

${(g.goodsName)!}

${(g.goodsDetail)!}

¥${(g.goodsPrice)!}

颜色分类

白瓷花瓶+20支快乐花

白瓷花瓶+20支兔尾巴草

20支快乐花

20支兔尾巴草

数量  库存${(g.goodsStock)!}

1

请选择商品属性!

馨***呀

不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分

2016年12月27日08:31颜色分类:大中小三件套(不含花)

么***周

花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!

2016年12月27日08:31颜色分类:大中小三件套(不含花)

馨***呀

不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分

2016年12月27日08:31颜色分类:大中小三件套(不含花)

么***周

花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!

2016年12月27日08:31颜色分类:大中小三件套(不含花)

馨***呀

不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分

2016年12月27日08:31颜色分类:大中小三件套(不含花)

么***周

花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!

2016年12月27日08:31颜色分类:大中小三件套(不含花)

馨***呀

不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分

2016年12月27日08:31颜色分类:大中小三件套(不含花)

么***周

花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!

2016年12月27日08:31颜色分类:大中小三件套(不含花)

馨***呀

不好意思评价晚了,产品很好,价格比玻璃品便宜,没有我担心的杂色,发货快,包装好,全5分

2016年12月27日08:31颜色分类:大中小三件套(不含花)

么***周

花瓶超级棒,我看图以为是光面的,收货发现是磨砂,但感觉也超有质感,很喜欢。磨砂上面还有点纹路,不过觉得挺自然的,不影响美观。包装也很好,绝对不会磕碎碰坏,好评!

2016年12月27日08:31颜色分类:大中小三件套(不含花)

<#include "common/footer.html">

点击加入购物车:

将商品id绑定到data-gid属性上面去:

为其设置点击事件:

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第3张图片

	/****************************proDetail 加入购物车*******************************/
	$(".btns .cart").click(function(){
		//获得添加购物车的id data-gid
		let gid = this.dataset.gid
		//发送添加购物车的数量
		let num = $("div.num span.fl").text()
		//发起请求添加购物车
		$.post('/cart/add',{gid,num},resp=>{
			if(resp.code===200){
				alert('增加成功')
			}
		},"json")
	});
	

这里我们后端要思考:购物车的东西我们因该放在哪里?

Redis 可以作为缓存系统,将热点数据存储在内存中,提高读写性能和响应速度,减少对后端数据存储的压力。

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第4张图片

    @RequestMapping("/add")
    @ResponseBody
    public JsonResponseBody add(User user, CartItemVo vo, HttpServletRequest request){
        String token = CookieUtils.getCookieValue(request, "userToken");
        User userByToken = redisService.getUserByToken(token);
        //将购物车的商品放到缓存数据库中
        redisService.saveCart(userByToken,vo);
        return JsonResponseBody.success();
    }

这里写一个类用来放入保存到redis中去:

注意这个类要实现实现Serializable接口!!!

在Java中,实现Serializable接口是为了让一个对象可以被序列化和反序列化。序列化指的是将对象转换成字节流,以便可以在网络上传输或者保存在磁盘上;而反序列化则是将字节流重新转换成对象。

CartItemVo:
package com.lya.lyaspshop.vo;

import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;

@Data
public class CartItemVo implements Serializable {

    private Long gid;
    private String goodsName;
    private String goodsTitle;
    private BigDecimal goodsPrice;
    private String goodsImg;
    private String goodsType;
    private Integer num;

    public BigDecimal cartprice(){
        return goodsPrice.multiply(BigDecimal.valueOf(num.doubleValue()));
    }

}

保存到redis中的逻辑:

redis中有许多的数据结构:

  • String(字符串类型)常见使用场景是:存储 Session 信息、存储缓存信息(如详情页的缓存)、存储整数信息,可使用 incr 实现整数+1,和使用 decr 实现整数 -1;
  • List(列表类型)常见使用场景是:实现简单的消息队列、存储某项列表数据;
  • Hash(哈希表类型)常见使用场景是:存储 Session 信息、存储商品的购物车,购物车非常适合用哈希字典表示,使用人员唯一编号作为字典的 key,value 值可以存储商品的 id 和数量等信息、存储详情页信息;
  • Set(集合类型)是一个无序并唯一的键值集合,它的常见使用场景是:关注功能,比如关注我的人和我关注的人,使用集合存储,可以保证人员不会重复;
  • Sorted Set(有序集合类型)相比于 Set 集合类型多了一个排序属性 score(分值),它的常见使用场景是:可以用来存储排名信息、关注列表功能,这样就可以根据关注实现排序展示了。

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第5张图片

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第6张图片

    @Override
    public void saveCart(User user, CartItemVo vo) {
        HashOperations operations = redisTemplate.opsForHash();
        //获取购物车key
        String bigKey=REDIS_CART_PREFIX + user.getId();
        //获取购物车中商品的gid
        String hashKey=vo.getGid().toString();
        //判断购物车中是否有该商品
        Boolean has = operations.hasKey(bigKey, hashKey);
        //如果有数据 修改购物车
        if(has){
            CartItemVo item = operations.get(bigKey, hashKey);
            vo.setNum(item.getNum()+vo.getNum());
        }
        //添加缓存
        operations.put(bigKey, hashKey,vo);
    }

展示购物车:

    @Override
    public List loadCart(User user) {
        //获取购物车中的商品
        HashOperations operations = redisTemplate.opsForHash();
        String bigKey=REDIS_CART_PREFIX + user.getId();
        //根据用户id获取购物车数据
        List values = operations.values(bigKey);
        return values;
    }

退出当前登录:
 

前台:

后台:

清除缓存就行:

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第7张图片

    @RequestMapping("/userLogout")
//    指定返回JsonResponseBody格式
    public String logout (UserVo userVo , HttpServletRequest request, HttpServletResponse response){

        String userToken = CookieUtils.getCookieValue(request, "userToken");
        redisService.removeUser(userToken);

        CookieUtils.deleteCookie(request,response,"userToken");
        CookieUtils.deleteCookie(request,response,"nickname");
            return "redirect:/";
    }

调用redis内置方法delete

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第8张图片

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第9张图片

使用参数解析器:

HandlerMethodArgumentResolver是Spring框架中的一个接口,用于解析处理方法参数。

在Spring MVC中,当一个请求到达时,框架会尝试将请求参数映射到控制器方法的参数上。HandlerMethodArgumentResolver接口定义了一组方法,用于解析不同类型的方法参数。

实现HandlerMethodArgumentResolver接口的类可以自定义参数解析逻辑,并告诉Spring如何将请求参数转换为方法参数。

通常,开发人员可以根据业务需求实现自己的HandlerMethodArgumentResolver,以支持自定义的请求参数类型或者处理逻辑。

使用HandlerMethodArgumentResolver可以帮助简化控制器方法的参数处理过程,提高代码的可读性和可维护性。

当您使用参数解析器时,您可以将输入的参数进行解析,并根据解析后的结果执行相应的操作。参数解析器可以帮助您从输入中提取所需的信息,并对其进行处理。

package com.lya.lyaspshop.core;

import com.lya.lyaspshop.exception.BusinessException;
import com.lya.lyaspshop.pojo.User;
import com.lya.lyaspshop.service.impl.RedisServiceImpl;
import com.lya.lyaspshop.utils.CookieUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;

import static com.lya.lyaspshop.core.Constants.USER_CACHE_TOKEN;
import static com.lya.lyaspshop.resp.JsonResponseStatus.NO_LOGIN;

@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private RedisServiceImpl redisService;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType() == User.class;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
        String token = CookieUtils.getCookieValue(request, USER_CACHE_TOKEN);
        if (token == null) throw new BusinessException(NO_LOGIN);
        return redisService.getUserByToken(token);
    }

}

配置:配置类才能使用

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第10张图片

package com.lya.lyaspshop.core;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Component
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private UserArgumentResolver userArgumentResolver;

    @Override
    public void addArgumentResolvers(List resolvers) {
        resolvers.add(userArgumentResolver);
    }

}

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第11张图片

使用解析类:

Spring Boot快速搭建一个简易商城项目三,【加入购物车篇】_第12张图片

你可能感兴趣的:(spring,boot,java,后端)