Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)二十一(购物车)

window.location.href = “http://www.leyou.com/cart.html”;

});

}

结果:

在这里插入图片描述

添加完成后,页面会跳转到购物车结算页面:cart.html

3.3.查询购物车


3.3.1.校验用户登录

因为会多次校验用户登录状态,因此我们封装一个校验的方法:

在common.js中:

在这里插入图片描述

3.3.2.查询购物车

页面加载时,就应该去查询购物车。cart.html中

var cartVm = new Vue({

el: “#cartApp”,

data: {

ly,

carts: [],// 购物车数据

},

created() {

this.loadCarts();

},

methods: {

loadCarts() {

// 先判断登录状态

ly.verifyUser()

.then(() => {

// 已登录

})

.catch(() => {

// 未登录

this.carts = ly.store.get(“carts”) || [];

this.selected = this.carts;

})

}

}

components: {

shortcut: () => import(“/js/pages/shortcut.js”)

}

})

刷新页面,查看控制台Vue实例:

在这里插入图片描述

3.5.2.渲染到页面

接下来,我们在页面中展示carts的数据:

页面位置:

在这里插入图片描述

修改后:

在这里插入图片描述

要注意,价格的展示需要进行格式化,这里使用的是我们在common.js中定义的formatPrice方法:

在这里插入图片描述

效果:

在这里插入图片描述

3.6.修改数量


我们给页面的 +-绑定点击事件,修改num 的值:

在这里插入图片描述

两个事件:

increment© {

c.num++;

ly.verifyUser()

.then(() => {

// TODO 已登录,向后台发起请求

})

.catch(() => {

// 未登录,直接操作本地数据

ly.store.set(“carts”, this.carts);

})

},

decrement© {

if (c.num <= 1) {

return;

}

c.num–;

this.verifyUser()

.then(() => {

// TODO 已登录,向后台发起请求

})

.catch(() => {

// 未登录,直接操作本地数据

ly.store.set(“carts”, this.carts);

})

},

3.7.删除商品


给删除按钮绑定事件:

在这里插入图片描述

点击事件中删除商品:

deleteCart(i) {

ly.verifyUser()

.then(() => {

// 已登录

})

.catch(() => {

// 未登录

this.carts.splice(i, 1);

ly.store.set(“carts”, this.carts);

})

}

3.8.选中商品


在页面中,每个购物车商品左侧,都有一个复选框,用户可以选择部分商品进行下单,而不一定是全部:

在这里插入图片描述

我们定义一个变量,记录所有被选中的商品:

在这里插入图片描述

3.8.1.选中一个

我们给商品前面的复选框与selected绑定,并且指定其值为当前购物车商品:

在这里插入图片描述

3.8.2.初始化全选

我们在加载完成购物车查询后,初始化全选:

在这里插入图片描述

3.8.4.总价格

然后编写一个计算属性,计算出选中商品总价格:

computed: {

totalPrice() {

return this.selected.map(c => c.num * c.price).reduce((p1, p2) => p1 + p2, 0);

}

}

在页面中展示总价格:

在这里插入图片描述

效果:

在这里插入图片描述

4.已登录购物车

===================================================================

4.1.购物车的微服务


4.1.1.创建购物车的微服务

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.1.2.pom依赖

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns=“http://maven.apache.org/POM/4.0.0”

xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>

leyou

com.leyou.parent

1.0.0-SNAPSHOT

4.0.0

com.leyou.service

ly-cart

org.springframework.boot

spring-boot-starter-web

org.springframework.cloud

spring-cloud-starter-netflix-eureka-client

org.springframework.cloud

spring-cloud-starter-openfeign

org.springframework.boot

spring-boot-starter-data-redis

4.1.3.配置文件

在这里插入图片描述

在这里插入图片描述

server:

port: 8088

spring:

application:

name: cart-service

redis:

host: 192.168.206.66

eureka:

client:

service-url:

