初学者必看,SpringBoot+MybatisPlus+Swagger快速开发套路和总结-2

简介: 初学者必看,SpringBoot+MybatisPlus+Swagger快速开发套路和总结

MP插件

业务类搞好后,为了让接口的功能更完善,我们最后加上mp自带的插件


https://baomidou.gitee.io/mybatis-plus-doc/#/performance-analysis-plugin


mp的2.x文档更详细一点


下面分别介绍主要的插件和一些常见知识点


主键生成策略

下面是我对实体类字段进行的设置,


这样设置的话我的主键在每次创建新用户的时候都会自动填充为分布式全局唯一ID 字符串类型


private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "讲师ID")
/**
 * 分布式应用时,我们需要生成分布式ID,可以选择使用@TableId(type=IdType.ID_WORKER),数据库中的主键为:
 * IdType包括以下几类:
 * AUTO : 数据库主键自增
 * INPUT: 用户自行输入
 * ID_WORKER: 分布式全局唯一ID, 长整型
 * UUID: 32位UUID字符串
 * NONE: 无状态
 * ID_WORKER_STR: 分布式全局唯一ID 字符串类型
 */
@TableId(value = "id", type = IdType.ID_WORKER_STR)
private String id;

6b6c7ba520f6e66926f43cff8846cfad_3591946aa75fef5bb92d69ba357792f8.png


自动填充详解

自动填充一般应用在数据库创建时间或修改时间字段


[自动填充功能官网](自动填充功能 | MyBatis-Plus (baomidou.com))


配置类

package com.caq.servicebase.handle;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    //插入的时候填充创建和修改字段
    @Override
    public void insertFill(MetaObject metaObject) {
        //属性名称,不是字段名称
        this.setFieldValByName("gmtCreate",new Date(),metaObject);
        this.setFieldValByName("gmtModified",new Date(),metaObject);
    }
//修改的时候填充修改字段
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("gmtModified",new Date(),metaObject);
    }
}

定义字段

@ApiModelProperty(value = "创建时间")
@TableField(fill= FieldFill.INSERT)
private Date gmtCreate;
@ApiModelProperty(value = "更新时间")
@TableField(fill=FieldFill.INSERT_UPDATE)
private Date gmtModified;

测试自动填充

85e2c54d2b4cc05bb29d5e1493624216_ffddf1f1a3f0b718061d52849d1e319f.png


乐观锁

锁是针对数据冲突的解决方案


悲观锁


正如其名,它指的是对数据被外界修改持保守(悲观),因此在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制


乐观锁


相对悲观锁而言,乐观锁假设认为数据一般情况下不会有冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现了冲突,则让返回用户错误的信息,让用户决定如何去做。乐观锁的实现方式一般是记录数据版本


乐观锁的实现方式


  • 取出记录,获取当前Version
  • 更新时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

6f922f58d266479371f012fa834ca377_d7c3e6612ecc94731b04e53fe60d4650.png


乐观锁配置需要两步


配置插件

//乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    return new OptimisticLockerInterceptor();
}

在实体类的字段上加上@Version注解

@Version
private Integer version;

逻辑删除

只对自动注入的 sql 起效:


  • 插入: 不作限制
  • 查找: 追加 where 条件过滤掉已删除数据,且使用 wrapper.entity 生成的 where 条件会忽略该字段
  • 更新: 追加 where 条件防止更新到已删除数据,且使用 wrapper.entity 生成的 where 条件会忽略该字段
  • 删除: 转变为 更新


例如:


  • 删除: update user set deleted=1 where id = 1 and deleted=0
  • 查找: select id,name,deleted from user where deleted=0


字段类型支持说明:


  • 支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime)
  • 如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now()


附录:


  • 逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
  • 如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。


配置

@Bean
public ISqlInjector sqlInjector() {
    return new LogicSqlInjector();
}

实体类字段上加上@TableLogic注解

@TableLogic
private Integer deleted;

