【SpringBoot开发】之商城项目案例(商品详情及添加购物车)

发布时间:2024年01月02日

?🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是君易--鑨,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的博客专栏《SpringBoot开发之商城项目系列》。🎯🎯

🎁如果感觉还不错的话请给我关注加三连吧!🎁🎁


前言

? ? ? ? 在之前的商城项目系列的博客中我们实现了用户登陆、商城首页的数据绑定,今天的这期博客给老铁们带来的是商品详情页面的实现以及添加购物车的功能实现。

一、商品详情界面的实现

? ? ? ? 首先在我们的index.html上将点击商品跳转指定请求路径填写完成

? ? ? ? ?在我们的商品控制层中编写对其的查询商品详情信息的请求

? ? ? ? ?其次,我们在商品的详情界面进行对应的数据绑定

? ? ? ? 接下来就是我们进行一个功能测试的展示?

注意事项
	注意:
				1)${goods.goodsTitle!}:只能判断goodsTitle属性是否为空,不能判断goods对象是否为空
				2)${(goods.goodsTitle)!}:既可以判断goods对象是否为空,也可以判断goodsTitle属性是否为空

二、添加购物车

? ? ? ? ? ? ? ?在商品详情的js文件中设置对应添加购物车的点击事件,因为我们在头部导入了一些js依赖,因此我们在js依赖中设置点击事件。

? ? ? ? ?我们在cart.js文件中进行设置我们的点击事件

? ? ? ? ?我们编写对其的购物车控制层,我们购物车并不存放到我们的数据库中,而是存放到我们的缓存中。(注:购物车存放到缓存中需要注意过期时间,以及数据持久化的问题需要优化)我们现在对应的redis编写对应的接口方法。首先定义一个参数接受类。

?CartVo.java
package com.yx.yxshop.vo;

import com.yx.yxshop.pojo.Goods;
import lombok.Data;
import lombok.EqualsAndHashCode;

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

/**
 * com.yx.yxshop.vo
 *
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create 2024/1/1
 * 购物车数据接受类
 */
@Data
public class CartVo implements Serializable {

//    商品id
    private Long gid;
//  商品名称
    private String goodsName;
//    接受数量
    private Integer num;
//  商品标题
    private String goodsTitle;
//    商品价格
    private BigDecimal goodsPrice;
//  商品类型
    private String goodsType;

}

? ? ? ? ?下面是对应的接口类以及接口实现类的代码

接口类?

?接口实现类
package com.yx.yxshop.service.impl;

import com.yx.yxshop.core.Constans;
import com.yx.yxshop.pojo.User;
import com.yx.yxshop.service.IRedisService;
import com.yx.yxshop.vo.CartVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;

import static com.yx.yxshop.core.Constans.REDIS_CAR_PREFIX;
import static com.yx.yxshop.core.Constans.REDIS_USER_PREFIX;

/**
 * com.yx.yxshop.service.impl
 *
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create 2023/12/30
 * 接口实现类
 */
@Service
public class IRedisServiceImpl implements IRedisService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void saveUser(String token, User user) {
        //        将个人信息存放到我们的缓存中
        redisTemplate.opsForValue().set(REDIS_USER_PREFIX +token,user);
    }

    @Override
    public User loadUser(String token) {
        return (User) redisTemplate.opsForValue().get(REDIS_USER_PREFIX+token);
    }

    @Override
    public void saveCart(User user, CartVo vo) {
//        我们根据需求利用hash结构存储值
//        拿到哈希的操作对象
        HashOperations<String,String,CartVo> Operations = redisTemplate.opsForHash();
//         获取大键
        String bigkey=REDIS_CAR_PREFIX + user.getId();
//      获取hashkey
        String hashkey=vo.getGid().toString();
//        进行缓存查找
        Boolean has = Operations.hasKey(bigkey, hashkey);
        if (has){//有,则修改缓存的数据
//            获取原有的购物车信息
            CartVo cartVo = Operations.get(bigkey, hashkey);
//            数量设置
            vo.setNum(cartVo.getNum()+vo.getNum());

        }
            //         如果没有这个数据,就是增加购物车
        Operations.put(bigkey,hashkey,vo);

    }

    @Override
    public List<CartVo> loadCart(User user) {
//        我们根据需求利用hash结构存储值
//        拿到哈希的操作对象
        HashOperations<String,String,CartVo> Operations = redisTemplate.opsForHash();
//        获取大键
        String bigkey=REDIS_CAR_PREFIX + user.getId();
//        获取指定用户的购物车
        List<CartVo> values = Operations.values(bigkey);
//        返回购物车信息
        return  values;
    }

}
控制层编写
package com.yx.yxshop.controller;

