SpringBoot整合MyBatisPlus

SpringBoot整合MyBatisPlus

SpringBoot

1.简介

Spring Boot是一个基于 Spring 的框架,旨在简化 Spring 应用的配置和开发过程,通过自动配置和约定大于配置的原则,使开发者能够快速搭建独立、生产级别的应用程序。

  • 可以创建独立的Spring应用程序
  • 嵌入了tomcat、jetty等应用服务器程序,可以不需要发布部署即可直接启动项目
  • 提供了很多准备好的启动器,简化项目配置
  • 自动配置Spring以及第三方依赖
  • 绝对无代码生成,也完全不需要任何xml配置

2.构建系统

2.1. 依赖管理

Spring Boot的每个版本都提供了一个它所支持的依赖的列表。 在实践中,你不需要在构建配置中为这些依赖声明版本,因为Spring Boot会帮你管理这些。 当你升级Spring Boot本身时,这些依赖也会一同升级。

你仍然可以指定某个依赖的版本,来覆盖spring boot默认的版本。

3.代码结构

3.1. “default” 包

当一个类不包括 package 的声明时,它被认为是在 “default package” 中。 通常应避免使 “default package”。 对于使用了 @ComponentScan, @ConfigurationPropertiesScan, @EntityScan 或者 @SpringBootApplication 注解的Spring Boot应用程序来说,它可能会造成一个问题:项目中的所有jar里面的所有class都会被读取(扫描)。

我们建议你遵循Java推荐的包的命名惯例,使用域名反转作为包名(例如, com.example.project)。

3.2. 启动类的位置

启动类通常放在一个根package中,高于其他的类,@SpringBootApplication 注解一般都是注解在启动类上的。它默认会扫描当前类下的所有子包。例如,如果你正在编写一个JPA应用程序,你的 @Entity 类只有定义在启动类的子包下才能被扫描加载到。这样的好处也显而易见,@SpringBootApplication 默认只会扫描加载你项目工程中的组件。

如果你不想使用 @SpringBootApplication ,它所导入的 @EnableAutoConfiguration@ComponentScan 注解定义了该行为,所以你也可以使用这些来代替。

一个项目典型的布局如下。

com
 +- example
     +- myapplication
         +- MyApplication.java
         |
         +- customer
         |   +- Customer.java
         |   +- CustomerController.java
         |   +- CustomerService.java
         |   +- CustomerRepository.java
         |
         +- order
             +- Order.java
             +- OrderController.java
             +- OrderService.java
             +- OrderRepository.java

MyApplication.java 文件声明了 main 方法,以及标识了基本的 @SpringBootApplication 注解,如下所示。

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

}

4.Configuration 类

Spring Boot倾向于通过Java代码来进行配置的定义。 虽然也可以使用XML来配置 SpringApplication ,但还是建议你通过 @Configuration 类来进行配置。 通常,可以把启动类是作为主要的 @Configuration 类。

4.1. 导入额外的 Configuration 类

你不需要把所有的 @Configuration 放在一个类中。 @Import 注解可以用来导入额外的配置类。 另外,你可以使用 @ComponentScan 来自动扫描加载所有Spring组件,包括 @Configuration 类。

4.2. 导入 XML Configuration

如果你确实需要使用基于XML的配置,我们建议你仍然从 @Configuration 类开始,然后通过 @ImportResource 注解来加载XML配置文件。

5.自动装配

核心在启动类上面添加的@SpringBootApplication注解

@SpringBootApplication注解是一个组合注解,包含了:

  • @SpringBootConfiguration
    • @Configuration:表示当前启动类可以作为一个配置类,里面可以写@Bean来配置bean(等同于xml中的一个bean标签)
  • @EnableAutoConfiguration
    • @AutoConfigurationPackage
      • @Import(AutoConfigurationPackages.Registrar.class):自动递归扫描启动类所在的包
    • @Import(AutoConfigurationImportSelector.class):手动配置除自动扫描的bean以外的其他bean
  • @ComponentScan:扫描启动类所在包以外的其他包
5.1. 逐步取代自动配置

