在Spring Boot微服务使用knife4j发布后端API接口

news2024/9/22 7:29:50

记录:422

场景:在Spring Boot微服务上,应用knife4j发布后端API接口,辅助开发与调试。

版本:JDK 1.8,Spring Boot 2.6.3,knife4j-3.0.3,springfox-swagger2-3.0.0。

Knife4j: 是一个集Swagger2 和 OpenAPI3为一体的增强解决方案

1.在pom.xml引入依赖

1.1直接引入knife4j

<dependency>
  <groupId>com.github.xiaoymin</groupId>
  <artifactId>knife4j-spring-boot-starter</artifactId>
  <version>3.0.3</version>
</dependency>

1.2间接引入springfox-swagger2等包

在引入knife4j后,相关联的io.swagger、io.springfox等一序列依赖会被引入。

2.配置application.yml

2.1在yml中指定路径匹配策略

spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

2.2指定路径匹配策略原因

Spring MVC的path有两种:ANT_PATH_MATCHER和PATH_PATTERN_PARSER。

Spring Boot微服务默认使用PATH_PATTERN_PARSER。

当Spring Boot 2.6.3和knife4j-3.0.3以及springfox-swagger2-3.0.0集成时,使用默认的PATH_PATTERN_PARSER启动报错。

2.3不指定路径匹配策略报错

报错信息:

org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException

解决方式:

在yml中指定Spring MVC的path策略为:ant_path_matcher。

3.基于注解配置Swagger2

3.1配置类

@Configuration
@EnableSwagger2
public class SwaggerConfig {
  @Bean("docketApi")
  public Docket docketApi() {
    return new Docket(DocumentationType.SWAGGER_2)
      .apiInfo(apiInfo())
      .select()
      .apis(RequestHandlerSelectors.basePackage("com.hub.example"))
      .paths(PathSelectors.any())
      .build();
  }
  private ApiInfo apiInfo() {
    return new ApiInfoBuilder()
      .title("hub-example-206微服务API文档")
      .description("微服务API文档")
      .version("1.1.1")
      .license("Apache License")
      .licenseUrl("http://www.apache.org/licenses/")
      .contact(new Contact("beiZhen"
              , "https://blog.csdn.net/zhangbeizhen18"
              , "beiZhen@beiZhen.com"))
      .build();
  }
}

3.2解析

@EnableSwagger2,标记开启Swagger2相关功能。

Docket类,springfox.documentation.spring.web.plugins.Docket,在此类是Swagger提供给使用者的配置类,可以按需配置个性化功能。

4.在实体类中使用Swagger2注解

4.1注解@ApiModel和@ApiModelProperty

@ApiModel:作用在实体类上。

@ApiModelProperty:作用在实体类属性上。

4.2示例

(1)CityReqDTO

@Data
@ApiModel("城市请求对象")
public class CityReqDTO {
  @ApiModelProperty(value = "城市ID",
          required = true)
  private Long cityId;
  @ApiModelProperty("城市名称")
  private String cityName;
}

(2)CityResDTO

@Data
@Builder
@ApiModel("城市请求对象")
public class CityResDTO implements Serializable {
  @ApiModelProperty(value = "城市ID",
          required = true)
  private Long cityId;
  @ApiModelProperty("城市名称")
  private String cityName;
  @ApiModelProperty("城市面积")
  private Double landArea;
  @ApiModelProperty("城市人口")
  private Long population;
  @ApiModelProperty("城市GDP")
  private Double gross;
  @ApiModelProperty("城市描述")
  private String cityDescribe;
  @ApiModelProperty("数据年份")
  private String dataYear;
  @JsonFormat(
          pattern = "yyyy-MM-dd HH:mm:ss"
  )
  @ApiModelProperty("操作时间")
  private Date updateTime;
}

(3)ResultObj

@Data
@ApiModel("统一响应结果对象")
public class ResultObj<T> implements Serializable {
  @ApiModelProperty(value = "编码",
          required = true,
          example = "200: 成功,400: 失败")
  private int code;
  @ApiModelProperty("成功失败标志")
  private boolean success;
  @ApiModelProperty("成功失败信息")
  private String msg;
  @ApiModelProperty("业务数据")
  private T data;
  
  private ResultObj(int code, T data, String msg) {
      this.code = code;
      this.data = data;
      this.msg = msg;
      this.success = code == 200;
  }
  
