后端职责可以粗浅的理解为处理各种数据,那么处理数据就可以从下面几个方面考虑:
数据的来源
根据不同的数据来源,我们探究两个方面的内容:
数据的形式
数据的操作
当然,一通操作以后,各个来源的数据需要通信,所以还有一个:数据的交互
想要持久化存储数据,需要将数据存入数据库。
想要对数据进行各种丰富的处理,需要将数据存放进 Java 的各种数据结构中(List、Map…)。
还有一个来源就是用户在前端的输入。
数据操作: SQL 语言
数据操作: 方法调用
数据操作: JavaScript
数据的来源有三个,一般都是以 Java 后端作为中间桥梁。我们一对一对的看。数据交互要达到的效果就是统一形式、互相操作。
数据库与 Java 后端:
数据库一般只是用来提供数据,所以交互的任务就落到了 Java 后端的身上。
数据库里面数据组织的形式是表,Java 里面是类,因为我们要把数据拿到 Java 里面去操作。一个很自然的想法就是,将表直接映射成 Java 里面的类,由于类只是一个结构,我们具体操作的是类的对象。所以我们更多地会说成将表映射成对象。由于这里的表特指关系型数据库的表,所以这种映射被称为 Object–relational mapping,即对象关系映射,简称 ORM.
那么表能变成对象吗?我们发现是可以的。因为表里的各个属性可以映射到对象的属性上来,每一条表的记录都可以映射成一个对象的各个属性
理论上是可行的,那实际操作呢?Java 要想将表的记录转变成对象,那就只能通过一系列方法的执行来做到了。
Java 程序员甚至不需要懂 SQL,就完成了和数据库的交互。可以概括如下:
定义实体类
写接口
调用接口
但是默认的这些方法所能够拥有的功能是有限的,对于国内的互联网公司来说,业务可能会十分复杂,数据访问量也会比较大,这时候良好的 SQL 可能就是必要的啦。虽然说 Spring Data JPA 支持自定义 SQL,但是这不是它的长处,在某些情境下是要受到限制的。于是虽然世界上整体流行使用 JPA,但是我们国内用的不多。
于是我们需要一种对 SQL 支持良好的框架,程序员的注意力可以从写 Java 代码转到了写 SQL 上。这款框架就是 MyBatis.
那么 MyBatis 的步骤就是多了几步:
定义实体类
写接口
写 SQL
接口与 SQL 绑定
调用接口
在 MyBatis 官方文档里有这样几句话:
MyBatis 创建时的一个思想是:数据库不可能永远是你所想或所需的那个样子。 我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们并不都是那样。 如果能有一种数据库映射模式,完美适配所有的应用程序,那就太好了,但可惜也没有。 而 ResultMap 就是 MyBatis 对这个问题的答案。
MyBatis Plus. 它在 MyBatis 的基础上增加了一些常用的接口和功能。并且还有一个神奇的代码生成器,只需要在图形界面点两下,代码和映射文件都会帮你生成好,连代码都不需要写了。
后端对数据的处理
不管你是用什么方式从数据库拿到的数据,在 Java 里面就是一个个对象,这时候就可以拿 Java 语言对数据进行各种操作咯。那么处理完成以后,你还需要返回给前端
前后端数据交互
既然要返回给前端,那么数据形式仍然要统一。前端可以认识的形式就是 JSON,所以我们需要把 Java 对象转换成 JSON,数据格式如果统一的话,那么我们还要想的就是前后端如何通信。
前端每一个请求都对应一个URL,我们将 URL 和 Java 的方法建立映射,一旦在前端访问到 URL,我们就执行相应的后端方法处理相应的请求。
而这些工作在 Spring Boot 里面都有了很好的支持,我们通常使用注解来进行实现。
当然前端也可以发送 JSON 格式的数据给后端,后端转换为 Java 对象,再通过 ORM 框架完成存入数据库的操作。
后端分层的依据
我们可以看到,Java 后端承载着太多的使命:
数据库访问
数据处理
前后端交互
那么将每一项使命放在不同的包里,就对应的变成了 dao 层、service 层和 controller 层。
springboot 的角色是用来处理用户请求的,从client端向springboot端发送请求,然后向数据库请求数据,数据库返回数据给前端
点击右边的数据库 -> + -> 数据源-> MySQL,输入账号、密码、数据库名称,这里是kob,点击测试连接,成功后点击应用就可以了。

创建数据库 kill9
create database kill9;
添加依赖
在pom.xml下添加依赖,依赖可以 Maven仓库地址 中寻找。
Spring Boot Starter JDBC
Project Lombok
MySQL Connector/J
mybatis-plus-boot-starter
mybatis-plus-generator
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-jdbc</artifactId>
- <version>2.7.0</version>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.22</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>8.0.28</version>
- </dependency>
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-boot-starter</artifactId>
- <version>3.5.1</version>
- </dependency>
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-generator</artifactId>
- <version>3.5.1</version>
- </dependency>
选择哪个版本号,都可以,个人习惯是最新的几个版本里选用的人最多的版本。
点击 maven 的重新加载,刷新 Maven。
在application.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
点击运行 出现报错 可能是因为路径问题。
点击运行,输入网址 http://127.0.0.1:8080/pk/index/ 显示界面就成功了
SpringBoot中的常用模块:
pojo层:将数据库中的表对应成Java中的Class
mapper层(也叫Dao层):将pojo层的class中的操作,映射成sql语句
service层:写具体的业务逻辑,组合使用mapper中的操作
controller层:负责请求转发,接受页面过来的参数,传给Service处理,接到返回值,再传给页面

