mp,swagger

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); // 帮我们自动生成id
        System.out.println(result); // 受影响的行数
        System.out.println(user); // 发现,id会自动回填
    }
    
  2. 更新

    // 测试更新
    @Test
    public void testUpdate(){
        User user = new User();
        // 通过条件自动拼接动态sql
        user.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), 	// 默认的全局唯一id
    UUID(4), 	// 全局唯一id uuid
    ID_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 {
          // 插入时的填充策略
          @Override
          public 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);
          }
          
          // 更新时的填充策略
          @Override
          public 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 = new
        PerformanceInterceptor();
        performanceInterceptor.setMaxTime(100); // ms设置sql执行的最大时间,如果超过了则不
        执行
        performanceInterceptor.setFormat(true); // 是否格式化代码
        return performanceInterceptor;
    }
    
    
  3. 测试(只要该条sql 超过了规定的时间就会抛异常)

条件构造器wrapper

  • 用于描写一些复杂的sql

image-20211110084458842

void contextLoads() {
    
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // 查询name不为空的用户,并且邮箱不为空的用户,年龄大于等于12
    wrapper
        .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);
        // 使用Swagger
        gc.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_2
        mpg.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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值