Skip to content

🐍 AcWing SpringBoot - KOB


五、配置 mysql


5.1 下载 &安装



  • 安装:
微信截图_20251119134523
微信截图_20251119134529
  • 其它页面默认配置即可 ...

5.2 入门操作


  • 配置环境变量:

    C:\Program Files\MySQL\MySQL Server 8.0\bin( 如果安装到了其他目录,填写相应目录的地址即

    可)添加到环境变量 PATH 中,这样就可以在任意目录的终端中执行 mysql 命令了。

  • 检查是否安装成功 / 是否添加好环境变量(添加到环境变量后):

shell
mysql --version

  • mysql 服务的启动&关闭(默认开机自动启动,如果想手动操作,可以参考如下命令)
  • 关闭:net stop mysql80
  • 启动:net stop mysql80

  • mysql の 常用操作:

    • 连接用户名为 root,密码为 123456 的数据库服务:mysql -uroot -p123456

    • show databases; :列出所有数据库

    • create database kob; :创建数据库

    • drop database kob; :删除数据库

    • use kob; : 使用数据库 kob

    • show tables; : 列出当前数据库的所有表

    • create table user(id int, username varchar(100))

      创建名称为 user 的表,表中包含 idusername 两个属性。

    • drop table user; :删除表

    • insert into user values(1, 'irai'); :在表中插入数据

    • select * from user; :查询表中所有数据

    • delete from user where id = 2; :删除某行数据


六、配置 SpringBoot


6.1 地址



6.2 配置 Maven


  • pom.xml 中添加依赖:
    • Spring Boot Starter JDBC
    • Project Lombok
    • MySQL Connector/J
    • mybatis-plus-spring-boot3-starter
    • mybatis-plus-generator
    • spring-boot-starter-security
    • jjwt-api
    • jjwt-impl
    • jjwt-jackson

6.3 application.properties


  • application.properties 中添加数据库配置:
properties
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/kob?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

6.4 SpringBoot 简单介绍


  • SpringBoot 中的常用模块
    • pojo 层:将数据库中的表对应成 Java 中的 ClassORM
    • mapper 层(也叫 Dao 层):将 pojo 层的 class 中的操作,映射成 sql 语句
    • service 层:写具体的业务逻辑,组合使用 mapper 中的操作
    • controller 层:负责请求转发,接受页面过来的参数,传给 Service 处理,接到返回值,再传给页面

6.5 实现用户表的 CRUD


6.5.1 前置工作


  • 配置好 Maven 的依赖
  • application.properties 的数据库配置也要配置好
  • 在自己的数据库里创建 kob 数据库
sql
create database kob;
  • kob 数据库里创建 user 这张表
sql
create table user(id int, username varchar(100), password varchar(100));
  • IDEA 可以连接上对应的数据库 URL :
shell
jdbc:mysql://localhost:3306/kob?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
微信截图_20251119143651

6.5.2 pojo


  • 在目录 backend 下创建目录 pojo , pojo 目录下创建 User.java 这个类

  • 我们引入了 lombok 这个依赖就可以快速构建 pojo

java
package com.kob.backend.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    // 对应 sql 里 user 表
    private Integer id;
    private String username;
    private String password;
}

6.5.3 Mapper


  • 我们引入了 Mybatis-Plus 的依赖,这里我们也可以使用 Mybatis-Plus 快速构建 mapper

  • 在目录 backend 下创建目录 mapper , mapper 目录下创建 UserMapper 这个接口

  • 让这个接口继承于 BaseMapper 并传入泛型,即 BaseMapper<User> 就可以让

    MyBatis-Plus 给我们构建好一个关于 Usermapper 接口了

java
package com.kob.backend.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.kob.backend.pojo.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

6.5.4 Mybatis-Plus 快速开始


  • 对于刚刚我们创建表的语句 :
sql
create table user(id int, username varchar(100), password varchar(100));
  • 生成几条测试数据:
sql
INSERT INTO user (id, username, password) VALUES
(1, 'admin', 'admin123'),
(2, 'irai', 'irai123'),
(3, 'john', 'john123'),
(4, 'alice', 'alice123'),
(5, 'bob', 'bob123');
微信截图_20251119145457

❗ ​注意:

  • 对于在 Maven 仓库复制过来的依赖引入,需要重点注意的问题,否则会报错!!!
微信截图_20251119152426
  • 像这种带有 spring-boot 的最好就不要添加版本号,让最上面那个依赖统一管理版本:
微信截图_20251119152417

  • 6.5.3 我们已经编写了 user 表的 mapper ,我们添加测试方法进行功能测试:
java
package com.kob.backend;

import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class BackendApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userMapper.selectList(null);
        userList.forEach(System.out::println);
    }

}
  • 运行结果:
微信截图_20251119152749
  • 这就打印出了 查询所有 User 返回的结果 ... ,其实它直接实现了 User 表的 CRUD
  • 具体参考:BaseMapper Interface

6.5.5 完成 CRUD


  • 接下来我们完成用户表简单的 CRUD 接口

  • 下面严格来说需要按照三层架构来写,也就是说其实应该有 Service

    但是由于逻辑太简单,为了方便调试,只使用 Controller 层来完成编写



  • controller 目录下创建 user 目录, 再在 user 目录下创建 UserController
