You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Thymeleaf中setResolvablePatterns()配置失效问题排查

问题:Thymeleaf模板解析器使用setResolvablePatterns()替代setCheckExistence(true)时出错

按照Thymeleaf官方文档建议,应为不同模板解析器设置可解析模式。我配置了两个SpringResourceTemplateResolver,分别处理HTML和JavaScript类型的模板,尝试用setResolvablePatterns()替代setCheckExistence(true),但出现以下模板解析错误:

o.t.TemplateEngine : [THYMELEAF] Exception processing template "users/login": Error resolving template [users/login], template might not exist or might not be accessible by any of the configured Template Resolvers
 org.thymeleaf.exceptions.TemplateInputException: Error resolving template [users/login], template might not exist or might not be accessible by any of the configured Template Resolvers

改用setCheckExistence(true)则可正常工作,请问问题出在哪里?

我的配置代码如下:

public SpringResourceTemplateResolver htmlTemplateResolver() {
    SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
    templateResolver.setApplicationContext(applicationContext);
    templateResolver.setPrefix("classpath:templates/web/");
    templateResolver.setSuffix(".html");
    templateResolver.setTemplateMode(TemplateMode.HTML);
    templateResolver.setCharacterEncoding("UTF-8");
    templateResolver.setOrder(0);

    templateResolver.setResolvablePatterns(Collections.singleton("/*.html"));
    // templateResolver.getResolvablePatternSpec().addPattern("/*.html"); // 同样无效

    // templateResolver.setCheckExistence(true);
    return templateResolver;
}

public SpringResourceTemplateResolver javaScriptTemplateResolver() {
    SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
    templateResolver.setApplicationContext(applicationContext);
    templateResolver.setPrefix("classpath:static/build/js/");
    templateResolver.setSuffix(".js");
    templateResolver.setTemplateMode(TemplateMode.JAVASCRIPT);
    templateResolver.setCharacterEncoding("UTF-8");
    templateResolver.setOrder(1);

    templateResolver.setResolvablePatterns(Collections.singleton("/*.js"));
    // templateResolver.setResolvablePatterns(Collections.singleton("*.js")); // 同样无效
    // templateResolver.setResolvablePatterns(Collections.singleton("*"));    // 同样无效

    // templateResolver.setCheckExistence(true);
    return templateResolver;
}

问题原因与解决方案

核心问题:setResolvablePatterns()的匹配逻辑理解错误

setResolvablePatterns()是针对调用模板时传入的模板名称(比如这里的users/login)进行匹配,而非拼接prefix、suffix后的完整资源路径。

你的配置存在两个关键错误:

  1. 模板名称不带后缀:因为已经通过setSuffix(".html")和setSuffix(".js")自动添加后缀,实际传入的模板名称是users/login(无.html),而非users/login.html,所以/*.html或*.js这种带后缀的模式完全匹配不上。
  2. 路径匹配范围不足:/*.html模式只能匹配根路径下的模板(比如login对应login.html),但你的模板名称是users/login这种带子路径的,根路径模式无法覆盖。

而setCheckExistence(true)能工作的原因是:开启该选项后,解析器会尝试加载模板,若不存在才交给下一个解析器;但setResolvablePatterns()是先判断模板名称是否匹配模式,不匹配则直接跳过当前解析器,不会尝试加载。

修正后的配置

根据模板结构调整可解析模式:

HTML解析器

匹配所有带子路径的HTML模板名称,用通配符**即可:

templateResolver.setResolvablePatterns(Collections.singleton("**"));

如果需要更精准匹配(比如只处理users目录下的模板),可以写成:

templateResolver.setResolvablePatterns(Collections.singleton("users/**"));

JavaScript解析器

假设JS模板名称是app、utils/validate这类不带.js后缀的,同样用对应路径的通配符:

templateResolver.setResolvablePatterns(Collections.singleton("**"));
// 若JS模板都在固定子目录下,可写成"js/**"

修正后的完整示例:

public SpringResourceTemplateResolver htmlTemplateResolver() {
    SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
    templateResolver.setApplicationContext(applicationContext);
    templateResolver.setPrefix("classpath:templates/web/");
    templateResolver.setSuffix(".html");
    templateResolver.setTemplateMode(TemplateMode.HTML);
    templateResolver.setCharacterEncoding("UTF-8");
    templateResolver.setOrder(0);

    // 匹配所有带子路径的HTML模板名称
    templateResolver.setResolvablePatterns(Collections.singleton("**"));
    return templateResolver;
}

public SpringResourceTemplateResolver javaScriptTemplateResolver() {
    SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
    templateResolver.setApplicationContext(applicationContext);
    templateResolver.setPrefix("classpath:static/build/js/");
    templateResolver.setSuffix(".js");
    templateResolver.setTemplateMode(TemplateMode.JAVASCRIPT);
    templateResolver.setCharacterEncoding("UTF-8");
    templateResolver.setOrder(1);

    // 匹配所有带子路径的JS模板名称
    templateResolver.setResolvablePatterns(Collections.singleton("**"));
    return templateResolver;
}

额外说明

如果调用JS模板时传入的名称带.js后缀(不建议,违背setSuffix的配置逻辑),才需要将模式改为**.js,但这种做法不符合Thymeleaf的配置规范,建议保持模板名称不带后缀,由解析器自动补充。

内容的提问来源于stack exchange,提问作者Slevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:55:38