  public static <T> ResultObj<T> data(int code, T data, String msg) {
      return new ResultObj<>(code, data, msg);
  }
}

4.3解析

在使用@ApiModel、@ApiModelProperty等注解后,可以清晰展现每个实体类业务意义、实体类属性业务意义。一目了然,可以不用再写注解。

5.在Controller类中使用Swagger2注解

5.1注解@Api和@ApiOperation

@Api:作用在Controller类上。

@ApiOperation:作用在Controller类的方法上。

5.2示例

@RestController
@RequestMapping("/hub/example/city")
@Slf4j
@Api(tags = "城市信息获取服务")
public class CityController {
  @ApiOperation(value = "使用城市编码获取信息接口",
      notes = "使用城市编码获取信息"
  )
  @GetMapping("/queryByCityId")
  public ResultObj<CityResDTO> queryByCityId(String cityId) {
    CityResDTO cityResDTO = CityResDTO.builder()
        .cityId(Long.parseLong(cityId)).cityName("杭州")
        .landArea(16850D).population(1238L)
        .gross(1.88D).cityDescribe("杭州是一个互联网城市")
        .dataYear("2022").updateTime(new Date())
        .build();
    log.info("接收参数: "+cityId);
    log.info("返回数据: "+cityResDTO.toString());
    return ResultObj.data(200, cityResDTO, "执行成功");
  }
  
  @ApiOperation(value = "使用城市编码和名称获取信息接口",
      notes = "使用城市编码和城市名称获取信息"
  )
  @PostMapping("/queryByCity")
  public ResultObj<CityResDTO> queryByCity(@RequestBody CityReqDTO cityReqDTO) {
    CityResDTO cityResDTO = CityResDTO.builder()
      .cityId(cityReqDTO.getCityId())
      .cityName(cityReqDTO.getCityName())
      .landArea(8657.32D).population(1291L)
      .gross(2.4D).cityDescribe("苏州是一个工业城市")
      .dataYear("2022").updateTime(new Date())
      .build();
    log.info("接收参数: "+cityReqDTO.toString());
    log.info("返回数据: "+cityResDTO.toString());
    return ResultObj.data(200, cityResDTO, "执行成功");
  }
  @ApiOperation(value = "使用城市名称获取信息接口",
      notes = "使用城市名称获取信息",
      extensions = {@Extension(
          name = "扩展参数",
          properties = {@ExtensionProperty(name = "cityCode", value = "330100"),
                  @ExtensionProperty(name = "dataFrequency", value = "RealTime")
          })}
  )
  @GetMapping("/queryByCityName")
  public ResultObj<CityResDTO> queryByCityName(String cityName) {
    // 1.从请求头获取城市编码
    RequestAttributes reqAttributes = RequestContextHolder.currentRequestAttributes();
    HttpServletRequest request = ((ServletRequestAttributes) reqAttributes).getRequest();
    String cityCode = request.getHeader("cityCode");
    // 2.组装返回参数
    CityResDTO cityResDTO = CityResDTO.builder()
            .cityId(Long.parseLong(cityCode)).cityName(cityName)
            .landArea(16850D).population(1238L)
            .gross(1.88D).cityDescribe("杭州是一个互联网城市")
            .dataYear("2022").updateTime(new Date())
            .build();
    log.info("接收参数: "+cityName);
    log.info("请求头cityCode = : "+cityCode);
    log.info("返回数据: "+cityResDTO.toString());
    return ResultObj.data(200, cityResDTO, "执行成功");
  }
}

5.3解析

在使用@Api和@ApiOperation等注解后,可以清晰展现每个Controller类业务意义、Controller类发布的Restful方法的业务意义。一目了然,可以不用再写注解。

6.在浏览器中查看Swagger2发布的API接口信息

6.1登录地址

(1)默认地址

地址:http://127.0.0.1:18080/doc.html

解析:根据实际组装IP和端口。

(2)本例地址

本例地址:http://127.0.0.1:18206/hub-example-206/doc.html

页面发布的jar包:knife4j-spring-ui-3.0.3.jar,

页面位置:\META-INF\resources\doc.html。

6.2API接口首页

在页面中可以看到微服务发布的Restful接口信息概览。

6.3接口信息

选择其中一个接口,能看到接口文档、调试、Open功能列表。

7.使用knife4j的API接口调试后端接口

7.1设置knife4j的API接口支持传递请求头

设置knife4j的API接口支持传递请求头。

