SpringBoot05-配置文件-热加载/日志框架slf4j/接口文档工具Swagger/Knife4j

七、配置文件【重点】


7.1 SpringBoot 的配置文件格式

springboot 是 约定大于配置, 几乎是不需要配置文件就可以帮助完成配置,

但是有些默认不好用的时候,也可以通过配置文件改变配置

比如:端口,访问路径,文件上传大小,jdbc 连接信息
SpringBoot 的配置文件

  • 文件名必须是 application
  • 位置,resources
  • 格式支持 properties 和 yml

特殊的,有时也会见到名为 bootstrap.yml 文件


  • 更推荐使用 yml 文件格式:
  1. yml 文件,会根据换行和缩进帮助咱们管理配置文件所在位置
  2. yml 文件,相比 properties 更轻量级一些
  3. K: V 表示一对键值对 (冒号:后一定有一个空格)
  4. 严格以空格的缩进来控制层级关系; 只要是左对齐的都是属于一个层级的数据
  5. 属性和值大小写敏感.

yml 文件的劣势:

  1. 严格遵循换行和缩进
  2. 在填写 value 时,一定要在:后面跟上空格

配置文件的作用

  • 修改 SpringBoot 的配置的默认值:
  • 比如默认启动的 Tomcat 的端口是 8080, 可以修改为 8081
properties yml
服务器配置示例:server.port=8081 服务器配置示例:server:port: 8081

配置文件的位置:

  • 一般默认都是放在 resources / 下
  • 也有其他位置的,暂且不讨论

7.2 多环境配置 / 切换 [了解]

实际开发中,有三种环境:develop test production

  1. 开发环境 dev- 程序员日常开发所需 (本地)
  2. 测试环境 test- 项目的集成测试
  3. 生产环境 prod- 最终项目部署的环境,真实环境

SpringBoot 支持多环境的配置。只需要根据环境需要,编写多个配置文件,通过配置属性选择使用哪个环境使用步骤:

  1. 多环境的配置文件命名:application- 环境名.yml

  2. 在总文件 application.yml 中通过属性:spring.profiles.active: 环境名

Spring 框架中「启用的环境配置集」

单词 基础含义 Spring 语境下的专业含义
spring 春天;弹簧 特指 Spring 框架(无额外翻译)
profiles 个人资料(复数) 「环境配置集」(多套配置文件的抽象)
active 活跃的、启用的、生效的 启用的、当前生效的

7.3 获取配置文件数据 [常用]

场景:

  1. 加密盐值
  2. 秘钥
  3. token 令牌信息
  4. 项目自定义信息等等

解释:将 yml 配置的值,赋值给对应的类

yaml

复制代码
# yml中的示例
aliyun:
  accessKey: ATYSBD23B1N44
  accessSecret: 123456

java

java 复制代码
// 哪里需要获得yml中的数据,哪里只需要加@Value注解取值即可
@RestController
public class UserController {

    // 注意${} , 其中写的是yml中key
    @Value("${aliyun.accessKey}")
    private String accessKey;

    @GetMapping("/user")
    public R findUserById(){
        System.out.println(accessKey );
        return R.ok();
    }

这样写,其实就是将这些数据抽取到 yml 中定义,而不是直接写在代码中,目的就是为了后期方便维护

7.4 热加载

热加载 / 热部署:实现不停机更新代码导入依赖 xml

XML 复制代码
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
</dependency>

新版 idea (2022 版以后) 在设置里找]

File->Settings->Advanced Settings 中找到 Compiler 并勾选 Allow auto-make to start even if developed application is currently running

测试,以 Debug 方式启动项目 , 改动代码按ctrl+F9 , 就会自动重启项目刷新

八、SpringBoot 整合日志框架 [重要]

8.0 日志

作用:

  1. 方便调试
  2. 记录运行信息
  3. 记录异常信息

现在如何实现记录日志的呢

  • sout 这个输出语句

弊端

  • 无论什么情况,只要到此处输出语句一定执行,不能有选择的可控输出
  • 只能输出到控制台
  • 信息不完整
  • 输出语句要删掉

