Gateway网关下Knife4j文档聚合,报错:SyntaxError Unexpected token ‘‘, !DOCTYPE ... is not valid JSON

Gateway网关下Knife4j文档聚合,报错:SyntaxError: Unexpected token ‘<’, "<!DOCTYPE "… is not valid JSON

一、情景再现

在这里插入图片描述

二、原因分析

bz这里使用的是Sa-Token下的微服务 - 网关统一鉴权,报错原因在网上找了好久也没找到,最终问题发现在Sa-Token的全局过滤器上。

这是最开始的Sa-Token全局过滤器
@Configuration
public class SaTokenConfigure {
    // 注册 Sa-Token全局过滤器
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
            // 拦截地址
            .addInclude("/**")    /* 拦截全部path */
            // 开放地址
            .addExclude(
                    // Knife4j前端页面
                    "/doc.html",
                    // Swagger资源路径
                    "/webjars/**",
                    "/swagger-resources/**",
                    "/swagger-ui/**",
                    "/swagger-ui.html",
                    // 聚合的OpenAPI文档路径(关键!)
                    "/v2/api-docs",
                    "/v2/api-docs/**",
                    // 其他白名单
                    "/favicon.ico")
            // 鉴权方法:每次访问进入
            .setAuth(obj -> {

                // 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
                SaRouter.match("/**").notMatch(Constant.WHITE_LIST).check(r -> StpUtil.checkLogin());
            })
            // 异常处理方法:每次setAuth函数出现异常时进入
            .setError(e -> {
                return SaResult.error(e.getMessage());
            });
    }
}

