SSM整合开发

记录使用SSM(Spring + SpringMVC + MyBatis)框架前后端分离完成的一个简易电商用户端系统的开发流程,此项目已部署上线。仅用来检测自己对ssm的学习掌握情况。该系统使用git进行版本控制,由我和室友两人共同完成后台所有功能的开发,现特记录如下。该项目的Github地址为:HeavyTiger/mall: 使用ssm+vue框架实现的商城系统 (github.com),欢迎各路大佬或想参考该项目共同学习的小伙伴为该项目加上小星星⭐!

项目技术栈及工具使用

  1. Spring + SpringMVC + MyBatis + Maven完成开发
  2. JWT技术实现身份权限认证
  3. PageHelper实现快速分页
  4. IDEA集成开发环境
  5. git实现版本控制管理
  6. Navicat编写数据库结构及骨架,测试远程数据库
  7. ApiFox完成接口文档及接口测试
  8. XShell + Xftp远程控制服务器
  9. Tomcat测试及部署war包
  10. CentOS_8.3阿里云服务器部署生产环境

电商用户端需求

用户层要求

  1. 用户能够在网页端完成注册登录,登录后通过服务器颁发token访问站内资源,30分钟内有效,超过30分钟需要重新登录
  2. 用户能够查看并完善自己的全部个人信息

商品层要求

  1. 用户能够分页浏览由供应商发布的商品,通过各种字段信息检索发布的商品

购物车层要求

  1. 用户在商品页浏览时,把所需商品选中添加到购物车
  2. 用户在购物车页面可以查看添加进购物车的商品
  3. 用户在购物车页面可以更新购物车中的商品选购数量
  4. 用户在购物车页面可以移除不需要的商品
  5. 用户可以在订单页面中通过查看订单详情,展示该订单中的所有商品信息

订单层要求

  1. 用户可以在购物车页面中结算选购的所有商品,计算金额,生成订单
  2. 用户可以查询自己在平台上消费的所有订单

SSM框架的整合

SSM项目的文件树:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
E:\PROGRAMDEMO\MALL
│ .gitignore
│ LICENSE
│ pom.xml
│ README.md

├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─mall
│ │ │ ├─controller
│ │ │ │ CustomerController.java
│ │ │ │ OrderCartController.java
│ │ │ │ OrderController.java
│ │ │ │ ProductController.java
│ │ │ │
│ │ │ ├─interceptor
│ │ │ │ CheckInterceptor.java
│ │ │ │
│ │ │ ├─mapper
│ │ │ │ CustomerMapper.java
│ │ │ │ OrderCartMapper.java
│ │ │ │ OrderMapper.java
│ │ │ │ ProductMapper.java
│ │ │ │ SupplierMapper.java
│ │ │ │ TagMapper.java
│ │ │ │
│ │ │ ├─pojo
│ │ │ │ Customer.java
│ │ │ │ EnumResult.java
│ │ │ │ Order.java
│ │ │ │ OrderCart.java
│ │ │ │ ProductDetail.java
│ │ │ │ ProductSearch.java
│ │ │ │ ResultBean.java
│ │ │ │ Supplier.java
│ │ │ │ Tag.java
│ │ │ │
│ │ │ ├─service
│ │ │ │ │ CustomerService.java
│ │ │ │ │ OrderCartService.java
│ │ │ │ │ OrderService.java
│ │ │ │ │ ProductService.java
│ │ │ │ │ SupplierService.java
│ │ │ │ │ TagService.java
│ │ │ │ │
│ │ │ │ └─impl
│ │ │ │ CustomerServiceImpl.java
│ │ │ │ OrderCartServiceImpl.java
│ │ │ │ OrderServiceImpl.java
│ │ │ │ ProductServiceImpl.java
│ │ │ │ SupplierServiceImpl.java
│ │ │ │ TagServiceImpl.java
│ │ │ │
│ │ │ └─util
│ │ │ JsonUtil.java
│ │ │ JwtUtil.java
│ │ │
│ │ └─resources
│ │ ├─com
│ │ │ └─mall
│ │ │ └─mapper
│ │ │ CustomerMapper.xml
│ │ │ OrderCartMapper.xml
│ │ │ OrderMapper.xml
│ │ │ ProductMapper.xml
│ │ │ SupplierMapper.xml
│ │ │ TagMapper.xml
│ │ │
│ │ └─conf
│ │ applicationContext.xml
│ │ database.properties
│ │ mybatis-config.xml
│ │ spring-dao.xml
│ │ spring-mvc.xml
│ │ spring-service.xml
│ │
│ └─test
│ └─java
│ └─com
│ └─mall
│ └─service
│ └─impl
│ CustomerServiceImplTest.java
│ OrderCartServiceImplTest.java
│ OrderServiceImplTest.java
│ ProductServiceImplTest.java
│ SupplierServiceImplTest.java
│ TagServiceImplTest.java