分页

  • 自定义查询语句分页(自己写sql/mapper)
  • spring 注入 mybatis 配置分页插件

配置类

//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}

性能分析

性能分析拦截器,用于输出每条 SQL 语句及其执行时间


注意!该插件只用于开发环境,不建议生产环境使用。。。


配置类

//性能分析插件
@Bean
@Profile({"dev","test"})    //设置dev test环境开启,保证效率
public PerformanceInterceptor performanceInterceptor(){
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    performanceInterceptor.setMaxTime(100);//设置sql执行的最大时间ms
    performanceInterceptor.setFormat(true);
    return performanceInterceptor;
}


通用CRUD

介绍完了mp的组件,要想使用只需要把它们写进一个配置类中让boot扫描即可


配置类

注入mp插件,完善接口功能


e30269f9fae1d363059869d19a4e37d2_818a116d401cbd76fc307f679d2614f3.png


CRUD接口

package com.caq.mybatisplusdemo.controller;
@Api("crud测试")
@RestController
@RequestMapping("/testMP/user")
public class crudDemo {
    @Autowired
    UserService userService;
    @ApiOperation("增加用户")
    @PostMapping("save")
    public R saveUser(@RequestBody User user){
        boolean save = userService.save(user);
        if (save){
            return R.ok();
        }else {
            return R.error();
        }
    }
    @ApiOperation("查看所有用户")
    @GetMapping("list")
    public R listUser(){
        List<User> list = userService.list(null);
        return R.ok().data("items",list);
    }
    @ApiOperation("查看某个用户")
    @GetMapping("getByIdUser")
    public R getByIdUser(@PathVariable String id){
        User user = userService.getById(id);
        return R.ok().data("user",user);
    }
    @ApiOperation("按ID删除user")
    @DeleteMapping("delete")
    public R removeUser(@ApiParam(name = "id",value = "讲师ID",required = true)@PathVariable String id){
        boolean delete = userService.removeById(id);
        if (delete){
            return R.ok();
        }else {
            return R.error();
        }
    }
    @ApiOperation("按ID更改user")
    @PostMapping
    public R updateUser(@RequestBody User user){
        boolean update = userService.updateById(user);
        if (update){
            return R.ok();
        }else {
            return R.error();
        }
    }
}


三、Swagger


还是一样的套路,开局三连问


是什么?

一款接口测试工具


有什么好处?

对于后端开发人员来说


  • 不用再手写WiKi接口拼大量的参数,避免手写错误
  • 对代码侵入性低,采用全注解的方式,开发简单
  • 方法参数名修改、增加、减少参数都可以直接生效,不用手动维护
  • 缺点:增加了开发成本,写接口还得再写一套参数配置


对于前端开发来说


  • 后端只需要定义好接口,会自动生成文档,接口功能、参数一目了然
  • 联调方便,如果出问题,直接测试接口,实时检查参数和返回值,就可以快速定位是前端还是后端的问题


对于测试


  • 对于某些没有前端界面UI的功能,可以用它来测试接口
  • 操作简单,不用了解具体代码就可以操作
  • 操作简单,不用了解具体代码就可以操作


怎么用?

引入swagger的依赖


目前推荐使用2.7.0版本,因为2.6.0版本有bug


引入依赖

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <scope>provided</scope>
    <version>2.7.0</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.7.0</version>
</dependency>

springBoot整合swagger

@Configuration
@MapperScan("com.caq.mybatisplusdemo.mapper")
@EnableSwagger2
public class MpConfig {
    @Bean
    public Docket webApiConfig() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("webApi")
                .apiInfo(webApiInfo())
                .select()
                .paths(Predicates.not(PathSelectors.regex("/admin/.*")))
                .paths(Predicates.not(PathSelectors.regex("/error.*")))
                .build();
    }
    private ApiInfo webApiInfo() {
        return new ApiInfoBuilder()
                .title("mp测试")
                .description("本文档描述了mp接口定义")
                .version("1.0")
                .contact(new Contact("java", "http://java.com", "534215342@qq.com"))
                .build();
    }
}