自动配置是非侵入性的。 在任何时候,你都可以开始定义你自己的配置来取代自动配置的特定部分。 例如,如果你添加了你自己的 DataSource bean,默认的嵌入式数据库支持就会“退步”从而让你的自定义配置生效。

如果你想知道在应用中使用了哪些自动配置,你可以在启动命令后添加 --debug 参数。 这个参数会为核心的logger开启debug级别的日志,会在控制台输出自动装配项目以及触发自动装配的条件。

5.2. 禁用指定的自动装配类

如果你想禁用掉项目中某些自动装配类,你可以在 @SpringBootApplication 注解的 exclude 属性中指定,如下例所示。

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {

}

如果要禁用的自动装配类不在classpath上(没有导入),那么你可以在注解的 excludeName 属性中指定类的全路径名称。 excludeexcludeName 属性在 @EnableAutoConfiguration 中也可以使用。 最后,你也可以在配置文件中通过 spring.autoconfigure.exclude[] 配置来定义要禁用的自动配置类列表。

6. Spring Bean 和 依赖注入

你可以使用任何标准的Spring技术来定义你的Bean以及依赖注入关系。 推荐使用构造函数注入,并使用 @ComponentScan 注解来扫描Bean。

如果你按照上面的建议构造你的代码(将你的启动类定位在顶级包中),你可以在启动类添加 @ComponentScan 注解,也不需要定义它任何参数, 你的所有应用组件(@Component@Service@Repository@Controller 和其他)都会自动注册为Spring Bean。

也可以直接使用 @SpringBootApplication 注解(该注解已经包含了 @ComponentScan)。

下面的例子展示了一个 @Service Bean,它使用构造器注入的方式注入了 RiskAssessor Bean。

@Service
public class MyAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    public MyAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }

    // ...

}

如果一个Bean有多个构造函数,你需要用 @Autowired 注解来告诉Spring该用哪个构造函数进行注入。

@Service
public class MyAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    private final PrintStream out;

    @Autowired
    public MyAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
        this.out = System.out;
    }

    public MyAccountService(RiskAssessor riskAssessor, PrintStream out) {
        this.riskAssessor = riskAssessor;
        this.out = out;
    }

    // ...

}

上面示例中通过构造器注入的 riskAssessor 字段被标识为了 final,表示一旦Bean创建这个字段就不被改变了。这也是我们推荐的做法。

7.启动方式

7.1.直接在main方法中启动
7.2.打包启动

1)添加打包插件

<build>    
    <plugins>        
        <plugin>            
            <groupId>org.springframework.boot</groupId>            
            <artifactId>spring-boot-maven-plugin</artifactId>        
        </plugin>    
    </plugins>
</build>

2)执行打包命令

切换到当前项目pom.xml所在的目录,执行命令

mvn clean package

3)切换到target目录下执行命令启动项目

java -jar jar包文件的相对路径

8.热部署

热部署:修改代码后不需要重启服务,即可生效,提高开发效率

1)添加依赖

		<!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
            <scope>true</scope>
        </dependency>

2)打包插件下面添加一个配置

<build>
    <plugins>
        <!-- 打包插件 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <!--fork :  如果没有该项配置,可能devtools不会起作用,即应用不会restart -->
                <fork>true</fork>
            </configuration>
        </plugin>
    </plugins>
</build>

在这里插入图片描述

修改代码后点击图上这个按钮,或者按Ctrl+F9,即可reload

MyBatisPlus

1.简介

MyBatisPlus(简称MyBatis+)是一款基于MyBatis的增强工具,它是在MyBatis的基础上进行扩展和增强的。它提供了很多更加方便和便捷的功能,用于简化与数据库的交互,并提供更高层次的抽象和封装,使开发者能更快速、更简单地操作数据库。

2.特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

3.框架结构

在这里插入图片描述

4.核心功能