8.1 常见的日志框架

  • slf4j ( Simple Logging Facade for Java)

SLF4J 本身不实现日志功能,只定义一套统一的日志接口(门面)

slf4j 只是一个日志标准,并不是日志系统的具体实现。它用于提供日志操作的接口,提供获取日志对象的方法

  • **log4j **apache 实现的一个开源日志组件
  • **logback ** 相对于 logback,有更好的特性,springboot 默认使用 logback
  • log4j2 是 log4j 的升级版本,拥有更好的性能,支持异步日志
  • commons-logging
    注意:

slf4j 属于日志接口,log4j、logback、log4j2 属于日志实现

4 是 for 的谐音 / 简写

(Java 生态的通用惯例:用数字 4 替代单词 for,比如 Log4j = Log for Java

  • Log4j :Log for Java,是具体的日志实现(真正负责日志打印、输出到文件 / 控制台);
  • SLF4J :Simple Logging Facade for Java,是日志门面(接口),本身不打印日志,只对接 Log4j/Logback 等实现。

8.2 日志的等级

日志级别按照从低到高为:ALL < TRACE < DEBUG< INFO < WARN < ERROR <FATAL < OFF程序会打印高于或等于所设置级别的日志,设置的 日志等级越高,打印出来的日志就越少


All:最低等级,会输出所有日志记录

Trace:追踪,就是程序推进一下

Debug:调试日志

Info:消息日志,可用于输出应用程序的运行过程

Warn:输出警告级别的日志

Error:输出错误信息日志

Fatal:输出每个严重的错误日志.(致命的 /重大的)

OFF:最高等级的,用于关闭所有日志记录

8.3 整合 Log4j2

8.3.0 依赖

Spring Boot 默认使用 LogBack,但是我们没有看到显示依赖的 jar 包,其实是因为所在的 jar 包 spring-boot-starter-logging 都是作为 spring-boot-starter-web 或者 spring-boot-starter 依赖的一部分。

如果这里要使用 Log4j2,需要从 spring-boot-starter-web 中排除 spring-boot-starter-logging 依赖,同时显示声明使用 Log4j2 的依赖 jar 包,具体如下:

pom.xml

XML 复制代码
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <!-- 去掉springboot默认配置 -->
  <exclusions>
    <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
    </exclusion>
  </exclusions>
</dependency>

再单独引入 log4j2 的依赖 xml

XML 复制代码
<!-- 引入log4j2依赖 -->
<dependency> 
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

8.3.1 编写配置文件

在 resources 下面新建 log4j2.xml,输入以下内容:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!-- status log4j2内部输出自身的日志信息的级别,可以不设置,没太大用 -->
<!-- configuration中主要包括有 Properties、Appenders、Loggers标签 -->
<Configuration status="fatal" monitorInterval="30">
    <!--打印在本地,根据具体存储地址填写 ./logs是当前项目名下的位置-->
    <Properties>
        <Property name="baseDir" value="./logs"/>
        <!--
			常见的配置如下:
        - %d{yyyy-MM-dd HH:mm:ss.SSS} : 日志生成时间,输出格式为"年-月-日 时:分:秒.毫秒"
        - %p : 日志输出格式
        - %c : 类名
        - %m : 日志内容,即 logger.info("message")
        - %n : 换行符
        - %T : 线程号
        - %L : 日志输出所在行数
        - %M : 日志输出所在方法名
        -->
        <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} %5p: --- [%15.15t] %-30.30logger{1} : %m%n</Property>
    </Properties>
    <!-- 输出源,常见的主要有Console、RollingFile、File 三种子节点
        Console:用于定义输出到控制台的Appender
        RollingFile:定义指定方式触发新的Appender
      -->
    <Appenders>
        <!-- 输出到控制台 -->
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout>
                <pattern>${pattern}</pattern>
            </PatternLayout>
        </Console>
        <!-- 输出到本地磁盘,形成日志文件 -->
        <RollingFile name="localFileLog" fileName="${baseDir}/debug.log"
                     filePattern="${baseDir}/debug_%i.%d{yyyy-MM-dd}.log">
            <!-- 过滤器 -->
            <Filters>
                <!-- 限制日志级别在debug及以上在info以下 -->
                <ThresholdFilter level="debug"/>
                <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <!-- 日志格式 -->
            <PatternLayout>
                <pattern>${pattern}</pattern>
            </PatternLayout>
            <!-- 策略 -->
            <Policies>
                <!-- 每隔一天转存 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 文件大小,如果太大,可能不会按照模板生成,可以改成10KB试试 -->
                <SizeBasedTriggeringPolicy size="10 MB"/>
            </Policies>
        </RollingFile>
    </Appenders>
    <Loggers>
        <!-- 这个level可以控制输出的级别-->
        <Root level="debug">
            <AppenderRef ref="console"/>
            <!--<AppenderRef ref="localFileLog"/>-->
        </Root>
    </Loggers>
