乐优商城第十九天(购物车)

html5的web存储

localstorage 没有时间限制,只能保存字符串。可以在网页之间传输信息。

购物车的流程。

首先,我们在商品详情页点击加入购物车,把sku信息保存在localstorge中,当页面跳转到购物车页面的时候,我们判断有没有登陆 ,没有登陆的话,我们保存在本地的购物车,也是localstoreage中,如果登录u了,我们把数据提交到后台处理。

本地购物车也要判断是否登陆,如果登陆,要进行和后台的合并。

后台添加的逻辑

我们把skuId和num发送到后台,后台会将我们的购物车添加到redis中

public void addCart(Cart cart) {
    //凡事走到这里的,都是登录过的
    //用户名我们在token中已经解析过了
    UserInfo userInfo = LoginInterceptor.getUserInfo();
    String key = KEY_PREFIX + userInfo.getId();
    //通过key获取redis中的数据
    BoundHashOperations<String, Object, Object> cartsData = redisTemplate.boundHashOps(key);
    Long skuId = cart.getSkuId();
    Integer num = cart.getNum();
    Boolean boo = cartsData.hasKey(skuId.toString());
    //如果购物车中存在此商品
    if (boo) {
        //修改购物车中商品的数量
        //1.首先从redis中得到该商品
        String json = cartsData.get(skuId.toString()).toString();
        //将得到的数据解析成对象
        Cart redisCart = JsonUtils.parse(json, Cart.class);
        //修改对象中商品的数量
        redisCart.setNum(redisCart.getNum() + num);
    } else {
        //根据skuid查询商品的详细信息
        ResponseEntity<Sku> skuResp = this.goodsClient.querySkuBySkuId(skuId);
        if (!skuResp.hasBody()) {
            logger.error("没有查到相关sku的信息:{}" + skuId);
            throw new RuntimeException();
        }
        //将信息和数量封装在cart        Sku skuBody = skuResp.getBody();
        cart.setImage(StringUtils.isBlank(skuBody.getImages()) ? "" : StringUtils.split(skuBody.getImages(), ",")[0]);
        cart.setOwnSpec(skuBody.getOwnSpec());
        cart.setPrice(skuBody.getPrice());
        cart.setTitle(skuBody.getTitle());
        cart.setUserId(userInfo.getId());
    }
    //将此商品添加到redis    cartsData.put(skuId.toString(), JsonUtils.serialize(cart));
}

查询购物车

/**
 * 查询购物车
 *
 * @return
 */
public List<Cart> queryCart() {
    UserInfo userInfo = LoginInterceptor.getUserInfo();
    Long userId = userInfo.getId();
    String key = KEY_PREFIX + userId;
    if (!this.redisTemplate.hasKey(key)) {
        return null;
    }
    BoundHashOperations<String, Object, Object> cartData = this.redisTemplate.boundHashOps(key);
    List<Object> values = cartData.values();
    if (CollectionUtils.isEmpty(values)) {
        return null;
    }
    List<Cart> carts = new ArrayList<>();
    for (Object value : values) {
        Cart c = JsonUtils.parse(value.toString(), Cart.class);
        carts.add(c);
    }
    return carts;
}

这边逐一将字符串进行系列化,因为我们的stringrestemplate保存到全是字符串的形式。

更新商品的信息,对商品的数量进行修改

public void updateCart(Long skuId, Integer num) {
    //得到用户的信息
    UserInfo userInfo = LoginInterceptor.getUserInfo();
    Long userId = userInfo.getId();
    String key = KEY_PREFIX + userId;
    //根据key查询到数据
    if (this.redisTemplate.hasKey(key)) {
        BoundHashOperations<String, Object, Object> cartData = this.redisTemplate.boundHashOps(key);
        String json = cartData.get(skuId.toString()).toString();
        Cart redisCart = JsonUtils.parse(json, Cart.class);
        redisCart.setNum(num);
        cartData.put(skuId.toString(), JsonUtils.serialize(redisCart));
    } else {
        logger.error("您所修改的商品不存在");
    }

删除购物车中商品的信息

 * 删除购物车
 * @param skuId
 */
public void daleteCart(Long skuId) {
    //首先得到登陆用户的信息
    UserInfo userInfo = LoginInterceptor.getUserInfo();
    Long userId = userInfo.getId();
    String key = KEY_PREFIX + userId;
    Boolean boo = this.redisTemplate.hasKey(key);
    if (boo) {
        BoundHashOperations<String, Object, Object> cartData = this.redisTemplate.boundHashOps(key);
            cartData.delete(skuId.toString());
    }
}

购物车我们实现的功能

未登陆状态,数据保存在localstrage中

登陆后,未登陆的数据保存到后台,然后查询数据,查询到的数据就是本地加登陆状态的数据。


在购物车微服务,我们也要校验用户有没有登陆,并拿到用的id,我们采用springmvc的过滤器来做这个判断。

过滤器的实现思路,首先用一个类继承HandlerInterceptorAdapter类,选择要实现的方法,哪个拦截器,前置后置,最终。

然后将这个拦截器添加到springmvc中


public class LoginInterceptor extends HandlerInterceptorAdapter {

    private JwtProperties jwtProperties;

    //一个线程域,存放登陆的对象
    private static final ThreadLocal<UserInfo> t_user = new ThreadLocal<>();

    public LoginInterceptor(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    //获取登陆用户的方法
    public static UserInfo getUserInfo() {
        return t_user.get();
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {
            //首先拿到令牌
            String token = CookieUtils.getCookieValue(request, jwtProperties.getCookieName());
            //判断令牌是否是空
            if (StringUtils.isBlank(token)) {
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
                return false;
            }
            //令牌不为空,解析得到用户的信息
            UserInfo userInfo = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey());
            t_user.set(userInfo);
            return true;
        } catch (Exception e) {
            //抛出异常,证明未登陆,401
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        t_user.remove();
    }

}
@Configuration
@EnableConfigurationProperties(JwtProperties.class)
public class MvcConfig implements WebMvcConfigurer {


    //把配置文件注入
    @Autowired
    private JwtProperties jwtProperties;

    //将拦截器注入
    @Bean
    public LoginInterceptor loginInterceptor() {
        return new LoginInterceptor(jwtProperties);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");

    }







猜你喜欢

转载自blog.csdn.net/qpc672456416/article/details/80719094