【Project】云商城

项目简介

本项目前端选用 Vue + ElementUI + Thymeleaf 技术栈,后端选用 Spring Boot + Spring Cloud + Spring Cloud Alibaba + MyBatis-Plus + MySQL + Redis + ElasticSearch + RabbitMQ + Docker + Nginx 等技术栈。

云商城目前已实现注册、登录、上架、检索、购物车、订单、支付、秒杀等功能。

项目结构

  • yun-mall父工程。负责依赖管理与版本控制
    • mall-common公共服务。提供公共工具类、常量类、异常类与 TO/VO 类等
    • mall-gateway网关服务。配置其他微服务的路由规则
    • mall-auth-server认证服务。负责用户注册、登录与社交登录
    • mall-cart购物车服务。负责将用户挑选好的 SKU 添加到购物车中
    • mall-order订单服务。负责下订单、锁库存与第三方支付
    • mall-product商品服务。核心服务,负责管理所有商品信息
    • mall-search检索服务。负责在商城检索页提供商品检索功能
    • mall-seckill秒杀服务。负责提供定时秒杀功能
    • mall-third-party第三方服务。负责提供对象云存储与手机短信功能
    • mall-ware仓储服务。被其他微服务远程调用,管理商品的库存信息
    • mall-coupon优惠券服务。被其他微服务远程调用,查询会员的优惠券信息
    • mall-member会员服务。被其他微服务远程调用,查询会员信息
    • renren-fast:人人开源后台管理系统
    • renren-generator:人人开源代码生成器

image-20220204192231397

技术选型

本项目前端选用 Vue + ElementUI + Thymeleaf 技术栈,具体为:

  • Vue:前端框架
  • Element :基于 Vue 的桌面端组件库(提供了许多 Vue 组件)
  • Axios:异步通信框架
  • Thymeleaf :Spring 模板引擎
  • Node.js:服务端 js

后端选用 Spring Boot + Spring Cloud + MyBatis-Plus + MySQL + Redis + ElasticSearch + RabbitMQ + Nginx + Docker技术栈。具体为:

  • Spring Boot
  • MyBatis-Plus:持久层框架
  • Redis:缓存中间件
  • ElasticSearch:全文搜索引擎中间件
  • RabbitMQ:消息中间件
  • Docker:应用容器引擎
  • Nginx:反向代理服务器
  • Redisson:分布式锁
  • Spring Cloud
    • Spring Cloud - Ribbon:负载均衡
    • Spring Cloud - OpenFeign:声明式 HTTP 客户端(调用服务远程)
    • Spring Cloud - Gateway:API 网关(webflux 编程模式)
    • Spring Cloud - Sleuth:调用链监控
  • Spring Cloud Alibaba
    • Spring Cloud Alibaba - Nacos:注册中心(服务注册与发现)
    • Spring Cloud Alibaba - Nacos:配置中心(动态配置管理)
    • Spring Cloud Alibaba - Seata:分布式事务解决方案
    • Spring Cloud Alibaba - Sentinel:服务容错(限流、降级、熔断)
    • Spring Cloud Alibaba OSS 对象云存储
  • Spring Cache:分布式缓存技术
  • Spring Session:分布式 Session 技术

服务端口号

各个微服务的端口号:

  • mall-gateway:88
  • mall-coupon:7000
  • mall-member:8000
  • mall-order:9000
  • mall-product:10000
  • mall-ware:11000
  • mall-search:12000
  • mall-auth-server:20000
  • mall-seckill:25000
  • mall-third-party:30000
  • mall-cart:50000
  • renren-fast:8080

第三方技术栈端口号:

  • MySQL:3306
  • Redis:6379
  • ElasticSearch:9200
  • Kibana:5601
  • Nginx:80
  • RabbitMQ:5672;管理台:15672

域名管理

1
2
3
4
5
6
7
8
192.168.56.102	yunmall.com
192.168.56.102 search.yunmall.com
192.168.56.102 item.yunmall.com
192.168.56.102 auth.yunmall.com
192.168.56.102 cart.yunmall.com
192.168.56.102 order.yunmall.com
192.168.56.102 member.yunmall.com
192.168.56.102 seckill.yunmall.com
阅读全文

【Spring Boot】Spring Boot2 源码分析

自动配置原理

依赖管理

