当前位置: 代码迷 >> 综合 >> mp,swagger
  详细解决方案

mp,swagger

热度:45   发布时间:2023-11-25 03:26:56.0

Mybatis-plus

快速入门

  1. 导入依赖

    <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version>
    </dependency>
    尽量不要同时导入 mybatis 和 mybatis-plus,版本的差异
    
  2. 连接数据库

    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?
    useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  3. 配置实体类、mapper接口(继承BaseMapper泛型为要操作的实体类)

    // 在对应的Mapper上面继承基本的类 BaseMapper
    @Repository // 代表持久层
    public interface UserMapper extends BaseMapper<User> {
          
    // 所有的CRUD操作都已经编写完成了
    // 你不需要像以前的配置一大堆文件了!
    }
  4. 主启动类上去扫描我们的mapper接口

    @MapperScan("com.kuang.mapper")
    

日志

配置一个标准的日志

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

CRUD

  1. 插入

    数据库插入的id 默认值: 全局的唯一id

    // 测试插入
    @Test
    public void testInsert(){
          User user = new User();user.setName("狂神说Java");user.setAge(3);user.setEmail("24736743@qq.com");int result = userMapper.insert(user); // 帮我们自动生成idSystem.out.println(result); // 受影响的行数System.out.println(user); // 发现,id会自动回填
    }
    
  2. 更新

    // 测试更新
    @Test
    public void testUpdate(){
          User user = new User();// 通过条件自动拼接动态sqluser.setId(6L);user.setName("关注公众号:狂神说");user.setAge(18);// 注意:updateById 但是参数是一个 对象!int i = userMapper.updateById(user);System.out.println(i);
    }
    

主键生成策略

雪花算法

生成策略

public enum IdType {
     AUTO(0), 	// 数据库id自增NONE(1), 	// 未设置主键INPUT(2), 	// 手动输入ID_WORKER(3), 	// 默认的全局唯一idUUID(4), 	// 全局唯一id uuidID_WORKER_STR(5); 	//ID_WORKER 字符串表示法
}
  • 主键自增
  1. 实体类字段上使用:@TableId(type=IdType>AUTO)

  2. 数据库字段设置为自增

插入、更新操作

自动填充

创建时间、修改时间!这些个操作一遍都是自动化完成的,我们不希望手动更新!

  1. 数据库级别

    1. 在表中新增字段 create_time, update_time
    2. 默认值分别设置为:CURRENT_TIMESTAMP
    3. 同步实体类(插入属性)
    4. 勾选修改时间的更新选项
  2. Java代码级别

    1. 表中增加字段

    2. 实体类同步并增加注解

      创建时间: @TableField( fill = FieldFill . INSERT )

      修改时间: @TableField( fill = FieldFill . INSERT_UPDATE )

    3. 编写处理器处理注解

      @Slf4j
      @Component // 一定不要忘记把处理器加到IOC容器中!
      public class MyMetaObjectHandler implements MetaObjectHandler {
               // 插入时的填充策略@Overridepublic void insertFill(MetaObject metaObject) {
               log.info("start insert fill.....");// setFieldValByName(String fieldName, Object fieldVal, MetaObject)this.setFieldValByName("createTime",new Date(),metaObject);this.setFieldValByName("updateTime",new Date(),metaObject);}// 更新时的填充策略@Overridepublic void updateFill(MetaObject metaObject) {
               log.info("start update fill.....");this.setFieldValByName("updateTime",new Date(),metaObject);}
      }

乐观锁

乐观锁 : 十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题, 再次更新值测试

悲观锁:十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!

乐观锁实现

  • 取出记录时,获取当前 version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败
乐观锁:1、先查询,获得版本号 version = 1
-- A
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1-- B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败!
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1

MP 的乐观锁插件

  1. 数据库增加version 字段

  2. 实体嘞增加version 属性

  3. 注册组件

    // 扫描我们的 mapper 文件夹
    @MapperScan("com.kuang.mapper")
    @EnableTransactionManagement
    @Configuration // 配置类
    public class MyBatisPlusConfig {
          
    // 注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
          return new OptimisticLockerInterceptor();
    }
    }
    

