springboot
简介
-
可以创建独立的Spring应用程序
-
嵌入了tomcat、jetty等应用服务器程序,可以不需要发布部署即可直接启动项目
-
提供了很多准备好的启动器,简化项目配置
-
自动配置Spring以及第三方依赖
-
绝对无代码生成,也完全不需要任何xml配置
创建SpringBoot项目
步骤
1.创建maven项目
2.pom加入依赖
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>springBoot</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springBoot</name> <description>springBoot</description> <properties> <java.version>8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
3.创建启动引导类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootApplication{
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
4.创建控制器
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("Hello,SpringBoot.....");
return "Hello SpringBoot";
}
}
5.启动项目
依赖管理
dependencyManagement标签的作用:依赖管理
1.它只负责对jar版本进行管理,不负责导入依赖的jar包,在我们项目中添加依赖的时候就不需要再写版本号了,但是如果自己又写了版本号,就会覆盖它默认的版本号!
2.SpringBoot里面提供了很多个starter(启动器),其本质就是一个项目包,在这个项目包中依赖了其他包,而我们项目中只需要依赖这个starter包,maven就会自动去依赖这个starter包所有依赖的其他包了(变成简介依赖)
3.starter-web:就是对SpringMVC所需的所有jar包进行了封装,导入starter-web包,就相当于导入了SpringMVC所需的所有jar包。
项目包结构
由于SpringBoot项目中没有xml配置文件,而我们写的那些类添加了@Controller、@Service、@Repository、@Component注解,需要Spring的扫描包才能创建对象,保存到Spring容器中;SpringBoot内部会自动递归扫描启动类(添加了@SpringBootApplication注解的类)所在的包,所以启动类必须放在包级别较高的包内。
main方法启动项目
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
main方法里面一行代码,底层做了以下事情:
-
将项目打包成一个jar包
-
发布部署到内嵌的tomcat的webapps目录下
-
修改server.xml配置
-
-
使用java -jar 命令启动tomcat
自动配置原理
核心在启动类上面添加的@SpringBootApplication注解
@SpringBootApplication注解是Spring Boot的核心注解,它其实是一个组合注解
虽然定义使用了多个Annotation进行了原信息标注,但实际上重要的只有三个Annotation:
-
@SpringBootConfiguration
-
@Configuration:表示当前启动类可以作为一个配置类,里面可以写@Bean来配置bean(等同于xml中的一个bean标签)
-
-
@EnableAutoConfiguration
-
@AutoConfigurationPackage
-
@Import(AutoConfigurationPackages.Registrar.class):自动递归扫描启动类所在的包
-
-
@Import(AutoConfigurationImportSelector.class):手动配置除自动扫描的bean以外的其他bean
-
-
@ComponentScan:扫描启动类所在包以外的其他包
即 @SpringBootApplication = (默认属性)@Configuration + @EnableAutoConfiguration + @ComponentScan。
所以,如果我们使用如下的SpringBoot启动类,整个SpringBoot应用依然可以与之前的启动类功能对等
深入探索SpringApplication执行流程
SpringApplication的run方法的实现是我们本次旅程的主要线路,该方法的主要流程大体可以归纳如下:
1) 如果我们使用的是SpringApplication的静态run方法,那么,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提前做几件事情:
- 根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
- 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
- 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
- 推断并设置main方法的定义类。
2) SpringApplication实例初始化完成并且完成设置后,就开始执行run方法的逻辑了,方法执行伊始,首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener。调用它们的started()方法,告诉这些SpringApplicationRunListener,“嘿,SpringBoot应用要开始执行咯!”。
3) 创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4) 遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,告诉他们:“当前SpringBoot应用使用的Environment准备好了咯!”。
5) 如果SpringApplication的showBanner属性被设置为true,则打印banner。
6) 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。
7) ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
8) 遍历调用所有SpringApplicationRunListener的contextPrepared()方法。
9) 最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
10) 遍历调用所有SpringApplicationRunListener的contextLoaded()方法。
11) 调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
12) 查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
13) 正常情况下,遍历执行SpringApplicationRunListener的finished()方法、(如果整个过程出现异常,则依然调用所有SpringApplicationRunListener的finished()方法,只不过这种情况下会将异常信息一并传入处理)
启动注解类
每个SpringBoot程序都有一个主入口,也就是main方法,main里面调用SpringApplication.run()启动整个spring-boot程序,该方法所在类需要使用@SpringBootApplication注解,以及@ImportResource注解(if need),@SpringBootApplication包括三个注解,功能如下:
@EnableAutoConfiguration:SpringBoot根据应用所声明的依赖来对Spring框架进行自动配置。
@SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的XML配置文件中(applicationContext.xml),装配所有bean事务,提供了一个spring的上下文环境。
@ComponentScan:组件扫描,可自动发现和装配Bean,默认扫描SpringApplication的run方法里的Booter.class所在的包路径下文件,所以最好将该启动类放到根包路径下。
启动方式
1.直接在main方法中启动
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包文件的相对路径
热部署
作用:修改代码后不需要重启服务,即可生效,提高开发效率
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>
(3)修改代码后点击图上这个按钮,或者按Ctrl+F9,即可reload
配置文件
yaml
yaml:基本语法
大小写敏感
数据值前边必须有空格,作为分隔符
使用缩进表示层级关系
缩进时不允许使用Tab键,只允许使用空格(各个系统Tab对应的空格数目可能不同,导致层次混乱)。
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
#表示注释,从这个字符一直到行尾,都会被解析器忽略。
yaml:参数引用
配置文件:总结
(1)配置文件类型
- properties:使用语法和往常一样
- yaml/yml:注空格
(2)yaml:简洁,以数据为核心
- 基本语法
- 大小写敏感
- 数据值前面必须有空格,作为分隔符
- 使用空格缩进表示层级关系,相同缩进表示同一级
- 数据格式
- 对象
- 数组:使用“-”表示数组每个元素
- 纯量
- 参数引用
- ${key}
读取配置内容
- @value
- Enviroment
- @ConfigurationProperties
profile文件
我们在开发Spring Boot/应用时,通常同一套程序会被安装到不同环境,比如:开发、测试、生产等。其中数据库地址、服务器端口等等配置都不同,如果每次打包时,都要修改配置文件,那么非常麻烦。profile功能就是来进行动态配置切换的。
(1)profile配置方式
多profile文件方式
yml多文档方式
(2)profile激活方式
配置文件
虚拟机参数
命令行参数
SpringBoot整合Junit和Mybatis
1.SpringBoot测试
(1) 添加测试启动器依赖
<!-- SpringBoot的测试启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
(2) 编写单元测试类
@SpringBootTest
public class HelloControllerTest {
@Autowired
private HelloController helloController;
@Test
public void hello() {
String hello = helloController.hello();
System.out.println(hello);
}
}
2.集成Mybatis
(1)添加starter-mybatis启动器的依赖、
<!-- SpringBoot的测试启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- mysql 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--
SpringBoot的mybatis启动器
这个启动器是Mybatis官方开发的,不在SpringBoot的dependenciesManagement管理范围之内
所以这里必须写版本号
-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
(2)配置数据库连接信息、mybatis别名和映射文件路径
#数据库连接信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///user1?characterEncoding=utf-8
username: root
password: 123456
mvc:
path match:
matching-strategy: ant_path_matcher #解决SpringBoot和Swagger2版本冲突
# 别名 mapper映射
mybatis:
type-aliases-package: com.example.springboot.entity
mapper-locations: classpath*:/mapper/*Mapper.xml
config-location: classpath:mybatis-config.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志
map-underscore-to-camel-case: true #驼峰转换
# 日志信息
# OFF:这是最高的日志级别,用于关闭所有日志记录。
# FATAL:这个级别指出每个严重的错误事件将会导致应用程序的退出。
# ERROR:这个级别指出虽然发生错误事件,但仍然不影响系统的继续运行。
# WARN:这个级别表明会出现潜在错误的情形。
# INFO:这个级别表明消息在粗粒度级别上突出强调应用程序的运行过程。
# DEBUG:这个级别指出细粒度信息事件对调试应用程序是非常有帮助的,就是输出debug的信息。
# TRACE:这个级别指示比DEBUG更细粒度的信息事件。
logging:
level:
org.example: trace
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--开启驼峰 下划线转驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
(3)mapper层接口和xml
(4)启动类+@MapperScan注解
(5)单元测试
3.Thymeleaf模板
简介
在SpringBoot项目中,没有webapp目录,更没有WEB-INF目录,无法存放jsp页面或者其他静态资源,但是我们要使用SpringBoot来实现webapp项目,静态资源是必须的,那就只能放在resources目录下了,所有页面都只能使用html页面了!
- 【异步:推荐】可以在html中使用JS的Fetch API异步请求
- 【同步】可以使用SpringBoot的Thymeleaf模板技术
- 模板技术:JSP、Velocity、Freemarker、Thymeleaf
SpringBoot集成MybatisPlus合Swagger
整合Swagger
简介
无论是前端还是后端开发,都或多或少地被接口文档折磨过,都期望有一个好的接口文档。但是这个接口文档对于程序员来说,就跟注释一样,经常会抱怨别人写的代码没有写注释,然而自己写起代码来,也不喜欢写注释。
所以随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了,这时候Swagger就出现了。
基本介绍
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。
作用
Swagger是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
优势
1.支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了,对程序员来说非常方便。
2.提供 Web 页面在线测试 API:Swagger 生成的文档支持在线测试。参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口。
Swagger开源工具
Swagger Codegen
通过Codegen 可以将描述文件生成html格式和cwiki形式的接口文档,同时也能生成多种语言的服务端和客户端的代码。支持通过jar包,docker,node等方式在本地化执行生成。也可以在后面的Swagger Editor中在线生成。
Swagger UI
提供了一个可视化的UI页面展示描述文件。接口的调用方、测试、项目经理等都可以在该页面中对相关接口进行查阅和做一些简单的接口请求。该项目支持在线导入描述文件和本地部署UI项目。
Swagger Editor
类似于markendown编辑器的编辑Swagger描述文件的编辑器,该编辑支持实时预览描述文件的更新效果。也提供了在线编辑器和本地部署编辑器两种方式。
Swagger Inspector
它是一个可以对接口进行测试的在线版postman。比在Swagger UI里面做接口请求,会返回更多的信息,也会保存你请求的实际请求参数等数据。
Swagger Hub
集成了上面所有项目的各个功能,开发者可以以项目和版本为单位,将其描述文件上传到Swagger Hub中。
SpringBoot集成MybatisPlus和Swagger
SpringBoot整合Swagger
1.pom.xml的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.在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("cmf", "https://blog.csdn.net/2201_75716464?spm=1000.2115.3001.5343", "1979473816@qq.com"))
// 版本号
.version("1.0")
.build();
}
}
4.启动项目,访问http://localhost:8080/swagger-ui/
添加文档内容
Swagger使用的注解及其说明:
@Api:用在类上,说明该类的作用。
@ApiOperation:注解来给API增加方法说明。
@ApiParam:定义在参数上
@ApiResponses:用于表示一组响应
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息 l code:数字,例如400 l message:信息,例如"请求参数没填好" l response:抛出异常的类
@ApiModel:描述一个Model的信息l @ApiModelProperty:描述一个model的属性
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
自定义响应类
1.创建结果返回相关的两个类
- ResultCodeEnum
package com.cqgcxy.config;
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.config;
/**
* @author: 陈孟芳
* @data: 2023/12/6 8:56
*/
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
Mybatisplus
1.导入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>
2.配置application.yml
#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射mybatis-plus: configuration: map-underscore-to-camel-case: true #日志 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3. 修改entity实体类
4.删除*Mapper.xml,并修改Mapper接口
5.修改Service接口和实现类
Service接口
Service实现类
6.修改Contrller代码
package com.cqgcxy.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cqgcxy.config.R;
import com.cqgcxy.dto.AccountInfoDTO;
import com.cqgcxy.entity.AccountInfo;
import com.cqgcxy.service.AccountInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 账户信息 前端控制器
* </p>
*
* @author cmf
* @since 2023-12-07
*/
@RestController
@RequestMapping("/account-info")
@Api(value = "AccountInfoController",tags = {"人员信息管理控制器"})
public class AccountInfoController {
@Autowired
private AccountInfoService accountInfoService;
@GetMapping("/getAccountInfoByAccount/{account}")
@ApiOperation("根据账号进行查询")
public R<AccountInfo> getAccountInfoByAccount(@PathVariable("account") String account){
return R.Success(accountInfoService.getById(account));
}
}
7.启动项目,访问http://localhost:8080/doc.html
MybatisPlus标准CRUD和分页
Mybatis-plus代码生成器
(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 com.cqgcxy;
/**
* @author: 陈孟芳
* @data: 2023/12/7 8:57
*/
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("cmf");
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/user1?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
mpg.setDataSource(dsc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 包配置
PackageConfig pc = new PackageConfig();
// pc.setModuleName(scanner("模块名"));
pc.setParent("com.cqgcxy");
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注解
(5)MybatisPlus插件推荐
Mybatis-plus标准CRUD
package com.cqgcxy.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cqgcxy.config.R;
import com.cqgcxy.dto.AccountInfoDTO;
import com.cqgcxy.entity.AccountInfo;
import com.cqgcxy.service.AccountInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 账户信息 前端控制器
* </p>
*
* @author cmf
* @since 2023-12-07
*/
@RestController
@RequestMapping("/account-info")
@Api(value = "AccountInfoController",tags = {"人员信息管理控制器"})
public class AccountInfoController {
@Autowired
private AccountInfoService accountInfoService;
@PostMapping("/addAccountInfo")
@ApiOperation("新增人员信息")
public R<Void> addAccountInfo(@RequestBody AccountInfo accountInfo){
boolean b = accountInfoService.save(accountInfo);
if (b) {
return R.Success();
}else {
return R.Failed();
}
@DeleteMapping("/removeAccountInfoByAccount/{account}")
@ApiOperation("根据账号进行删除")
public R<Void> removeAccountInfoByAccount(@PathVariable("account") String account){
System.out.println(account);
boolean b = accountInfoService.removeById(account);
if (b){
return R.Success();
}else {
return R.Failed();
}
}
@PutMapping("/editAccountInfo")
@ApiOperation("根据账号名称修改账号信息")
public R<Void> editAccountInfo(@RequestBody AccountInfo accountInfo){
boolean b = accountInfoService.updateById(accountInfo);
if (b){
return R.Success();
}else {
return R.Failed();
}
}
}
Mybatis-plus分页
(1)config包下配置mybatis-plus分页插件类
package com.cqgcxy.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: 陈孟芳
* @data: 2023/12/7 10:26
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
(2)Controller中分页实现
package com.cqgcxy.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cqgcxy.config.R;
import com.cqgcxy.dto.AccountInfoDTO;
import com.cqgcxy.entity.AccountInfo;
import com.cqgcxy.service.AccountInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 账户信息 前端控制器
* </p>
*
* @author cmf
* @since 2023-12-07
*/
@RestController
@RequestMapping("/account-info")
@Api(value = "AccountInfoController",tags = {"人员信息管理控制器"})
public class AccountInfoController {
@Autowired
private AccountInfoService accountInfoService;
@ApiOperation(value = "分页查询")
//get请求路径
@GetMapping("/{pageNumber}/{pageSize}")
public R getPage(@PathVariable Long pageNumber,
@PathVariable Long pageSize){
//构造器
Page<AccountInfo> p = new Page<>(pageNumber,pageSize);
Page<AccountInfo> page = accountInfoService.page(p);
return R.Success(page);
}
}