0%

SpringBoot学习笔记

1 springboot概述

1.1 概述

Spring Boot是Spring提供的一个子项目,用于快速构建Spring应用程序。

1.2 传统方式构建spring应用程序

1 导入依赖繁琐。
2 项目配置繁琐。

1.3 SpringBoot特性

1.3.1 起步依赖

本质上就是一个Maven坐标,整合了完成一个功能需要的所有坐标。(解决配置繁琐的问题)

1.3.2 自动配置

遵循约定大于配置的原则,在boot程序启动后,一些bean对象会自动注入到iloc容器,不需要手动声明,简化开发。(解决项目配置繁琐的问题)

1.3.3 其他特性

1 内嵌的Tomcat、Jetty(无需部署WAR文件)。
2 外部化配置。部署完毕后,需要修改,只需要修改项目外部配置文件,直接重新启动项目就可以。
3 不需要XML配置(properties/yml)。

2 sprintboot入门

需求:使用SpringBoot开发一个web应用,浏览器发起请求/hello后,给浏览器返回字符串”hello world~”。

1 创建Maven工程。
2 导入spring-boot-starter-web起步依赖。
3 编写Controller。

1
2
3
4
5
6
7
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "Hello World~";
}
}

4 提供启动类。

1
2
3
4
5
6
7
//启动类
@SpringBootApplication
public class SpringbootSyqApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootSyqApplication.class, args);
}
}

3 sprintboot工程创建

手动创建SpringBoot工程
1 创建Maven工程。
2 引入依赖。
3 提供启动类。

4 springboot配置文件_基本使用

4.1 学习路径

4.1.1 基础篇

配置文件。
整合MyBatis。
Bean管理。
自动配置管理。
自定义starter。

4.1.2 实战篇

项目开发。
整合三方技术。
项目部署。

4.1.3 面试篇

面试题。
源码。

4.2 配置文件

1 properties配置文件。application.properties文件。

1
2
3
4
//修改端口号
server.port=9090
//修改虚拟目录
server.servlet.context-path=/start

2 yaml配置文件(实际开发中更常用)。application.yml(主要)/application.yaml。

5 yml配置信息书写和获取

5.1 三方技术配置信息

只需编写配置信息,起步依赖会自动获取配置信息。

5.2 自定义配置信息

不仅需要编写配置信息,还需要实现配置信息的获取代码。

5.3 yml配置信息书写

1 值前边必须有空格,作为分隔符。
2 使用空格作为缩进表示层级关系,相同的层级左侧对齐。

1
2
3
4
5
# 学生的爱好-数组
hobbies:
- 打篮球
- 打豆豆
- 打游戏

5.4 配置信息的获取

5.4.1 @Value

1
2
3
4
5
6
//获取yml文件中指定键对应的值。
@Value("${键名}")

@Value("${email.user}")
//发件人邮箱
public String user;

在使用@Value注解时,多个层级的键名使用.来连接。

5.4.2 ConfigurationProperties(prefix=”前缀”)

实体类的成员变量名与配置文件中的键名一致。

1
@ConfigurationProperties(prefix="email")

6 springboot整合mybatis

1 引入mybatis-spring-boot-starter依赖。pom.xml文件修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--web起步依赖(springboot自带)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatis的起步依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!--mysql驱动依赖-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>

2 yml文件数据库配置。数据库驱动,数据库链接,用户名,密码等。SpringBoot自动读取配置信息。

1
2
3
4
5
6
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/kongming
username: root
password: 181234

目标:查询User表指定id的数据,响应给浏览器。
Mapper编写:

1
2
3
4
5
6
@Mapper
public interface UserMapper {
// 通过id找到User
@Select("select * from user where id = #{id}")
public User findById(Integer id);
}

Service编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface UserService {
public User findById(Integer id);
}

//把当前UserServiceImpl类的对象交给IOC容器
@Service
public class UserServiceImpl implements UserService {
//注入一个UserMapper对象实现数据库查询
@Autowired
private UserMapper userMapper;

@Override
public User findById(Integer id) {
//CTRL+I重写方法
return userMapper.findById(id);
}
}

Controller编写:

1
2
3
4
5
6
7
8
9
10
@RestController
public class UserController {
//注入一个Service对象
@Autowired
private UserService userService;
@RequestMapping("/findById")
public User findById(Integer id){
return userService.findById(id);
}
}

7 Bean扫描

标签:

1
<context:component-scan base-package="com.kongming">

注解:

1
@ComponentScan(basePackages="com.kongming")

在SpringBoot启动类的注解,实际上是一个组合注解:

1
2
3
4
5
6
7
8
9
//默认扫描添加了该注解的启动类所在的包及其子包。
@SpringBootApplication
//可以手动添加不在该包内的包
@ComponentScan(basePackages="com.kongming")

//等价于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

8 Bean注册

8Bean注册1
如果要注册的Bean对象来自于第三方(不是自定义的),是无法用@Component及衍生注解声明bean的。Spring提供了两个注解来解决问题:
1 @Bean
2 @Import

1
mvn install:install-file -Dfile=C:\SunYuQi\data\研一\工作\springboot资料\02_资料\02_Bean注册资料\common-pojo-1.0-SNAPSHOT.jar -DgroupId=cn.itcast -DartifactId=common-pojo -Dversion=1.0 -Dpackaging=jar
1
2
3
4
5
6
<!--第三方包导入-->
<dependency>
<groupId>cn.itcast</groupId>
<artifactId>common-pojo</artifactId>
<version>1.0</version>
</dependency>

8.1 @Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//启动类,不建议在启动类中
@Configuration
//建议放在启动类所在的包中
@SpringBootApplication
public class SpringbootSyqApplication {

public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(SpringbootSyqApplication.class, args);
Country country = context.getBean(Country.class);
System.out.println(country);
}
//注入Country对象
//将方法返回值交给IOC容器管理,成为IOC容器的bean对象
@Bean
public Country country(){
return new Country();
}
}

建议的写法:

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
@Configuration
public class CommonConfig {
//注入Country对象
@Bean
public Country country(){
return new Country();
}
//对象默认的名字是方法名
@Bean
public Province province(){
return new Province();
}

//修改Bean对象的默认名称
@Bean("aa")
//如果方法的内部需要使用到ioc容器中已经存在的bean对象,那么只需要在方法上声明即可,spring会自动的注入。
@Bean()
public Province province(){
System.out.println("province"+country());
return new Province();
}
}