查询、分页查询

  • 查询

    # 属性查找
    User user = userMapper.selectById(1L);# 属性查找一批
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));# 使用map k-v 查找
    HashMap<String, Object> map = new HashMap<>();
    // 自定义要查询
    map.put("name","狂神说Java");
    map.put("age",3);
    List<User> users = userMapper.selectByMap(map);
    
  • 分页查询

    1. limit 分页查询

    2. pageHelper

    3. MP的内置插件

    4. 拦截器组件

    // 分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
    }
    
    1. 使用
    // 测试分页查询
    @Test
    public void testPage(){
          
    // 参数一:当前页
    // 参数二:页面大小
    // 使用了分页插件之后,所有的分页操作也变得简单的!
    Page<User> page = new Page<>(2,5);
    userMapper.selectPage(page,null);
    page.getRecords().forEach(System.out::println);
    System.out.println(page.getTotal());
    }

删除、逻辑删除

  1. 删除

    // 测试删除
    @Test
    public void testDeleteById(){
          userMapper.deleteById(1240620674645544965L);
    }// 通过id批量删除
    @Test
    public void testDeleteBatchId(){
          userMapper.deleteBatchIds(Arrays.asList(1240620674645544961L,1240620674645544962L));
    }// 通过map删除
    @Test
    public void testDeleteMap(){
          HashMap<String, Object> map = new HashMap<>();map.put("name","狂神说Java");userMapper.deleteByMap(map);
    }
    
  2. 逻辑删除

    并非真正意义上的物理删除,而是通过一个变量让他们失效

    1. 数据表和实体类中增加一个deleted 属性

    2. 配置

      // 逻辑删除组件!
      @Bean
      public ISqlInjector sqlInjector() {
              return new LogicSqlInjector();
      }
      
      # 配置逻辑删除
      mybatis-plus.global-config.db-config.logic-delete-value=1
      mybatis-plus.global-config.db-config.logic-not-delete-value=0
      

性能分析插件

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

MP也提供性能分析插件,如果超过这个时间就停止运行!

  1. 在SpringBoot中配置环境为dev或者 test 环境!

  2. 导入插件

    /** * SQL执行效率插件 */
    @Bean
    @Profile({
          "dev","test"})// 设置 dev test 环境开启,保证我们的效率
    public PerformanceInterceptor performanceInterceptor() {
          PerformanceInterceptor performanceInterceptor = newPerformanceInterceptor();performanceInterceptor.setMaxTime(100); // ms设置sql执行的最大时间,如果超过了则不执行performanceInterceptor.setFormat(true); // 是否格式化代码return performanceInterceptor;
    }
  3. 测试(只要该条sql 超过了规定的时间就会抛异常)

条件构造器wrapper

  • 用于描写一些复杂的sql

image-20211110084458842

?

void contextLoads() {
    QueryWrapper<User> wrapper = new QueryWrapper<>();// 查询name不为空的用户,并且邮箱不为空的用户,年龄大于等于12wrapper.isNotNull("name").isNotNull("email").ge("age",12);userMapper.selectList(wrapper)// 查询名字狂神说wrapper.eq("name","狂神说");User user = userMapper.selectOne(wrapper); // 查询一个数据,出现多个结果使用List// 查询年龄在 20 ~ 30 岁之间的用户wrapper.between("age",20,30); // 区间Integer count = userMapper.selectCount(wrapper);// 查询结果数// 查询年龄在 20 ~ 30 岁之间的用户// 左和右 t%wrapper.notLike("name","e").likeRight("email","t");List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);// id 在子查询中查出来wrapper.inSql("id","select id from user where id<3");List<Object> objects = userMapper.selectObjs(wrapper);// 通过id进行排序wrapper.orderByAsc("id");List<User> users = userMapper.selectList(wrapper);userMapper.selectList(wrapper).forEach(System.out::println); // 和我们刚才学习的map对比一下
}

代码自动生成器

AutoGenerator 是 MyBatis-Plus 的代码生成器

通过 AutoGenerator 可以快速生成 Entity、 Mapper、Mapper XML、Service、Controller 等各个模块的代码

极大的提升了开发效率。