defaultZone: http://127.0.0.1:10086/eureka

registry-fetch-interval-seconds: 5

instance:

prefer-ip-address: true

ip-address: 127.0.0.1

instance-id: e u r e k a . i n s t a n c e . i p − a d d r e s s . {eureka.instance.ip-address}. eureka.instance.ipaddress.{server.port}

lease-renewal-interval-in-seconds: 3

lease-expiration-duration-in-seconds: 10

4.1.4.启动类

在这里插入图片描述

在这里插入图片描述

@SpringBootApplication

@EnableDiscoveryClient

@EnableFeignClients

public class LyCartApplication {

public static void main(String[] args) {

SpringApplication.run(LyCartApplication.class, args);

}

}

4.1.5.添加到网关的路由当中

在这里插入图片描述

5.已登录购物车

===================================================================

接下来,我们完成已登录购物车。

在刚才的未登录购物车编写时,我们已经预留好了编写代码的位置,逻辑也基本一致。

5.1.添加登录校验


购物车系统只负责登录状态的购物车处理,因此需要添加登录校验,我们通过JWT鉴权即可实现。

5.1.1.引入JWT相关依赖

我们引入之前写的鉴权工具:ly-auth-common

在这里插入图片描述

com.leyou.auth

ly-auth-common

1.0.0-SNAPSHOT

5.1.2.配置公钥

在这里插入图片描述

ly:

jwt:

pubKeyPath: C:\Users\ZHENG\Desktop\leyou_msgrs\rsa\rsa.pub # 公钥地址

cookieName: LY_TOKEN # cookie的名称

5.1.3.加载公钥

在这里插入图片描述

在这里插入图片描述

package com.leyou.cart.config;

import com.leyou.auth.utils.RsaUtils;

import lombok.Data;

import lombok.extern.slf4j.Slf4j;

import org.springframework.boot.context.properties.ConfigurationProperties;

import javax.annotation.PostConstruct;

import java.security.PublicKey;

@Data

@ConfigurationProperties(prefix = “ly.jwt”)

@Slf4j

public class JwtProperties {

private String pubKeyPath;// 公钥

private PublicKey publicKey; // 公钥

private String cookieName;

@PostConstruct

public void init(){

try {

// 获取公钥和私钥

this.publicKey = RsaUtils.getPublicKey(pubKeyPath);

} catch (Exception e) {

log.error(“初始化公钥失败!”, e);

throw new RuntimeException();

}

}

}

5.1.4.编写过滤器

引入依赖:

在这里插入图片描述

com.leyou.common

ly-common

1.0.0-SNAPSHOT

代码:

因为很多接口都需要进行登录,我们直接编写SpringMVC拦截器,进行统一登录校验。同时,我们还要把解析得到的用户信息保存起来,以便后续的接口可以使用。

在这里插入图片描述

在这里插入图片描述

package com.leyou.interceptor;

import com.leyou.auth.entity.UserInfo;

import com.leyou.auth.utils.JwtUtils;

import com.leyou.cart.config.JwtProperties;

import com.leyou.common.utils.CookieUtils;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.context.properties.EnableConfigurationProperties;

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

@Slf4j

public class UserInterceptor implements HandlerInterceptor {

private JwtProperties prop;

private static final ThreadLocal tl = new ThreadLocal<>();

public UserInterceptor(JwtProperties prop) {

this.prop = prop;

}

@Override

public boolean preHandle(HttpServletRequest request,

HttpServletResponse response,

Object handler) throws Exception {

//获取Cookie

String token = CookieUtils.getCookieValue(request, prop.getCookieName());

try {

//解析token

UserInfo user = JwtUtils.getUserInfo(prop.getPublicKey(), token);

//传递User

tl.set(user);

//放行

return true;

} catch (Exception e) {

log.error(“[购物车服务]解析用户身份失败”, e);

return false;

}

}

@Override

public void afterCompletion(HttpServletRequest request,

HttpServletResponse response,

Object handler, Exception ex)

throws Exception {

tl.remove();

}

public static UserInfo getLoginUser() {

return tl.get();

}

}

