P2. 配置MySQL和用户注册登录模块
-
- [0 概述](#0 概述)
- Tips
- [1 预备知识](#1 预备知识)
-
- [1.1 SpringBoot 常用模块](#1.1 SpringBoot 常用模块)
- [1.2 pojo层的实现](#1.2 pojo层的实现)
- [1.3 mapper层的实现](#1.3 mapper层的实现)
- [1.4 controller层调试CRUD](#1.4 controller层调试CRUD)
- [2 Spring Security](#2 Spring Security)
-
- [2.1 Spring Security 介绍](#2.1 Spring Security 介绍)
- [2.2 Spring Security 对接数据库](#2.2 Spring Security 对接数据库)
- [2.3 密码的加密](#2.3 密码的加密)
- [3 Jwt验证](#3 Jwt验证)
-
- [3.1 传统Session验证方式](#3.1 传统Session验证方式)
- [3.2 Jwt验证方式](#3.2 Jwt验证方式)
- [3.3 Jwt验证所需的配置](#3.3 Jwt验证所需的配置)
- [4 用户注册和登录模块的实现](#4 用户注册和登录模块的实现)
-
- [4.1 用户注册和登录 API 的实现](#4.1 用户注册和登录 API 的实现)
-
- [4.1.1 /user/account/login/](#4.1.1 /user/account/login/)
- [4.1.2 /user/account/info/ /user/account/register/](#4.1.2 /user/account/info/ /user/account/register/)
- [4.2 用户登录模块的前端](#4.2 用户登录模块的前端)
-
- [4.2.1 登录页面和 Login 函数及全局变量 user 的定义与使用](#4.2.1 登录页面和 Login 函数及全局变量 user 的定义与使用)
- [4.2.2 获取 user 信息和退出功能](#4.2.2 获取 user 信息和退出功能)
- [4.3 前端页面授权](#4.3 前端页面授权)
- [4.4 登录状态持久化及小问题处理](#4.4 登录状态持久化及小问题处理)
- [5 配置MySQL](#5 配置MySQL)
-
- [5.1 MySQL的基本结构](#5.1 MySQL的基本结构)
- [5.2 IDEA中配置MySQL](#5.2 IDEA中配置MySQL)
- [5.3 Spring使用MySQL需要的依赖](#5.3 Spring使用MySQL需要的依赖)
- [5.4 图形化使用MySQL](#5.4 图形化使用MySQL)
0 概述
以用户注册登录模块为例,学习实现一个具体的业务逻辑的流程。
-
明白
SpringBoot
如何和MySQL
结合,如何调用数据库中的数据。 -
了解
pojo, mapper, service, controller
各层的功能及其实现,学会自己写一个业务逻辑。 -
了解
Jwt
验证原理,知道密码加密的实现。 -
重点掌握
SpringBoot
实现一个业务API
功能的3个流程service, service.impl, controller
。 -
重点掌握前端如何绑定变量,如何定义全局变量
vuex
,如何调用全局变量的函数。也就是要求掌握第 4 小节所有的代码逻辑。
由于配置 MySQL
不涉及逻辑内容,因此放置在本文的最后介绍。
Tips
- 在写项目的时候要减少搭轮子的时间 ,去找网上现成的轮子,比如
JwtUtil
这种。 - 要放行更多接口的时候可以在
config.SecurityConfig
类中添加。 - 使用
Mybatis-plus
从而避免写SQL
语句,不用写简单的CRUD
操作。具体的接口可以查看Mybatis-plus指南。一些简单的使用在1.4 小节中进行了示范 (querywrapper, userMapper.xxx
)。 - 强烈换成阿里源去下依赖,用外网下依赖直接给我整崩溃了,搞了半天重开了个项目,换成阿里源下载依赖才搞好。
- 实现和重写接口的方法可以通过
alt + insert
快捷键添加。
1 预备知识
1.1 SpringBoot 常用模块
习惯上会在写后端的时候分层(文件夹)去实现,一共分成 4
层: pojo, mapper, service, controller
。
-
pojo
: 将MySQL
中的表table
翻译成Java
中的类class
。 -
mapper
: 对class
的CRUD操作转化成SQL
语句。每个
class
需要相应的CRUD操作,操作完成后最终会存到数据库中,因此需要涉及到SQL
语句。 -
service
: 业务通常要处理多张表,因此组合多个mapper
实现具体业务。 -
controller
: 调度service
,接收前端请求和参数,选择将参数传给哪个service
,再把service
结果返回给前端。
1.2 pojo层的实现
pojo
是将 MySQL
中的 user
表转化成 User
类,每个类需要自己的属性和方法,属性需要自己对照数据库中的字段定义,可以通过安装的依赖 lombok
自动实现这些机械化的方法,如 get, set, equals, toString
及有参,无参构造函数。(依赖的安装见 5.3 节)
backend.pojo.User
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
}
1.3 mapper层的实现
本来是需要写大量的 SQL
语句,但 MyBatis-plus
已经帮我们实现好了 SQL
语句,只需要通过 extends BaseMapper<class_name>
集成过来就行,因此不需要写任何 SQL
语句了。
注意
mapper
是一个interface
而不是class
。
java
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
1.4 controller层调试CRUD
实现完 pojo, mapper
后可以在 controller
层中进行一些调试工作。
让我们测试一下上面的 pojo, mapper
,学习一下怎么调用 MyBatis-plus
实现的接口。
@RestController
的作用可以理解成把返回值转成Json
格式再返回给前端。下面的CRUD操作仅为了演示怎么调试及使用接口,实际实现某个业务功能的时候有另外的写法,而且一般在
service
实现。
之后在 http://localhost:3000/.../
中就能查看是否正确取得结果。
注意是自己设置的后端端口号,
resources/application.properties
中server.port=3000
设置。
java
@RestController
public class UserController {
@Autowired
UserMapper userMapper;
@RequestMapping("/user/all/")
public List<User> getAllUser() {
return userMapper.selectList(null);
}
@RequestMapping("/user/{userId}/")
public User getUser(@PathVariable int userId) {
return userMapper.selectById(userId);
}
// 可以通过封装 queryWrapper 实现复杂一点的操作,这边的功能和上一个函数相同
@RequestMapping("/user/querywrapper/{userId}/")
public User getQueryUser(@PathVariable int userId) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", userId);
return userMapper.selectOne(queryWrapper);
}
// 查询符合多个条件的直接在 queryWrapper 后面加条件即可
@RequestMapping("/user/querywrapper/{userId}")
public List<User> getSomeUser(@PathVariable int userId) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("id", 1).le("id", 2);
return userMapper.selectList(queryWrapper);
}
@RequestMapping("/user/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 success";
}
@RequestMapping("/user/delete/{userId}/")
public String deleteUser(@PathVariable int userId) {
userMapper.deleteById(userId);
return "delete success";
}
}
2 Spring Security
2.1 Spring Security 介绍
某些功能需要用户拥有权限才能访问,因此需要加上授权机制,进行权限判断 ,安装依赖 spring-boot-starter-security
把 Spring
实现好的模块集成进来。会发现上面的操作都需要登录之后才能运行,默认用户名为 user
,密码在 IDEA
的控制台中输出。
2.2 Spring Security 对接数据库
现在有个问题就是只能用它默认的用户进行登录,我们希望通过数据库里的用户进行登录,因此需要对 Spring Security
进行配置。
实现 service.impl.UserDetailsServiceImpl
类,继承 UserDetailsService
接口,用来接入数据库信息。
重写其 loadUserByUsername
方法,该方法是通过 username
找到对应用户的 username, password
(UserDetails
类型)。
service.impl.UserDetailServiceImpl
java
@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 RuntimeException("用户不存在!");
return new UserDetailsImpl(user);
}
}
实现辅助类 UserDetailsImpl
,该类实现接口 UserDetails
,该接口的所有方法在 Spring Security
中指出。
这下就可以通过数据库中用户来登录,但是要先把用户密码改成 {noop}<password>
形式,告诉数据库当前字段是未加密的明文。
2.3 密码的加密
这里就有一个很有趣的问题,为什么忘记密码之后只能重置密码,不能知道原来的密码是什么呢?
这是由于密码的加密算法是一个单向的加密,反向解码基本不可能。注册存储的是加密后的密码
encoded_pw_save
,每次用户登录输入密码pw
,调用match
方法看pw, encoded_pw_save
是否匹配,如果匹配则成功登录。当用户忘记密码之后,数据库存储的是加密后的密码,无法解密出原来的密码,因此只能重置。
config.SecurityConfig
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
之后可以在 test
中的 BackendApplicationTests
中进行一些测试,首先输出一下 pw
对应的加密后密文(每次加密结果可能不同),再看一下 pw, encoded_pw
能否匹配,结果为 True
,之后把数据库中的密码修改成密文格式就能够正常登陆了(加 {noop}
也无法登录,只能密文登录)。
java
void contextLoads() {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
System.out.println(passwordEncoder.encode("<pw>"));
System.out.println(passwordEncoder.matches("<pw>", "<encoded_pw>"));
}
之后可以修改 controller
添加用户 addUser
的实现,直接存储加密之后的密码。
java
@RequestMapping("/user/add/{userId}/{username}/{password}/")
public String addUser(
@PathVariable int userId,
@PathVariable String username,
@PathVariable String password) {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodedPassword = passwordEncoder.encode(password);
User user = new User(userId, username, encodedPassword);
userMapper.insert(user);
return "add success";
}
3 Jwt验证
3.1 传统Session验证方式
所有的页面可以简单的分为2种,一种是公开页面,也就是不登录就可以查看的页面(比如 login, register, homepage
);一种是授权页面,也就是需要登录才能查看的页面(其实可以细分成有某个页面的权限才能访问等,但我们的项目暂时用不到这么细致)。
那么问题就来了,Server
如何判断某个用户是否能够访问某个授权页面呢?
首先,先介绍一下传统的 Session
验证方式(如下图所示),仅做了解,并不使用这种方式。
3.2 Jwt验证方式
对于最近的应用都会遇到跨域问题,通常有多个端(Web, App ...
),或是多个服务器,这时 Session
方式就难以处理。
每个服务器都要存下用户的
SessionID
。
因此提出新的验证方式: Jwt
验证,这个方式的优点在于: 方便处理跨域问题,不需要在 Server
端存储信息。
3.3 Jwt验证所需的配置
- 安装依赖
jjwt-api, jjwt-impl, jjwt-jackson
。 - 实现
utils.JwtUtil
类,作用是创建和解析jwt_token
。 - 实现
config.filter.JwtAuthenticationTokenFilter
类,用来验证jwt_token
,如果验证成功则提取user
信息到Spring Security
的上下文中(存储用户的认证信息,全局共享),以便进行后续的权限验证。 - 配置
config.SecurityConfig
类,放行登录、注册等接口。
4 用户注册和登录模块的实现
4.1 用户注册和登录 API 的实现
首先更改一下用户 user
的属性,id
改成自增,在 pojo
中为 id
添加注解 @TableId(type = IdType.AUTO)
。
一共需要实现3个 API
:
/user/account/token/
: 验证用户名密码,验证成功后返回jwt_token
;/user/account/info/
: 根据jwt_token
返回用户信息;/user/account/register/
: 注册账号。
SpringBoot
实现 API
可以分为 service
声明接口,service.impl
实现接口的具体逻辑,controller
接收前端 url
。
4.1.1 /user/account/login/
service.user.account.loginService
一般习惯上返回一个
Map<String, String>
接收各种信息,key
要和前端对应起来。
java
public interface LoginService {
Map<String, String> login(String username, String password);
}
service.impl.user.account.loginServiceImpl
先封装明文的用户名密码,再验证用户是否登录(失败则进行自动处理),之后取出用户 user
,最后把 user_id
封装成 jwt_token
。
记得加上
@Service
的注解。
java
@Service
public class LoginServiceImpl implements LoginService {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public Map<String, String> login(String username, String password) {
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(username, password);
// 如果认证失败(例如,用户名或密码不正确),此方法将抛出一个异常
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
UserDetailsImpl loginUser = (UserDetailsImpl) authenticate.getPrincipal();
User user = loginUser.getUser();
String jwt = JwtUtil.createJWT(user.getId().toString());
Map<String, String> map = new HashMap<>();
map.put("error_message", "success");
map.put("token", jwt);
return map;
}
}
controller.user.account.LoginController
密码需要用密文形式传输,而 get
请求是明文传输,因此 用post
请求,同时要记得把 "/user/account/token/"
的 url
放行。
这里传入的参数就是前端传过来的参数,以
map
形式传入,接口传入的参数需要把对应的key
抽出来再传入。记得加上
@RestController
注解。
java
@RestController
public class LoginController {
@Autowired
private LoginService loginService;
@PostMapping("/user/account/token/")
public Map<String, String> getToken(@RequestParam Map<String, String> map) {
String username = map.get("username");
String password = map.get("password");
return loginService.getToken(username, password);
}
}
在前端中可以对 /user/account/token/
进行调试,resp
就是 LoginServiceImpl
中返回的 Map<String, String>
,在前端浏览器中的控制台可以查看结果。
javascript
$.ajax({
url: "http://localhost:3000/user/account/token/",
type: "post",
data: {
username: "user_1",
password: "p1",
},
success(resp) {
console.log(resp);
},
error(resp) {
console.log(resp);
}
});
4.1.2 /user/account/info/ /user/account/register/
另外两个接口 API
的流程就不再赘述了,过程是一样的,只介绍一下具体逻辑 ServiceImpl
的实现,Controller
中的请求为 Get, Post
也要记得区分,修改删除添加一般都是 Post
,获取一般是 Get
。
service.impl.InfoServiceImpl
这边根据 token
取出 user
的代码直接背过(实现是基于之前 3.3 节的配置),之后但凡要取出 user
直接复制这段代码。
java
@Service
public class InfoServiceImpl implements InfoService {
@Override
public Map<String, String> getinfo() {
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
UserDetailsImpl loginUser = (UserDetailsImpl) authentication.getPrincipal();
User user = loginUser.getUser();
Map<String, String> res = new HashMap<>();
res.put("error_message", "success");
res.put("id", user.getId().toString());
res.put("username", user.getUsername());
return res;
}
}
前端测试代码,需要在请求报文的表头带上自己的 jwt_token
,token
根据第一个 api
获取:
这边是需要登录之后得到
jwt_token
才能获取user
,也就是说需要授权,因此需要加上报文头headers
,jwt_token
头部的内容在config.filter.JwtAuthenticationTokenFilter
中定义,以此验证jwt_token
。
javascript
$.ajax({
url: "http://localhost:3000/user/account/info/",
type: "get",
headers: {
Authorization: "Bearer " + "<jwt_token>",
},
success(resp) {
console.log(resp);
},
error(resp) {
console.log(resp);
}
});
对于 /user/account/register/
注册的实现,需要判断用户名和密码是否合法,用户名是否已存在,两次密码是否一致等等,最后再把用户添加到数据库,由于密码的加密,数据库的查询和添加等操作在前面已经介绍过了,请大家尝试自行实现以验证是否理解之前内容。
4.2 用户登录模块的前端
4.2.1 登录页面和 Login 函数及全局变量 user 的定义与使用
用户注册和登录的前端页面的实现(html
)就不介绍了,自行去 Bootstrap
搜索喜欢的样式改一改就行。
登陆之后需要记录当前用户 user
,这里介绍一下全局变量 user
的定义和使用,可以使用 vuex
使用全局变量。
store.index
需要在 index.js
中把 user
导入到 modules
。
javascript
import MoudleUser from './user'
export default createStore({
/* ... */
modules: {
user: MoudleUser,
}
})
store.user
简单的来说 state
定义 user
的属性,mutations
定义更新 state
属性的函数,actions
定义需要修改 state
属性的相关函数。
javascript
import $ from 'jquery'
export default {
state: {
id: "",
username: "",
photo: "",
token: "",
is_login: false,
},
getters: {
},
mutations: {
updateUser(state, user) {
state.username = user.username;
state.id = user.id;
state.photo = user.photo;
state.is_login = user.is_login;
},
updateToken(state, token) {
state.token = token;
}
},
actions: {
login(context, data) {
$.ajax({
url: "http://localhost:3000/user/account/token/",
type: "post",
data: {
username: data.username,
password: data.password,
},
success(resp) {
if (resp.error_message == "success") {
context.commit("updateToken", resp.token);
data.success(resp);
} else {
data.error(resp);
}
},
error(resp) {
data.error(resp);
}
});
}
},
modules: {
}
}
接下来就需要在登录的时候调用 login
函数即可,介绍一下如何调用和传入参数。
views.user.account.UserAccountLoginView
以下仅展示核心部分代码,首先表单提交时要绑定触发 login
函数(并不是 store
中的 login
),另外要将变量 ref
和输入框 input
进行绑定,报错信息通过 {``{ error_message }}
绑定。
在自定义的表单提交后触发的 login
中要调用 store.user
中 action
的函数 store.dispatch("<函数名>, data")
,这样之后就能获得用户的 jwt_token
,在成功登录之后需要跳转到主页面。
修改
ref
变量时要记得通过.value
修改值。
javascript
<form @submit.prevent = "login">
<div class="mb-3">
<label for="username" class="form-label">用户名</label>
<input v-model = "username" type="text" id="username" class="form-control" placeholder="输入用户名">
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<input v-model = "password" type="password" id="password" class="form-control" placeholder="...">
</div>
<div class="error-message">{{ error_message }}</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
<script>
import { useStore } from 'vuex'
import { ref } from 'vue'
import router from '@/router/index'
export default {
setup() {
const store = useStore();
let username = ref('');
let password = ref('');
let error_message = ref('');
const login = () => {
error_message.value = "";
store.dispatch("login", {
username: username.value,
password: password.value,
success() {
router.push({ name: 'home' });
},
error() {
error_message.value = "用户名或密码错误";
}
});
};
return {
username,
password,
error_message,
login
}
}
}
</script>
4.2.2 获取 user 信息和退出功能
在 store.user
的 action
中实现函数 getinfo
,在登录成功之后获取用户信息(在 login
成功后调用 getinfo
)。
...resp
作用是解析key, value
到当前对象。
javascript
getinfo(context, data) {
$.ajax({
url: "http://localhost:3000/user/account/info/",
type: "get",
headers: {
Authorization: "Bearer " + context.state.token,
},
success(resp) {
if (resp.error_message === "success") {
context.commit("updateUser", {
...resp,
is_login: true,
});
data.success(resp);
} else {
data.error(resp);
}
},
error(resp) {
data.error(resp);
}
});
}
javascript
const login = () => {
error_message.value = "";
store.dispatch("login", {
username: username.value,
password: password.value,
success() {
store.dispatch("getinfo", {
success() {
console.log(store.state.user);
router.push({ name: 'home' });
},
error(resp) {
console.log(resp);
}
});
},
error() {
error_message.value = "用户名或密码错误";
}
});
}
之后可以更改导航栏信息 NavBar
,如果已登录则显示用户名,否则显示登录和注册按钮。
html
<ul class="navbar-nav" v-if = "$store.state.user.is_login">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
{{ $store.state.user.username }}
</a>
<ul class="dropdown-menu">
<router-link class="dropdown-item" :to = "{name: 'user_bot_index'}">Bots</router-link>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">退出</a></li>
</ul>
</li>
</ul>
<ul class="navbar-nav" v-else>
<li class="nav-item">
<router-link class = "nav-link" :to = "{name: 'user_account_login'}" role="button">
登录
</router-link>
</li>
<li class="nav-item">
<router-link class = "nav-link" :to = "{name: 'user_account_register'}" role="button">
注册
</router-link>
</li>
</ul>
之后实现一下 logout
退出功能,和之前的流程一样,只需要把所有 state
清空即可,请自行实现,验证之前的内容是否理解掌握。注册页面的实现同样也不介绍了,都是一样的流程,请自行实现。
4.3 前端页面授权
当用户未登录时,如果访问授权页面则重定向到登录页面,强制要求用户登录,在 router
中实现该功能。
beforeEach
是进到每个页面之前要执行的函数。
javascript
import store from "../store/index"
const routes = [
{
path: '/',
name: 'home',
redirect: '/pk/',
meta: {
requestAuth: true,
}
},
/* ... */
{
path: '/:catchAll(.*)',
redirect: "/404/"
},
]
router.beforeEach((to, from, next) => {
if (to.meta.requestAuth && !store.state.user.is_login) {
next({ name: "user_account_login" });
} else {
next();
}
});
4.4 登录状态持久化及小问题处理
每次刷新的时候登录状态都会重置为"未登录状态",这是因为 jwt_token
是存储在内存中,因此要把 token
存储在浏览器的 localstore
硬盘中。
首先修改 store.user
中的登录和退出函数,分别将 jwt_token
在本地保存和删除。
javascript
login(context, data) {
/* ... */
success(resp) {
if (resp.error_message === "success") {
localStorage.setItem("jwt_token", resp.token);
context.commit("updateToken", resp.token);
data.success(resp);
} else {
data.error(resp);
}
},
});
},
logout(context) {
localStorage.removeItem("jwt_token");
context.commit("logout");
}
之后每次进入到登录页面时,先判断本地是否存在 jwt_token
,如果存在再判断 token
是否已经过期(调用 state.dispatch("getInfo")
,如果成功则说明未过期),如果未过期则跳转到首页,不需要重新登录。
至此,就实现了登录状态的持久化,每次刷新都会跳转到首页,并且保持登录状态。细心的朋友会发现,每次刷新都会闪一下登录页面,视觉效果不太好,因此 user
中再维护一个全局变量 is_pulling_info
,通过这个变量设置默认先不让登录页面的组件显示 v-if = "$store.state.user.is_pulling_info"
,如果未登录再显示。
登录页面添加以下代码:
javascript
const jwt_token = localStorage.getItem("jwt_token");
if (jwt_token) {
store.commit("updateToken", jwt_token);
store.dispatch("getinfo", {
success() {
router.push({ name: "home" });
store.commit("updatePullingInfo", false);
},
error() {
store.commit("updatePullingInfo", false);
},
});
} else {
store.commit("updatePullingInfo", false);
console.log(store.state.user.is_pulling_info);
}
5 配置MySQL
5.1 MySQL的基本结构
MySQL
中包含多个数据库 databases
,每个 database
含有多个表 tables
(每张表 table
可以理解成 Java
中的 class
类)。
MySQL
级别相关操作:
启动
MySQL
(需要管理员权限):net start mysql80
链接
Mysql
:mysql -u root -p
以下操作仅做简单介绍,在实际写项目的时候由于是使用 MyBatis-plus
,因此不会用到这些 SQL
语句。
database
级别相关操作:
创建数据库
create database kob_db;
删除数据库drop database kob_db;
进入数据库use kob_db;
查看
MySQL
中所有数据库show databases;
table
级别相关操作: (要先进入需要的 database
)
创建表
create table user(id int, username varchar(100), password varchar(100));
删除表
drop table user;
查看当前数据库中所有表show tables;
row
级别相关操作:
增:
insert into user values(1, 'yukiii', '123');
删:delete from user where id = 1;
查:
select * from user;
select password from user where id = 1;
5.2 IDEA中配置MySQL
IDEA
中配置 MySQL
数据库 kob_db
的步骤如下:
- 从
MySQL
中选择要连接的数据库
- 填写用户,密码,选择要连接到
kob_db
数据库,架构选择默认架构
- 测试连接,成功后则
IDEA
中配置成功
5.3 Spring使用MySQL需要的依赖
打开Maven仓库地址,在搜索栏搜索要装的依赖,再将依赖复制到 pom.xml
的 <dependencies>
。
需要安装的依赖:
Spring Boot Starter JDBC
,Project Lombok
,MySQL Connector/J
,mybatis-plus-boot-starter
,mybatis-plus-generator
,依赖解析的会比较久
在 pom.xml
添加完后,会发现报红,需要在右侧的 Maven
选项中重新加载所有依赖项。
SpringBoot
在访问 MySQL
时也需要用户名和密码,在 resources/application.properties
添加以下代码:
用户名和密码填写自己的
MySQL
用户,url
中换成MySQL
端口和数据库名。
java
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/kob_db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
5.4 图形化使用MySQL
对某个表中记录 的 CRUD
操作都在图形化界面中提供,每个操作之后都要记得点击上传,更新到数据库中。
对表进行修改的操作,在右侧右键要修改的表可以跳出相应界面。