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
- @AutoConfigurationPackage
- @ComponentScan:扫描启动类所在包以外的其他包
5.1. 逐步取代自动配置
自动配置是非侵入性的。 在任何时候,你都可以开始定义你自己的配置来取代自动配置的特定部分。 例如,如果你添加了你自己的 DataSource
bean,默认的嵌入式数据库支持就会“退步”从而让你的自定义配置生效。
如果你想知道在应用中使用了哪些自动配置,你可以在启动命令后添加 --debug
参数。 这个参数会为核心的logger开启debug级别的日志,会在控制台输出自动装配项目以及触发自动装配的条件。
5.2. 禁用指定的自动装配类
如果你想禁用掉项目中某些自动装配类,你可以在 @SpringBootApplication
注解的 exclude
属性中指定,如下例所示。
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {
}
如果要禁用的自动装配类不在classpath上(没有导入),那么你可以在注解的 excludeName
属性中指定类的全路径名称。 exclude
和 excludeName
属性在 @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.代码生成器
-
导入依赖
<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>
-
在启动引导类同包下创建代码生成器类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(); } }
-
启动CodeGenerator类中的main方法,根据控制台提示输入要处理表格的名字。
-
成功生成后找到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生成器
方法 | 主键生成策略 | 主键类型 | 说明 |
---|---|---|---|
nextId | ASSIGN_ID | Long,Integer,String | 支持自动转换为 String 类型,但数值类型不支持自动转换,需精准匹配,例如返回 Long,实体主键就不支持定义为 Integer |
nextUUID | ASSIGN_UUID | String | 默认不含中划线的 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
-
pom.xml的properties便签中加入以下代码
<properties> <properties> <swagger.version>3.0.0</swagger.version> </properties>
-
在pom.xml的dependencies标签中添加Swagger依赖
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>${swagger.version}</version> </dependency>
-
在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(); } }
-
启动项目,访问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更换
-
添加依赖
<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency>
-
启动项目,访问http://localhost:8080/doc.html
3.自定义响应类
-
在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(); } }
-
-
在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(使用代码生成器)
-
创建maven项目
-
导入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>
-
配置application.yml
#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射 mybatis-plus: configuration: map-underscore-to-camel-case: true #日志 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
-
修改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; }
-
删除*Mapper.xml,并修改Mapper接口
@Mapper public interface AccountInfoMapper extends BaseMapper<AccountInfo> { }
-
修改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 { }
-
修改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)); } }
-
启动项目,访问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**