</Configuration>

8.3.2 代码中使用日志

直接在项目的文件内使用日志对象即可无论 Controller,Service,Mapper, 项目的任何位置都可以使用

java 复制代码
@RestController // 组合注解 = @Controller + @ResponseBody,说明:
                // 1. 这是一个控制器,处理HTTP请求;
                // 2. 方法返回值自动转为JSON(而非跳转视图)
@Slf4j // Lombok核心注解:自动生成以下代码(无需手动写):
       // private static final org.slf4j.Logger log = 
       //     org.slf4j.LoggerFactory.getLogger(TestLogController.class);
       // 对比注释里的Log4j创建方式,@Slf4j是SLF4J(日志门面)的简化,更通用
// 用了这个注解,代码中只需要直接使用log对象
public class TestLogController {

    // 导入包import org.apache.logging.log4j.LogManager;
    // 导入包import org.apache.logging.log4j.Logger;
    // private Logger logger = LogManager.getLogger(TestLogController.class);

    @GetMapping("/log")
    public R log() {
        log.debug("");
        // 下面这些需要配合上方成员变量logger对象
        // {} 是拼接参数
        // logger.debug("这是debug日志,接收id = {},{}",id,"zs");
        // logger.info("这是info日志,接收id = {}",id);
        // logger.warn("这是warn日志,接收id = {}",id);
        // logger.error("这是error日志,接收id = {}",id);

        log.debug("这是debug日志,接收id = {},{}",id,"zs");
        log.info("这是info日志,接收id = {}",id);
        log.warn("这是warn日志,接收id = {}",id);
        log.error("这是error日志,接收id = {}",id);

        return R.ok( );
    }
}

日志占位符 {}

注意:实际开发中,不允许使用输出语句定位问题!要用日志:::

九、SpringBoot 整合 Knife4j

9.1 接口文档

开发中一般写接口文档比较麻烦,需要定义++访问路径++ ,++请求方式++ ,++请求参数++ ,请求列表,请求参数实例,++返回结果++ ,返回结果类型,返回体结构,返回结构实例,返回参数列表,++返回状态码++列表等等等等等....

关键还会经常随着需求的更新而改变.....还有,就是这玩意儿真的手写起来太费劲,且不好分工,前端说这东西是后端写的,后端是这东西是前端写的.....

这是一个手写的 word 版的接口文档....

** 某公司的 api 接口文档截图**

9.2 接口文档工具

正是有这样那样的问题,才催生了这些接口文档工具,可以方便的生成接口文档,还可以当接口测试工具去测试,还可以导出成 pdf,word,markdown, 太舒服了常见的工具:

  • Swagger (丝袜哥 er)
  • Knife4j (乃夫 for j)它们之间的关系是:
  • Swagger 是一个开源框架,用于设计、构建和文档化 API。它提供了一组工具和规范,可以生成具有交互式界面的 API 文档。Swagger 可以通过注解或配置文件来定义 API 的元数据,包括请求和响应的数据结构、参数、路径等。它还支持自动生成客户端代码和执行 API 测试。
  • Knife4j 是一个基于 Swagger 的增强工具,为 Swagger 文档提供了更直观、美观和易于使用的界面。它通过自定义样式和感知能力来改进 Swagger 生成的文档。Knife4j 提供了一些额外的功能,如开发者友好的文档展示、在线测试工具、接口权限管理等。它可以轻松集成到 Spring Boot 等框架中,提供更好的 API 文档展示和管理体验。

