书接上回,上篇已经初始化完前端,这篇讲解后端初始化
用户中心(上)
后端初始化
数据库
在阿里云服务器上安装mysql5.7
初始化后端项目的三种常见方式(springboot框架搭建)
第一种方法
在github上搜索springboot-templates,直接拉取现成的模板【git+项目链接拉取到本地仓库】。
这种方法不推荐,别人的代码多少用着不放心。
第二种方法
第三种方法
直接在IDEA里生成(本质上也是第二种方法,集成在idea里了)强推!!!
开始初始化
在上面的搜索框引入的依赖有:
lombok
这个依赖可以帮助开发者自动生成实体类的get/set方法,编写实体类更加简单了。
Spring Boot DevTools
Spring Configuration Processor
MySQL Driver
这个依赖是数据库厂商对JDBC的实现,选用5.1.37版本,这个要和数据库软件对应好。
Spring Web
选用这个依赖,spring boot会自动整合spring和springmvc框架,而且还会进行版本的管理,我们只要指定springboot的版本就可,这就是springboot的强大之处。
Mybatis Framework
这个框架是持久层框架,对JDBC的封装,更有好的操作数据库。
以上六个依赖是springboot可以帮我们引入的,我们还需要自己手动引入一些依赖,依赖信息不用自己写,上mvnreposity查。有以下:
<!--mybatis-plus框架,可以自动生成xml,不用自己写单表的sql,但是多表操作还得自己写-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<!--单元测试,其实这个都不用引入,因为springboot会自动映入单元测试库-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<!--常用类库,里面有一些工具类,比如字符串是否为空-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
最后springboot会引入maven插件,目前我还没用到,不知道这个插件有啥用,本着自动生成的不删原则,先放着。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
选择完要添加的依赖,点击finish,等待项目生成和依赖下载,然后手动补齐自己的依赖。
idea连接阿里云数据库
写一个CRUD的Demo
前面项目初始化完成,数据库也成功连接之后,就可以写一个增删改查的demo了,主要是验证一下项目初始化有没有问题。
- 创建数据库,新建表,插入数据。
- 引入依赖
- 在 application.yml 配置文件中添加mysql数据库的相关配置(.yml的配置文件比properties文件好用)
【踩过的坑:这里的配置信息是有层级关系的,注意前面的空格】
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/kplusone?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password:
- 在com.kplusone.usercenter包下新建一个mapper文件夹
- 在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:
添加这个注解的作用是把mapper对象注入到spring容器当中,具体原理可以参考
@SpringBootApplication
@MapperScan("com.kplusone.usercenter.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 编写实体类 User.java(此处使用了 Lombok 简化代码)
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
- 编写 Mapper 包下的 UserMapper接口
public interface UserMapper extends BaseMapper<User> {
}
- 测试(内含遇到的bug,bug的原因是导包的时候没有区分junit4和junit5)
底层原因:Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库(本项目使用的是spring boot 2.6.7)依赖信息如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
下面这个测试是使用junit5的:
package com.kplusone.usercenter;
import com.kplusone.usercenter.mapper.UserMapper;
import com.kplusone.usercenter.model.domain.User;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.List;
//不加runwith是因为springbootTest可以根据路径找到启动器UserCenterApplication
//这个测试类所在的包路径应该和启动类UserCenterApplication的包路径一致,这是一种编程的约定,慢慢的就成为强制性的,不然就报错,在编程里面有一种【**约定大于配置的说法**】,以后慢慢体会。
@SpringBootTest
class UserCenterApplicationTests {
@Resource
private UserMapper userMapper;
@Test//这里不能使用junit4里的,如果是引用junit4里的就必须要使用runwith,因为springboot默认使用junit5,要改成4必须通过runwith注解告诉框架,不然springboot启动不起来。第二种方法就是引用Jupiter的test,这样就不需要引用runwith,因为他就和springbootTest整合了,会启动spring boot环境
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);
Assertions.assertEquals(5, userList.size());
userList.forEach(System.out::println);
}
}
下面这个测试是使用junit4的:
先要自己手动引入junit4的依赖,因为springboot的依赖架构里没有版本4。
package com.kplusone.usercenter;
import com.kplusone.usercenter.mapper.UserMapper;
import com.kplusone.usercenter.model.domain.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;//junit整合spring的体现。
import javax.annotation.Resource;//与Autowired对应的是Resource,他不是spring里的,也可以注入对象,根据对象名字注入的。spring框架应该是把这个注解整合进去了。
import java.util.List;
/**
* 今日找bug得到的感悟:
* 1.别一直复习之前的内容,往后学到某一个知识点会突然醒悟之前不理解的,
* 这样的效率高,因为这是站在一个更高的角度看待问题,一直停留在之前的知识体系很难
* 发现自己还不懂什么。
* 2.还有一点就是学编程实操放在第一位,动手做项目,show me the code
* 3.实操过程认真对待每一次的bug,不放过任何一个细节,深入本质,这样会进步很快
* 4.FPGA也同样适用以上三点
*/
@SpringBootTest//这个注解是配合下面注解使用的,不能省略,它的作用是为了创建SampleTest对象
@RunWith(SpringRunner.class)
//junit4里的注解(这个注解直译就是这个类和SpringRunner.class一起跑,这样才能把springboot启动起来。因为junit4本不是spring框架里的组件所以要引入RunWith,这也说明为什么spring如此流行,因为他善于整合其他优秀的组件和框架),还有就是为啥数据库连不上(YML配置文件写错了,datasource在spring之下,层级关系很严格)
public class SampleTest {
@Resource// 从Spring容器里注入对象。usermapper是接口不能实例化,底层用了jdk的动态代理。
private UserMapper userMapper;//autowired是按照类型注入,resource是按照名字注入的
@Test//这里test默认引入的是springboot默认的单元测试库junit5,但是我们自己用就引入junit4,所以在这个测试类上就要加上@RunWith注解。
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);//直接调用基类的方法,queryWrapper是查询条件的包装类,这里空是代表查询所有
Assert.assertEquals(5, userList.size());//断言(Junit4里的类,就是判断运行结果和预期是否一致,如果不一致,程序运行会停在这一行)
userList.forEach(System.out::println);//其实就是增强for循环(等效迭代器,就是一种语法糖)和流式编程【应该是lamda表达式】(或许还有消费者模式在里面,楠老师讲过,这样做项目回忆知识点比单纯看知识点效率更高)
}
}
题外话:
-
mybatisplus之所以不用写单表的增删改查配置文件就是因为mapper接口直接继承了BaseMapper,Basemapper里有框架直接生成的增删改查方法。
以上三点都是做项目引发的思考,从而带动复习了框架的八股文,所以说以项目需求带动学习知识点效率是比单独去学知识点或八股文的效率高的,但是前替还是得对知识有框架的认识,才能在做项目的过程中对自己提出很多有价值的问题,通过百度解决这些问题就是在复习八股文。以后学任何新的编程知识都先学会最小必要知识,然后就用起来,再在用的过程中不断深挖,千万不要一上来就想着把所有知识的细节都掌握,那是不可能的,效率极低,而且还要注意不要学过时的技术。
参考资料:自己的笔记和别人的笔记