开发工具箱
开发工具箱
定西Spring配置
统一异常处理
统一结果返回对象
MyBatis-Plus配置
ResultMap配置
SpringBoot配置
Docker配置
Vue配置
Swagger配置
那些难记又经常用的代码片段-待补充
Spring配置
Spring核心配置文件
AOP最佳实战
统一结果返回对象
一般的返回结果结构:
1 | { |
首先创建一个枚举类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package com.zzmr.common.result;
import lombok.Getter;
public enum ResultCodeEnum {
SUCCESS(200, "成功"),
FAIL(201, "失败");
/*SERVICE_ERROR(2012, "服务异常"),
DATA_ERROR(204, "数据异常"),
LOGIN_AUTH(208, "未登录"),
PERMISSION(209, "没有权限");*/
private Integer code;
private String message;
private ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}创建返回结果类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65package com.zzmr.common.result;
import lombok.Data;
public class Result<T> {
// 状态码
private Integer code;
// 信息
private String message;
// 数据
private T data;
// 构造私有化,
private Result() {
}
// 封装返回的是数据
public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
Result<T> result = new Result<>();
if (body != null) {
result.setData(body);
}
result.setCode(resultCodeEnum.getCode());
result.setMessage(resultCodeEnum.getMessage());
return result;
}
// 成功
public static <T> Result<T> ok() {
return build(null, ResultCodeEnum.SUCCESS);
}
// 成功-有数据
public static <T> Result<T> ok(T data) {
return build(data, ResultCodeEnum.SUCCESS);
}
// 失败
public static <T> Result<T> fail() {
return build(null, ResultCodeEnum.FAIL);
}
// 失败-有数据
public static <T> Result<T> fail(T data) {
return build(data, ResultCodeEnum.FAIL);
}
public Result<T> message(String msg) {
this.setMessage(msg);
return this;
}
public Result<T> code(Integer code) {
this.setCode(code);
return this;
}
}此时修改Controller
1
2
3
4
public Result findAll() {
return Result.ok(sysRoleService.list());
}
如果返回的数据为空,就可以不在ok()中放入数据,这样也是可以进行返回的
统一异常处理
当控制器方法出现异常时,我们希望都返回相同格式的数据,就算是有异常,然后仍是Result格式的结果
异常处理可以分为:
- 全局异常处理
- 特定异常处理
- 自定义异常处理
全局异常处理
1 | package com.zzmr.common.config.exception; |
特定异常处理
1 | // 特定异常处理 |
如果加了特定异常处理,同时也有全局,那么程序会默认找特定的,没有特定的才会使用全局的
自定义异常处理
- 创建异常类,继承RuntimeException
- 在异常类中添加上相关的属性,状态码,描述信息
- 在出现异常的地方手动抛出异常
- 在之前创建异常类中,添加上执行方法(就是上面的方法)
异常类:
1 | package com.zzmr.common.config.exception; |
手动抛出异常
1 | // 模拟异常效果 |
添加执行方法
1 | // 自定义异常处理 |
MyBatis-Plus配置
逻辑删除
在配置文件中加入:
1 | # 此为默认值,不需要修改 意思就是1为删除了,0为未删除 |
此时再调用删除方法时,就会自动进行逻辑删除
代码生成器
- 引入依赖:
1
2
3
4
5
6
7
8
9
10
11<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency> - 编写工具类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65package com.zzmr.code;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
public class CodeGet {
public static void main(String[] args) {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir("D:\\Codefield\\guigu-oa-parent\\service-oa"+"/src/main/java");
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setAuthor("zzmr");
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/guigu-oa?serverTimezone=GMT%2B8&useSSL=false");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("010203");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.zzmr");
pc.setModuleName("auth"); //模块名
pc.setController("controller");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
// 指定表名
strategy.setInclude("sys_user");
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
} - 同时会生成一个实体类,如果事先已经创建好了,可以删除,然后把service和mapper中引入的实体类换成自己的就行了.
分页插件
- 配置分页插件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package com.zzmr.common.config.mp;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
} - 编写controller的分页方法
- 当前页,每页显示的记录数
- 条件参数
- 调用service的方法实现条件分页查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// 条件分页查询
// page 当前页 limit 每页显示的记录数
public Result pageQueryRole( Long page, Long limit,
SysRoleQueryVo sysRoleQueryVo) {
// 调用service的方法实现
// 1. 创建page对象,传递分页相关参数
Page<SysRole> pageParam = new Page<>(page, limit);
// 2. 封装条件,判断条件是否为空,不为空进行封装
LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
String roleName = sysRoleQueryVo.getRoleName();
if (!StringUtils.isEmpty(roleName)) {
// 不为空,封装
// 下面的lambda表达式相当于取数据库中roleName的字段名和roleName进行模糊搜索
wrapper.like(SysRole::getRoleName, roleName);
}
// 3. 调用方法实现
IPage<SysRole> pageModel = sysRoleService.page(pageParam, wrapper);
return Result.ok(pageModel);
}
ResultMap配置
SpringBoot配置
Docker配置
安装tomcat
安装redis
安装mysql
Vue配置
Swagger配置
项目配置
使用Swagger只需要按照它的规范去定义接口及接口相关的信息,就可以做到生成接口文档,以及在线接口调试页面,Knife4j
是为Java MVC框架集成Swagger生成Api文档的增强解决方案
使用方式
- 导入依赖
1
2
3
4
5<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency> - 在配置类中加入
knife4j
相关配置(某个带有@Configuration
的配置类中即可)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/**
* 通过knife4j生成接口文档
* @return
*/
public Docket docket() {
ApiInfo apiInfo = new ApiInfoBuilder()
.title("苍穹外卖项目接口文档")
.version("2.0")
.description("苍穹外卖项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.sky.controller"))
.paths(PathSelectors.any())
.build();
return docket;
} - 设置静态资源映射,否则接口文档页面无法访问(要放在某个继承自
WebMvcConfigurationSupport
类中),这个方法其实就是重写的父类的方法1
2
3
4
5
6
7
8/**
* 设置静态资源映射
* @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
顺便把这个配置类也放着:
1 | package com.sky.config; |
这就配置好了,启动项目进入浏览器访问localhost:8080/doc.html
,即可进入接口文档页面
Swagger和yapi的区别
- yapi是设计阶段使用的工具,管理和维护接口
- Swagger是在开发阶段使用的框架,帮助后端开发人员做后端的接口测试
Swagger常用注解
具体使用案例
@Api(tags = "员工相关接口")
,给Controller上加,在页面上表示一级目录,**tags=**不能省略,否则无效,1
2
3
public class EmployeeController {
}@ApiOperation(value = "员工登录接口")
,给接口上加,表示具体接口的名称1
2
3
public Result<EmployeeLoginVO> login( { EmployeeLoginDTO employeeLoginDTO)
}@ApiModel
和@ApiModelProperty()
,给实体类和属性上加1
2
3
4
5
6
7
8
9
10
public class EmployeeLoginDTO implements Serializable {
private String username;
private String password;
}
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果