访问swagger聚合文档(http://localhost:8080/doc.html)报错,以为是依赖问题,更换依赖版本后还是不行。(SpringBoot-2.7.12、JDK11)

<!--网关进行聚合的组件knife4j-->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-gateway-spring-boot-starter</artifactId>
    <version>4.5.0</version>
</dependency>
    
<!--其他模块knife4j-->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
    <version>4.5.0</version>
</dependency>

然后我把关注点放在了Sa-Token全局过滤器的异常处理那里。浏览器在报错,idea的控制台却没有报错,于是我把异常处理方法改成了项目的通用返回结果类R。

// 异常处理方法:每次setAuth函数出现异常时进入
.setError(e -> {
    return R.error(e.getMessage());
});

再次访问聚合文档,还是报错。

在这里插入图片描述

但是与第一次报错有所区别,第一次是“Unexpected token ‘<’, "<!DOCTYPE "”,而这次却是“Unexpected token ‘R’, “R(code=100””。它们指的都是返回给浏览器不是JSON格式数据。于是我又把异常处理返回结果改为了自定义异常处理类。

.setError(e -> {
    throw new CommonException(e.getMessage(),100500);
});
@Getter
public class CommonException extends RuntimeException{
    private int code;

    public CommonException(String message, int code) {
        super(message);
        this.code = code;
    }

    public CommonException(String message, Throwable cause, int code) {
        super(message, cause);
        this.code = code;
    }

    public CommonException(Throwable cause, int code) {
        super(cause);
        this.code = code;
    }
}

再次访问文档,发现报错原因变成了这样,于是又在拦截路径那里添加放行路由"/v3/api-docs/**"。

在这里插入图片描述

再次访问文档,发现报错原因又变成了这样,于是又在拦截路径那里添加放行路由-微服务自定义的Swagger分组路径"/standardSwagger/**"。

在这里插入图片描述

再次访问文档,成功打开文档。

在这里插入图片描述

三、参考代码

修改后的Sa-Token全局过滤器
@Configuration
public class SaTokenConfigure {
    // 注册 Sa-Token全局过滤器
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
            // 拦截地址
            .addInclude("/**")    /* 拦截全部path */
            // 开放地址
            .addExclude(
                    // Knife4j前端页面
                    "/doc.html",
                    // Swagger资源路径
                    "/webjars/**",
                    "/swagger-resources/**",
                    "/swagger-ui/**",
                    "/swagger-ui.html",
                    // 聚合的OpenAPI文档路径(关键!)
                    "/v2/api-docs",
                    "/v2/api-docs/**",
                    "/v3/api-docs/**",
                    // 微服务自定义的Swagger分组路径
                    "/userSwagger/**",
                    "/standardSwagger/**",
                    // 其他白名单
                    "/favicon.ico")
            // 鉴权方法:每次访问进入
            .setAuth(obj -> {
                // 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
                SaRouter.match("/**").notMatch(Constant.WHITE_LIST).check(r -> StpUtil.checkLogin());
            })
            // 异常处理方法:每次setAuth函数出现异常时进入
            .setError(e -> {
                throw new CommonException(e.getMessage(),100500);
            });
    }
}
网关配置文件
server:
  port: 8080
spring:
  application:
    name: gateway
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
  cloud:
    nacos:
      server-addr: localhost:8848
    gateway:
      routes:
        - id: standard-service # 路由规则id,自定义,唯一
          uri: lb://standard-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表
          predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务
            - Path=/codeTable/**,/data-standard/**,/test/**,/standardSwagger/** # 这里是以请求路径作为判断规则
          filters:
            # 仅对 /standard/** 路径重写,其他路径保持不变
            - RewritePath=/standardSwagger(?<segment>/?.*), $\{segment}
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**,/userSwagger/**
          filters:
            - RewritePath=/userSwagger(?<segment>/?.*), $\{segment}

#knife4j的网关聚合配置 文档地址:http://{gateway.host}:{gateway.port}/doc.html
knife4j:
  #  # 聚合swagger文档
  gateway:
    enabled: true
    # 排序规则(tag/operation排序自4.2.0版本新增)
    # 取值:alpha-默认排序规则,官方swagger-ui默认实现,order-Knife4j提供的增强排序规则,开发者可扩展x-order,根据数值来自定义排序
    tags-sorter: order
    operations-sorter: order
    # 指定手动配置的模式(默认为该模式)
    strategy: manual
    discover:
      # 是否开启服务发现模式的配置
      enabled: false
      # 指定版本号(swagger2|openapi3)
      version: swagger2
    routes:
      - name: 数据标准管理接口
        # 真实子服务访问url地址-提供OpenAPI的文档
        url: /standardSwagger/v2/api-docs?group=standardSwagger
        #        url: /v3/api-docs
        service-name: standard-service
        # 路由前缀
        # 兼容OpenAPI3规范在聚合时丢失contextPath属性的异常情况,由开发者自己配置contextPath,Knife4j的前端Ui做兼容处理,与url属性独立不冲突,仅OpenAPI3规范聚合需要,OpenAPI2规范不需要设置此属性,默认为(apiPathPrefix)
        context-path: /
        order: 2

      - name: 用户管理接口
        #事实上我们也可以通过路由转发到其它单个服务上面去,从而达到聚合其它服务的说明文档,比如下面的云服务接口
        url: /userSwagger/v2/api-docs?group=userSwagger
        service-name: user-service
        # 路由前缀
        context-path: /
        order: 3
子服务配置文件
knife4j:
  enable: true
  openapi:
    title: 数据工厂(数据标准管理)服务
    description: 数据工厂(数据标准管理)服务
    email: 123456@gmail.com
    concat: rq
    url: https://docs.xiaominfo.com
    version: v4.0
    license: Apache 2.0
    license-url: https://stackoverflow.com/
    terms-of-service-url: https://stackoverflow.com/
    group:
      default:
        group-name: standardSwagger
        api-rule: package
        api-rule-resources:
          - com.cqie.standard.controller
nse-url: https://stackoverflow.com/
    terms-of-service-url: https://stackoverflow.com/
    group:
      default:
        group-name: standardSwagger
        api-rule: package
        api-rule-resources:
          - com.cqie.standard.controller
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值