JAVA零基础入门8-实现购物车功能

当我们制作好了菜品展示之后,用户可以根据需求来进行点单操作,将选好的菜品加入到购物车里,方便后续进行结算,今天要完成的是实现一个加入购物车的功能

2023/11/17

1.缓存点单信息

        逻辑如下:

        要实现购物车的功能,我们需要在每个菜品后面绑定一个添加的操作,用户每次点击添加后,会发送菜品的一些相关信息到controller,然后我们将它存到缓存redis中,因为购物车不可能一直存在,所有我们本次第一次使用redis来缓存数据。

        前端页面修改如下:

        <td th:if="${session.USERTYPE == 'customer'}">
            <input type="text" th:id="carinput+${cai.id}" style="display: none" value="0">
            <button type="button" th:id="carbutton+${cai.id}" th:data-id="${cai.id}" onclick="addcar(this)">+1</button>
        </td>

<script th:inline="javascript">
    function addcar(button){
        const caiId = button.getAttribute('data-id')
        const input = document.getElementById("carinput"+caiId)
        //value为字符串,需要转换
        let cainum = parseInt(input.value,10);
        cainum+=1;
        const formata = new FormData
        formata.append('id',caiId)
        formata.append('num',cainum)
        fetch('/car',{
            method:'POST',
            body:formata
        }).then(res=>res.json()   )
            .then(res=>{
            console.log(res.message);
            alert(res.message)
        })
    }
</script>

如果用户为消费者,则在每个菜品后面添加一个“+1”的按钮,使用fetch异步发送请求,每次点击后,向后端发送菜品id同时num+1,菜品数量初始化为0

        后端代码修改如下:

@Controller
public class CarController {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    private HashOperations<String, Object, Object> hashOperations;
    @PostMapping("/car")
    public ResponseEntity<Map<String,String>> addCar(@RequestParam("id")int id, @RequestParam("num")int num, HttpSession session){
        String username = (String) session.getAttribute("USER");
        if (username==null){
            Map<String,String> response = new HashMap<>();
            response.put("message","用户未登录");
            return ResponseEntity.badRequest().body(response);
        }
        // 构建Redis中的购物车键,这里使用了哈希结构
        String cartKey = "cart:" + username;
        String caiid = "cai" + id;
        // 获取Redis哈希操作的引用
        hashOperations = redisTemplate.opsForHash();

        // 更新Redis中的购物车数据
        // 如果该商品已经存在于购物车中,它的数量将被累加
        // 如果该商品是新添加的,它将被初始化为传入的数量
        hashOperations.increment(cartKey, caiid, num);
        // 更新model,用于视图显示或进一步的处理
        Map<String,String> response = new HashMap<>();
        response.put("message","商品已加入购物车");
//        model.addAttribute("message", "商品已添加到购物车");
        return ResponseEntity.ok().body(response); // 或重定向到购物车页面
    }

首先自动注解redistemplate意味着我们可以使用redis的一些操作,同时注解hashOperation意味着我们可以使用哈希操作(object意味着可以处理任何数据),在方法中我们不适用String类型,这种是返回视图模板,通过model来渲染数据,需要刷新页面,不适合我们异步请求,因此使用ResopnseEntity类型。

具体的逻辑如下:

        我们有三个参数分别是id,num和session,在前面的logincontroller中我们定义了当验证用户密码通过后,会为用户创建一个session存储在redis中,因此此时我们可以直接获取session的用户名,如果用户名不为空则说明已经验证过了同时处于有效期内,这时,我们将用car+username的方法为每个用户新建购物车,初始化hashOperation为redis的hash操作,然后使用hashOperation的increment方法,增加num

        实现如下:

2.展示购物车

        在将菜品信息加入到缓存中后,我们要想办法将它给提取出来,一开始我想要使用的是model方法,毕竟动态渲染真的很方便,但是提交表单后页面会自动刷新,弹窗会自动消失,因此我采用了fetch方法

        前端代码修改如下:

<button id="carbutton" onclick="showcar()" type="submit">进入购物车</button>
<script>
    function showcar(){
        fetch('/getcarinfo',{
            method:'POST'
        }).then(res=>res.json())
            .then(data=>{
                updatacar(data);
                document.getElementById("carModal").style.display="block";
            }).catch(err=>console.error("error",err))
    }
    function updatacar(carinfo){
        const tbody = document.querySelector("#carModal .modal-content table tbody");
        tbody.innerHTML="";
        for(const[key,value]of Object.entries(carinfo)){
            const row = document.createElement('tr');
            row.innerHTML = `<td>${key}</td><td>${value}</td>`
            tbody.appendChild(row);
        }
    }
    function closeModal3() {
        document.getElementById("carModal").style.display = 'none';
    }
</script>
<div id="carModal"  class="modal" style="display: none">
    <div class="modal-content">
        <h2>购物车</h2>
        <span class="close-button"  id="closeModalButton3" onclick="closeModal3()">&times</span>
        <table class="centered-table">
            <thead>
            <tr>
                <th>菜名</th>
                <th>数量</th>
            </tr>
            </thead>
            <tbody>
            <tr></tr>
            </tbody>
        </table>
    </div>
</div>

        后端代码修改如下:

  @PostMapping("/getcarinfo")
    public ResponseEntity<Map<Object,Object>> getcarinfo(Model model,HttpSession session){
        String username = (String)session.getAttribute("USER");
        System.out.println(username);
        String cartKey = "cart:" + username;
        // 获取Redis哈希操作的引用
        hashOperations = redisTemplate.opsForHash();
        Map<Object, Object> carinfo = hashOperations.entries(cartKey);
        System.out.println(carinfo);
        return ResponseEntity.ok().body(carinfo);

    }

在展示方面我们依然采用了模拟对话弹窗的方式,展示了菜品的id信息和添加的数量,当点击进入购物车按钮后,调用fetch请求,后端接收请求后,根据用户名来获取对应的购物车信息,返回给前端一个carinfo,前端拿到数据后,调用updata方法,更新tbody中的数据

这里我们使用了一个queryselector元素选择器,可以选择类,id,标签名等多种方式,定位到tbody后,我们使用for of 方法,将carinfo对象的键值赋值给key和value,并使用反引号的方式新加到tr元素中,最终呈现效果如下:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值