└─web
└─WEB-INF
web.xml

使用Maven进行依赖管理,在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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<?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">
<modelVersion>4.0.0</modelVersion>

<groupId>com.mall</groupId>
<artifactId>mall</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<!-- spring版本 -->
<spring.version>5.1.9.RELEASE</spring.version>
</properties>

<!--导入依赖-->
<dependencies>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--datasource-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!--mysql_connector_8.0.25-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!--servlet_api,注意低于3.0版本会与junit4冲突,导致单元测试报错-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.0</version>
</dependency>
<!--page helper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.7</version>
</dependency>
<!--json web token-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
<!--约定解决静态资源导出问题-->
<build>
<resources>
<resource>
<directory>src/main/resource</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

配置Spring的Context上下文:

上下文关系如下图所示:

image-20211227212701984

applicationContext.xml为根上下文,在其中引入所有的其他上下文:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<import resource="spring-dao.xml"/>
<import resource="spring-service.xml"/>
<import resource="spring-mvc.xml"/>
</beans>

spring-dao.xml为Spring中dao层相关的上下文:

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
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<context:property-placeholder location="classpath:conf/database.properties"/>

<!--配置druid连接池数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 配置连接池属性 -->
<!-- 基本属性 url、user、password -->
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>

<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="1"/>
<property name="minIdle" value="1"/>
<property name="maxActive" value="20"/>

<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000"/>

<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>

<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
</bean>
<!--注册SqlSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:conf/mybatis-config.xml"/>
</bean>
<!--配置扫描Mapper接口包,动态实现Mapper接口注入到spring容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 给出需要扫描Dao接口包 -->
<property name="basePackage" value="com.mall.mapper"/>
</bean>

</beans>

在该层中引入了database.properties,控制连接的用户名密码URL等信息:

1
2
3
4
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mall?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false
jdbc.username=mall
jdbc.password=123456

在该层注册SqlSessionFactoryBean时,可以引入配置文件mybatis-config.xml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置数据源,交给Spring做-->
<!--取别名-->
<typeAliases>
<package name="com.mall.pojo"/>
</typeAliases>
<!--配置分页助手插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<!--指定使用的数据库-->
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
<!--绑定mapper-->
<mappers>
<package name="com.mall.mapper"/>
</mappers>
</configuration>

spring-service.xml上下文用来配置Service层相关的包扫描以及事务注解支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

<!-- 扫描service相关的bean -->
<context:component-scan base-package="com.mall.service" />

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- enable transaction annotation support -->
<tx:annotation-driven/>
</beans>

spring-mvc.xml上下文用来配置拦截器包扫描和声明注解支持

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
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.mall.controller"/>
<!--开启SpringMVC注解的支持-->
<mvc:annotation-driven/>

<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--对哪些资源实施拦截操作-->
<mvc:mapping path="/**"/>
<!--不拦截登录和注册相关的Api-->
<mvc:exclude-mapping path="/login"/>
<mvc:exclude-mapping path="/register"/>
<mvc:exclude-mapping path="/userExist"/>
<bean class="com.mall.interceptor.CheckInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>

所有前后端分离的SSM项目基本都可以使用这一套模板创建Spring上下文,提升开发的效率。

数据库的相关设计

创建数据库

数据库命名:mall

字符集:utf8mb4 MySQL在5.5.3之前,Unicode收录的字符有限,所以MySQL将utf8存储设计为3字节存储(即utf8mb3),后来Unicode收录的字符增多(比如增加了表情),所以扩展为4个字节,名为utf8mb4。该字符集支持中文。MySQL在5.5.3版本之后增加了utf8mb4编码,mb4即most bytes 4,专门用来兼容四字节的Unicode。

数据库创建语句:

1
2
3
4
########## 创建mall数据库 ##########
CREATE DATABASE IF NOT EXISTS mall;
ALTER DATABASE mall CHARACTER SET utf8mb4;
USE mall;

创建表

用户表:customers

字段设计:用户表存储用户的基本信息,包括用户id,用户登录信息(用户名、密码),用户的个人信息(用户性别、联系电话、电子邮箱、用户简介),为了简化开发,所以没有将详情分表存储。

存储引擎:需要支持事务,选择InnoDB引擎。

用户表创建语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
########################
# Create customers table
########################