当前新建的Spring Boot项目的父项目:

1
2
3
4
5
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

其父项目又依赖spring-boot-dependencies.pom

1
2
3
4
5
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

该文件中声明了开发中常用的jar包版本,因此其子项目中不需要给依赖写上版本号,会自动导入父项目里版本的jar包。该特性被称为版本仲裁

1
2
3
4
5
6
7
8
9
<properties>
<activemq.version>5.15.13</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.82</appengine-sdk.version>
<artemis.version>2.12.0</artemis.version>
<aspectj.version>1.9.6</aspectj.version>
<assertj.version>3.16.1</assertj.version>
...
</properties>

自定义依赖版本

若想自定义修改依赖的版本,则只需要在当前项目里指定配置版本号,其会覆盖父项目中的默认版本号。

1
2
3
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>

场景启动器

spring-boot-starter-* 代表某种场景,只要引入了该starter,这个场景的所有依赖都会自动引入。第三方提供的简化开发的场景启动器命名格式:*-spring-boot-starter官方所有支持的Starter

所有场景启动器最底层的依赖,SpringBoot自动配置的核心依赖spring-boot-starter

1
2
3
4
5
6
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>

该starter场景将导入Spring Boot提供的127种自动配置类xxxAutoConfiguration,这些自动配置类将导入许多常用的组件用于简化开发(例如DispatcherServlet等),无需开发人员手动添加这些组件。

spring-boot-starter.pom的主要内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- This module was also published with a richer model, Gradle metadata, -->
<!-- which should be used instead. Do not delete the following line which -->
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
<!-- that they should prefer consuming it instead. -->
<!-- do_not_remove: published-with-gradle-metadata -->
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.5.3</version>
<name>spring-boot-starter</name>
<description>Core starter, including auto-configuration support, logging and YAML</description>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>1.3.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.28</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

场景启动器starter工作原理

image-20210809210934337

场景启动器工作原理的本质:调用的xxx-starter项目导入的所有xxx-autoconfigure项目中编写了许多自动配置类xxxAutoConfiguration,这些自动配置类将在Spring Boot启动时被注册到容器中,从而将其内编写的组件按照条件注册到容器中,因此开发人员可以在自己的项目中调用到这些组件。

阅读全文

【Spring】Spring 汇总

img

Spring 内容汇总

源码分析

【Spring】Spring5 AOP 源码分析

【Spring】Spring5 事务源码分析

【Spring MVC】Spring MVC 源码分析

【Spring Boot】Spring Boot2 源码分析

【Spring】Spring5 源码中常用接口的底层原理

学习笔记

【Spring】Spring 常用注解

【Spring】Spring 中的设计模式

【Spring】Spring5 IoC

【Spring】Spring5 AOP

【Spring】Spring5 事务

【Spring】Spring5 注解驱动开发

【Spring MVC】Spring MVC

【Spring MVC】SSM 整合案例

【Spring Boot】Spring Boot2

【Spring】Spring Cache

【Spring】Spring Session

【Spring】Spring Security

【Alibaba】支付宝支付服务

支付宝开放平台

官方文档:https://opendocs.alipay.com/common/02kkv7

进入支付宝开放平台的沙箱环境进行开发测试:

image-20220121192322486

设置自定义 RSA2 密钥:

image-20220121191335093

点击【支付宝密钥生成器】下载支付宝开放平台开发助手,生成应用私钥应用公钥

image-20220121194115930

在【加签管理】中添加应用公钥,支付宝将为我们生成支付宝公钥:

image-20220121191805902

阅读全文

【Alibaba】阿里云短信服务

阿里云提供了短信服务,可以使用该服务实现短信验证码功能。我们选择的是阿里云的短信服务实现云商城中的短信验证功能。

开通阿里云短信服务

选择某个短信服务进行开通

image-20201110084936446

在云市场就能看到购买的服务

image-20201110085141506

验证短信是否能发送

在购买短信的页面,能进行短信调试

image-20201110085315288

输入对应手机号即可发送短信

image-20201110085348103

阅读全文

【Project】云商城 - 订单服务

本文将详细介绍云商城的订单服务。云商城完整项目介绍见文章 【Project】云商城

订单服务

电商系列涉及到 3 流,分别为信息流资金流物流,而订单系统作为中枢将三者有机的集合起来。