package com.kuang;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
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.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
// 代码自动生成器
public class KuangCode {
    public static void main(String[] args) {
    // 需要构建一个 代码自动生成器 对象AutoGenerator mpg = new AutoGenerator();// 配置策略// 1、全局配置GlobalConfig gc = new GlobalConfig();String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath+"/src/main/java");// 作者名gc.setAuthor("zj");// 是否打开目录gc.setOpen(false);gc.setFileOverride(false); // 是否覆盖gc.setServiceName("%sService"); // 去Service的I前缀gc.setIdType(IdType.ID_WORKER);// 时间日期格式gc.setDateType(DateType.ONLY_DATE);// 使用Swaggergc.setSwagger2(true);mpg.setGlobalConfig(gc);//2、设置数据源DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3306/kuang_community?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8");dsc.setDriverName("com.mysql.cj.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("123456");dsc.setDbType(DbType.MYSQL);mpg.setDataSource(dsc);//3、包的配置PackageConfig pc = new PackageConfig();pc.setModuleName("blog");pc.setParent("com.kuang");pc.setEntity("entity");pc.setMapper("mapper");pc.setService("service");pc.setController("controller");mpg.setPackageInfo(pc);//4、策略配置StrategyConfig strategy = new StrategyConfig();strategy.setInclude("blog_tags","course","links"); // 设置要映射的表名strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setColumnNaming(NamingStrategy.underline_to_camel);strategy.setEntityLombokModel(true); // 自动lombok;strategy.setLogicDeleteFieldName("deleted");// 自动填充配置TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);TableFill gmtModified = new TableFill("gmt_modified",FieldFill.INSERT_UPDATE);ArrayList<TableFill> tableFills = new ArrayList<>();tableFills.add(gmtCreate);tableFills.add(gmtModified);strategy.setTableFillList(tableFills);// 乐观锁strategy.setVersionFieldName("version");strategy.setRestControllerStyle(true);strategy.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_2mpg.setStrategy(strategy);mpg.execute(); //执行}
}

Swagger

前后端分离

前后端分离

  • 前端 ==> 前端控制层、视图层
  • 后端 ==> 后端控制层、服务层、数据访问层
  • 前后端通过API进行交互、相对独立且松耦合

前后端集成,前端或者后端无法做到“及时协商,尽早解决”,最终导致问题集中爆发

Swagger

  • 号称世界上最流行的API框架
  • Restful Api 文档在线自动生成器 => API 文档 与API 定义同步更新
  • 直接运行,在线测试API
  • 支持多种语言 (如:Java,PHP等)
  • 官网:https://swagger.io/

快速入门

  1. 导入依赖 ( Springfox-swagger2 、springfox-swagger-ui )

    <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version>
    </dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version>
    </dependency>
    
  2. 编写SwaggerConfig 配置类来配置Swagger

    @Configuration //配置类
    @EnableSwagger2// 开启Swagger2的自动配置
    public class SwaggerConfig {
            
    }
    
  3. 访问:http://localhost:8080/swagger-ui.html

配置Swagger

  1. Swagger实例Bean是Docket,通过配置Docket 实例配置Swagger

    @Bean     //配置docket以配置Swagger具体参数
    public Docket docket() {
          return new Docket(DocumentationType.SWAGGER_2);
    }
    
  2. 通过apiInfo( ) 属性配置文档信息