swagger的注解

@Api():用在请求的类上,表示对类的说明,也代表了这个类是swagger2的资源


参数:


tags:说明该类的作用,参数是个数组,可以填多个。
value="该参数没什么意义,在UI界面上不显示,所以不用配置"
description = "用户基本信息操作"

@ApiOperation():用于方法,表示一个http请求访问该方法的操作


参数:


value="方法的用途和作用"    
notes="方法的注意事项和备注"    
tags:说明该方法的作用,参数是个数组,可以填多个。
格式:tags={"作用1","作用2"} 
(在这里建议不使用这个参数,会使界面看上去有点乱,前两个常用)

@ApiModel():用于响应实体类上,用于说明实体作用


参数:


description="描述实体的作用"  

@ApiModelProperty:用在属性上,描述实体类的属性


参数:


value="用户名"  描述参数的意义
name="name"    参数的变量名
required=true     参数是否必选

@ApiImplicitParams:用在请求的方法上,包含多@ApiImplicitParam


@ApiImplicitParam:用于方法,表示单独的请求参数


参数:


name="参数ming" 
value="参数说明" 
dataType="数据类型" 
paramType="query" 表示参数放在哪里
    · header 请求参数的获取:@RequestHeader
    · query   请求参数的获取:@RequestParam
    · path(用于restful接口) 请求参数的获取:@PathVariable
    · body(不常用)
    · form(不常用) 
defaultValue="参数的默认值"
required="true" 表示参数是否必须传

@ApiParam():用于方法,参数,字段说明 表示对参数的要求和说明


参数:

name="参数名称"
value="参数的简要说明"
defaultValue="参数默认值"
required="true" 表示属性是否必填,默认为false

@ApiResponses:用于请求的方法上,根据响应码表示不同响应


一个@ApiResponses包含多个@ApiResponse


@ApiResponse:用在请求的方法上,表示不同的响应


参数:

code="404"    表示响应码(int型),可自定义
message="状态码对应的响应信息"   

@ApiIgnore():用于类或者方法上,不被显示在页面上


@Profile({“dev”, “test”}):用于配置类上,表示只对开发和测试环境有用


使用swagger需要注意的问题


  • 对于只有一个HttpServletRequest参数的方法,如果参数小于5个,推荐使用 @ApiImplicitParams的方式单独封装每一个参数;如果参数大于5个,采用定义一个对象去封装所有参数的属性,然后使用@APiParam的方式
  • 默认的访问地址:ip:port/swagger-ui.html#/,但是在shiro中,会拦截所有的请求,必须加上默认访问路径(比如项目中,就是ip:port/context/swagger-ui.html#/),然后登陆后才可以看到
  • 在GET请求中,参数在Body体里面,不能使用@RequestBody。在POST请求,可以使用@RequestBody和@RequestParam,如果使用@RequestBody,对于参数转化的配置必须统一
  • controller必须指定请求类型,否则swagger会把所有的类型(6种)都生成出来
  • swagger在生产环境不能对外暴露,可以使用@Profile({“dev”, “prod”,“pre”})指定可以使用的环境


四、功能测试


下面我们就开始用Swagger来测试我们写的接口


Swagger测试

登录swaggerUI


ip:prot/swagger-ui.html


29da8c324e3e7198fe40bb80a109b117_2fa118b6acbdfb63ed4c74f5ee495c83.png


删除功能测试

逻辑删除我们是用Mp中的插件来实现的


所以在mp的配置类中添加逻辑删除插件即可


  • 插入: 不作限制
  • 查找: 追加 where 条件过滤掉已删除数据,且使用 wrapper.entity 生成的 where 条件会忽略该字段
  • 更新: 追加 where 条件防止更新到已删除数据,且使用 wrapper.entity 生成的 where 条件会忽略该字段
  • 删除: 转变为 更新

例如:


  • 删除: update user set deleted=1 where id = 1 and deleted=0
  • 查找: select id,name,deleted from user where deleted=0


