侧边栏壁纸
博主头像
术业有道之编程博主等级

亦是三月纷飞雨,亦是人间惊鸿客。亦是秋霜去叶多,亦是风华正当时。

  • 累计撰写 99 篇文章
  • 累计创建 50 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

springboot3+webflux集成open api

Administrator
2024-05-04 / 0 评论 / 0 点赞 / 13 阅读 / 8926 字

写在前面

有个项目使用springboot3.2、webflux ,发现一直使用的knife4j开发的 swagger增强不可用了。目前市面上很多组件对webflux的支持非常有限,大部分是直接不支持。本文是记录在springboot3.2、webflux下使用open apiknife4j-ui做集成的示例。

一、引入包

  • 环境说明
    • openjdk 21
    • kotlin 1.9.20
    • gradle 8.5
implementation("org.springframework.boot:spring-boot-starter-webflux")
// 我用的 kotlin,如果是java 下面4个包不需要
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
// spring open api 包支持
implementation("org.springdoc:springdoc-openapi-starter-webflux-ui:2.3.0")
// 第三方 knife4j对open api的ui支持(纯属比默认的api页面好看点,可以不要)
implementation("com.github.xiaoymin:knife4j-openapi3-ui:4.4.0")
// 我自己写的权限组件
implementation("io.github.liuchengts:spring-boot-webflux-auth-starter:1.0.0.3")

二、配置

  • 配置webflux open api
/**
 * openApi 文档配置
 */
@Configuration
class WebFluxOpenApiConfig {
    @Bean
    fun openApi(@Value("\${springdoc.version}") appVersion: String?): GroupedOpenApi {
        val packagedToMatch = arrayOf("com.lc.flow.controllers")// 你的api包
        return GroupedOpenApi.builder().group("flow-v2-server") //名称
            .addOpenApiCustomizer { openApi ->
                openApi.info(
                    Info().title("flow-v2-server Api").version(appVersion)
                )
            }
            .packagesToScan(*packagedToMatch)
            .build()
    }
}
  • 配置 webflux-auth
@Configuration
class AuthConfiguration @Autowired constructor(
    private val filterWhiteListService: FilterWhiteListService
) {

    @PostConstruct
    fun init() {
        /**
         * 匹配白名单
         * 规则:
         * 1、* 表示单级路由通配符
         * 匹配成功后会进入下一级路由匹配;
         * 匹配失败后会使用当前真实单级路由进行匹配;
         * 当真实单级路由匹配失败后本方法返回匹配失败,匹配成功则进入前两种场景
         * 2、** 表示多级路由通配符
         * 匹配成功后会直接返回成功,跳过后面的所有匹配逻辑;
         * 没有成功会进行 * 模式匹配
         * 3、开头带 / 或不带 效果相同
         *
         * 注意:请忽略示例中的星号前后空格(与注释冲突,必须要空格)
         * 例1: /a/b/c     等效 a/b/c
         * 例2: /**/b/c    效果 ** 开头的全部放行,不会再验证 b/c 任意级路由任意字符
         * 例3: /a/ * /c   效果  中间a和b中间的路由可以是任意字符
         * 例4: /a/b/ *    效果  验证完/a/b 之后 后面的最后一级可以是任意字符
         * 例5: /a/b/ **   效果  验证完/a/b 之后 后面的可以是任意级路由任意字符
         *
         */
        filterWhiteListService.addWhiteList(
            "/login",
            "/login/**",
            "/doc.html",
            "/v3/api-docs/**",
            "/v3/api-docs.yaml",
            "/v3/api-docs/swagger-config",
            "/swagger-ui.html",
            "/swagger-ui/**",
            "/swagger-resources",
            "/swagger-resources/**",
            "/configuration/ui",
            "/configuration/security",
            "/webjars/**"
        )
    }
}
  • 配置 application.yml(这种配置需要配置nginxopen api的代理)
server:
  #配置代理,参考:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto.webserver.use-behind-a-proxy-server
  forward-headers-strategy: framework
# 配置 springdoc(open api)参考:https://springdoc.org/index.html#Introduction
springdoc:
  version: '@springdoc.version@'
  api-docs:
    enabled: true
  swagger-ui:
    enabled: true

参考文档: springdoc

到这里,本地启动就完成了:

  • 访问knife4j好看些的页面:http://localhost:8080/doc.html
  • 访问原始页面:http://localhost:8080/swagger-ui.html

注意:

通过nginx代理了这个springboot使用的不是 location / {},会发现api文档访问不了了。原因是没有设置WebFlux的 base-path导致open api的起始地址是/v3/api-docsnginx代理命中不到导致404

有二种办法解决:

  • nginx角度:配置nginxopen api的代理
 location /v3/api-docs {
         proxy_pass http://localhost:8080;
         add_header Access-Control-Allow-Origin '*';
         add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
         add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Conten    t-Type,Authorization';
         proxy_set_header X-Real-IP $remote_addr;
         proxy_set_header Host $host;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header Accept-Encoding '';
         proxy_cache_valid any 1m;
         if ($request_method = 'OPTIONS') {
            return 204;
         }
     }
  • WebFlux的角度:配置WebFlux的 base-path
spring:
  webflux:
    base-path: /api
# 去掉 forward-headers-strategy: framework 这个配置,不需要了

推荐第二种,简单明了。在项目中加了/api请求前缀后,nginx代理springboot时去掉路径跟随即可,例如:

location /api {
        proxy_pass http://v2-flow-server;// 这里没有 / ,表示nginx命中的/api不会传递到http://v2-flow-server/后面,省去了一层/api
        add_header Access-Control-Allow-Origin '*';
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Conten    t-Type,Authorization';
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Accept-Encoding '';
        proxy_cache_valid any 1m;
        if ($request_method = 'OPTIONS') {
           return 204;
        }
     }

好了,到这里全部完成。

个人公众号

0

评论区