Day01-开始学习准备

166 阅读9分钟

1. 第四阶段课程安排

  • 编程技术清单:

    • Mybatis框架相关

    • Spring Boot框架相关

    • Spring MVC框架相关 / Spring框架相关

    • Spring Validation框架相关

      • 检查请求参数格式的有效性
    • Vue CLI相关

      • 前端技术
    • Spring Security框架相关

      • 处理认证与授权
    • Redis的基本使用

    • Spring AOP

  • 项目清单:

    • csmall-product:服务器端项目,商品管理
    • csmall-passport:服务器端项目,管理员管理
    • csmall-web-client:客户端项目

2. 创建csmall-product项目

创建Spring Boot项目,参数:

image-20230220093403339.png

在后续界面中,关于Spring Boot的版本,应该选择2.x某个版本,且不需要勾选任何依赖项,直接将项目创建出来!

关于pom.xml文件,主要调整Spring Boot父级项目版本,目前使用2.5.x系列版本:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">

    <!-- 模块版本,取值是相对固定的 -->
    <modelVersion>4.0.0</modelVersion>

    <!-- 父级项目的配置,主要实现了基础的自动配置与某些依赖项的版本管理 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <!-- 当前项目的配置 -->
    <groupId>cn.tedu</groupId>
    <artifactId>csmall-product</artifactId>
    <version>0.0.1</version>

    <!-- 属性配置 -->
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <!-- 当前项目使用的依赖项 -->
    <!-- scope标签:配置依赖项的作用域 -->
    <!-- scope取值为test:此依赖项仅能作用于src/test下的代码,且不参与项目的正式运行时的编译或打包 -->
    <dependencies>
        <!-- Spring Boot框架的基础依赖项 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- Spring Boot测试框架的依赖项 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 如果以下插件的依赖项报错,你可以: -->
    <!-- 1. 显式的添加版本号 -->
    <!-- 2. 直接删除整个build标签 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.5.9</version>
            </plugin>
        </plugins>
    </build>

</project>

3. 创建数据库与数据表

创建mall_pms数据库:

image-20230220103116768.png

然后,在项目中配置此数据库的Database面板。

可参考视频教程:doc.canglaoshi.org/doc/idea_da…

Console面板中,粘贴mall_pms.sql中的脚本,并执行,以创建数据表、插入一些模拟数据:

image-20230220120056006.png

4. 添加数据库编程的依赖

需要添加mybatis-spring-boot-starter依赖,用于实现基于Mybatis的数据库编程。

另外,还需要添加mysql-connector-java依赖,用于连接到MySQL数据库服务器。

pom.xml中添加依赖项:

<!-- Mybatis整合Spring Boot的依赖项 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>
<!-- MySQL的依赖项 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

当添加以上Mybatis的依赖项后,此项目默认将无法启动(也无法执行任何测试)!因为Spring Boot项目中的与数据库编程相关的依赖项中包含自动配置,当启动项目或执行基于Spring Boot的测试时,会自动读取连接数据库的配置信息,如果尚未配置这些信息,就会报错!

则需要在application.properties中添加配置:

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

当添加以上配置后,无论是启动项目,还是执行基于Spring Boot的测试,都不再报错,即使以上各属性的配置值有误,也不会报告错误,因为此时只会读取以上信息,并不会真实的连接到数据库!

为了检测以上各配置值是否正确,可以在src/test/java下默认已存在的测试类中编写测试代码:

@SpringBootTest
class CsmallProductApplicationTests {

    @Test
    void contextLoads() {
    }

    @Autowired
    DataSource dataSource;

    @Test
    void getConnection() throws Throwable {
        dataSource.getConnection();
    }

}

如果配置的主机名有误,执行测试会报告错误:

Caused by: java.net.UnknownHostException: localhast

如果配置的端口号有误,执行测试会报告错误:

Caused by: java.net.ConnectException: Connection refused: connect

如果配置的数据库名称有误,执行测试会报告错误:

java.sql.SQLSyntaxErrorException: Unknown database 'mall_pms_haha'

如果配置的用户名有误,执行测试会报告错误:

java.sql.SQLException: Access denied for user 'root1234'@'localhost' (using password: YES)

如果配置的密码有误,执行测试会报告错误:

java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)

如果未配置密码,或配置密码的属性值有误(相当于没有配置预期的属性),执行测试会报告错误:

java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: NO)

5. MySQL中的数据类型与Java属性的类型的对应关系

MySQL中的类型Java属性的类型
tinyint / smallint / intInteger
bigintLong
char / varchar / text系列String
datetimeLocalDateTime
decimalBigDecimal

6. 关于Lombok框架

Lombok是一款可以基于注解在编译期生成特定代码的框架!

在项目中添加依赖项:

<!-- Lombok的依赖项,主要用于简化POJO类的编写 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    <scope>provided</scope>
</dependency>

当添加以上依赖项后,在POJO类型上,可以添加@Data注解,则Lombok框架会在编译期自动生成此类型中基于所有属性的Setters & Getters、hashCode()equals()toString()这些方法(需要当前类的父类存在无参数构造方法)。

在Lombok框架中,还有其它常用注解:

  • @Setter:添加在属性上,用于生成此属性的Setter方法,也可以添加在类上,用于生成此类中所有属性的Setters方法
  • @Getter:用法与@Setter相同,此注解用于生成Getter方法
  • @ToString:添加在类上,用于生成基于此类中所有属性的toString()方法,此注解可以配置callSuper属性,用于表示是否调用父类的toString()方法
  • @EqualsAndHashCode:添加在类上,用于生成基于此类中所有属性的equals()方法和hashCode()方法
  • @NoArgsConstructor:添加在类上,用于生成此类的无参数构造方法
  • @AllArgsConstructor:添加在类上,用于生成基于此类中所有属性的全参数构造方法
  • @Slf4j:待定

**注意:**在你的开发工具中,需要安装Lombok插件,例如:

image-20230220153534824.png

如果未使用以上插件,IntelliJ IDEA等开发工具将无法识别生成的代码,经编写时无法给出对应的提示,强行写出的代码也会报错,但是,并不影响运行!

关于以上插件的安装教程:doc.canglaoshi.org/doc/idea_lo…

由于使用Lombok后,应该在开发工具中安装插件,所以,在某些开发团队中是禁止使用Lombok框架的。

7. 关于POJO类的编写规范

POJO类型的编写规范有:

  • 各属性均是private权限
  • 各属性均存在规范命名且public权限的Setters & Getters
  • 存在基于全部属性的hashCode()equals()方法,且,如果2个对象的类型相同、各属性值也全部相同,则必须返回相同的hashCode(),且equals()对比结果为true
  • 实现Serializable接口

因为使用的许多框架都会默认你的代码是遵守这些规范的,所以,有些框架在实现有些效果时,会自动的调用Setters & Getters方法,或其它方法,或转换类型为Serializable

另外,为了便于查看对象的各属性值,还建议添加toString()方法。

8. Mybatis的基础配置

需要使得Mybatis框架清楚各Mapper接口的位置,可以:

  • 在各Mapper接口上添加@Mapper注解
  • 【推荐】在配置类上通过@MapperScan注解指定Mapper接口的根包

采用以上第2种做法时,应该在项目的根包下创建config.MybatisConfiguration类,在类上添加@Configuration注解,将此类标记为配置类,然后通过@MapperScan注解配置Mapper接口的根包:

package cn.tedu.csmall.product.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("cn.tedu.csmall.product.mapper")
public class MybatisConfiguration {
}

src/main/resources下创建mapper文件夹,用于存放配置SQL语句的XML文件。

application.properties中添加配置,指定XML文件的位置:

