it编程 > 编程语言 > Java

SpringBoot 3升级后aj-captcha行为验证码底图加载失效的排查过程与解决方案

17人参与 2026-09-16 Java

引言

项目从 spring boot 2.2.6 升级到 3.4.5 后,aj-captcha 1.3.0 验证码接口返回 repcode: 6113,提示"底图未初始化成功,请检查路径"。本文记录排查过程与解决方案。

一、问题现象

调用验证码接口:

post /api/public/safety/get
{"captchatype":"blockpuzzle","ts":1785983564105}

返回结果:

{
  "code": 200,
  "message": "操作成功",
  "data": {
    "repcode": "6113",
    "repmsg": "底图未初始化成功,请检查路径",
    "repdata": null,
    "success": false
  }
}

图片资源确实存在于 resources/images/jigsaw/ 下,配置也写了 jigsaw: classpath:images/jigsaw,但底图缓存为空。

二、根因分析

2.1 aj-captcha 加载底图的两条路径

反编译 imageutils.cacheimage() 发现,它根据配置路径是否为空走不同逻辑:

条置加载方式说明
路径为空getresourcesimagesfile("defaultimages/jigsaw/original")从 jar 内加载默认图片
路径非空getimagesfile(path + "/original")按文件系统加载 new file(path)

项目配置了 classpath:images/jigsaw,路径非空,走第二条。而 getimagesfile 内部执行 new file("classpath:images/jigsaw/original") —— 把 classpath: 前缀当成了物理目录名,文件不存在,返回空 map,缓存为空。

2.2 starter 原本的补救机制

在 spring boot 2 下,starter 的 ajcaptchaserviceautoconfiguration 会自动装配,其中有一段关键逻辑 initializebasemap()

// starter 原始流程(spring boot 2 自动装配)
if (jigsaw.startswith("classpath:")) {
    config.put("captcha.init.original", "true");
    initializebasemap(jigsaw, picclick);  // ← 关键:预加载 classpath 资源
}
captchaservicefactory.getinstance(config);

initializebasemap 使用 spring 的 pathmatchingresourcepatternresolver 按通配符 classpath:images/jigsaw/original/*.png 加载图片,调用 imageutils.cachebootimage() 预填充缓存。之后即使 cacheimage 文件系统加载失败(空 map),putall(emptymap) 也不会清空已有数据。

2.3 升级后自动装配失效

spring boot 3 废弃了 spring.factories 自动装配机制,改用 autoconfiguration.imports。aj-captcha 1.3.0 未适配 spring boot 3,自动装配不生效。

开发者手动创建了 ajcaptchaconfig,但只复制了属性转换(toproperties),遗漏了 initializebasemap 预加载步骤

starter 原始流程:  initializebasemap()  →  cachebootimage()  →  getinstance()
手动配置流程:      (缺失)              →  (缺失)           →  getinstance()

缓存始终为空,接口报 6113。

三、解决方案

ajcaptchaconfig.captchaservice() 中,captchaservicefactory.getinstance() 之前补全 initializebasemap 逻辑:

@bean
public captchaservice captchaservice(ajcaptchaproperties properties, stringredistemplate stringredistemplate) {
    captchacacheserviceredisimpl.setredistemplate(stringredistemplate);

    // 补全:classpath 资源预加载(复刻 starter 的 initializebasemap 逻辑)
    if (isclasspathresource(properties.getjigsaw()) || isclasspathresource(properties.getpicclick())) {
        initializebasemap(properties.getjigsaw(), properties.getpicclick());
    }

    return captchaservicefactory.getinstance(toproperties(properties));
}

/**
 * 预加载 classpath 底图到 imageutils 缓存
 * <p>复刻 starter 的 ajcaptchaserviceautoconfiguration.initializebasemap 逻辑</p>
 */
private void initializebasemap(string jigsaw, string picclick) {
    try {
        map<string, string> originalmap = loadclasspathimages(jigsaw + "/original/*.png");
        map<string, string> slidingblockmap = loadclasspathimages(jigsaw + "/slidingblock/*.png");
        map<string, string> picclickmap = loadclasspathimages(picclick + "/*.png");
        imageutils.cachebootimage(originalmap, slidingblockmap, picclickmap);
    } catch (exception e) {
        log.error("验证码底图预加载失败", e);
        throw new runtimeexception("验证码底图预加载失败", e);
    }
}

/**
 * 使用 pathmatchingresourcepatternresolver 加载 classpath 通配符图片资源
 *
 * @param pattern 资源路径通配符,如 classpath:images/jigsaw/original/*.png
 * @return 文件名 → base64 编码的 map
 */
private map<string, string> loadclasspathimages(string pattern) throws exception {
    map<string, string> result = new hashmap<>();
    pathmatchingresourcepatternresolver resolver = new pathmatchingresourcepatternresolver();
    resource[] resources = resolver.getresources(pattern);
    for (resource resource : resources) {
        byte[] bytes = filecopyutils.copytobytearray(resource.getinputstream());
        string base64 = base64utils.encodetostring(bytes);
        result.put(resource.getfilename(), base64);
    }
    return result;
}

四、总结

维度说明
根本原因spring boot 3 废弃 spring.factories,aj-captcha 1.3.0 未适配,自动装配失效
直接原因手动配置遗漏了 initializebasemap 预加载步骤,classpath 资源未被加载
隐蔽点cacheimage 对 classpath 路径走文件系统加载,静默返回空 map,不报错
修复方式在创建 captchaservice 前补全 pathmatchingresourcepatternresolver 预加载逻辑

教训:升级框架大版本时,第三方 starter 若未适配新版本,手动补全配置一定要对照原始自动装配类的完整逻辑,不能只复制属性转换部分,容易遗漏关键的初始化步骤。

以上就是springboot 3升级后aj-captcha行为验证码底图加载失效的排查过程与解决方案的详细内容,更多关于springboot 3升级aj-captcha验证码底图加载失效的资料请关注代码网其它相关文章!

(0)

您想发表意见!!点此发布评论

推荐阅读

SpringBoot结合jasypt进行配置文件加解密的方法步骤

09-16

Spring AOP 接口日志脱敏:控制打印内容,避免敏感字段外泄

09-16

Spring注入值中含有特殊符号的处理详解

09-16

Java 对象拷贝避坑:如何避免空值覆盖与数据误改

09-16

Spring 级联属性赋值最佳实践

09-16

Java中ArrayList动态数组的实现与性能优化指南

09-16

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论