注意:

  • 这里我们使用了ThreadLocal来存储查询到的用户信息,线程内共享,因此请求到达Controller后可以共享User

  • 并且对外提供了静态的方法:getLoginUser()来获取User信息

5.1.5.配置过滤器

配置SpringMVC,使过滤器生效:

在这里插入图片描述

在这里插入图片描述

package com.leyou.cart.config;

import com.leyou.interceptor.UserInterceptor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.context.properties.EnableConfigurationProperties;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration

@EnableConfigurationProperties(JwtProperties.class)

public class MvcConfig implements WebMvcConfigurer {

@Autowired

private JwtProperties prop;

@Override

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(new UserInterceptor(prop)).addPathPatterns(“/**”);

}

}

5.2.后台购物车设计


数据结构设计

当用户登录时,我们需要把购物车数据保存到后台,可以选择保存在数据库。但是购物车是一个读写频率很高的数据。因此我们这里选择读写效率比较高的Redis作为购物车存储。

Redis有5种不同数据结构,这里选择哪一种比较合适呢?

  • 首先不同用户应该有独立的购物车,因此购物车应该以用户的作为key来存储,Value是用户的所有购物车信息。这样看来基本的k-v结构就可以了。

  • 但是,我们对购物车中的商品进行增、删、改操作,基本都需要根据商品id进行判断,为了方便后期处理,我们的购物车也应该是k-v结构,key是商品id,value才是这个商品的购物车信息。

综上所述,我们的购物车结构是一个双层Map:Map<String,Map<String,String>>

  • 第一层Map,Key是用户id

  • 第二层Map,Key是购物车中商品id,值是购物车数据

  • Map<string,Map<String,String>>

实体类

在这里插入图片描述

@Data

public class Cart {

private Long userId;// 用户id

private Long skuId;// 商品id

private String title;// 标题

private String image;// 图片

private Long price;// 加入购物车时的价格

private Integer num;// 购买数量

private String ownSpec;// 商品规格参数

}

4.3.添加商品到购物车


4.3.1.页面发起请求:

已登录情况下,向后台添加购物车:

在这里插入图片描述

这里发起的是Json请求。那么我们后台也要以json接收。

4.3.2.后台添加购物车

Service

这里我们不访问数据库,而是直接操作Redis。基本思路:

  • 先查询之前的购物车数据

  • 判断要添加的商品是否存在

  • 存在:则直接修改数量后写回Redis

  • 不存在:新建一条数据,然后写入Redis

代码:

在这里插入图片描述

在这里插入图片描述

controller

先分析一下:

  • 请求方式:新增,肯定是Post

  • 请求路径:/cart ,这个其实是Zuul路由的路径,我们可以不管

  • 请求参数:Json对象,包含skuId和num属性

  • 返回结果:无

在这里插入图片描述

在这里插入图片描述

package com.leyou.cart.web;

import com.leyou.cart.pojo.Cart;

import com.leyou.cart.service.CartService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.HttpStatus;

import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RestController;

@RestController

public class CartController {

@Autowired

private CartService cartService;

/*

新增购物车

*/

@PostMapping(“cart”)

public ResponseEntity addCart(@RequestBody Cart cart){

cartService.addCart(cart);

return ResponseEntity.status(HttpStatus.CREATED).build();

}

}

完善CartService

在这里插入图片描述

在这里插入图片描述

package com.leyou.cart.service;

import com.leyou.auth.entity.UserInfo;

import com.leyou.cart.pojo.Cart;

import com.leyou.common.utils.JsonUtils;

import com.leyou.interceptor.UserInterceptor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.BoundHashOperations;

import org.springframework.data.redis.core.StringRedisTemplate;

import org.springframework.stereotype.Service;

@Service

public class CartService {

@Autowired

private StringRedisTemplate redisTemplate;

private static final String KEY_PREFIX = “cart:uid:”;

public void addCart(Cart cart) {

//获取登录的用户

UserInfo user = UserInterceptor.getLoginUser();

//key

String key = KEY_PREFIX + user.getId();

//hashKey

String hashKey = cart.getSkuId().toString();

//记录num

Integer num = cart.getNum();

BoundHashOperations<String, Object, Object> operation = redisTemplate.boundHashOps(key);

//判断当前购物车商品是否存在

if(operation.hasKey(hashKey)){

//存在,修改数量

String json = operation.get(hashKey).toString();

cart = JsonUtils.toBean(json, Cart.class);

cart.setNum(cart.getNum() + num);

}

//写回redis

operation.put(hashKey,JsonUtils.toString(cart));

}

}

4.3.3.运行测试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在虚拟机的redis当中查看

在这里插入图片描述

5.4.查询购物车


5.4.1.页面发起请求

在这里插入图片描述

5.4.2.后台实现

Controller

在这里插入图片描述

/**

  • 查询购物车列表

  • @return

*/

@GetMapping

public ResponseEntity<List> queryCartList(){

return ResponseEntity.ok(cartService.queryCartList());

}

Service

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

资料过多,篇幅有限,需要文中全部资料可以点击这里免费获取前端面试资料PDF完整版!

自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。

zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6JOd55uS5a2QaXRibHVlYm94,size_20,color_FFFFFF,t_70,g_se,x_16)