CREATE TABLE customers (
customer_id INT UNSIGNED AUTO_INCREMENT NOT NULL,
customer_username VARCHAR(20) NULL,
customer_password VARCHAR(20) NULL,
customer_gender CHAR(1) NULL,
customer_phone VARCHAR(20) NULL,
customer_email VARCHAR(20) NULL,
customer_description VARCHAR(100) NULL,
PRIMARY KEY (customer_id)
) ENGINE=InnoDB;

供应商表:providers

字段设计:供应商表存储供应商的基本信息,包括供应商id,供应商登录信息(用户名、密码),供应商的详情信息(联系电话、电子邮箱、供应商描述),为了简化开发,所以没有将详情分表存储。

存储引擎:需要支持事务,选择InnoDB引擎。

供应商表创建语句

1
2
3
4
5
6
7
8
9
10
11
12
13
########################
# Create suppliers table
########################

CREATE TABLE suppliers (
supplier_id INT UNSIGNED AUTO_INCREMENT NOT NULL,
supplier_username VARCHAR(20) NULL,
supplier_password VARCHAR(20) NULL,
supplier_phone VARCHAR(20) NULL,
supplier_email VARCHAR(20) NULL,
supplier_description VARCHAR(100) NULL,
PRIMARY KEY (supplier_id)
) ENGINE=InnoDB;

标签表:tags

字段设计:标签表存商品的分类信息,包括标签id,标签名称。

存储引擎:需要支持事务,选择InnoDB引擎。

供应商表创建语句

1
2
3
4
5
6
7
8
9
###################
# Create tags table
###################

CREATE TABLE tags (
tag_id INT UNSIGNED AUTO_INCREMENT NOT NULL, -- 分类表ID,自动生成
tag_name VARCHAR(10) NULL, -- 类别名称
PRIMARY KEY (tag_id)
) ENGINE=InnoDB;

商品表:products

字段设计:商品表存储商品的基本信息,包括商品id,商品详情信息(商品名称、商品价格、商品库存数量、商品分类、商品描述、上下架状态、商品的供应商id)

存储引擎:需要支持事务,选择InnoDB引擎。

供应商表创建语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#######################
# Create products table
#######################

CREATE TABLE products(
product_id INT UNSIGNED AUTO_INCREMENT NOT NULL, -- 商品id
product_name VARCHAR(20) NULL, -- 商品名称
product_price DECIMAL(8,2) NULL, -- 商品价格
product_stock INT UNSIGNED NULL, -- 商品库存数量
product_tag_id INT UNSIGNED NULL, -- 商品分类
product_description VARCHAR(100) NULL, -- 商品描述
product_status TINYINT DEFAULT 1 , -- 上下架状态:0下架,1上架
supplier_id INT UNSIGNED NOT NULL, -- 添加商品前需指定供应商 外键,引用supplier.supplier_id
PRIMARY KEY (product_id)
) ENGINE=InnoDB;

购物车表:order_carts

字段设计:购物车表存储用户加入购物车的商品数据,包括购物车id,用户信息(用户id),商品信息(商品id、加入购物车的数量、商品价格、购买标识),订单信息(订单id)、添加时间

存储引擎:需要支持事务,选择InnoDB引擎。

供应商表创建语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
##########################
# Create order_carts table
##########################
CREATE TABLE order_carts (
order_cart_id INT UNSIGNED AUTO_INCREMENT NOT NULL, -- 购物车ID
customer_id INT UNSIGNED NOT NULL, -- 用户ID
product_id INT UNSIGNED NOT NULL, -- 商品ID
product_amount INT NULL, -- 加入购物车数量
product_price DECIMAL(8,2) NULL, -- 商品价格
status TINYINT DEFAULT 1, -- 购买标识,0为已购买;1为未购买
order_id INT UNSIGNED NULL, -- 订单id
add_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 加入购物车时间
PRIMARY KEY (order_cart_id)
) ENGINE=InnoDB;

订单表:orders

字段设计:订单表存储用户的订单信息,包括订单id,订单编号,用户信息(用户id),收货人信息(收货人姓名、收货人地址、收货人联系方式),订单信息(订单金额、下单时间)

存储引擎:需要支持事务,选择InnoDB引擎。

供应商表创建语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#####################
# Create orders table
#####################
CREATE TABLE orders (
order_id INT UNSIGNED AUTO_INCREMENT NOT NULL, -- 订单ID
order_sn VARCHAR(32) NULL, -- 订单编号(年+月+日+order_id) yyyymmddnnnnnnnnnn
customer_id INT UNSIGNED NOT NULL, -- 下单用户ID
shipping_user VARCHAR(20) NULL, -- 收货人姓名
shipping_address VARCHAR(100) NULL, -- 收货人地址
shipping_phone VARCHAR(20) NULL, -- 收货人联系方式
order_money DECIMAL(8,2), -- 订单金额
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 下单时间
PRIMARY KEY (order_id)
) ENGINE=InnoDB;