选择:文档管理->个性化设置->开启动态请求参数。

注意:默认没有开启,即默认不支持设置请求头部。

7.2调试GET请求

选择接口:使用城市名称获取信息接口。

在接口页面,选择:调试。

(1)设置请求头部

(2)设置请求参数

根据参数列表设置请求参数。

(3)发起请求

点击:发送,发起请求,调用后端微服务。

可以看到后端返回值信息。

7.3调试POST请求

选择接口:使用城市编码和名称获取信息接口。

在接口页面,选择:调试。

(1)设置请求头部

(2)设置请求参数

根据参数列表设置请求参数。

(3)发起请求

点击:发送,发起请求,调用后端微服务。

可以看到后端返回值信息。

以上,感谢。

2023年4月26日

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/465387.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第三十二篇,记一次Windows下Qt使用boost的经历

Win10系统 Qt版本如下所示 Qt中使用的编译器是MinGW&#xff0c;如下图 boost版本是1.82.0 好的&#xff0c;描述一下过程&#xff1a; 按这个教程下载、编译boost&#xff0c;在boost的目录下生成了stage/lib/目录&#xff0c;然后加入到Qt工程里&#xff0c;主要是include目…

win10安装Anaconda,配置Pytorch环境

一、安装Anaconda Anaconda实际上是一个包管理器&#xff0c;可以理解为一个工具。Anaconda自带Python&#xff08;选中版本&#xff09;解释器以及其他一些数据分析与挖掘需要的模块而无需用户手动添加这些常用模块&#xff08;安装模块会出现各种错误&#xff09;。早期学Pyt…

Django个性化推荐系统,以电影为例

背景 随着科学技术发展&#xff0c;电脑已成为人们生活中必不可少的生活办公工具&#xff0c;在这样的背景下&#xff0c;网络技术被应用到各个方面&#xff0c;为了提高办公生活效率&#xff0c;网络信息技术飞速发展。在这样的背景下人类社会进入了全新的信息化的时代。电影…

flask+opencv:实时视频直播推流平台Demo

简介&#xff1a;推流&#xff0c;指的是把采集阶段封包好的内容传输到服务器的过程。其实就是将现场的视频信号传到网络的过程。网上调查、对话访谈、在线培训等内容现场发布到互联网上。利用互联网的直观、快速&#xff0c;表现形式好、内容丰富、交互性强、地域不受限制、受…

华为OD机试真题(Java),猴子爬山(100%通过+复盘思路)

一、题目描述 一天一只顽猴想去从山脚爬到山顶&#xff0c;途中经过一个有个N个台阶的阶梯&#xff0c;但是这猴子有一个习惯&#xff1a; 每一次只能跳1步或跳3步&#xff0c;试问猴子通过这个阶梯有多少种不同的跳跃方式&#xff1f; 二、输入描述 输入只有一个整数N&…

AI语音生成器是下一大安全威胁吗?

ChatGPT一经上市&#xff0c;有关监管人工智能的讨论就开始升温。任何试图遏制这种技术的做法都可能需要国际合作&#xff0c;需要我们在过去几十年来从未见过的合作程度&#xff0c;因此不太可能遏制人工智能。 人工智能是一项功能强大的技术&#xff0c;有望彻底改变我们生活…

AIGC - 生产力新工具 Bito AI

文章目录 Bito AI 是什么Bito AI 能干啥官网免费的吗&#xff1f;如何使用 Bito方式一&#xff1a;方式二&#xff1a;在这里插入图片描述方式三 Bito AI 是什么 Bito AI是继Github Copilot、Cursor、CodeWhisperer等AI智能编程产品之后发了一大AI编程工具 。 Bito是一款建立…

表情迁移 - 2D人像动起来(附带生成web服务提供api接口)

左边原图,右边是渲染后的视频文件 开源地址:https://github.com/AliaksandrSiarohin/first-order-model 官方模型下载地址(需科学上网): google-driveyandex-disk本文docker容器已自带人脸模型 若还需要行为、物品、动画等追踪模型需下载后拷贝至容器内即可使用 API请求…

Android之 Camera相机使用

一 简介 1.1 随着信息时代的发展&#xff0c;相机在我们生活中使用越来越频繁&#xff0c;也成为手机的基本配置之一。相机可以用来拍照&#xff0c;拍视频&#xff0c;人脸识别&#xff0c;视频聊天&#xff0c;扫码支付&#xff0c;监控等常见领域 不管什么场景&#xff0c…

