SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)

花了一段实现刚学完SpringBoot,做个项目练练手。教程视频来源于B站。
视频链接: 【SpringBoot项目实战完整版】SpringBoot+MyBatis+MySQL电脑商城项目实战_哔哩哔哩_bilibili

目录

一、系统概述与环境搭建

1. 系统开发及运行环境

2.项目分析

3.创建项目

4.配置并运行项目

4.1 运行项目

4.2 配置项目

4.3 其他配置

三、用户登录注册

3.1 用户注册

3.1.1  用户-创建数据表

3.1.2 用户-创建实体类

3.1.3用户-注册-持久层

3.1.4用户-注册-业务层

                1.1 业务的定位

                1.2 规划异常

                1.3 接口和抽象方法

                1.4 实现接口方法


一、系统概述与环境搭建

1. 系统开发及运行环境

       电脑商城系统开发所需的环境及相关软件进行介绍。
        1.操作系统: Windows 10
        2.Java开发包: JDK 8
        3.项目管理工具: Maven 3.6.3
        4.项目开发工具:IntelliJ IDEA 2022.2.2 x64
        5.数据库:MySQL  MariaDB-10.3.7-winx64
        6.浏览器: Google Chrome
        7.服务器架构:Spring Boot 2.7.5 + MyBatis 2.2.2 + AJAX2

2.项目分析

        1.在开发某个项目之前,应先分析这个项目中可能涉及哪些种类的数据。本项目中涉及的数据:用户、商品、商品类别、收藏、订单、购物车、收货地址。

        2.关于数据,还应该要确定这些数据的开发顺序。设计开发顺序的原则是:先开发基础、简单或熟悉的数据。以上需要处理的数据的开发流程是:用户-收货地址-商品类别-商品-收藏-购物车-订单。

        3.在开发每种数据的相关功能时,先分析该数据涉及哪些功能。在本项目中以用户数据为例,需要开发的功能有:登录、注册、修改密码、修改资料、上传头像

        4.然后,在确定这些功能的开发顺序。原则上,应先做基础功能,并遵循增查删改的顺序来开发。则用户相关功能的开发顺序应该是:注册-登录-修改密码-修改个人资料-上传头像。

        5.在实际开发中,应先创建该项目的数据库,当每次处理一种新的数据时,应先创建该数据在数据库中的数据表,然后在项目中创建该数据表对应的实体类。

        6.在开发某个具体的功能时,应遵循开发顺序:持久层-业务层-控制器-前端页面。

3.创建项目

       1.给项目添加Web->Spring Web、SQL->MyBatis Framework、SQL->MySQL Driver的依赖。点击【Next】按钮完成项目创建。

SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)_第1张图片SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)_第2张图片SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)_第3张图片SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)_第4张图片

        2.Maven配置

        其中在maven的配置上,点击File->Setting->搜索maven->如下配置。 

       但在User settings file 配置不大对,但能项目能正常启动(不知道为什么,后面需要再说),因为我在G:\Maven\apache-maven-3.6.3-bin\目录下没看到/conf目录,可能IDEA自动给我默认选了C盘下的目录了吧

SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)_第5张图片

        3.首次创建完Spring Initializr项目时,解析项目依赖需消耗一定时间(Resolving dependencies of store...)

SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)_第6张图片

4.配置并运行项目

4.1 运行项目

        首先先保证Springboot项目能够启动起来,找到程序的入口,即被@SpringBootApplication注解修饰的入口启动类,运行入口启动类,如果观察到图形化的界面,即项目成功启动。