4.1.代码生成器
  1. 导入依赖

    <properties>
        <mybatis-plus-generator.version>3.4.1</mybatis-plus-generator.version>
        <velocity-engine-core.version>2.3</velocity-engine-core.version>
    </properties>
    
    <!--        逆向工程代码生成器-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>${mybatis-plus-generator.version}</version>
    </dependency>
    <!--        生成器默认模板引擎-->
    <dependency>
        <groupId>org.apache.velocity</groupId>
        <artifactId>velocity-engine-core</artifactId>
        <version>${velocity-engine-core.version}</version>
    </dependency>    
    
  2. 在启动引导类同包下创建代码生成器类CodeGenerator

    package cn.edu.cqie;
    
    import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
    import com.baomidou.mybatisplus.core.toolkit.StringPool;
    import com.baomidou.mybatisplus.generator.AutoGenerator;
    import com.baomidou.mybatisplus.generator.InjectionConfig;
    import com.baomidou.mybatisplus.generator.config.*;
    import com.baomidou.mybatisplus.generator.config.po.TableInfo;
    import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
    import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
    import org.apache.commons.lang3.StringUtils;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Scanner;
    
    public class CodeGenerator {
        /**
         * <p>
         * 读取控制台内容
         * </p>
         */
        public static String scanner(String tip) {
            Scanner scanner = new Scanner(System.in);
            StringBuilder help = new StringBuilder();
            help.append("请输入" + tip + ":");
            System.out.println(help.toString());
            if (scanner.hasNext()) {
                String ipt = scanner.next();
                if (StringUtils.isNotEmpty(ipt)) {
                    return ipt;
                }
            }
            throw new MybatisPlusException("请输入正确的" + tip + "!");
        }
    
        public static void main(String[] args) {
            // 代码生成器
            AutoGenerator mpg = new AutoGenerator();
            // 全局配置
            GlobalConfig gc = new GlobalConfig();
            String projectPath = System.getProperty("user.dir");
            gc.setOutputDir(projectPath + "/src/main/java");
            gc.setAuthor("<作者名>");
            gc.setOpen(false);
            // 设置名字
            gc.setControllerName("%sController");
            gc.setServiceName("%sService");
            gc.setServiceImplName("%sServiceImpl");
            gc.setMapperName("%sMapper");
            // 设置 resultMap
            gc.setBaseResultMap(true);
            gc.setBaseColumnList(true);
            mpg.setGlobalConfig(gc);
            // 数据源配置   需要修改
            DataSourceConfig dsc = new DataSourceConfig();
            dsc.setUrl("jdbc:mysql://localhost:3306/<数据库名>?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true");
            dsc.setDriverName("com.mysql.cj.jdbc.Driver");
            dsc.setUsername("<用户名>");
            dsc.setPassword("<密码>");
            mpg.setDataSource(dsc);
            // 自定义配置
            InjectionConfig cfg = new InjectionConfig() {
                @Override
                public void initMap() {
                    // to do nothing
                }
            };
            // 包配置
            PackageConfig pc = new PackageConfig();
            //  pc.setModuleName(scanner("模块名"));
            pc.setParent("com.example");
            mpg.setPackageInfo(pc);
            // 如果模板引擎是 velocity
            String templatePath = "/templates/mapper.xml.vm";
            // 自定义输出配置
            List<FileOutConfig> focList = new ArrayList<>();
            // 自定义配置会被优先输出
            focList.add(new FileOutConfig(templatePath) {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                    return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
                            + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
                }
            });
            cfg.setFileOutConfigList(focList);
            mpg.setCfg(cfg);
            // 配置模板
            TemplateConfig templateConfig = new TemplateConfig();
            templateConfig.setXml(null);
            mpg.setTemplate(templateConfig);
            // 策略配置
            StrategyConfig strategy = new StrategyConfig();
            strategy.setNaming(NamingStrategy.underline_to_camel);
            strategy.setColumnNaming(NamingStrategy.underline_to_camel);
            strategy.setEntityLombokModel(true);
            strategy.setRestControllerStyle(true);
            // 写于父类中的公共字段
            strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
            strategy.setControllerMappingHyphenStyle(true);
            strategy.setTablePrefix(pc.getModuleName() + "_");
            mpg.setStrategy(strategy);
            mpg.setTemplateEngine(new VelocityTemplateEngine());
            mpg.execute();
        }
    }
    
  3. 启动CodeGenerator类中的main方法,根据控制台提示输入要处理表格的名字。

  4. 成功生成后找到mapper包下的接口,在其加上@Mapper

