导航
[封装01-设计模式] 设计原则 和 工厂模式(简单抽象方法) 适配器模式 装饰器模式
[封装02-设计模式] 命令模式 享元模式 组合模式 代理模式
[React 从零实践01-后台] 代码分割
[React 从零实践02-后台] 权限控制
[React 从零实践03-后台] 自定义hooks
[React 从零实践04-后台] docker-compose 部署react+egg+nginx+mysql
[React 从零实践05-后台] Gitlab-CI使用Docker自动化部署
[源码-webpack01-前置知识] AST抽象语法树
[源码-webpack02-前置知识] Tapable
[源码-webpack03] 手写webpack - compiler简单编译流程
[源码] Redux React-Redux01
[源码] axios
[源码] vuex
[源码-vue01] data响应式 和 初始化渲染
[源码-vue02] computed 响应式 - 初始化,访问,更新过程
[源码-vue03] watch 侦听属性 - 初始化和更新
[源码-vue04] Vue.set 和 vm.$set
[源码-vue05] Vue.extend
[源码-vue06] Vue.nextTick 和 vm.$nextTick
[部署01] Nginx
[部署02] Docker 部署vue项目
[部署03] gitlab-CI
[深入01] 执行上下文
[深入02] 原型链
[深入03] 继承
[深入04] 事件循环
[深入05] 柯里化 偏函数 函数记忆
[深入06] 隐式转换 和 运算符
[深入07] 浏览器缓存机制(http缓存机制)
[深入08] 前端安全
[深入09] 深浅拷贝
[深入10] Debounce Throttle
[深入11] 前端路由
[深入12] 前端模块化
[深入13] 观察者模式 发布订阅模式 双向数据绑定
[深入14] canvas
[深入15] webSocket
[深入16] webpack
[深入17] http 和 https
[深入18] CSS-interview
[深入19] 手写Promise
[深入20] 手写函数
[深入21] 数据结构和算法 - 二分查找和排序
[深入22] js和v8垃圾回收机制
[深入23] JS设计模式 - 代理,策略,单例
[前端学java01-SpringBoot实战] 环境配置和HelloWorld服务
[前端学java02-SpringBoot实战] mybatis + mysql 实现歌曲增删改查
[前端学java03-SpringBoot实战] lombok,日志,部署
[前端学java04-SpringBoot实战] 静态资源 + 拦截器 + 前后端文件上传
[前端学java05-SpringBoot实战] 常用注解 + redis实现统计功能
[前端学java06-SpringBoot实战] 注入 + Swagger2 3.0 + 单元测试JUnit5
[前端学java07-SpringBoot实战] IOC扫描器 + 事务 + Jackson
[前端学java08-SpringBoot实战总结1-7] 阶段性总结
[前端学java09-SpringBoot实战] 多模块配置 + Mybatis-plus + 单多模块打包部署
[前端学java010-SpringBoot实战] bean赋值转换 + 参数校验 + 全局异常处理
(一) 前置知识
(1) 一些单词
scalar 纯量
quote 引用
// single quotes 单引号
// double quotes 双引号
palette 调色板
implicit 隐式,含蓄
hibernate 冬眠 休眠
Advice 建议 通知
persistent 持久的,执着的
profile 概述 简介 环境 // spring.profile
assert 断言
future 未来 将来 // feature 特征
digits 数字 位数
integer 整数
fraction 小数
advice 建议 通知 // @ControllerAdvice
exception 异常
abstract 抽象的
public 任何对象都可以访问
private 只能被自己的方法访问,子类和其他任何类都不能访问
protected 只能被自己和子类访问,其他类型的类不能访问
final 不能被继承
static 可以通过类自身和实例来调用
abstract 抽象类,不自己实现方法,子类需要实现方法
(2) @ConfigurationProperties + @Component 实现配置绑定
- 注意区分 @Component 和 @Configuration 的区别
bean
-------
// @Component + @ConfigurationProperties 两个组件配合,用来实现 ( 配置绑定 ),绑定application.properties或者application.yml文件中的变量
// @Component 把组件注册到容器中,即向IOC中添加组件 => 必须在容器中的组件,才能拥有spring提供的强大功能,即容器中的组件才能使用 @ConfigurationProperties
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Component // 向IOC中添加组件
@ConfigurationProperties(prefix = "myapp") // prefix 即 application.yml中的前缀
public class TestConfigurationPropertiesAndComponentBean {
String author;
String email;
}
application.yml
-------
myapp: # 通过 @ConfigurationProperties(prefix = "myapp") 指定
author: woow_wu7
email: woow.wu7@gmail.com
(3) 复习拦截器 - HandlerInterceptor + WebMvcConfigurer
(1)
HandlerInterceptor
- preHandle => controller目标方法执行前
- postHandle => controller目标方法执行后
- afterCompletion => 页面渲染完后
(2)
具体流程
1. 在 ( interceptor ) 文件夹中添加拦截器,并实现 ( HandlerInterceptor ) 接口,并在 ( preHandle ) 等中处理逻辑
2. 在 ( config ) 文件夹中通过实现 ( WebMvcConfigurer ) 接口,然后添加拦截规则
(4) 复习 swagger
1. 安装
<!-- Swagger -->
<!-- 自动生成 ( 接口文档 ) 及 ( 自测工具 ) -->
<!-- Swagger2 3.0 只需要 ( springfox-boot-starter ) 就可以了 -->
<!-- Swagger2 2.x 则需要 ( springfox-swagger2 ) 和 ( springfox-swagger-ui )-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
2. 编写配置类
src/main/java/com.example.demo/config/Swagger2Config.java
-------
@Configuration // 标注当前类是一个启动类,即项目启动时就要去加载了
@EnableSwagger2 // 开启 Swagger2 的配置
public class Swagger2Config {
@Bean // 把该组件添加到IOC容器中
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// Swagger2进行包扫描,扫描 controller,这里填写 controller 的文件夹全路径
.apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// 标题
.title("react-admin-java-api 使用Swagger2构建RESTful APIs")
// 描述
.description("react-admin-java-api Swagger2的接口文档")
// 作者信息
.contact(new Contact("woow_wu7", "https://github.com/woow-wu7/7-react-admin-java", "woow_wu7@gmail.com"))
// 服务网址
.termsOfServiceUrl("http://120.53.220.141:81/admin-home")
.version("1.0")
.build();
}
}
3.
访问 http://localhost:7000/swagger-ui/index.html
即是: 项目启动地址/swagger-ui/index.html
如果是远程部署后访问地址:服务器地址/swagger-ui/index.html
(5) 复习一些前端的知识
(1) trim
- 字符串的 ( trim ) 方法用来去除 ( 字符串 ) 两端的空格,返回一个 ( 新的字符串 ),不改变原字符串
(2) git rm -r --cached 文件夹或者文件
- 比如:git rm -r --cached dist
- 表示:把 ( 当前dist ) 的 ( 跟踪记录删除 ),但是 ( 工作区的dist文件夹还是存在 )
- git rm
- 同时从 ( 工作区和索引 ) 中删除文件,即本地文件也被删除了
- git rm --cached
- 从 ( 索引中删除 ) 文件,本地文件还是存在,但该文件不被版本所控制了
- git rm -r
- 上面的 -r 是 ( recursive ) 递归的意思
- 总的表示 递归的删除
(6) 多模块配置注意的问题
- 关于mybatis的xml方式配置
- mapper模块
-
resources/maybaits/mybatis-config.xml
和mybatis/xxx.xml
是在mapper
模块配置的
-
- controller模块
- 但是关于mybatis的配置文件指定,是在
controller
模块中的application.yml
文件中配置的,因为在 controller模块中才具有启动类Application
- 但是关于mybatis的配置文件指定,是在
- mapper模块
(7) public private protected static final abstract
-
public
- 公共访问控制符
- 将一个类声明为 ( 公共类或方法或属性 ),可以 ( 被任何对象访问 )
- 一个程序的主要类一定是公共类
-
protected
- 保护访问控制符
- 只允许自己和子类访问,其他类型的类不能访问
-
private
- 私有访问控制符
- 只允许自己类的方法访问,其他类(包括子类)的方法都不能访问
-
abstract
- 将一个类声明为 ( 抽象类 ),没有实现的方法,需要子类实现
- final和abstract不能同时出现
-
final
- 将一个类声明为 ( 非继承类 ),表示该类 ( 不能被其他类继承 )
- final和abstract不能同时出现
-
static
- 修饰的方法和变量,既可以通过 ( 类来调用 ),也可以通过 ( 实例对象调用 )
如果没有通过static修饰,则该类必须先实例化,然后再通过实例对象调用
(8) java异常分类 - Throwable + Error + Exception
(9) java中的枚举enum类型
- java中枚举是一种特殊的类,一般用来表示 ( 一组常量 )
// 枚举 - enum
// CustomExceptionType - 自定义 异常枚举类型
public enum CustomExceptionType {
CLIENT_ERROR(400, "客户端错误"),
SERVICE_ERROR(500, "服务端错误"),
OTHER_ERROR(999, "未知错误");
private String desc; // 异常描述
private int code; // 异常状态码
CustomExceptionType(int code, String desc) { // 有参构造器
this.code = code;
this.desc = desc;
}
public int getCode() { // getter
return code;
}
public String getDesc() { // setter
return desc;
}
}
(二) java-bean 赋值转换
-
VO
( View Object 和前端view层数据结构相对应 ) -
BO/DTO
( Business object / Data Transfer Object 通常是多个PO的组合体 ) -
PO
( Persistent Object 持久对象,该类的成员与数据库字段一一对应 )
VO(view object)
---------------------------------- controller
BO(business object)
---------------------------------- service
PO(persistent object)
---------------------------------- mapper
(三) 参数验证 spring-boot-starter-validation
- spring-boot-starter-validation
(1) 安装验证相关依赖
<!--校验组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--web组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
(2) 添加验证规则
- 一般用于POST,PUT请求
- 1.在bean实体中添加规则
比如:@NotNull
- 2.在controller的参数中添加
比如:@Validated 或者 @Valid 作用于bean参数
bean
-------
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Component
@ApiModel(description = "返回响应的数据") // swagger
public class MusicBean {
@ApiModelProperty(value = "歌曲名") // swagger
String name;
@NotBlank(message = "album不能为空") // spring-boot-starter-validation => @NotBlank只能用于字符串,trim后长度必须大于0
String album;
@NotNull(message = "singer不能为空") // spring-boot-starter-validation => @NotNull不能为为null,但可以是空字符串
String singer;
Timestamp startTime;
Timestamp endTime;
}
controller
-------
// 增
@PostMapping("/music")
public Integer addMusic(
@Validated // spring-boot-starter-validation 验证插件,然后在music实体中添加具体的验证规则
@RequestBody MusicBean music
) {
return musicService.addMusic(music);
}
(3) 上面 2 中存在的问题
- 如果上面的2中的 singer 为null,后端就会给前端抛出错误,但是写的具体的错误信息不会返回给前端
- 所以我们需要在controller的方法中添加参数,
类型是 BindingResult
// 增
@PostMapping("/music")
public Object addMusic(
// @Validated // spring-boot-starter-validation 验证插件,然后在music实体中添加具体的验证规则
@Valid
@RequestBody MusicBean music,
BindingResult br
) {
if (br.hasErrors()) {
log.info(br.getFieldError().getDefaultMessage());
return br.getFieldError().getDefaultMessage(); // 将错误返回给前端
}
return musicService.addMusic(music);
}
(4) 上面 3 中存在的问题
- 错误是返回了,但是
状态码还是200
则需要使用HttpServletResponse
// 增
@PostMapping("/music")
public Object addMusic(
// @Validated // spring-boot-starter-validation 验证插件,然后在music实体中添加具体的验证规则
@Valid
@RequestBody MusicBean music,
BindingResult br, // spring-boot-starter-validation
HttpServletResponse resp // spring-boot-starter-validation
) {
if (br.hasErrors()) {
resp.setStatus(412); // 412 一个或者多个请求头字段在当前请求中报错
log.info(br.getFieldError().getDefaultMessage());
return br.getFieldError().getDefaultMessage();
}
return musicService.addMusic(music);
}
(5) @NotBlank @NotEmpty @NotNull @NoneNull 的区别
- @NotEmpty
用于类上
不能为null,并且长度必须大于0 -
@NotNull
用于类的属性上
不能为null,但是可以是空字符串 -
@Blank
用于类的属性上,并且只用于String类型
不能为null,而且调用trim()后,长度必须大于0 - @NonNull
用于方法或构造函数的参数上使用,生成一个空值检查语句
(6) @Valid 和 @Validated 的区别
(四) 全局异常处理
- @RestControllerAdvice
- @ExceptionHandler
- RuntimeException
(4.1)具体流程
- 新建exception的package,然后新建三个文件
-
CustomExceptionBean
错误信息收集 -
ApiResponseBean
返回给前端的最终数据结构 WebExceptionHandler
-
(4.1.1) CustomExceptionBean
CustomExceptionBean
-------
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CustomExceptionBean extends RuntimeException{
public int code;
public String message;
}
(4.1.2) ApiResponseBean
ApiResponseBean
-------
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AjaxResponseBean {
public boolean isOk;
public int code;
public String message;
public Object data;
// 成功 - 无数据
// 请求成功的响应,返回值不带查询数据,( 用于添加,删除,修改 )
public AjaxResponseBean success() {
AjaxResponseBean ajaxResponseBean = new AjaxResponseBean();
AjaxResponseBean.builder()
.isOk(true)
.code(200)
.message("请求成功")
.build();
return ajaxResponseBean;
}
// 成功 - 带数据
// 请求成功的响应,返回值带查询数据,( 用于查询 )
public static AjaxResponseBean success(Object obj) {
AjaxResponseBean ajaxResponse = new AjaxResponseBean();
AjaxResponseBean.builder()
.isOk(true)
.code(200)
.message("请求成功")
.data(obj)
.build();
return ajaxResponse;
}
// 失败
public static AjaxResponseBean error(CustomExceptionBean customExceptionBean) {
AjaxResponseBean ajaxResponse = new AjaxResponseBean();
AjaxResponseBean.builder()
.isOk(false)
.code(customExceptionBean.getCode())
.message(customExceptionBean.getMessage())
.build();
return ajaxResponse;
}
}
(4.1.3) WebExceptionHandler
WebExceptionHandler
-------
@RestControllerAdvice
public class WebExceptionHandler {
@ExceptionHandler
public AjaxResponseBean customException(
CustomExceptionBean customExceptionBean
) {
customExceptionBean.setCode(400);
return AjaxResponseBean.error(customExceptionBean);
}
}
资料
mysql常见crud https://www.jianshu.com/p/49fcde3e4559
swagger常用注解 https://blog.csdn.net/jiangyu1013/article/details/83107255
@ControllerAdvice https://fookwood.com/spring-boot-tutorial-11-ca
public private protected final static abstract 的区别