在开发中,我们一般做逻辑删除


所谓逻辑删除不是真正的删除,而是在逻辑上删除不是在数据库中删除


步骤一

//逻辑删除插件
@Bean
public ISqlInjector sqlInjector() {
    return new LogicSqlInjector();
}


步骤二


实体类字段上加上@TableLogic注解


@TableLogic
private Integer deleted;

cc3057eb3b3f9f7fb308e05bfbe99215_5dafa40d8a9e41d45465e67158529d8e.png


讲师分页功能

分页功能我们也是用Mp中的插件来实现的


所以在mp的配置类中添加分页插件即可


步骤一


分页插件


//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}

步骤二


分页Controller方法


 @ApiOperation("分页查询讲师功能")
    @GetMapping("pageTeacher/{current}/{limit}")
    public R pageTeacher(@PathVariable long current,
                         @PathVariable long limit) {
        //创建page对象
        Page<EduTeacher> pageTeacher = new Page<>(current, limit);
        //调用方法实现分页
        //调用方法的时候,底层封装,把分页所有数据封装到pageTeacher对象里面
        teacherService.page(pageTeacher, null);
        long total = pageTeacher.getTotal();
        List<EduTeacher> records = pageTeacher.getRecords();
        Map<String, Object> map = new HashMap();
        map.put("total", total);
        map.put("rows", records);
        return R.ok().data(map);
//        两种方式都可以
//        return R.ok().data("total",total).data("rows",records);
    }

12905cbcc79127d4b517107d93736f94_64588b1510353f10aeb0dd1ed4ca80e1.png


1b62b29a83ef145894352ba1900c7925_93ba1c8c297da69ca0cbf33216901525.png

相关文章
|
30天前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
88 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
30天前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
52 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
1天前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
8 0
|
28天前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
49 1
|
29天前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
24 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
30天前
|
SQL Java 数据库连接
mybatis使用二:springboot 整合 mybatis,创建开发环境
这篇文章介绍了如何在SpringBoot项目中整合Mybatis和MybatisGenerator,包括添加依赖、配置数据源、修改启动主类、编写Java代码,以及使用Postman进行接口测试。
15 0
mybatis使用二:springboot 整合 mybatis,创建开发环境
|
30天前
|
Java 数据库连接 API
springBoot:后端解决跨域&Mybatis-Plus&SwaggerUI&代码生成器 (四)
本文介绍了后端解决跨域问题的方法及Mybatis-Plus的配置与使用。首先通过创建`CorsConfig`类并设置相关参数来实现跨域请求处理。接着,详细描述了如何引入Mybatis-Plus插件,包括配置`MybatisPlusConfig`类、定义Mapper接口以及Service层。此外,还展示了如何配置分页查询功能,并引入SwaggerUI进行API文档生成。最后,提供了代码生成器的配置示例,帮助快速生成项目所需的基础代码。
|
12天前
|
JavaScript 前端开发 Java
SpringBoot_web开发-webjars&静态资源映射规则
https://www.91chuli.com/ 举例:jquery前端框架
12 0
|
29天前
|
开发框架 Java API
「SpringBrick快速入门指南」:一款基于Spring Boot的高级插件化开发框架
「SpringBrick快速入门指南」:一款基于Spring Boot的高级插件化开发框架
46 0
|
30天前
|
机器学习/深度学习 移动开发 自然语言处理
基于人工智能技术的智能导诊系统源码,SpringBoot作为后端服务的框架,提供快速开发,自动配置和生产级特性
当身体不适却不知该挂哪个科室时,智能导诊系统应运而生。患者只需选择不适部位和症状,系统即可迅速推荐正确科室,避免排错队浪费时间。该系统基于SpringBoot、Redis、MyBatis Plus等技术架构,支持多渠道接入,具备自然语言理解和多输入方式,确保高效精准的导诊体验。无论是线上医疗平台还是大型医院,智能导诊系统均能有效优化就诊流程。
下一篇
无影云桌面