4.2.CRUD接口

CRUD 接口 | MyBatis-Plus (baomidou.com)

4.3.条件构造器

条件构造器 | MyBatis-Plus (baomidou.com)

4.4.主键策略

提示

主键生成策略必须使用 INPUT

支持父类定义 @KeySequence 子类继承使用

内置支持:

  • DB2KeyGenerator
  • H2KeyGenerator
  • KingbaseKeyGenerator
  • OracleKeyGenerator
  • PostgreKeyGenerator

如果内置支持不满足你的需求,可实现 IKeyGenerator 接口来进行扩展.

举个例子

@KeySequence(value = "SEQ_ORACLE_STRING_KEY", clazz = String.class)
public class YourEntity {

    @TableId(value = "ID_STR", type = IdType.INPUT)
    private String idStr;

}

Spring-Boot

方式一:使用配置类

@Bean
public IKeyGenerator keyGenerator() {
    return new H2KeyGenerator();
}

方式二:通过 MybatisPlusPropertiesCustomizer 自定义

@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
    return plusProperties -> plusProperties.getGlobalConfig().getDbConfig().setKeyGenerator(new H2KeyGenerator());
}
4.5.自定义ID生成器
方法主键生成策略主键类型说明
nextIdASSIGN_IDLong,Integer,String支持自动转换为 String 类型,但数值类型不支持自动转换,需精准匹配,例如返回 Long,实体主键就不支持定义为 Integer
nextUUIDASSIGN_UUIDString默认不含中划线的 UUID 生成

Spring-Boot

方式一:声明为 Bean 供 Spring 扫描注入

@Component
public class CustomIdGenerator implements IdentifierGenerator {
    @Override
    public Long nextId(Object entity) {
      	//可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.
      	String bizKey = entity.getClass().getName();
        //根据bizKey调用分布式ID生成
        long id = ....;
      	//返回生成的id值即可.
        return id;
    }
}

方式二:使用配置类**

@Bean
public IdentifierGenerator idGenerator() {
    return new CustomIdGenerator();
}

方式三:通过 MybatisPlusPropertiesCustomizer 自定义

@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
    return plusProperties -> plusProperties.getGlobalConfig().setIdentifierGenerator(new CustomIdGenerator());
}

5.扩展

5.1.逻辑删除

说明:

只对自动注入的 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()

附录:

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

使用方法

步骤 1: 配置 com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig

  • 例: application.yml
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

步骤 2: 实体类字段上加上@TableLogic注解

@TableLogic
private Integer deleted;

整合

1.创建springboot项目

1)创建一个maven结构java项目

2)引入SpringBoot的依赖

在父级项目的pom.xml中写一个parent标签

	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>

3)创建子模块SpringBoot-01-Hello

		<!-- SpringBoot的web启动器:SpringMVC -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

4)编写启动类,写一个main方法+注解

package com.cqgcxy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

5)在子模块中编写一个Controller类

package com.cqgcxy.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/hello")
    public String hello(){
        System.out.println("哥哥姐姐们,起飞了.....");
        return "Hello SpringBoot";
    }
}

2.整合Swagger

1)简介:

作为后端开放人员,最烦的事就是自己写接口文档和别人没有写接口文档,不管是前端还是后端开发,多多少少都会被接口文档所折磨,前端会抱怨后端没有及时更新接口文档,而后端又会觉得编写接口文档太过麻烦。

Swagger 可以较好的解决接口文档的交互问题,以一套标准的规范定义接口以及相关的信息,就能做到生成各种格式的接口文档,生成多种语言和客户端和服务端的代码,以及在线接口调试页面等等。只需要更新 Swagger 描述文件,就能自动生成接口文档,做到前端、后端联调接口文档的及时性和便利性。

Swagger是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。

2)优势:

  • 支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了,对程序员来说非常方便,可以节约写文档的时间去学习新技术。
  • 提供 Web 页面在线测试 API:光有文档还不够,Swagger 生成的文档还支持在线测试。参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口。