    //配置文档信息
    private ApiInfo apiInfo() {
          Contact contact = new Contact("联系人名字", "http://xxx.xxx.com/联系人访问链接", "联系人邮箱");return new ApiInfo("Swagger学习", // 标题"学习演示如何配置Swagger", // 描述"v1.0", // 版本"http://terms.service.url/组织链接", // 组织链接contact, // 联系人信息"Apach 2.0 许可", // 许可"许可链接", // 许可连接new ArrayList<>()// 扩展);
    }
    
  3. Docket 实例关联上 apiInfo()

    @Bean
    public Docket docket() {
          return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
    }
    

配置扫描接口

1、构建Docket时通过select()方法配置怎么扫描接口

@Bean
public Docket docket() {
    return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("swagger_study.controller"))// 还可以使用 paths 进行路径过滤 即这里只扫描请求以/swagger_study 开头的接口.paths(PathSelectors.ant("/swagger_study/")).build();
}
// RequestHandlerSelectors 还可以有一下参数用来配置扫描包any() 		// 扫描所有,项目中的所有接口都会被扫描到
none() 		// 不扫描接口// 通过方法上的注解扫描,如withMethodAnnotation(GetMapping.class)只扫描get请求
withMethodAnnotation(final Class<? extends Annotation> annotation)// 通过类上的注解扫描,如.withClassAnnotation(Controller.class)只扫描有controller注解的类中的接口
withClassAnnotation(final Class<? extends Annotation> annotation)// 根据包路径扫描接口
basePackage(final String basePackage) 
// paths 同样也可以有如下配置any() 	// 任何请求都扫描
none() 	// 任何请求都不扫描
regex(final String pathRegex)	 // 通过正则表达式控制
ant(final String antPattern) 		// 通过ant()控制

配置是否使用swagger

@Beanpublic Docket docket(){    return new Docket(DocumentationType.SWAGGER_2)        .apiInfo(apiInfo())        // 关闭swagger        .enable(false)        .select()        .apis(RequestHandlerSelectors.basePackage("swagger_study.controller"))        .paths(PathSelectors.ant("/swagger_study/"))        .build();}
  1. 问题:(如果项目处于test、dev 环境时使用 swagger ,处于prod 时不使用swagger)

    @Beanpublic Docket docket(Environment environment) {
             // 设置要显示swagger的环境 Profiles of = Profiles.of("dev", "test"); // 判断当前是否处于该环境 // 通过 enable() 接收此参数判断是否要显示 boolean b = environment.acceptsProfiles(of); return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .enable(b) //配置是否启用Swagger,如果是false,在浏览器将无法访问 .select() .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller")) .paths(PathSelectors.ant("/kuang/**")) .build();}
    

配置API分组

  1. 如果没有配置分组,默认是default。通过 .groupName()方法即可配置分组

    @Beanpublic Docket docket(Environment environment) {
             return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())      .groupName("hello") // 配置分组 // 省略配置....}
    
  2. 配置多个分组只需要配置多个 docket 即可

    @Beanpublic Docket docket1(){
             return new Docket(DocumentationType.SWAGGER_2).groupName("group1");}@Beanpublic Docket docket2(){
             return new Docket(DocumentationType.SWAGGER_2).groupName("group2");}@Beanpublic Docket docket3(){
             return new Docket(DocumentationType.SWAGGER_2).groupName("group3");}
    

配置实体类

  1. 实体类

    @ApiModel("用户实体")public class User {
             @ApiModelProperty("用户名")   public String username;   @ApiModelProperty("密码")   public String password;}
    

    @ApiModel 为类添加注释

    @ApiModelProperty 为类属性添加注释

    只要出现在接口方法的返回值上的实体都会显示在这里

    而@ApiModel和@ApiModelProperty这两个注解只是为实体添加注释的

  2. 只要这个实体在请求接口的返回值上(即使是泛型),都能映射到实体项中

    @RequestMapping("/getUser")public User getUser(){
             return new User();}
    

常用注解

Swagger注解 简单说明
@Api(tags = “xxx模块说明”) 作用在模块类上
@ApiOperation(“xxx接口说明”) 作用在接口方法上
@ApiModel(“xxxPOJO说明”) 作用在模型类上:如VO、BO
@ApiModelProperty(value = “xxx属性说明”,hidden = true) 作用在类方法和属性上,hidden设置为true可以隐藏该属性
@ApiParam(“xxx参数说明”) 作用在参数、方法和字段上,类似@ApiModelProperty

小结

Swagger就是用来给一些比较难理解的属性或者接口,增加一些配置信息,让人更容易阅读

正式环境要记得关闭Swagger,安全考虑、节省运行

皮肤

导入不同的 ui 包 实现不同的皮肤定义

  1. 默认

    <dependency>   <groupId>io.springfox</groupId>   <artifactId>springfox-swagger-ui</artifactId>   <version>2.9.2</version></dependency>
    

    http://localhost:8080/swagger-ui.html

  2. bootstrap-ui

    <dependency>   <groupId>com.github.xiaoymin</groupId>   <artifactId>swagger-bootstrap-ui</artifactId>   <version>1.9.1</version></dependency>
    

    http://localhost:8080/doc.html

  3. layui-ui

    <dependency>   <groupId>com.github.caspar-chen</groupId>   <artifactId>swagger-ui-layer</artifactId>   <version>1.1.3</version></dependency>
    

    http://localhost:8080/docs.html

  4. mg-ui

    <dependency>   <groupId>com.zyplayer</groupId>   <artifactId>swagger-mg-ui</artifactId>   <version>1.0.6</version></dependency>
    

    http://localhost:8080/document.html

  相关解决方案