订单模块是电商系统的枢纽,在订单这个模块上获取多个模块的数据和信息,同时对这些信息进行加工处理后流向下个环节,这一系列就构成了订单的信息疏通

本项目的订单服务 mall-order 需要实现的功能:

  • 订单服务登录拦截
  • 用户在购物车页点击【去结算】,将购物车内商品信息封装成订单确认页数据 OrderConfirmVo,并跳转到订单确认页 confirm.html
  • 用户在订单确认页确定订单信息后点击【提交订单】,将根据前端传来的订单确认页数据创建出订单实体对象,并持久化到数据库中。30 分钟后关闭失败订单
  • 之后远程调用库存服务锁定库存。并在 50 分钟后进行失败订单的库存解锁
  • 用户点击【支付订单】后,使用支付宝支付服务完成订单支付

在订单服务中使用消息队列保证整体事务一致性(订单和库存事务一致)。其他要求并发性不高的场景可以使用 Seata(例如后台管理系统中的分布式事务)

完整的订单中心依次需要流程:

电商订单流程图

订单创建与支付:

  • 订单创建前需要预览订单,选择收货信息等
  • 订单创建需要锁定库存,库存有才可创建,否则不能创建
  • 订单创建后超时未支付需要解锁库存
  • 支付成功后,需要进行拆单,根据商品打包方式,所在仓库,物流等进行拆单
  • 支付的每笔流水都需要记录,以待查账
  • 订单创建,支付成功等状态都需要给MQ发送消息,方便其他系统感知订阅

逆向流程:

  • 修改订单,用户没有提交订单,可以对订单一些信息进行修改,比如配送信息,优惠信息,及其他一些订单可修改范围的内容,此时只需对数据进行变更即可。
  • 订单取消,用户主动取消订单和用户超时未支付,两种情况下订单都会取消订单,而超时情况是系统自动关闭订单,所以在订单支付的响应机制上面要做支付的
阅读全文

【Project】云商城 - 购物车服务

本文将详细介绍云商城的购物车服务。云商城完整项目介绍见文章 【Project】云商城

购物车服务

购物车服务 mall-cart 负责将用户挑选好的 SKU 添加到购物车中。添加后的效果如下:

image-20220115200411629

购物车服务需要实现的功能:

  • 登录用户可以添加购物车,并且在结算购物车前该信息一直保留
  • 临时用户(未登录用户)也可以添加购物车,并且该信息可以保留 30 天
  • 临时用户在 30 天内再次访问本网站仍然能看到之前添加过的购物车信息
  • 临时用户一旦登录,就会把其之前添加的商品一起合并到自己登录用户的购物车里

实现思路:

  • 为实现购物车信息一直保留,需要将购物车的信息一直存放在 Redis 中,并且开启 Reids 的持久化
  • 为实现临时用户功能,需要使用拦截器,判断每个访问本网站的用户是否已登录(Redis 中的 Session 是否存储了 loginUser 数据),如果没登录过就要为其设置一个唯一标识 user-key 并且以 Cookie 的形式保存在浏览器中 30 天。这样下次临时用户登录时仍然能获取其购物车数据
阅读全文

【Project】云商城 - 检索服务

本文将详细介绍云商城的检索服务。云商城完整项目介绍见文章 【Project】云商城

检索服务

检索服务 mall-search 负责实现的功能:

  • 商品上架:在后台管理系统中【上架】某个商品时,将其 SPU 传给商品服务。商品服务会查询出该 SPU 所包含的所有 SKU 的详细信息并封装成一个个 SkuEsModel,然后远程调用检索服务将这些 SKU 信息保存到 ElasticSearch 中,用于在商城页面快速查询出某个 SKU 的详细信息
  • 检索 SKU:根据前端传来的关键词等参数对商品(SKU)进行检索。
阅读全文

【Project】云商城 - 数据库设计

数据库设计

云商城完整项目介绍见文章 【Project】云商城

本项目共有 6 个数据库:

  • yunmall_admin:后台管理系统数据库
  • yunmall_oms:订单数据库
  • yunmall_pms:商品数据库
  • yunmall_sms:积分数据库
  • yunmall_ums:会员数据库
  • yunmall_wms:库存数据库

下面逐个介绍每个数据库的设计结构。

阅读全文