mybatis.mapper-locations=classpath:mapper/*.xml

9. 关于Mapper接口中的抽象方法

  • 返回值类型:如果要执行的SQL语句是增、删、改类型的,统一使用int作为返回值类型,Mybatis会自动返回“受影响的行数”,不推荐使用void;如果要执行的SQL语句是查询类型的,只需要保证返回值类型足以“放得下”你需要的结果值即可

  • 方法名称:自定义,不建议重载

    根据《阿里巴巴Java开发手册》的规范:

    【参考】各层命名规约:

    A) Service/DAO 层方法命名规约

    1) 获取单个对象的方法用 get 做前缀。

    2) 获取多个对象的方法用 list 做前缀。

    3) 获取统计值的方法用 count 做前缀。

    4) 插入的方法用 save/insert 做前缀。

    5) 删除的方法用 remove/delete 做前缀。

    6) 修改的方法用 update 做前缀。

  • 参数列表:根据需要执行的SQL语句来设计参数,尽量将多个具有相关性的参数封装起来

10. 关于Mapper映射文件(.xml文件)的配置

  • 根标签必须是<mapper>标签

  • 根标签必须配置namespace属性,取值为映射的接口的全限定名(包名加类名/接口名)

  • 在根标签的子级,根据需要配置的SQL语句的类型,选择使用<insert> / <delete> / <update> / <select>标签来配置SQL语句,这些标签必须配置id属性,取值为映射的抽象方法的名称

    • 在不考虑获取自动编号的ID的情况下,增、删、改使用的标签可以随意调换,但是非常不推荐
  • <select>标签上,必须配置resultTyperesultMap中的1个属性

    • 当配置resultType时,此属性的值是抽象方法对应的类型

      • 如果是基本数据类型,则直接写类型,例如resultType="int"
      • 如果是引用数据类型,则写全限定名,例如resultType="cn.tedu.csmall.product.pojo.entity.Album"
      • 如果引用类型是java.lang包中的,可以不写包名,例如resultType="String"

11. 关于SQL规范

  • insert语句中,应该显式的写出字段列表
  • select语句中,如果是统计查询,应该使用count(*)
  • select语句中,如果是查询数据,不允许使用星号表示字段列表
  • select语句中,如果是查询列表,必须显式的指定ORDER BY子句

12. 插入相册数据

在项目的根包下创建pojo.entity.Album类:

@Data
public class Album implements Serializable {

    private Long id;
    private String name;
    private String description;
    private Integer sort;
    private LocalDateTime gmtCreate;
    private LocalDateTime gmtModified;

}

在项目的根包下创建mapper.AlbumMapper接口,并声明“插入相册数据”的抽象方法:

public interface AlbumMapper {
    int insert(Album album);
}

src/main/resources/mapper下粘贴得到AlbumMapper.xml文件,通过此文件配置以上接口中的抽象方法映射的SQL语句:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="cn.tedu.csmall.product.mapper.AlbumMapper">

  <!-- int insert(Album album); -->
  <insert id="insert">
    INSERT INTO pms_album (
    name, description, sort
    ) VALUES (
    #{name}, #{description}, #{sort}
    )
  </insert>

</mapper>

src/test/java的根包下创建mapper.AlbumMapperTests测试类,在类上添加@SpringBootTest注解,在类中自动装配AlbumMapper接口类型的属性,然后,编写并执行测试方法:

@SpringBootTest
public class AlbumMapperTests {

    @Autowired
    AlbumMapper mapper;

    @Test
    void insert() {
        Album album = new Album();
        album.setName("测试数据001");
        album.setDescription("测试数据的简介001");
        album.setSort(255); // 注意:此值必须是 [0, 255] 区间内的值

        mapper.insert(album);
        System.out.println("插入数据完成!");
    }

}

**注意:**你的测试类,与被测试的类/接口,不要使用完全相同的名称!

如果通过@MapperScan指定的Mapper接口的根包,与实际Mapper接口所在的根包不相符,启动项目或执行基于Spring Boot测试时就会报错:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'cn.tedu.csmall.product.mapper.AlbumMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

如果存在以下错误,执行测试时会出现错误提示:

  • 在XML文件中的<mapper>标签的namespace属性值配置有误
  • 在XML文件中的<insert>等标签的id属性值配置有误
  • application.properties中配置的XML文件的位置,与实际使用的XML文件的位置不相符
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): cn.tedu.csmall.product.mapper.AlbumMapper.insert

另外,在插入数据时,如果插入数据的表中的ID是自动编号的,应该在<insert>标签上配置useGeneratedKeys="true"keyProperty="属性名"这2个属性,以获取自动编号的ID值!例如:

<!-- int insert(Album album); -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO pms_album (
        name, description, sort
    ) VALUES (
        #{name}, #{description}, #{sort}
    )
</insert>

再次执行测试,可以发现:Mybatis会将自动编号的ID值“回填”到参数对象中keyProperty对应的属性中,例如:

插入数据之前,参数:Album(id=null, name=测试数据007, description=测试数据的简介007, sort=255, gmtCreate=null, gmtModified=null)

插入数据完成!受影响的行数:1

插入数据之后,参数:Album(id=21, name=测试数据007, description=测试数据的简介007, sort=255, gmtCreate=null, gmtModified=null)