```java
package com.cy.store;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class StoreApplication {
    public static void main(String[] args) {
        SpringApplication.run(StoreApplication.class, args);
    }
}

SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)_第7张图片

4.2 配置项目

        检查数据库是否成功连接,在/test包中写个测试代码:

@SpringBootTest
class StoreApplicationTests {
    @Autowired  //自动注入/自动装配
    private DataSource dataSource;

    @Test
    void contextLoads() {
    }

    @Test
    void getConnection() throws SQLException {
        System.out.println(dataSource.getConnection());
    }

}

        如果启动项目时提示:“配置数据源失败:'url'属性未指定,无法配置内嵌的数据源”。有如下的错误提示。

SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)_第8张图片

        解决以上操作提示的方法:在resources文件夹下的application.properties文件中添加数据源的配置。

        配置数据源,数据库信息。这一步建议在创建项目完后立马检查配置。步骤:按照上面测试代码的方式获取数据源连接观察是否能成功连接。

spring.datasource.url=jdbc:mysql://localhost:3306/store?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456

4.3 其他配置

        1.为了方便查询JSON数据,隐藏没有值的属性,减少流量消耗,服务器不应该向客户端响应为null的属性。解决方式有两种:

        方式一:在属性或类之前添加@JsonInclude(value=Include.NON_NULL)

        方式二:可以在application.propertise配置文件中添加全局配置:

# 服务器向客户端不响应为null的属性
spring.jackson.default-property-inclusion=NON_NULL

        2.SpringBoot项目的默认访问路径是“/”,如果需要修改的话可以在配置文件中指定SpringBoot访问项目路径的项目名。但是不建议修改

server.servlet.context-path=/store

三、用户登录注册

3.1 用户注册

3.1.1  用户-创建数据表

        创建store数据库,创建t_user用户数据表。

        1.使用use命令先选中store数据库:use store;

        2.在store数据库中创建t_user表。(直接复制到Navicat中,点击查询,执行脚本)

CREATE TABLE t_user (
uid INT AUTO_INCREMENT COMMENT '用户id',
username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',
password CHAR(32) NOT NULL COMMENT '密码',
salt CHAR(36) COMMENT '盐值',
phone VARCHAR(20) COMMENT '电话号码',
email VARCHAR(30) COMMENT '电子邮箱',
gender INT COMMENT '性别:0-女,1-男',
avatar VARCHAR(50) COMMENT '头像',
is_delete INT COMMENT '是否删除:0-未删除,1-已删除',
created_user VARCHAR(20) COMMENT '日志-创建人',
created_time DATETIME COMMENT '日志-创建时间',
modified_user VARCHAR(20) COMMENT '日志-最后修改执行人',
modified_time DATETIME COMMENT '日志-最后修改时间',
PRIMARY KEY (uid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.1.2 用户-创建实体类

1.项目中许多实体类都会有日志相关的四个属性,所以在创建实体类之前,应先创建这些实体类的基dsdi 类,将4个日志属性声明在基类中。在com.cy.store.entity包下创建BaseEntity,作为实体类的基类。

package com.cy.store.entity;
import java.io.Serializable;
import java.util.Date;
/** 实体类的基类 */
public class BaseEntity implements Serializable {
private String createdUser;
private Date createdTime;
private String modifiedUser;
private Date modifiedTime;
// Generate: Getter and Setter、toString()
}

因为这个基类的作用就是用于被其他实体类继承的,所以应声明为抽象类。

为什么要继承sealization接口?因为要在网络中以流的形式传输,所以需要serialize序列化

2.创建com.cy.store.entity.User用户数据的实体类,继承自BaseEntity类,在中声明相关属性。

package com.cy.store.entity;
import java.io.Serializable;
import java.util.Objects;
/** 用户数据的实体类 */
public class User extends BaseEntity implements Serializable {
private Integer uid;
private String username;
private String password;
private String salt;
private String phone;
private String email;
private Integer gender;
private String avatar;
private Integer isDelete;
// Generate: Getter and Setter、Generate hashCode() and equals()、toString()
}

Tips:实体类可使用lombok插件,类上声明几个注解@Data @AllArgConsturctor等注解表示自动生成get/set方法,以及有参和无参构造函数。

3.1.3用户-注册-持久层

(1)准备工作

        1.在src/test/java下的com.store.StoreApplicationTest测试类中编写并执行获取数据库连接的单元测试,以检查数据库连接的配置是否正确。参加上面环境配置的数据源的代码。

        2.执行src/test/java下的com.cy.storeApplicationTests测试类中的contextLoad观察是否执行成功。

(2)规划需要执行的SQL语句

        1.用户注册的本质就是向用户表中插入数据,需要执行的SQL语句大致是:

insert into t_user(除uid之外的字段列表) values(匹配的值列表)

        2.由于数据库表中的用户名字段被设计为UNIQUE,在执行插入数据之前,还应该检查该用户名是否被注册,因此需要有“根据用户名查询用户数据”的功能。需要执行的SQL语句大致是:

select * from t_user where username = ? 

(3)接口与抽象方法

        1.在com.cy.store包下创建一个mapper包,接着创建com.cy.store.mapper.UserMapper接口,并在接口中添加抽象方法。

/** 处理用户数据操作的持久层接口 */
public interface UserMapper {
/**
* 插入用户数据
* @param user 用户数据
* @return 受影响的行数
*/
Integer insert(User user);
/**
* 根据用户名查询用户数据
* @param username 用户名
* @return 匹配的用户数据,如果没有匹配的数据,则返回null
*/
User findByUsername(String username);
}

        2.由于这是项目中第一次创建持久层接口,还应在StoreApplication启动类之前添加@MapperScan("com.cy.store.mapper")注解,表示在项目一启动自动扫描这个包下的mapper接口。因为SpringBoot一开始不知道mapper接口放在哪,你得在项目启动入口告诉它在那个地方,通过注解的方式配置包扫描路径。

@SpringBootApplication
@MapperScan("com.cy.store.mapper")
public class StoreApplication {
public static void main(String[] args) {
SpringApplication.run(StoreApplication.class, args);
}
}

Mybats与Spring整合后需要实现实体类和数据表的映射关系。实现实体类和数据表的映射关系可以在Mapper接口添加@Mapper注解。但建议以后直接在SpringBoot启动类中加@MapperScan("mapper包")注解,这样比较方便,不需要对每个Mapper都添加@Mapper注解。

复习一下:一个数据表对应一个实体类,每个实体类都有一个Mapper接口,每个Mapper自动生成一个Mapper实现类,每个Mapper接口对应一个Mapper配置文件。

eg: t_user -->  User  --> UserMapper.java  --> UserMapper.xml 

(4)配置SQL映射

        1.在src/main/resource下创建mapper文件夹,并在文件夹下创建UserMapper.xml配置文件,进行以上两个抽象方法的映射配置。





    
    
        
        
        
        
        
        
    

    
    
    
        insert into t_user(
            username,password, salt,phone,email,gender,
            avatar,is_delete,created_user, created_time,modified_user,modified_time
        )values(
            #{username},#{password},#{salt},#{phone},#{email},#{gender},
            #{avatar},#{isDelete},#{createdUser},#{createdTime},#{modifiedUser},#{modifiedTime}
        )
    

    
    


几点说明:

1.插入/删除/修改语句会有返回值(int),返回受影响的行数;

2.实体类属性和表字段创建映射关系,映射方式:字段下划线变为属性驼峰形式。自己手动改吧,字段复制过来自己去掉下划线改成驼峰命名

3.插入标签里往往需要主键自增,开启主键自增的几个核心属性: userGeneratedKeys   keyProperty

        userGeneratedKeys:表示开启的某个属性的字段递增,值为true

        keyProperty:将表中的哪个属性自增

4.映射关系仅仅出现在select语句中,需要使用到reseltMap属性,来建立属性和字段的映射。也可以使用resultType,但必须实体类实行和表字段属性完全一致;增删改语句不存在属性字段映射的,因为看语句就知道了。

5.resultMap标签里的几个属性:

        id表示唯一标识,select标签需要指定resultMap属性为这个id;

        type标识映射那个实体类的全类名。在标签中指定字段column和属性property的映射。字段名属性名一致的就不用指定映射了,长的一样的Mybatis可以自动映射成功。

        注意:主键一定得指定映射,无论字段名和属性名是否一致。标签里

6.#{}和¥{}的区别 ?

程序执行流程分析

    比如执行insertUser(User user)方法,业务层调用insertUser(User user),业务层里的userMapper已经自动注入了,然后业务层调用持久层的userMapper接口的insertUser(User user)方法,因为userMapper配置文件有个SQL语句的id=“insertUser”(方法名),因此执行这个SQL,把方法里的参数user对象里的所有属性注入到