java
package com.kob.backend.controller.user;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

    // 注入 mapper 层对象
    @Autowired
    private UserMapper userMapper;

    // 查询所有用户信息
    @GetMapping("/all/")
    public List<User> getAll(){
        return userMapper.selectList(null);
    }

    // 根据 ID 来查找用户
    @GetMapping("/{userId}/")
    public User getUserById(@PathVariable int userId){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", userId);
        // 返回满足条件构造器的一条数据(id 是唯一的)
        return userMapper.selectOne(queryWrapper);
    }

    // 添加一条用户信息
    @GetMapping("/add/{userId}/{username}/{password}/")
    public String addUser(
            @PathVariable int userId,
            @PathVariable String username,
            @PathVariable String password
    ){
        User user = new User(userId, username, password);
        userMapper.insert(user);
        return "Add User Successfully";
    }

    // 根据 Id 删除一条用户信息
    @GetMapping("/delete/{userId}")
    public String deleteUserById(@PathVariable int userId){
        userMapper.deleteById(userId);
        return "Delete User Successfully";
    }

}

  • 📌 ​先叠一波甲:上述很多操作都是不规范的,但目的只是为了快速写个 demo 演示 Mybatis-Plus

  • 效果:

  • 查找全部用户信息:

微信截图_20251119155654
  • 根据 userid 来查找用户:
微信截图_20251119155707
  • 添加一个用户:
微信截图_20251119155601
微信截图_20251119155613
  • 根据 userid 删除一个用户:
微信截图_20251119155633

6.6 Spring Security


6.6.1 引入 Security


  • pom.xml 加上依赖:
xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <!--不要加版本号,让 spring-boot-starter-parent 统一管理-->
    <!--<version>...</version>-->
</dependency>

  • 重启项目,再访问任意资源文件都会发现访问不到,会被 Spring Security 拦截到,

    并且重定向到了 /login 这个路由上, 需要我们输入账号密码:

微信截图_20251120114645
  • 默认的 usernameuser ,而 password 会在每次运行的时候生成给我们:
微信截图_20251120114659
  • 使用用户名和密码登录后我们就可以正常访问到资源了,然后我们希望登出的话就进入路由 /logout :
微信截图_20251120115314
微信截图_20251120115503
  • 可以发现,我们现在进行登录只能用默认用户名和随机生成的密码,如果我们想让 Spring Security

    对接我们的数据库,也就是说,通过数据库来判断一组用户名密码能不能登录成功,这就需要做相应的配置


6.6.2 配置 Security


  • 实现 service.impl.UserDetailsServiceImpl 类,

    继承自 UserDetailsService 接口,用来接入数据库信息

  • 操作细节:在 backend 目录下创建一个 service 目录,再在 service 下创建一个 impl 目录

    然后 impl 目录下面创建一个 UserDetailsServiceImpl 类,这个类 implements

    UserDetailsService 这个接口,我们可以 alt + ins 键快速补全出要实现的方法:

微信截图_20251120125626
  • 可以发现要我们实现的方法 loadUserByUsername 的返回值类型是 UserDetails ,

    所以我们还需要写一个类实现 UserDetails : 在 impl 目录下创建一个 utils 目录

    然后在 utils 下创建一个类 UserDetailsImpl , 也是使用 alt + ins

    快速补全出实现方法


  • ➡️ UserDetailsServiceImpl
java
package com.kob.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import com.kob.backend.service.impl.utils.UserDetailsImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        User user = userMapper.selectOne(queryWrapper);
        if(user == null){
            throw new UsernameNotFoundException("用户不存在");
    }
        return new UserDetailsImpl(user);
    }
}

  • ➡️ UserDetailsImpl
java
package com.kob.backend.service.impl.utils;

import com.kob.backend.pojo.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDetailsImpl extends Throwable implements UserDetails {

    private User user;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

  • 但是当我们写好后,即使传入对应数据库的用户名和密码都还是登不进去

    那是因为 Spring Security 默认只认 “用户名 + 加密后的密码”(一般是 BCrypt

    那么我们需要额外写一个实现用户密码加密存储的类


  • backend/config 目录下创建一个类 SecurityConfig
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

  • 关于:BCryptPasswordEncoder() 的两个方法:
    • encode() :可以将一个明文转化为密文
    • matches() :可以判断传入的某个明文和传入的密文是否匹配

  • 那么我们可以在测试方法里试试这两个方法:
微信截图_20251120133914
  • 可以发现,即使我们输入相同的字符串,多次加密的结果也是不一样的
  • 但是如果使用匹配 matchs() , 它是可以判断是一样的:
微信截图_20251120134106
  • 那么有了这个 passwordEncoder() 我们就需要在之前 UserController 里面

    添加用户信息 addUser 那个接口把接收到的明文信息先转化为密文,然后再存储

java
// 添加一条用户信息
@GetMapping("/add/{userId}/{username}/{password}/")
public String addUser(
    @PathVariable int userId,
    @PathVariable String username,
    @PathVariable String password
){
    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    String encodePassword = passwordEncoder.encode(password);
    User user = new User(userId, username, encodePassword);
    userMapper.insert(user);
    return "Add User Successfully";
}

  • 之前我们添加的五条用户信息的密码都是明文存的,要不就是从测试方法里一个一个

    加密后的密码弄出来,然后手动修改一下,要不就都删掉,使用这个 addUser 接口来

    添加一遍,我就先都删掉,然后加入一条就好了

    (想这样操作先注释掉某些刚刚的配置然后使用 user + 随机密码登录)

微信截图_20251120135136
  • 添加成功后打开刚刚注释的配置,重新启动项目, 然后使用 irai 这个用户来登录

    这样就既登录进去,又访问到资源信息了:

微信截图_20251120140810