DolphinScheduler 2.0.5详解

文章目录 第一章 DolphinScheduler介绍1.1 关于DolphinScheduler1.2 DolphinScheduler特性1.3 配置建议1.3.1 Linux 操作系统版本要求1.3.2 服务器建议配置1.3.3 生产环境1.3.4 网络要求1.3.5 客户端 Web 浏览器要求 第二章 DolphinScheduler安装部署2.1 安装部署介绍2.2 单机版…

Mybatis笔记分享【狂神说java】

MyBatis 1、简介 1.1什么是MyBatis MyBatis 是一款优秀的持久层框架 它支持自定义 SQL、存储过程以及高级映射 MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作 MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff08;…

Windows环境下使用Internet Information Service( IIS)管理器上搭建Web资源网站

一、业务需求 在项目的开发过程中,需要将指定文件夹发布称为一个网站,可以通过网页查看该文件夹下的内容和子目录(及其子目录内容);同时也可以将内容上传到该文件夹中,方便他人使用,如下图所示: 二、思路分析 将文件夹发布为网站,可以使用Windows的IIS管理器搭建一个W…

Scala之模式匹配与隐式转换

目录 模式匹配&#xff1a; 基础语法如下&#xff1a; 模式守卫&#xff1a; 类型匹配&#xff1a; 对象匹配 样例类&#xff1a; 偏函数&#xff1a; 偏函数的化简写法&#xff1a; 偏函数的使用&#xff1a; 隐式转换&#xff1a; 官方定义&#xff1a; 个人理解&…

(小甲鱼python)文件永久存储(下)总结 文件处理with语句和上下文管理器、pickle模块详解

一、基础复习 上节课回顾&#xff1a; 1.文件永久存储(上) python文件永久存储(创建打开文件、文件对象的各种方法及含义) 2.文件永久存储(中)总结 路径处理 pathlib–面向对象的文件系统路径 绝对路径vs相对路径&#xff08;路径查询、路径修改、查找功能&#xff09; 二、文…

【JavaScript】new命令精华总结

相关概念 对象是什么? 1.对象是单个实物的抽象 2.对象是一个容器&#xff0c;封装了属性和方法 属性是对象的状态&#xff0c;方法是对象的行为&#xff0c;把对象中的函数一般称为方法 构造函数 专门用来生成实例对象的函数&#xff0c;是对象的模板&#xff0c;第一个字…

vue2数据响应式原理(7) 收集依赖,用get和set叙述出最基础的至高vue哲学

收集依赖在整个数据响应式中算是比较难的 首先 要理解这里所指的依赖 依赖 可能vue项目做多了就会想到 npm i 但其实跟这个是没有什么关系的 我们这里所指的依赖 是用到数据的地方 什么地方用到数据 什么地方就是依赖 简单说 就是依赖这个响应式数据 首先 我们看一下 vue1 和…

【Linux初阶】进程状态 | Linux下常见进程状态讲解 进程循环打印方法 ls>makefile指令 makefile$@^特殊符号的应用

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【Linux初阶】 ✒️✒️本篇内容&#xff1a;进程状态的概念&#xff0c;进程状态在普遍操作系统层面和Linux层面的理解&#xff0c;Linux常见进程状态&…

【论文阅读】轻量化网络MobileNet-V1

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、摘要二、MobileNet-V1核心点介绍&#xff1a;普通卷积和深度可分离卷积三、两个超参数四。后续实验 前言 今天重温一下轻量化经典论文MobileNet-V1&#x…

拿下车载激光雷达份额「第一」,图达通寻求「变阵」

在2022年的量产元年之后&#xff0c;激光雷达正尝试进入真正大规模量产周期。在此之前&#xff0c;有一些关键问题需要解决&#xff0c;其中包括&#xff1a;其一&#xff0c;帮助主机厂将激光雷达真正用起来&#xff0c;发挥价值&#xff1b;其二&#xff0c;丰富产品品类&…

【C语言】文件的相关操作(一文10分钟彻底弄懂)

前言&#xff1a; 欢迎各位童学来到本文&#xff0c;本文将主要通过一个实战案例&#xff08;奥运会奖牌&#xff09;来帮助各位小伙伴们熟悉并掌握文件的相关操作&#xff0c;相信经过一个实战案例的小项目后大家对文件的相关操作应该都能够轻车熟路了&#xff01; &#x1f…