Kaptcha 启动报 NoClassDefFoundError 是因 Guava 未显式引入或与 WebFlux 冲突;需手动添加 Guava 依赖、避免混用 WebFlux、适配 Jakarta Servlet、正确配置 DefaultKaptcha Bean 并设置响应头。

为什么 Kaptcha 启动就报 NoClassDefFoundError: com/google/common/collect/ImmutableList
Kaptcha 依赖 Guava,但新版(2.3.2+)只声明了 compile 依赖,不自动拉取 Guava;Maven 默认不会传递间接依赖。你看到的这个错,不是 Kaptcha 本身坏了,是它要调用的 ImmutableList 根本没进 classpath。
- 显式加 Guava 依赖:用
com.google.guava:guava:32.1.3-jre(JDK 17+ 兼容),别用老版本(如 18.0),否则可能和 Spring Boot 3.x 的模块系统冲突 - 如果项目已用 Spring Boot 2.7+ 或 3.x,检查是否启用了
spring-boot-starter-webflux—— Kaptcha 是 Servlet API 驱动的,和 WebFlux 不兼容,混用会触发java.lang.NoClassDefFoundError: javax/servlet/Filter - Gradle 用户注意:
implementation 'com.github.penggle:kaptcha:2.3.2'不能写成compile(已过时),且需确认仓库含 Maven Central(JCenter 已停服)
Spring Boot 2.x / 3.x 中怎么注册 Kaptcha 的 DefaultKaptcha Bean
不能靠 @Bean 简单 new 出来就完事——Kaptcha 初始化要读配置、建渲染器、配文字混淆器,硬 new 会缺默认字体、空指针在 createText。
- 手动构建必须调
Config:先 newProperties,put 进关键项如kaptcha.textproducer.char.length、kaptcha.image.width,再用new Config(properties)设置到DefaultKaptcha - 更稳的方式是用
DefaultKaptchaConfigurer(非官方类,需自写)或直接在@Configuration类里写完整初始化逻辑,例如指定字体路径:config.setFieldFont(new Font("Arial", Font.PLAIN, 28)) - Spring Boot 3.x 用户注意:
javax.servlet包已迁至jakarta.servlet,Kaptcha 2.3.2 暂不原生支持;必须加桥接依赖org.eclipse.jetty:jetty-servlets:12.0.5或降级用 2.3.1 + 手动 patch 字节码(不推荐)
getCaptcha() 接口返回空白图或 406 Not Acceptable
常见于 Controller 返回 void 或没设响应头,浏览器拿不到 image/png 流,或者 Spring MVC 把二进制当 JSON 处理了。
- Controller 方法必须明确设响应类型:
response.setContentType("image/png"),且调kaptchaProducer.createImage(text)后用ImageIO.write(..., "png", response.getOutputStream()) - 别用
@ResponseBody—— 它强制走消息转换器,会尝试把 BufferedImage 转 JSON,必然失败;也别用ResponseEntity<byte></byte>,除非你手动 setHeader("Content-Type","image/png") - 前端发请求时,
fetch('/captcha')默认带Accept: */*,但某些网关(如 Nginx)会过滤掉二进制响应头;可在后端加response.setHeader("Cache-Control", "no-store")防缓存干扰
验证码总被识别、字符太规律怎么办
Kaptcha 默认配置对 OCR 友好得过分——固定字体、无扭曲、字符间距匀称,Tesseract 5 分钟就能跑通。
立即学习“Java免费学习笔记(深入)”;
- 禁用默认干扰线:
kaptcha.noise.impl设为com.google.code.kaptcha.impl.NoNoise,改用自定义噪点(比如画随机半透明圆点) - 换字体文件:别用
new Font("Arial",...),从classpath:/fonts/verdana.ttf加载,并启用多字体支持:kaptcha.textproducer.font.names=verdana,arial,simsun - 字符生成逻辑必须重写:继承
WordRenderer,在renderWord里对每个字符做独立 x 偏移、y 微调、旋转 ±5°,再叠加 1px 高斯模糊(用ConvolveOp)
真正难的不是生成图,是让每次请求的干扰参数不重复又可复现——比如用 session ID 做随机种子,否则刷新时用户觉得“怎么又是一样的歪斜”。