因此,Knife4j 可以看作是 Swagger 的一个扩展和增强工具,通过提供更好的 UI 和功能来改进 Swagger 生成的 API 文档。它使用 Swagger 的核心功能和规范,并在此基础上进行了定制和改进,提供更好的用户体验和开发者工具。

swagger的界面

Knife4j的界面

9.3 整合 Knife4j

9.3.1 依赖xml

XML 复制代码
<!--  接口文档 -->
<dependency>
  <groupId>com.github.xiaoymin</groupId>
  <artifactId>knife4j-spring-boot-starter</artifactId>
  <version>3.0.3</version>
</dependency>

9.3.2 yml 配置

复制代码
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://ip:3306/test_springboot?serverTimezone=UTC&useSSL=false
    username: root
    password: ***
    type: com.alibaba.druid.pool.DruidDataSource
  mvc:
    pathmatch:    # Springfox使用的路径匹配是基于AntPathMatcher的
                    # 所以需要配置此参数
      matching-strategy: ant_path_matcher

9.3.3 Controller 接口加注解

java 复制代码
@RestController
@RequestMapping("/api/dept/")
@Api(tags = "部门接口")
public class TestKnife4jController {

    @Autowired
    private DeptMapper mapper;

    @GetMapping("/list")
    @ApiOperation(value = "查询所有部门")
    public ResultData test(){
        List<Dept> list = mapper.findAll( );
        return ResultData.ok( list );
    }

    @GetMapping("/{id}")
    @ApiOperation(value = "根据部门编号查询部门")
    public ResultData findById(@PathVariable String id){
        Dept dept = mapper.findById(id);
        return ResultData.ok( dept );
    }

    @PostMapping("/save1")
    @ApiOperation(value = "插入部门-表单")
    public ResultData save1(Dept dept){
        mapper.save(dept);
        return ResultData.ok( );
    }

    @PostMapping("/save2")
    @ApiOperation(value = "插入部门-json")
    public ResultData save2(@RequestBody Dept dept){
        mapper.save(dept);
        return ResultData.ok( );
    }
}

9.3.4 配置 [重点]

java 复制代码
package com.qf.config;

import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


@Configuration // 开启配置
@EnableSwagger2 // 启动Swagger2
public class Knife4jConfiguration {

    @Bean
    public Docket defaultApi2() {
        String groupName = "1.0版本";
        Docket docket = new Docket(DocumentationType.OAS_30)
                // 是否启用Swagger
                .enable(true)
                .apiInfo(new ApiInfoBuilder()
                        .title("这是Taotie-Test-knife4j API ")
                        .description("这是项目描述")
                        .termsOfServiceUrl("服务器URL")
                        .contact(new Contact("饕餮", null, "qiushiju0828@163.com"))
                        .version("1.0")
                        .build())
                //分组名称
                .groupName(groupName)
                .select()
                // 这里指定Controller扫描包路径,没有加注解的接口方法也会生成接口文档
                .apis(RequestHandlerSelectors.basePackage("com.qf.controller"))
                // 这里指定只有加了注解的才会生成接口文档
                //.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }
}

9.3.5 启动项目,访问接口文档

http://localhost:8080/doc.html

可以测试

特别注意:

  • Knife4j 依赖用的时候再添加
  • 否则,只是添加依赖,没有写配置文件,项目会报错:::

9.4 其他注解