import com.yx.yxshop.pojo.User;
import com.yx.yxshop.resp.JsonResponseBody;
import com.yx.yxshop.service.IRedisService;
import com.yx.yxshop.utils.CookieUtils;
import com.yx.yxshop.vo.CartVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * <p>
 * 购物车控制类 前端控制器
 * </p>
 *
 * @author yangxin
 * @since 2023-12-27
 */
@Controller
@RequestMapping("/cart")
public class CartController {

//    引入缓存接口
    @Autowired
    private IRedisService redisService;

    /**
     * 编写新增购物车的请求接口
     * @param vo
     * @return
     */
    @RequestMapping("/add")
    @ResponseBody
    public JsonResponseBody<?> add(CartVo vo, HttpServletRequest request){
//        根据用户token获取用户信息
        String token = CookieUtils.getCookieValue(request, "userToken");
//      调用读取用户信息的方法
        User user = redisService.loadUser(token);
//      将数据存放到缓存
        redisService.saveCart(user,vo);
        return JsonResponseBody.success();
    }

}

? ? ? ? 加下来我们运行项目进行网页测试功能

三、 跳转购物车显示数据

? ? ? ? 因为我们存储在缓存中的购物车信息并不是完整的,因此子在显示的时候需要进行异步对其数据的查询获取

? ? ? ? 然后在前端进行设置指定的跳转路径?

?????????在购物车vo类中添加一个计算单件商品总价的方法

? ? ? ? ?进行页面数据绑定

? ? ? ? 页面显示效果?

四、?退出登陆

? ? ? ? 退出登陆就是相当于将存储在网页应用程序中的Cookie进行清除即可,我们编写一个退出登陆的相应方法。

?下面是接口类和接口实现类的代码?

? ? ? ? 控制层编写请求?

? ? ? ? 页面设置退出的按钮?

?

? ? ? ? 接下来就是演示效果?

? ? ? ? 有上面的动图所示,我们的网页Cookie进行了相应的清除?

五、?参数解析器

? ? ? ? 我们在添加购物车、下单等等的应用场景中需要获取用户信息,我们对其封装成一个方法,减少我们的代码冗余。因此我们可以使用Spring自带的参数解析器。我们新建一个类

?UserArgumentResolver.java
package com.yx.yxshop.core;

import com.yx.yxshop.pojo.User;
import com.yx.yxshop.service.IRedisService;
import com.yx.yxshop.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;

/**
 * com.yx.yxshop.core
 *
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create 2024/1/1
 * 参数解析类
 */
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private IRedisService redisService;

    @Override
//    是否进行该操作
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType()== User.class;//只有是User.class的参数才进行该操作
    }

    @Override

    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//        获取request
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
        //        根据用户token获取用户信息
        String token = CookieUtils.getCookieValue( request, "userToken");
//      调用读取用户信息的方法
        User user = redisService.loadUser(token);
        return user;
    }
}

? ? ? ? ?参数解析类的使用的话还需要添加一个配置类

?WebConfig.java
package com.yx.yxshop.config;

import com.yx.yxshop.core.UserArgumentResolver;
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.WebMvcConfigurer;

import java.util.List;

@Component
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private UserArgumentResolver userArgumentResolver;

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

}

? ? ? ? ?我们直接运行即可使用


?🎉🎉本期的博客分享到此结束🎉🎉

📚📚各位老铁慢慢消化📚📚

🎯🎯下期博客博主会带来新货🎯🎯

🎁三连加关注,阅读不迷路?!🎁

文章来源:https://blog.csdn.net/weixin_74352229/article/details/135313972
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。