```java
//启动类
@SpringBootApplication
public class SpringbootSyqApplication {

public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(SpringbootSyqApplication.class, args);
Country country = context.getBean(Country.class);
System.out.println(country);

System.out.println(context.getBean("province"));
}
}

8.2 @Import

使用@Import相当于手动扫描类。
1 导入配置类。
2 导入ImportSelector接口实现类。

1
2
3
4
5
6
7
8
9
10
11
12
13
//启动类
@SpringBootApplication
@Import(CommonConfig.class)
public class SpringbootSyqApplication {

public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(SpringbootSyqApplication.class, args);
Country country = context.getBean(Country.class);
System.out.println(country);

System.out.println(context.getBean("province"));
}
}
1
2
3
4
5
6
7
8
9
10
@Import(CommonImportSelector.class)

public class CommonImportSelector implements ImportSelector {
//springboot会自动调用selectimports方法
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//从配置文件中读取
return new String[]{"config.CommonConfig"};
}
}

在配置文件中,每行一个类名。实现上述代码的注释部分,完整如下:

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
public class CommonImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//读取配置文件的内容
List<String> imports = new ArrayList<String>();
InputStream is = CommonImportSelector.class.getClassLoader().getResourceAsStream("common.imports");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//一行一行的读取内容
String line = null;
try {
while((line = br.readLine())!=null){
imports.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if(br!=null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
return imports.toArray(new String[0]);
}
}
1
2
3
4
5
6
7
8
9
10
@Target(ElementType.TYPE)
//当前的注解可以在类上使用
@Retention(RetentionPolicy.RUNTIME)
//当前的注解会保留在运行时阶段
@Import(CommonImportSelector.class)
public @interface EnableCommonConfig {
}

//启动类中的使用方式
@EnableCommonConfig

9 注册条件

9.1 需要注册条件的原因

配置文件中配置:

1
2
3
country:
name: china
system: socialism

在java文件中读取配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
public class CommonConfig {
//注入Country对象
@Bean
public Country country(@Value("${country.name}") String name, @Value("${country.system}") String system){
Country country = new Country();
country.setName(name);
country.setSystem(system);
return country;
}
//对象默认的名字是方法名
@Bean()
public Province province(Country country){
System.out.println("province"+country);
return new Province();
}
}

我们希望达到的效果是,如果配置文件中配置了指定的信息,则注入,否则不注入。

9.2 注册条件

SpringBoot提供了设置注册生效条件的注解@Conditional.
9注册条件1

1
2
3
4
5
6
7
8
9
10
//注入Country对象
//如果配置文件中配置了指定的信息,则注入,否则不注入。
@ConditionalOnProperty(prefix = "country",name = {"name","system"})
@Bean
public Country country(@Value("${country.name}") String name, @Value("${country.system}") String system){
Country country = new Country();
country.setName(name);
country.setSystem(system);
return country;
}
1
2
3
4
5
6
//如果ioc容器中不存在country,则注入Province,否则不注入
@Bean()
@ConditionalOnMissingBean(Country.class)
public Province province(){
return new Province();
}
1
2
3
4
5
6
7
@Bean()
//如果当前环境中存在DispatcherServlet类,则注入Province,否则不注入
//如果当前引入了web起步依赖,则环境中有DispatcherServlet类,否则没有
@ConditionalOnClass(name="org.springframework.web.servlet.DispatcherServlet")
public Province province(){
return new Province();
}

10 自动配置原理

10.1 需要学习自动配置原理的原因

1 自定义starter。
2 面试。

10.2 自动配置体验

遵循约定大于配置的原则,在boot程序启动后,起步依赖中的一些bean对象会自动注入到ioc容器。程序引入spring-boot-starter-web起步依赖,启动后,会自动往ioc容器中注入DispatcherServlet。

1
mvn install:install-file -Dfile=C:\SunYuQi\data\研一\工作\springboot资料\02_资料\03_自动配置\common-pojo-2.0-SNAPSHOT.jar -DgroupId=cn.itcast -DartifactId=common-pojo -Dversion=2.0 -Dpackaging=jar

10.3 自动配置原理

在主启动类上添加了SpringBootApplication注解,这个注解组合了EnableAutoConfiguration注解。
EnableAutoConfiguration注解又组合了Import注解,导入了AutoConfigurationImportSelector类。
实现selectImports方法,这个方法经过层层调用,最终会读取META-INF目录下的后缀名为imports的文件,当然了,boot2.7以前的版本,读取的是spring.factories文件。
读取到全类名之后,会解析注册条件,也就是@Conditional及其衍生注解,把满足注册条件的Bean对象自动注入到IOC容器中。

11 自定义starter

11.1 场景

在实际开发中,经常会定义一些公共组件,提供给各个项目团队使用。而在SpringBoot的项目中,一般会将公共组件封装为SpringBoot的starter。
xxxx-autoconfigure <—自动配置功能
xxxx-starter <—依赖管理功能

11.2 自定义mybatis的starter

1 创建dmybatis-spring-boot-autoconfigure模块,提供自动配置功能,并自定义配置文件 META/INF/spring/xxx.imports.
2 创建dmybatis-spring-boot-stater模块,在starter中引入自动配置模块。

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
//表示当前类是一个自动配置类
@AutoConfiguration
public class MybatisAutoConfig {
//SqlSessionFactoryBean
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
//把dataSource注入到sqlSessionFactoryBean就知道要连接的数据库
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
//MapperScannerConfigure
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(BeanFactory beanFactory){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//设置扫描的包:启动类所在的包及其子包
List<String> packages = AutoConfigurationPackages.get(beanFactory);
//启动类只有一个,所以packages中只会有一个包,直接取出0号元素即可。
String p = packages.get(0);
mapperScannerConfigurer.setBasePackage(p);
//扫描的注释
mapperScannerConfigurer.setAnnotationClass(Mapper.class);
return mapperScannerConfigurer;
}
}
1
com.kongming.config.MybatisAutoConfig

pom文件中是定义好的autoconfig和autoconfig的依赖。

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
<!--引入定义好的autoconfig-->
<dependency>
<groupId>com.kongming</groupId>
<artifactId>dmybatis-spring-boot-autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.14</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>

12 实战篇-开发模式和环境搭建

12.1 实战开发的技术栈

后台:
Validation做参数校验。
Mybatis做数据库操作。
Redis做缓存。
Junit做单元测试。
SpringBoot项目部署。
前端:
Vite Vue项目的脚手架。
Router路由。
Pina状态管理。
Element-Plus UI组件。

12.2 开发模式

接口文档:
1 路径和请求方式。
2 请求参数。
3 响应数据。

12.3 环境搭建

执行资料中的big_event.sql脚本,准备数据库表。
创建springboot工程,引入对应的依赖(web,mybatis,mysql驱动)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!--mysql驱动依赖-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>

配置文件application.yml中引入mybatis的配置信息。

1
2
3
4
5
6
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/kongming
username: root
password: 181234

创建包结构,并准备实体类。
12开发模式和环境搭建1
其中pojo存放实体类,utils存放工具类。

13 实战篇-注册接口

用户模块需要开发的接口:
1 注册。
2 登录。
3 获取用户详细信息。
4 更新用户基本信息。
5 更新用户头像。
6 更新用户密码。

lowbok:在编译阶段为实体类自动生成setter,getter,toString方法
使用lowbok:
(1)在pom文件中引入依赖;
(2)在实体类上添加注解。

1
2
3
4
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
@Data
public class User {
private Integer id;//主键ID
private String username;//用户名
private String password;//密码
private String nickname;//昵称
private String email;//邮箱
private String userPic;//用户头像地址
private LocalDateTime createTime;//创建时间
private LocalDateTime updateTime;//更新时间
}

在其余实体类中都添加Data注解。在缺少构造方法的实体类中添加下列注解:

1
2
3
4
//无参数构造方法
@NoArgsConstructor
//全参数构造方法
@AllArgsConstructor

13.1 注册

明确需求->阅读接口文档->思路分析->开发->测试。

13.1.1 基本信息

请求路径:/user/register
请求方式:POST
接口描述:该接口用于注册新用户

13.1.2 请求参数

请求参数格式:x-www-form-urlencoded

请求参数说明:

参数名称 说明 类型 是否必须 备注
username 用户名 string 5~16位非空字符
password 密码 string 5~16位非空字符

请求数据样例:

1
username=zhangsan&password=123456

13.1.3 响应数据

响应数据类型:application/json

响应参数说明:

名称 类型 是否必须 默认值 备注 其他信息
code number 必须 响应码, 0-成功,1-失败
message string 非必须 提示信息
data object 非必须 返回的数据

响应数据样例:

1
2
3
4
5
{
"code": 0,
"message": "操作成功",
"data": null
}

13.2 代码编写

1 Controller部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RestController
@RequestMapping("/user")
public class UserController {

//注入一个UserService对象
//在UserService部分要注入一个userService对象,使用@Service注解
@Autowired
private UserService userService;
@PostMapping("/register")
public Result register(String username, String password) {
//查询用户
User u = userService.findByUserName(username);
if(u == null){
//用户名没有占用
userService.register(username,password);
return Result.success();
}else{
//占用
return Result.error("用户名已被占用");
}
//注册
}
}

2 Service部分。

1
2
3
4
5
6
7
8
9
public interface UserService {
//CTRL+ALT转到对应UserService实体类
//ALT+ENTER生成方法
//根据用户名查询用户
User findByUserName(String username);

//注册
void register(String username, String password);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//在容器中注册当前类对象
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User findByUserName(String username) {
User u = userMapper.findByUserName(username);
return u;
}

@Override
public void register(String username, String password) {
//密码要加密处理
String md5String = Md5Util.getMD5String(password);
//添加到数据库
userMapper.add(username,md5String);
}
}

3 Mapper部分。

1
2
3
4
5
6
7
8
9
10
@Mapper
public interface UserMapper {
//根据用户名查询用户
@Select("select * from user where username=#{username}")
User findByUserName(String username);
//添加
@Insert("insert into user(username,password,create_time,update_time)" +
"values (#{username},#{password},now(),now())")
void add(String username, String password);
}

14 实战篇-注册接口参数校验

在接口文档中,请求参数必须是5-16位的非空字符。后端必须保证前端传来的参数是符合要求的。

14.1 手动添加校验

在controller层添加校验。

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
@RestController
@RequestMapping("/user")
public class UserController {

//注入一个UserService对象
//在UserService部分要注入一个userService对象,使用@Service注解
@Autowired
private UserService userService;
@PostMapping("/register")
public Result register(String username, String password) {
if(username != null && username.length()>=5 && username.length()<=16 &&
password != null && password.length()>=5 && password.length()<=16) {
//查询用户
User u = userService.findByUserName(username);
if(u == null){
//用户名没有占用
//注册
userService.register(username,password);
return Result.success();
}else{
//占用
return Result.error("用户名已被占用");
}
}else{
return Result.error("参数不合法");
}
}
}

14.2 Spring Validation

上述参数校验代码过于繁琐,Spring提供一个参数校验框架,使用预定义的注解完成参数校验。
1 引入Spring Validation起步依赖。

1
2
3
4
5
<!--validation依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2 在参数前面添加@Pattern注解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@RestController
@RequestMapping("/user")
@Validated
public class UserController {

//注入一个UserService对象
//在UserService部分要注入一个userService对象,使用@Service注解
@Autowired
private UserService userService;
@PostMapping("/register")
public Result register(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {
//查询用户
User u = userService.findByUserName(username);
if(u == null){
//用户名没有占用
//注册
userService.register(username,password);
return Result.success();
}else{
//占用
return Result.error("用户名已被占用");
}
}
}

3 在Controller类上添加@Validation注解。

4 在全局异常处理器中处理参数校验失败的异常。参数校验失败异常处理。@Restxxxb表示所有返回值都会被自动转化为json字符串。

1
2
3
4
5
6
7
8
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result handleException(Exception e) {
e.printStackTrace();
return Result.error(StringUtils.hasLength(e.getMessage())?e.getMessage():"操作失败");
}
}

15 实战篇-登录主逻辑

15.1 基本信息

请求路径:/user/login
请求方式:POST
接口描述:该接口用于登录

15.2 请求参数

请求参数格式:x-www-form-urlencoded

请求参数说明:

参数名称 说明 类型 是否必须 备注
username 用户名 string 5~16位非空字符
password 密码 string 5~16位非空字符

请求数据样例:

1
username=zhangsan&password=123456

15.3 响应数据

响应数据类型:application/json

响应参数说明:

名称 类型 是否必须 默认值 备注 其他信息
code number 必须 响应码, 0-成功,1-失败
message string 非必须 提示信息
data string 必须 返回的数据,jwt令牌

响应数据样例:

1
2
3
4
5
{
"code": 0,
"message": "操作成功",
"data": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOnsiaWQiOjUsInVzZXJuYW1lIjoid2FuZ2JhIn0sImV4cCI6MTY5MzcxNTk3OH0.pE_RATcoF7Nm9KEp9eC3CzcBbKWAFOL0IsuMNjnZ95M"
}

jwt令牌是一串字符串。

15.4 备注说明

用户登录成功后,系统会自动下发JWT令牌,然后在后续的每次请求中,浏览器都需要在请求头header中携带到服务端,请求头的名称为 Authorization,值为登录时下发的JWT令牌。
如果检测到用户未登录,则http响应状态码为401

15.5 代码实现

service和mapper使用用户注册中写好的即可。主要需要在controller中添加用户登录模块代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@PostMapping("/login")
public Result<String> login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {
//根据用户名查询用户
User loginUser = userService.findByUserName(username);
//判断该用户是否存在
if(loginUser == null){
return Result.error("用户名错误");
}
//判断密码是否正确。loginUser对象中的
if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){
//登录成功
return Result.success("jwt token令牌..");
}
return Result.error("密码错误");
}

16 实战篇-登录认证引入

登录认证-在未登录的情况下,可以访问到其他资源。

17 实战篇-JWT令牌

18 实战篇-登录认证-完成

19 实战篇-获取用户详细信息

20 实战篇-获取用户详细信息-Thread

21 实战篇-更新用户基本信息