索引和完整性设计

索引设计

主键

为了节省索引结构的存储空间,且保证索引字段有新值插入时索引树结构调整较小,本项目中所有的主键均采用自增非空主键,数据类型为UNSIGNED INT,且主键不参与业务逻辑,仅作为行的唯一标识,统一以xxx_id命名。主键定义语句已包含在建表语句中。

唯一索引

根据业务逻辑,数据库中有三个字段需要唯一约束。分别是customers(username),客户用户名唯一;suppliers(username),供应商用户名唯一;tags(tag_name),商品分类唯一。

唯一索引创建语句

1
2
3
4
5
6
## 唯一约束(customer_username)
ALTER TABLE customers ADD CONSTRAINT unique_username UNIQUE(customer_username);
## 唯一约束(supplier_username)
ALTER TABLE suppliers ADD CONSTRAINT unique_username UNIQUE(supplier_username);
## 唯一约束(tag_name)
ALTER TABLE tags ADD UNIQUE(tag_name);

普通索引

为了优化查询性能,在如下字段创建普通索引。

**联合索引(customer_username, customer_password)**:用户的登录、注册属于高频需求,需要根据给定的用户名查询密码。由于高频请求只涉及这两个字段,所以可以建立联合索引实现索引覆盖,减少一次回表操作。

1
2
## 联合索引(customer_username, customer_password)
ALTER TABLE customers ADD INDEX index_username_password (customer_username, customer_password);

联合索引(supplier_username, supplier_password)

供应商信息的注册登录同样需要校验,所以同样建立联合索引。

1
2
## 联合索引(supplier_username, supplier_password)
ALTER TABLE suppliers ADD INDEX index_username_password (supplier_username, supplier_password);

索引优化方案:

根据最左前缀原则,在建立联合索引的时候,合理地安排索引顺序可以少维护一个索引。根据业务需求,用户表和供应商表的两个复合索引顺序安排合理。

考虑到MySQL支持前缀索引,对于占用空间较大的字段,如果有较高的查询需求,可以定义字段的一部分作为索引。如

ALTER TABLE products ADD INDEX index_description(description(10));

这同时带来的损失是,可能会增加额外的记录扫描次数,即多次回表取出目标字段判断是否与查询条件一致,然后取索引指向位置的下一个记录,再次判断…,直到索引值与查询条件不一致,循环结束。要提升存储效率、兼顾查询效率,需要取适当的索引长度。可通过DISTINCT关键字计算各个索引长度下,目标列有多少个不同的索引值,与总行数相除,横向对比,设定一个可以接受的损失比例,选择合适的索引长度。

完整性设计

参照完整性主要体现在表的外键约束。具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
## 外键约束
ALTER TABLE products ADD CONSTRAINT fk_products_tags FOREIGN KEY(product_tag_id) REFERENCES tags(tag_id);
## 外键约束
ALTER TABLE products ADD CONSTRAINT fk_products_suppliers FOREIGN KEY (supplier_id) REFERENCES suppliers (supplier_id);
## 外键约束
ALTER TABLE order_carts ADD CONSTRAINT fk_order_carts_customers FOREIGN KEY (customer_id) REFERENCES customers (customer_id);
## 外键约束
ALTER TABLE order_carts ADD CONSTRAINT fk_order_carts_products FOREIGN KEY (product_id) REFERENCES products (product_id);
## 外键约束
ALTER TABLE order_carts ADD CONSTRAINT fk_order_carts_orders FOREIGN KEY (order_id) REFERENCES orders (order_id);
## 外键约束
ALTER TABLE orders ADD CONSTRAINT fk_orders_customers FOREIGN KEY (customer_id) REFERENCES customers (customer_id);

实体完整性主要体现在表级的完整性约束——主键。定义语句已在建表语句中包含。

对于外键字段,也添加了非空约束,通过NOT NULL指定列级完整性约束。具体实现可查看建表语句。

项目部署流程

首先使用Xshell连接CentOS服务器,安装MySQL数据库,安装流程借鉴该博客:centos8安装mysql8.0.22教程(超详细)_上善若水滴世界-CSDN博客

安装完成后,继续安装tomcat,直接下载tar包后使用xftp传入服务器中解压,解压完后可以直接使用。

IDEA中的文件打包成war包,将war包放入tomcat的webapps路径下,之后在tomcat的bin目录下运行脚本./startup.sh即可启动后台,不过记得要开放8080端口,开放后,即可从接口获取相应的数据。


-------------本文到此结束 感谢您的阅读-------------
谢谢你请我喝肥宅快乐水(๑>ڡ<) ☆☆☆