注解:
使用注解可以帮助我们不在需要配置繁杂的xml文件,以前最基本的web项目是需要写xml配置的,需要标注你的哪个页面和哪个 servle 是对应的,注解可以帮助我们减少这方面的麻烦。
@Controller:用于定义控制器类,在spring项目中由控制器负责将用户发来的URL请求转发到对应的服务接口(service层),一般这个注解在类中,通常方法需要配合注解@RequestMapping。
@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。
@Autowired:自动导入依赖的bean
@Service:一般用于修饰service层的组件
@Bean:用@Bean标注方法等价于XML中配置的bean。
@AutoWired:自动导入依赖的bean。byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。当加上(required=false)时,就算找不到bean也不报错。
在 backend 下创建 pojo 包 创建一个类 User,将数据库中的表 User转化为 Java 中的 User.class
- package com.kill9.backend.pojo;
-
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import lombok.AllArgsConstructor;
-
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- public class User {
- private Integer id;
- private String username;
- private String password;
- }
在backend创建mapper 包,创建一个 Java 类的接口 UserMapper
- @Mapper
- public interface UserMapper extends BaseMapper
{ -
- }
在backend 的 controller 下创建 user 包然后创建 UserController.
- package com.kill9.backend.controller.user;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.kill9.backend.mapper.UserMapper;
- import com.kill9.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.RestController;
-
- import java.util.List;
-
- @RestController
- public class UserController {
- @Autowired
- UserMapper userMapper;
- /**
- * 查询所有用户
- */
- @GetMapping("/user/all/")
- public List
getAll(){ - return userMapper.selectList(null);
- }
- /**
- * 查询单个用户
- */
- @GetMapping("/user/{userId}/")
- public User getUser(@PathVariable int userId){
- QueryWrapper
queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("id",userId);
- return userMapper.selectOne(queryWrapper);
-
- // 范围遍历
- // public List
getUser(int userId) - // queryWrapper.ge("id", 2).le("id", 3);
- // return userMapper.selectList(queryWrapper);
- }
- /**
- * 添加某个用户 直接输入 id name password
- * @param userId
- * @param username
- * @param password
- * @return Add User Sucessfully
- */
- @GetMapping("/user/add/{userId}/{username}/")
- 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
- * @param userId
- * @return Delete User Successfully
- */
- @GetMapping("/user/delete/{userId}/")
- public String deleteUser(@PathVariable int userId) {
- userMapper.deleteById(userId);
- return "Delete User Successfully";
- }
- }
查询user中的全部数据。
查询user中的单个数据。
添加 user 中的数据。

删除 user 中的数据。

是用户认证操作 – 一种授权机制,目的是安全。
原理解释
数据库可以知道sessionId对应的用户是谁
如果想让我们的security对接我们的数据库
需要把username在数据库中对应的的用户找出来,返回他的密码
需要用到数据库操作mapper,能写private就写private,用数据库记得加上autowired
3.1添加依赖1. 添加依赖,添加之后刷新。
spring-boot-starter-security
-
org.springframework.boot -
spring-boot-starter-security -
2.7.0
刷新之后显示登陆:

默认的叫 Username 是 user ,密码自动生成。

在backend 的 service 创建 impl 包,新建 UserDetailsServiceImpl 类。
实现service.impl.UserDetailsServiceImpl类,继承自UserDetailsService接口,用来接入数据库信息。
- package com.kill9.backend.service.impl;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.kill9.backend.mapper.UserMapper;
- import com.kill9.backend.pojo.User;
- 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;
-
- public class UserDetailsServiceImpl implements UserDetailsService {
- @Autowired
- private UserMapper userMapper;
- @Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- QueryWrapper
queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("username",username);
- User user = userMapper.selectOne(queryWrapper);
- if(user==null){
- throw new RuntimeException("用户不存在");
- }
- return new UserDetailsImpl(user);
- }
- }
在backend 的 service 包的 impl 包下创建utils 包 新建 UserDetailsImpl。
- package com.kill9.backend.service.impl.utils;
-
- import com.kill9.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 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;
- }
- }
如果实现登录的话,需要提供一个 PassworEncoder。
如果在数据库中指定明文来存储,需要在自己的密码加上{noop},才可以登录。
在 Test 下生成需要转换的密文,同时修改数据库下的密码为密文
- package com.kill9.backend;
-
- import org.junit.jupiter.api.Test;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
- import org.springframework.security.crypto.password.PasswordEncoder;
-
- @SpringBootTest
- class BackendApplicationTests {
-
- @Test
- void contextLoads() {
- PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
- System.out.println(passwordEncoder.encode("123456"));
- System.out.println(passwordEncoder.encode("111111"));
- }
-
- }

重启项目,进入login页面
登录成功,只要不给你显示密码错误就代表成功,显示Whitelabel Error Page也是成功,自己在后面添加路径就可以了登录。

1. 实现密文存储:
上传之后就能登录,数据库知道没有加密之后就不会用到PasswordEncoder
实现任何用户都可以登录在 config 下新建 SecurityConfig 。
实现config.SecurityConfig类,用来实现用户密码的加密存储。加密算法
如果不明文我们可以,将左边哈希到右边,就算数据库泄露我们也不会泄露用户密码
![]()
- package com.kill9.backend.config;
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
- import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
- import org.springframework.security.crypto.password.PasswordEncoder;
-
- @Configuration
- @EnableWebSecurity
- public class SecurityConfig {
- @Bean
- public PasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder();
- }
- }
使用密文添加用户 :
修改 controller 下的 user 的 UserController的注册,密码直接存储加密之后的密码。
- @GetMapping("/user/add/{userId}/{username}/{password}/")
- public String addUser(@PathVariable int userId,
- @PathVariable String username,
- @PathVariable String password){
- PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
- String encodePassword = passwordEncoder.encode(password);
- User user = new User(userId,username,encodePassword);
- userMapper.insert(user);
- return "Add User Successfully";
- }

完成~