导航
(一) 前置知识
(1) 一些单词
pet 宠物
configuration 配置
assistant 助理,售货员
resources 资源,系统资源文件夹
amend 修正,修订
authorize 授权v
authorization 授权n
bio 个人描述
refactor 重构
extract 提取 // extract common part from 'if' 从if语句中提取出相同的部分
mapper 映射器,变换器
persistent 持久的
judge 判断
sign in 登入
sign out 登出
sign up 注册
复制代码
(2) 如何给类或方法添加注释
把光标停在 ( 类名或者方法名 ) 上,然后 Alt+Enter,出现几个选项,选择Add Javadoc就OK了
(3) @Controller
当给类添加了@Controller注解时,SpringBoot就会自动识别扫描该类,把它作为bean去管理,同时也识别该类是一个controller
重点注意 controller server mapper 三者的关系
(4) IDEA常用快捷键
ctrl+p 方法参数提示
ctrl+alt+l 代码格式化
ctrol+alt+o 删除没有使用到的引入的文件或依赖
sout System.out.println()
(5) SpringBoot工程文件说明
src/main/java 所有的java代码
src/main/resources 配置文件和静态文件
resources/templates 模板文件
resources/static 静态文件,比如css,img文件
resources/application.properties 配置文件,当然也可以改成application.xml
(6) GitHub 授权登陆
1.点击头像 => settings => Developer settings => OAuth Apps => Register a new OAuth application => ...
3.通过上面的12两步,可以获取到 Client ID 和 Authorization callback URL
4.官网授权登陆教程 - [ 具体的跳转流程 ]
a. 携带3获得的相关parameter请求授权登陆地址,成功会扭转到redirect_uri地址,同时返回 ( code ) 和 ( state )
b. 用 ( code ) 换取 ( access_token )
c. 用 ( access_token ) 访问github的 ( user ) 接口,获取用户信息
5.测试:https://api.github.com/user?access_token=xxx
(7) IDEA 找不到 Database 选项卡
搜索 Plugins => Database Navigator 并安装该插件
这里我没用这个插件,而是使用 Navicat 来设计管理数据库
(8) mysql的一些基础知识
注意点: 最后面的分号一定要加
常用命令
连接数据库 mysql -h主机地址 -u用户名 -p用户密码
退出mysql exit
查看数据库 show databases;
创建数据库 create database 数据库名;
删除数据库 drop database 数据库名;
使用数据库 use 数据库名;
查看当前使用的数据库 select database();
查看表 show tables;
创建表 create table 表名 (dde列名 类型);
删除表 droop table 表名;
显示表结构 desc 表名;
修改密码 mysqladmin -uroot -p123456 password 12345678;
查看数据库的安装路径 show variables like "%char%";
(9) @Autowired 和 new 的区别?
@Autowired
注解方式是由spring创建的对象 ( 单例 ) 对象 作用域是整个项目 项目一启动就创建了
new
new出来的对象作用域只在你对应的类中 每个调用的时候都是会创建一个新的对象,是 ( 多例 )
(10) po dto entity bean 等文件夹的区别
po entity bean 三个类似,都是持久化对象persistent,即 数据库中的一条记录对象
dto 是经过处理后的po,和ui层即前端页面对应
(11) controller层,server层,mapper层,之间的关系
controller
负责http请求,将参数等信息传递给server层,并将结果返回给客户端
server
负责处理逻辑
当需要同时处理多个表的关系时,一般都交给sever来组装处理,比如合并多个model
接收controller传递的参数,并调用mapper
mapper ( DAO )
负责对数据库增删改查
(12) java中的 ( 数组 )
使用大括号包裹的成员 int[] a = {1, 2, 3, 4}
刚开始把我搞蒙蔽,注意不是ts中的 let a: number[] = [1,2,3,4]
int[] a = {1, 2, 3, 4}
复制代码
(13) RESTful API 接口规范
(14) Map
Map 中 键和值一一映射,可以通过键来获取值
Object put(Object k, Object v) 存
Object get(Object k) 取
public class CollectionsDemo {
public static void main(String[] args) {
Map m1 = new HashMap(); // new HashMap()
m1.put("Zara", "8");
m1.put("Mahnaz", "31");
System.out.println(" Map Elements");
System.out.print("\t" + m1);
}
}
结果:
Map Elements
{Mahnaz=31, Zara=8}
复制代码
(14) springboot中如何解析前端传来的json类型的参数
因为:前端在 POST 请求中,一般设置的header中的 Content-Type: application/json
所以:POST请求出入的参数被放在body中,以JSON形式传给后端
解决: 利用 @RequestBody 获取到body对象,然后通过 Map 做映射,通过get获取属性
// 新增
@PostMapping("/musics")
public void addMusics(
@RequestBody Map body
) {
String name = (String) body.get("name");
String album = (String) body.get("album");
String singer = (String) body.get("singer");
musicService.add(name, album, singer);
}
复制代码
(15) String -> Timestamp -> datetime 三者的转换
java中的Timestamp 相当于 数据库中的datatime
Timestamp.valueOf(String v)
public Boolean edit(Map body) {
int id = (int) body.get("id");
String name = (String) body.get("name");
String album = (String) body.get("album");
String singer = (String) body.get("singer");
// ( Timestamp ) 类型对应的是数据库中的 ( datetime ) 类型
Timestamp startTime = Timestamp.valueOf((String) body.get("startTime"));
// Timestamp.valueOf(string v) 将string转成timestamp
Timestamp endTime = Timestamp.valueOf((String) body.get("endTime"));
int status = musicMapper.editMusic(name, album, singer, startTime, endTime, id);
Boolean aBoolean = judgeIsSuccess(status);
return aBoolean;
}
复制代码
(16) 热更新
当每次修改java代码时都必须手动 run Application 很麻烦
spring-boot-devtools 可以实现热更新
设置过程
1.引入spring-boot-devtools的maven包
2.setting => Build,Execution,Deployment => Compiler => 勾上Build project automaticallly
第2步有个缺点,就是必须在没有running或debugging的情况才热更新
3.ctrl + shift + a 调出 action
4.在 action 中搜索 Registry
5.在 Registry 中勾选 compiler.autoMake.allow.when.app.running
6.如果前端展示是直接写的html,则还可以添加一个浏览器插件 LiveReload
如果是vue或者react的单页项目就不需要了
注意:(一般情况,请忽略该注意 )
描述:当只是修改html时,是不会再重启java程序的,因为本身并没有去修改server相关的代码
非要解决:需要配置如下
application.properties => spring.devtools.restart.exclude=static/**,public/**
org.springframework.boot
spring-boot-devtools
true
true
复制代码
(二) 从零开始一个项目
(1) 新建一个SpringBoot项目 ( Spring Assistant)
安装插件:file => setting => plugins => 在Marketplace中搜索并安装插件 => Spring Assistant
新建项目:file => New Project => Spring Assistant => Next => Web => Spring Web => Finish
使用 Spring Assistant 和使用 maven 创建项目的区别?
主要就是Spring Assistant配置好了web开发的 pom.xml 中的配置项
使用maven需要自己配置 parent spring-boot-starter-web spring-boot-starter-thymeleaf 等
也可以勾选下面这四个
(2) 配置文件的分离
怎么样根据不同的环境,来读取不同的配置文件?? ( 类似于前端的环境变量,比如process.env.NODE_ENV )
springboot的配置文件有以下
application.properties
application-dev.properties 开发环境
application-prod.properties 运行环境
application-test.properties 测试环境
在不同环境的配置文件中,设置同步变量的不同值即可
如下:
-------
server.port = 7777
# 第一段的github起到分类的作用,便于识别
# 1. 比如: server 和 github 就是不同的两种类型
# 2. 使用时需要使用 @Value 注解来引入这里定义的属性变量
github.client.client_id = 982573d16925889ea84c
github.client.client_secret = 9a2e9710af69531e51254e6902ab834905a7a755
github.client.redirect_uri = http://localhost:7777/callback
复制代码
(3) 利用 mybatis 操作 mysql 实现CURD
1. 安装相关的maven依赖
因为:是通过 Spring Assistant 创建的项目
所以:自动配好了 parent spring-boot-starter-web spring-boot-starter 等maven依赖
pom.xml
-------
mysql
mysql-connector-java
8.0.21
runtime
org.springframework.boot
spring-boot-starter-jdbc
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.3
复制代码
2. 在 application.properties 中配置数据源组件配置项
application.properties
-------
# 定义数据源组件
# 已弃用 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 注意 spring.datasource.url="jdbc:mysql://localhost:3306/数据库名称?时区信息"
# 注意 上面的时区信息不能少,不然会报错
# 分别是 ( 数据库url ) ( 数据库驱动 ) ( 用户名 ) ( 密码 )
spring.datasource.url=jdbc:mysql://localhost:3306/7-community-java?serverTimezone=GMT%2B8&useSSL=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
复制代码
3. 插入数据到数据库
3-1 新建model,通过new Model()将数据绑定到实例属性上,然后将实例传入mapper的insert方法中
model 主要是用于数据库操作相关的对象,专门命名为model
model 会在 mapper 或 controller 中用到
model
-------
public class UserModel {
private Integer id;
private String name;
private String accountId;
private String token;
private Long gmtCreate;
private Long gmtModified;
getter adnd setter and toString...
}
复制代码
3-2 新建mapper通过 @Mapper @Insert 将数据插入数据库
mapper 主要用于操作数据库
注意
mapper 是 interface
mapper中的 UserMapper.insert() 方法是在 controller 中被调用的
mapper
-------
@Mapper
public interface UserMapper {
@Insert("insert into user (name, account_id, token, gmt_create, gmt_modified) values (#{name}, #{accountId}, #{token}, #{gmtCreate}, #{gmtModified})")
void insert(UserModel user);
}
复制代码
3-3 新建 controller,通过 @Autowired 引入mapper,并调用mapper中的insert()方法
controller
-------
import com.example.demo.model.UserModel;
@Controller
public class AuthorizeController {
@Autowired
private UserMapper userMapper;
@GetMapping("/callback")
public String callback() {
UserModel user = new UserModel(); // 注意区分@Autowired 和 new 的区别
user.setToken(UUID.randomUUID().toString());
user.setName(gitHubUser.getName());
...
userMapper.insert(user);
// 1. 登陆后获取用户信息后,将数据写入user对象中
// 2. 调用 mapper 中的 userMapper.insert(user) 将user存入数据库
}
}
复制代码
4. 增删改查数据库数据
通过4-123步就能通过接口访问到music列表数据
数据库表如下图
4.1 新建model - MusicModel
model - MusicModel
-------
// model
// model 专门用来做数据库相关的模型对象
@Data
public class MusicModel {
private Integer id;
private String name;
private String album;
private String singer;
private String endTime;
private String startTime;
getter sertter toString 等
}
复制代码
4.2 新建 mapper - MusicMapper
mapper - MusicMapper
-------
// mapper
// 1. mapper文件夹主要是用来映射数据库的相关操作
// 2. 注意:mapper 是 interface
@Mapper
public interface MusicMapper {
@Select(
"SELECT * from music where"
+ " name like CONCAT('%',#{searchKey},'%') or "
+ " album like CONCAT('%',#{searchKey},'%') or "
+ " singer like CONCAT('%',#{searchKey},'%')"
+ " limit #{offset},#{pageSize}"
)
public List selectMusics(Integer pageSize, Integer offset, String searchKey); // 查找 - 分页 + 条件模糊查询
@Select("SELECT * from music limit #{offset},#{pageSize}")
public List selectMusicsOnlyPagination(Integer pageSize, Integer offset); // 查找 - 分页查询
@Select("SELECT * from music")
public List selectAllMusics(); // 查找 - 总数据
@Insert("insert into music (name, album, singer, startTime, endTime) values (#{name}, #{album}, #{singer}, #{startTime}, #{endTime})")
public int insertMusic(String name, String album, String singer, Date startTime, Date endTime); // 插入
@Update("update music set name=#{name},album=#{album},singer=#{singer},startTime=#{startTime},endTime=#{endTime} where id=#{id}")
public int editMusic(String name, String album, String singer, Timestamp startTime, Timestamp endTime, int id);
@Delete("delete from music where id=#{id}")
public int deleteMusic(int id); // 删除
}
复制代码
4.3 新建 service - MusicService
ervice - MusicService
-------
// service
// 1. 主要用于处理获取请求参数后的处理逻辑
// 2. server 是连接 controller 和 mapper(DAO) 的桥梁
@Service
public class MusicService {
@Autowired
private MusicMapper musicMapper;
// 逻辑抽离 - 判断操作是否成功,比如添加,删除
private Boolean judgeIsSuccess(int status) {
if (status > 0) {
System.out.println("操作成功");
return true;
} else {
System.out.println("操作失败");
return false;
}
}
// 列表
public PaginationDTO list(Integer pageSize, Integer current, String searchKey) {
Integer offset = pageSize * (current - 1); // 分页的偏移量
List musicModels;
if (searchKey != null) { // searchKey 是否存在
musicModels = musicMapper.selectMusics(pageSize, offset, searchKey); // 分页 + 条件
} else {
musicModels = musicMapper.selectMusicsOnlyPagination(pageSize, offset); // 分页
}
List totalMusics = musicMapper.selectAllMusics(); // 总数据是为了获取 total
PaginationDTO paginationDTO = new PaginationDTO(); // 这里之所以要new,是因为其他方法中也可能会用到paginationDTO,所以必须不能是单列
paginationDTO.musics = musicModels;
paginationDTO.total = totalMusics.toArray().length;
paginationDTO.current = current;
paginationDTO.pageSize = pageSize;
return paginationDTO;
}
// 新增
public Boolean add(String name, String album, String singer) {
Date startTime = new Date(); // 注意:数据库中的data是 ( datetime ) 格式
Date endTime = new Date();
int status = musicMapper.insertMusic(name, album, singer, startTime, endTime);
Boolean aBoolean = judgeIsSuccess(status);
return aBoolean;
}
// 修改
public Boolean edit(Map body) {
int id = (int) body.get("id");
String name = (String) body.get("name");
String album = (String) body.get("album");
String singer = (String) body.get("singer");
Timestamp startTime = Timestamp.valueOf((String) body.get("startTime")); // ( Timestamp ) 类型对应的是数据库中的 ( datetime ) 类型
Timestamp endTime = Timestamp.valueOf((String) body.get("endTime"));
int status = musicMapper.editMusic(name, album, singer, startTime, endTime, id);
Boolean aBoolean = judgeIsSuccess(status);
return aBoolean;
}
// 删除
public Boolean delete(int id) {
int status = musicMapper.deleteMusic(id);
Boolean aBoolean = judgeIsSuccess(status);
return aBoolean;
}
}
复制代码
4.4 新建 controller - Musics
controller - Musics
-------
//@Controller
//@ResponseBody
@RestController // 是上面两个注解的合集
public class MusicController {
@Autowired
MusicService musicService;
// 列表
// @RequestMapping(value="/musics", method = {RequestMethod.GET})
@GetMapping("/musics")
public PaginationDTO getMusics(
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "current", defaultValue = "1") Integer current,
@RequestParam(name = "searchKey", required = false) String searchKey
) {
PaginationDTO musics = musicService.list(pageSize, current, searchKey);
System.out.println(musics);
return musics;
}
// 新增
@PostMapping("/musics/add")
public Map addMusics(
@RequestBody Map body
) {
String name = (String) body.get("name");
String album = (String) body.get("album");
String singer = (String) body.get("singer");
Boolean isSuccess = musicService.add(name, album, singer);
body.put("isSuccess", isSuccess); // 是否成功
return body;
}
// 修改
@PostMapping("/musics/edit")
public Map editMusics(
@RequestBody Map body
) {
Boolean isSuccess = musicService.edit(body);
body.put("isSuccess", isSuccess); // 是否成功
return body;
}
// 删除
@PostMapping("/musics/delete")
public Map deleteMusics(
@RequestBody Map body
) {
int id = (int) body.get("id");
Boolean isSuccess = musicService.delete(id);
body.put("isSuccess", isSuccess); // 是否成功
return body;
}
}
复制代码
项目源码
资料