3)SpringBoot整合Swagger

  1. pom.xml的properties便签中加入以下代码

    	<properties>
    	<properties>
            <swagger.version>3.0.0</swagger.version>
        </properties>
    
  2. 在pom.xml的dependencies标签中添加Swagger依赖

    		<dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-boot-starter</artifactId>
                <version>${swagger.version}</version>
            </dependency>
    
  3. 在cn.edu.cqie包下创建config包,在config包下添加Swagger配置类

    package com.cqgcxy.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.oas.annotations.EnableOpenApi;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.service.Contact;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    
    // 表明当前类是配置类
    @Configuration
    @EnableOpenApi
    public class SwaggerConfig {
        @Bean
        public Docket createRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    // 为api选择启动生成器
                    .select()
                    // 指定要生成api文档的根包
                    .apis(RequestHandlerSelectors.basePackage("com.cqgcxy.controller"))
                    // 路径配置
                    .paths(PathSelectors.any())
                    .build();
        }
        /**
         * 创建一个ApiInfo对象
         * @return
         */
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    // 文档标题
                    .title("学习测试接口")
                    // 简介
                    .description("案例")
                    // 作者信息:作者姓名、作者地址、作者邮箱
                    .contact(new Contact("雨渐渐风纤纤", "http://www.baidu.com", "1750697007@qq.com"))
                    // 版本号
                    .version("1.0")
                    .build();
        }
    }
    
  4. 启动项目,访问http://localhost:8080/swagger-ui/

    在这里插入图片描述

4)添加文档内容

在完成了上述配置后,其实已经可以生产文档内容,但是这样的文档主要针对请求本身,描述的主要来源是函数的命名,通常需要自己增加一些说明来丰富文档内容。

Swagger使用的注解及其说明:

@Api:用在类上,说明该类的作用。

@ApiOperation:注解来给API增加方法说明。

@ApiParam:定义在参数上

@ApiResponses:用于表示一组响应

@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
l code:数字,例如400
l message:信息,例如"请求参数没填好"
l response:抛出异常的类

@ApiModel:描述一个Model的信息

l @ApiModelProperty:描述一个model的属性

案例:

//实体类
package com.cqgcxy.vo;


import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(
        value = "AccountInfoVo",
        description = "人员账号信息"
)
public class AccountInfoVo {
    @ApiModelProperty(value = "登录账号")
    private String account;
    @ApiModelProperty(value = "人员名称")
    private String userName;
}
package com.cqgcxy.controller;

import com.cqgcxy.config.result.R;
import com.cqgcxy.entity.AccountInfo;
import com.cqgcxy.service.AccountInfoService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;


@RestController
@Api(value = "积分等级管理",tags = {"人员信息"})
public class AccountInfoController {

    @Autowired
    private AccountInfoService accountInfoService;

    @GetMapping("/getById/{account}")
    @ApiOperation("根据账号查询人员信息")
    @ApiResponses({@ApiResponse(
            code = 100200,
            message = "OK"
    ), @ApiResponse(
            code = 202001,
            message = "账号不存在"
    ), @ApiResponse(
            code = 202002,
            message = "密码解码失败"
    )})
    public R<AccountInfo> getById(@ApiParam(value = "要查询的账号",required = true,example = "1") @PathVariable String account){
        return accountInfoService.getById(account);
    }
}

5)ui更换

  1. 添加依赖

    		<dependency>
                <groupId>com.github.xiaoymin</groupId>
                <artifactId>swagger-bootstrap-ui</artifactId>
                <version>1.9.6</version>
            </dependency>
    
  2. 启动项目,访问http://localhost:8080/doc.html

    在这里插入图片描述