在这里插入图片描述

在这里插入图片描述

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-srFRMgrm-1713508585832)]

[外链图片转存中…(img-WqCTDtno-1713508585832)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-XkjdQ2NW-1713508585833)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

[外链图片转存中…(img-1Krrh8Hr-1713508585833)]

最后

[外链图片转存中…(img-KAnkRrrt-1713508585833)]

[外链图片转存中…(img-9NXNJC6Q-1713508585833)]

资料过多,篇幅有限,需要文中全部资料可以点击这里免费获取前端面试资料PDF完整版!

自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。

  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本文介绍了一个基于Spring Boot、Spring Cloud和Vue前后分离项目实战。这个项目是一个简单的在线商城,包含了用户注册、登录、商品展示、购物、订单管理等功能。通过这个项目,读者可以深入理解前后分离的架构模式和互联网应用的开发方式。 首先,文章介绍了前后分离的基本概念和优势。前后分离是将应用的前和后代码分开来开发,使得前和后具有独立的开发周期和技术栈,进而提高了开发效率和代码质量。同时,前后分离还可以提供更好的用户体验和灵活性,对于互联网应用来说尤为重要。 接下来,文章介绍了项目的架构和技术栈。项目采用了Spring Boot和Spring Cloud框架来实现后代码,采用MyBatis作为ORM框架和Redis作为缓存中间件。同时,项目还采用了Vue.js作为前框架和Element UI组件库来实现前页面。通过这些开源框架和组件,可以快速搭建一个前后分离的互联网应用。 然后,文章介绍了项目的核心功能和代码实现。在用户注册和登录方面,项目采用了Spring Security框架和JWT令牌来实现用户认证和授权,保证了用户信息的安全性。在商品展示和购物方面,项目采用了Vue.js来实现前页面和事件处理。在订单管理方面,项目采用了MyBatis Plus来实现订单数据的持久化和分页查询。 最后,文章介绍了项目的测试和优化。通过对项目的压力测试和性能测试,文章发现项目还存在一些性能瓶颈和安全隐患,可以通过优化数据库查询、缓存配置和代码实现来提高应用的性能和安全性。 总之,这篇文章介绍了一个基于Spring Boot、Spring Cloud和Vue前后分离项目实战,通过实现一个在线商城的功能,展示了前后分离的开发模式和互联网应用的开发技术栈。本文可以作为前后分离开发的入门教程,也可以作为互联网应用开发的参考文档。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值