  • @Api:修饰整个类,描述 Controller 的作用
java 复制代码
@Api(tags ="用户管理API")
public class UserController {}
  • @ApiOperation:描述一个类的一个方法,或者说一个接口
java 复制代码
@ApiOperation(value="获取用户详细信息", notes="根据id来获取用户详细信息")
public ResultData<User> findUserById(Integer id){}
  • @ApiModel:用对象来接收参数 ,修饰类
  • @ApiModelProperty:用对象接收参数时,描述对象的一个字段例如:
java 复制代码
@ApiModel(description = "用户实体类")
public class User {
    @ApiModelProperty(name="id", value="用户id")
    private Integer id;
    @ApiModelProperty(value="用户姓名")
    private String name;
  • @ApiResponse:HTTP 响应其中 1 个描述
  • @ApiResponses:HTTP 响应整体描述,一般描述错误的响应
java 复制代码
// 针对响应状态 修饰方法
@ApiResponses({
            @ApiResponse(code=500, message = "服务器异常")
    })
  • @ApiIgnore:使用该注解忽略这个 API@ApiError :发生错误返回的信息 @ApiParam:单个参数描述,用在控制器的方法上 @ApiImplicitParam:一个请求参数,用在方法上
java 复制代码
@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Integer", paramType = "path")
java 复制代码
@ApiImplicitParams({
            @ApiImplicitParam(),
            @ApiImplicitParam()
    })
  • 针对返回值,使用泛型表示
java 复制代码
@ApiModel
public class R {
    @ApiModelProperty(value = "返回数据状态",notes = "200成功 500失败")
    private int code;
    private String msg;
    @ApiModelProperty(value = "返回数据",notes = "可以是具体的对象,也可以是null")
    private Object data;

十 总结

知识点重点 (完全掌握)

  • Spring

    • ioc , 控制反转,创建对象
      • @Controller,@Service,@Component
    • di, 依赖注入,属性赋值
      • @Autowired,@Value
  • SpringMVC - web层,控制层框架,主要功能是请求响应相关的代码

    • 如何请求匹配路径 @GetMapping @PostMapping @RequestMapping

    • 如何接收请求数据的.前端name和后端参数名一致/后端对象属性名一致

      • 特殊类型数据(List,Map)需要@RequestParam

      • 特殊类型数据 JSON,需要@RequestBody

    • 如何响应

      • 默认是返回String,值是页面字符串 例如: return "ok.html"

      • 前后端分离开发时,后端响应json数据,就在方法上加@ResponseBody注解

        • 如果所有方法都加@ResponseBody注解,那么我们就可以在类上把@Controller改成@RestController即可
  • mybatis - jdbc - 用来操作数据库的

    • 知道ORM --> 表/字段;类/属性

    • 知道编码流程,熟练crud

      • 实体类

      • Mapper接口,定义crud方法

      • Mapper映射文件,定义crud标签

      • 配置yml文件

      • 主类配置@MapperScan

    • 动态sql

      • 场景: 条件查询 where+if

      • 场景: 条件更新 set+if

      • 场景: 批量删除/插入 foreach

    • 多表联查

其他东西都是锦上添花(用到了,会 CV)

  • spring-aop

  • springmvc的会话,拦截器,全局异常

  • mybatis缓存,事务,注解开发,分页

  • SpringBoot 多环境切换,获得配置文件数据,热加载,接口工具

  • 整合日志框架

  • aop+自定义注解实现日志记录

编码上熟悉架构

  • 熟悉springboot整合ssm需要的jar包/依赖

  • 熟系三层架构编码风格

相关推荐
编织幻境的妖2 小时前
SQL查询连续登录用户方法详解
java·数据库·sql
未若君雅裁2 小时前
JVM面试篇总结
java·jvm·面试
kk哥88993 小时前
C++ 对象 核心介绍
java·jvm·c++
招风的黑耳3 小时前
我用SpringBoot撸了一个智慧水务监控平台
java·spring boot·后端
xunyan62343 小时前
面向对象(下)-接口的理解
java·开发语言
大佐不会说日语~3 小时前
Spring AI Alibaba 的 ChatClient 工具注册与 Function Calling 实践
人工智能·spring boot·python·spring·封装·spring ai
Miss_Chenzr3 小时前
Springboot优卖电商系统s7zmj(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
程序员游老板3 小时前
基于SpringBoot3+vue3的爱心陪诊平台
java·spring boot·毕业设计·软件工程·课程设计·信息与通信
期待のcode3 小时前
Springboot核心构建插件
java·spring boot·后端