3.自定义响应类

  1. 在cn.edu.cqie包下创建util包,在该包创建结果返回相关的两个类

    • ResultCodeEnum

      package com.cqgcxy.conf.result;
      
      import java.util.ArrayList;
      import java.util.List;
      
      public enum ResultCodeEnum {
      
          SUCCESS(100200, "返回成功"),
          SYSTEM_EXCEPTION(100500, "系统异常"),
          REQUEST_PARAM_ERROR(100401, "请求参数错误"),
          REQUEST_OUT_OVERTIME(100408, "请求超时"),
          REQUEST_NOT_FOUND(100404, "请求的资源或服务未找到"),
          REQUEST_LENGTH_LIMIT(100414, "请求URI太长"),
          REQUEST_Format_NOT_SUPPORTED(100415, "请求的格式不支持"),
          TOKEN_EXPIRED_REDIRECT(100302, "token过期,请重新登录"),
          DUPLICATE_KEY_EXCEPTION(100416, "数据已存在,请勿重复操作"),
      
          INTERFACE_BASIC_INFORMATION_NULL(100001, "接口基本信息为空"),
          INTERFACE_NAME_NULL(100002, "接口名称为空"),
          INTERFACE_SOURCE_NULL(100005, "接口来源为空"),
          INTERFACE_PROTOCOL_NULL(100003, "接口协议为空"),
          INTERFACE_NOT_ENABLED(100123, "接口未启用"),
          INTERFACE_IP_PORT_NULL(100012, "ip和端口为空"),
          INTERFACE_PATH_NULL(100004, "接口路径为空"),
          INTERFACE_REQUEST_METHOD_NULL(100008, "接口请求方式"),
          REQUEST_TIMEOUT(100014, "超时时限为空"),
          REQUEST_PARAM_NULL(100012, "请求参数为空"),
          INTERFACE_BASE_NOT_FOUND(100013, "未找到该条接口基本信息"),
          INTERFACE_SETTING_NOT_FOUND(100015, "未找到该条接口配置信息"),
          INTERFACE_BASE_EXIST(100026, "接口基本信息已存在"),
          INTERFACE_BASE_NOT_EXIST(100025, "接口基本信息不存在"),
          INTERFACE_SETTING_EXIST(100027, "接口配置信息已存在"),
          INTERFACE_SETTING_NOT_EXIST(100028, "接口配置信息不存在"),
          INTERFACE_PATH_ILLEGAL(100009, "接口路径不符合规范"),
          REQUIRED_FIELD_IS_BLANK(100007, "入参必填字段为空: "),
          REQUEST_OUT_API_FAIL(100018, "请求外部接口失败,返回状态码:"),
          REQUEST_OUT_GET_OVERTIME(100019, "GET请求外部接口失败,请求超时"),
          REQUEST_OUT_POST_OVERTIME(100020, "POST请求外部接口失败,请求超时"),
          REQUEST_OUT_PUT_OVERTIME(100021, "PUT请求外部接口失败,请求超时"),
          REQUEST_OUT_DELETE_OVERTIME(100022, "DELETE请求外部接口失败,请求超时"),
          OTHER_METHODS_NOT_SUPPORTED(100023, "现阶段不支持其他请求方式"),
          PARAM_BODY_CONTENT_ERROR(100024, "请求body不是json格式"),
          SPLICING_PARAM_IS_FAIL(100031, "拼接GET请求入参出错,请检查参数"),
      
          //登录登出模块
          PASSWORD_FAIL(210001, "登录账户或密码错误,请重新输入!"),
          INSUFFICIENT_PERMISSIONS(210002, "用户权限不足"),
          ACCOUNT_NOT_FIND_RESOURCE(210003, "用户未查询到资源"),
          APP_WAS_NOT_QUERIED(210004, "应用id不存在"),
          SIGNATURE_VERIFICATION_FAILED(210005, "验签未通过"),
          RANDOM_CODE_EXPIRED(210006, "随机码已过期"),
          INCORRECT_RANDOM_CODE_VALUE(210007, "随机码值不正确"),
          TOKEN_GENERATION_FAILED(210008, "token 生成失败"),
          NO_TOKEN_PASSED_IN(210009, "未传入 token"),
          NO_USER_FOUND_TOKEN(210009, "token 未查询到用户"),
          TOKEN_VERIFICATION_FAILED(210009, "token 校验失败"),
          ILLEGAL_TOKEN_INFORMATION(210010, "token 信息不匹配"),
          USER_DOES_NOT_EXIST(210011, "用户不存在"),
          SIGN_EXPIRED(210012, "sign 已过期"),
          PASSWORD_VIOLATION(210013, "密码需包含六位及以上字母和数字"),
      
          //需要跳转登录的code
          NO_REFRESH_PASSED_IN(210019, "未传入 token"),
          NO_REFRESH_USER_FOUND_TOKEN(210019, "token 未查询到用户"),
          REFRESH_VERIFICATION_FAILED(210019, "token 校验失败"),
          JSON_CONVERSION_ERROR(210019, "json转换出错"),
          REFRESH_GENERATION_FAILED(210019, "token 生成失败"),
      
          NO_LOGIN_STRATEGY(210020, "%s该认证策略不存在"),
      
          NOT_HAVE_ACCOUNT(202003, "账户不存在"),
          ;
      
          /**
           * 枚举值
           */
          private final Integer code;
      
          /**
           * 枚举描述
           */
          private final String message;
      
          /**
           * 构造一个<code>LocalCacheEnum</code>枚举对象
           *
           * @param code    枚举值
           * @param message 枚举描述
           */
          ResultCodeEnum(Integer code, String message) {
              this.code = code;
              this.message = message;
          }
      
          /**
           * 获取全部枚举
           *
           * @return List<LocalCacheEnum>
           */
          public static List<ResultCodeEnum> getAllEnum() {
              List<ResultCodeEnum> list = new ArrayList<>();
              for (ResultCodeEnum each : values()) {
                  list.add(each);
              }
              return list;
          }
      
          /**
           * 获取全部枚举值
           *
           * @return List<String>
           */
          public static List<Integer> getAllEnumCode() {
              List<Integer> list = new ArrayList<>();
              for (ResultCodeEnum each : values()) {
                  list.add(each.code);
              }
              return list;
          }
      
          public Integer getCode() {
              return code;
          }
      
          public String getMessage() {
              return message;
          }
      
          public <T> R<T> result() {
              return new R(getCode(), getMessage());
          }
      
          public <T> R<T> result(String message) {
              return new R(getCode(), message);
          }
      
          /**
           * 将返回码标准的信息 填充到message里面,message必须包含一个%s
           */
          public <T> R<T> resultFillingMessage(String message) {
              return new R(getCode(), String.format(message, getMessage()));
          }
      
          /**
           * 将message添加到返回码标准的信息后面 再返回{@link R}
           */
          public <T> R<T> resultAppendMessage(String message) {
              return new R(getCode(), getMessage() + message);
          }
      }
      
    • R

      package com.cqgcxy.conf.result;
      
      public final class R<T> {
          private int code;
          private String msg;
          private T data;
      
          public R() {
      
          }
      
          public R(int code) {
              this.code = code;
              this.msg = "";
              this.data = null;
          }
      
          public R(int code, String msg) {
              this.code = code;
              this.msg = msg;
              this.data = null;
          }
      
          public R(int code, String msg, T data) {
              this.code = code;
              this.msg = msg;
              this.data = data;
          }
      
          public static  R Success(Object data) {
              return new  R( ResultCodeEnum.SUCCESS.getCode(),  ResultCodeEnum.SUCCESS.getMessage(), data);
          }
      
          public static  R Success(String message, Object data) {
              return new  R( ResultCodeEnum.SUCCESS.getCode(), message, data);
          }
      
          public static  R Success() {
              return Success("");
          }
      
          public static  R Failed(String msg) {
              return new  R( ResultCodeEnum.SYSTEM_EXCEPTION.getCode(), msg);
          }
      
          public static R Failed() {
              return Failed("Failed");
          }
      
          public static R Failed(int code, String msg) {
              return new  R(code, msg);
          }
      
          public int getCode() {
              return code;
          }
      
          public void setCode(int code) {
              this.code = code;
          }
      
          public String getMsg() {
              return msg;
          }
      
          public void setMsg(String msg) {
              this.msg = msg;
          }
      
          public T getData() {
              return data;
          }
      
          public void setData(T data) {
              this.data = data;
          }
      
          public boolean succeeded() {
              return getCode() == ResultCodeEnum.SUCCESS.getCode();
          }
      
      
          public boolean failed() {
              return getCode() != ResultCodeEnum.SUCCESS.getCode();
          }
      
      }
      
  2. 在controller包下创建类AccountInfoController

    @RestController
    @RequestMapping("/accountInfo")
    public class AccountInfoController {
    
        @Autowired
        private AccountInfoService accountInfoService;
    
        @GetMapping("/getAll")
        public R<List<AccountInfo>> getAll(){
            return accountInfoService.selectAll();
        }
    }
    

