Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

问题背景

在一个基于 Spring Cloud Gateway + WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 CircleCaptcha 生成验证码图片。然而在部署上线后,访问该接口始终返回 404,而其他网关转发接口均正常。

该接口定义如下:

java 复制代码
@Configuration
public class RouterFunctionConfiguration {

    @Autowired
    private ValidateCodeHandler validateCodeHandler;

    @Bean
    public RouterFunction<?> routerFunction() {
        return RouterFunctions.route(
            RequestPredicates.GET("/code")
                .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
            validateCodeHandler);
    }
}

初步排查思路

起初怀疑为以下常见问题:

  1. Accept: text/plain 请求头不匹配;
  2. 路由被 gateway.routes/code/** 路由转发覆盖;
  3. RouterFunction Bean 未生效或未注入;
  4. ValidateCodeHandler 写法错误;
  5. 实际监听端口与预期不符(注册到 Nacos 的端口为 8080)。

经多项验证后发现,这些都不是直接原因


真正的原因:JVM 图形字体系统缺失导致验证码生成失败

查看日志后,发现关键错误如下:

java 复制代码
java.lang.NoClassDefFoundError: Could not initialize class sun.font.SunFontManager
    at sun.font.FontDesignMetrics.getMetrics(FontDesignMetrics.java:264)
    ...
    at cn.hutool.captcha.CircleCaptcha.createImage(...)

Hutool 的 CircleCaptcha 使用 Java AWT 图形库渲染验证码,而 AWT 依赖系统字体和图形环境支持。在当前使用的 Docker 镜像 openjdk:8-jre-slim 中,字体系统缺失,导致:

  • JVM 无法初始化字体管理器;
  • Captcha.createImage() 方法抛出 NoClassDefFoundError
  • WebFlux 返回 500,但表现为 /code 接口 404(无默认异常处理器);
  • 外部看起来像是"接口路由失效"。

解决方案

方案一:更换基础镜像(推荐)

将 Dockerfile 中基础镜像改为完整版本:

dockerfile 复制代码
FROM openjdk:8-jre  # 或 openjdk:8-jdk

该版本包含 AWT 和字体支持,开箱即用。


方案二:在 slim 镜像中安装字体依赖

如果仍想使用 slim 镜像,可在构建中添加字体:

dockerfile 复制代码
RUN apt-get update && apt-get install -y fontconfig ttf-dejavu

或者更小:

dockerfile 复制代码
RUN apt-get update && apt-get install -y fonts-dejavu-core

这会安装 JVM 字体渲染所需的核心字体文件和环境。


方案三:替换验证码实现逻辑

如果无需图形验证码,可以:

  • 改用字符验证码;
  • 替换为不依赖 AWT 的实现;
  • 或直接生成文本验证码。

验证建议

1. 使用 curl 添加请求头进行测试:

bash 复制代码
curl -H "Accept: text/plain" http://localhost:8001/code

2. 日志开启 Web 路由匹配调试:

yaml 复制代码
logging:
  level:
    org.springframework.web: DEBUG

总结

问题 原因
/code 接口 404 实际是内部抛出 NoClassDefFoundError,未进入 handler
报错类 sun.font.SunFontManager 无法初始化
根本原因 Docker 镜像缺少字体渲染环境
解决方式 更换镜像或安装字体

建议

在使用 Hutool、Captcha、或任何基于 AWT 的组件时,务必检查部署环境是否具备必要图形支持 。特别是在 Docker 化部署中,openjdk-slim 镜像虽小,但常缺关键功能,适用场景需慎重评估。

相关推荐
heartbeat..3 天前
深入理解 JVM:从核心原理到实战应用
java·jvm·jdk·学习笔记
草履虫建模5 天前
A13 String 详解:不可变、常量池、equals 与 ==、性能与常见坑
java·开发语言·spring·jdk·intellij-idea·java基础·新手
pingzhuyan7 天前
linux运维-KylinV10的aarch64架构-docker微服务运维部署(全篇)
linux·docker·jdk·rocketmq·kylin·aarch64
好好研究8 天前
MobaXterm远程连接云服务器(Centos环境)及配置jdk、Tomcat、MySQL环境
java·服务器·mysql·jdk·tomcat·aliyun服务器
莫问前路漫漫8 天前
WinMerge v2.16.41 中文绿色版深度解析:文件对比与合并的全能工具
java·开发语言·python·jdk·ai编程
草履虫建模9 天前
A01 开发环境与第一个 Java 程序(IDEA / JDK / Maven 基础)
java·spring·jdk·maven·intellij-idea·idea·基础
COSMOS_*12 天前
2025最新版 Android Studio安装及组件配置(SDK、JDK、Gradle)
android·ide·jdk·gitee·android studio
莫问前路漫漫12 天前
JDK 核心实操指南:从安装配置到项目打包调试全流程
java·jdk
程序猿_极客13 天前
【2025 年最新版】Java JDK 安装与环境配置教程(附图文超详细,Windows+macOS 通用)
java·开发语言·windows·macos·jdk
码界奇点16 天前
Tomcat与JDK版本对照全解析避坑指南生产环境选型建议
java·开发语言·容器·jdk·tomcat