如何添加对多个 Thymeleaf 模板模式的支持

Posted

技术标签:

【中文标题】如何添加对多个 Thymeleaf 模板模式的支持【英文标题】:How to add support for more than one Thymeleaf template modes 【发布时间】:2017-03-18 04:28:39 【问题描述】:

我有一个 Spring Boot 应用程序,它使用 Thymeleaf 3 作为应用程序页面的模板引擎。我们使用 spring-boot-starter-thymeleaf 提供的默认配置,html Thymeleaf 模板位于 src/main/resources/templates 文件夹下。

现在我们想使用 Thymeleaf 生成一些 javascript 文件,使用新的 javascript 模板模式。这些 javascript 模板可以位于同一个 HTML 模板文件夹或另一个文件夹中(例如:src/main/resources/jstemplates)。

我不知道有没有办法在不改变 spring-boot-starter-thymeleaf> 提供的默认配置中的任何内容的情况下添加这个配置,或者我必须创建一个完整的配置为一切。

我已经尝试了以下配置的第一个选项,它适用于 javascript 模板,但随后 html 模板不再适用。

配置:

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter
    implements ApplicationContextAware 

  private static final String UTF8 = "UTF-8";

  @Autowired
  private SpringTemplateEngine templateEngine;

  @Autowired
  private ThymeleafProperties properties;

  private ApplicationContext applicationContext;

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) 
    this.applicationContext = applicationContext;
  

  @Bean
  public ThymeleafViewResolver javascriptThymeleafViewResolver() 
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(this.templateEngine);
    resolver.setCharacterEncoding(UTF8);
    resolver.setContentType("application/javascript");
    resolver.setViewNames(new String[] ".js");
    resolver.setCache(this.properties.isCache());
    return resolver;
  

  @Bean
  public SpringResourceTemplateResolver javascriptTemplateResolver() 
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("classpath:/jstemplates/");
    resolver.setSuffix(".js");
    resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
    resolver.setCharacterEncoding(UTF8);
    return resolver;
  

一个测试 javascript 控制器:

@Controller
public class JavascriptController 

  @RequestMapping(method = RequestMethod.GET, value = "/test.js")
  public String testjs() 
    return "test";
  

根页面的控制器:

@Controller
public class MainController 

  @RequestMapping(method = RequestMethod.GET, value = "/")
  public String index(Model model) 
    return "index";
  

src/main/resources/jstemplates 文件夹中有一个 test.js 文件。如果我尝试使用 url http://localhost:8080/test.js,它会按预期工作。但是,例如,如果我尝试主 url (http://localhost:8080/),它会失败并出现以下错误:

原因:java.io.FileNotFoundException:类路径资源 【jstemplates/index.js】不存在,打不开

它应该寻找 templates/index.html 代替,所以似乎 javascriptTemplateResolver 会覆盖或优先于默认值,而不会退回到它。

有没有办法添加与默认 Thymeleaf 配置集成的另一个模板模式支持,或者我需要从头开始配置所有内容?

【问题讨论】:

【参考方案1】:

经过一番调试,我终于找到了解决方案。似乎 SpringResourceTemplateResolver 默认情况下不检查模板是否确实存在。在我的示例配置中,第一个模板解析器是为 javascript 模板配置的,如果模板存在,它会创建一个 View 而不先查看。

要解决这个问题,必须将模板 checkExistence 属性设置为 true。例如:

  @Bean
  public SpringResourceTemplateResolver javascriptTemplateResolver() 
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("classpath:/jstemplates/");
    resolver.setSuffix(".js");
    resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
    resolver.setCharacterEncoding(UTF8);
    resolver.setCheckExistence(true);
    return resolver;
  

我看到这个配置的唯一问题是,如果我们创建一个与 html 视图同名的 js 视图,它总是会得到 javascript 的。

编辑

为了解决最后一个问题,我对配置进行了一些更改:

移除解析器配置中的.js后缀 当控制器给出 javascript 视图名称时,该名称已包含 .js 后缀。

最终配置如下:

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter
    implements ApplicationContextAware 

  private static final String UTF8 = "UTF-8";

  @Autowired
  private ThymeleafProperties properties;

  @Autowired
  private TemplateEngine templateEngine;

  private ApplicationContext applicationContext;

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) 
    this.applicationContext = applicationContext;
  

  @Bean
  public ThymeleafViewResolver javascriptThymeleafViewResolver() 
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(this.templateEngine);
    resolver.setCharacterEncoding(UTF8);
    resolver.setContentType("application/javascript");
    resolver.setViewNames(new String[] "*.js");
    resolver.setCache(this.properties.isCache());
    return resolver;
  

  @Bean
  public SpringResourceTemplateResolver javascriptTemplateResolver() 
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(this.applicationContext);
    resolver.setPrefix("classpath:/templates/js/");
    resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
    resolver.setCharacterEncoding(UTF8);
    resolver.setCheckExistence(true);
    resolver.setCacheable(this.properties.isCache());
    return resolver;
  

还有示例控制器:

@Controller
public class JavascriptController 

  @RequestMapping(method = RequestMethod.GET, value = "/js/test.js")
  public String testjs() 
    return "test.js";
  

HTML 视图控制器保持不变。

【讨论】:

以上是关于如何添加对多个 Thymeleaf 模板模式的支持的主要内容,如果未能解决你的问题,请参考以下文章

「SpringBoot实战」视图技术-Thymeleaf

Spring Boot中添加Thymeleaf模板

SpringBoot页面展示Thymeleaf

SpringBoot整合Thymeleaf

SpringBoot笔记(五)模板引擎thymeleaf和freemarker

Spring Boot Thymeleaf 模板引擎的使用