4.整合Mybatis-plus(使用代码生成器)

  1. 创建maven项目

  2. 导入SpringBoot起步依赖和项目所需依赖(在pom.xml文件中添加以下内容)

    	<properties>
            <mybatis-plus.version>3.4.2</mybatis-plus.version>
        </properties>
    
    <!--        mybatis-plus-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>
    
  3. 配置application.yml

    #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
    mybatis-plus:
      configuration:
        map-underscore-to-camel-case: true
        #日志
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
  4. 修改entity实体类

    package com.cqgcxy.entity;
    
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableId;
    import lombok.Data;
    
    @Data
    public class AccountInfo {
        @TableId(value = "account", type = IdType.ASSIGN_ID)
        private String account;
        private String userName;
        private String password;
    }
    
  5. 删除*Mapper.xml,并修改Mapper接口

    @Mapper
    public interface AccountInfoMapper extends BaseMapper<AccountInfo> {
    }
    
  6. 修改Service接口和实现类

    Service接口:

    package com.cqgcxy.service;
    
    import com.baomidou.mybatisplus.extension.service.IService;
    import com.cqgcxy.entity.AccountInfo;
    
    public interface AccountInfoService extends IService<AccountInfo> {
    }
    

    Service实现类:

    package com.cqgcxy.service.impl;
    
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.cqgcxy.entity.AccountInfo;
    import com.cqgcxy.mapper.AccountInfoMapper;
    import com.cqgcxy.service.AccountInfoService;
    import org.springframework.stereotype.Service;
    
    
    @Service
    public class AccountInfoServiceImpl extends ServiceImpl<AccountInfoMapper, AccountInfo> implements AccountInfoService {
    }
    
  7. 修改Contrller代码

    package com.cqgcxy.controller;
    
    import com.cqgcxy.config.result.R;
    import com.cqgcxy.entity.AccountInfo;
    import com.cqgcxy.service.AccountInfoService;
    import io.swagger.annotations.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    
    @RestController
    @Api(value = "积分等级管理",tags = {"人员信息"})
    public class AccountInfoController {
    
        @Autowired
        private AccountInfoService accountInfoService;
    
        @GetMapping("/getById/{account}")
        @ApiOperation("根据账号查询人员信息")
        @ApiResponses({@ApiResponse(
                code = 100200,
                message = "OK"
        ), @ApiResponse(
                code = 202001,
                message = "账号不存在"
        ), @ApiResponse(
                code = 202002,
                message = "密码解码失败"
        )})
        public R<AccountInfo> getById(@ApiParam(value = "要查询的账号",required = true,example = "1") @PathVariable String account){
            return R.Success(accountInfoService.getById(account));
        }
    }
    
  8. 启动项目,访问http://localhost:8080/doc.html

xy.entity.AccountInfo;
import com.cqgcxy.service.AccountInfoService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api(value = “积分等级管理”,tags = {“人员信息”})
public class AccountInfoController {

   @Autowired
   private AccountInfoService accountInfoService;

   @GetMapping("/getById/{account}")
   @ApiOperation("根据账号查询人员信息")
   @ApiResponses({@ApiResponse(
           code = 100200,
           message = "OK"
   ), @ApiResponse(
           code = 202001,
           message = "账号不存在"
   ), @ApiResponse(
           code = 202002,
           message = "密码解码失败"
   )})
   public R<AccountInfo> getById(@ApiParam(value = "要查询的账号",required = true,example = "1") @PathVariable String account){
       return R.Success(accountInfoService.getById(account));
   }

}


8. **启动项目,访问http://localhost:8080/doc.html**









评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值