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

标签 spring-boot thymeleaf

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

现在我们想使用 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 :
@Controller
public class JavascriptController {

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

根页面的 Controller :
@Controller
public class MainController {

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

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

Caused by: java.io.FileNotFoundException: class path resource [jstemplates/index.js] cannot be opened because it does not exist



它应该寻找 templates/index.html ,所以看起来 javascriptTemplateResolver 覆盖或优先于默认的,而不会退回到它。

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

最佳答案

经过一些调试,我终于找到了解决方案。似乎 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 View 同名的 js View ,它总是会得到 javascript View 。

编辑

为了解决最后一个问题,我对配置进行了一些更改:
  • 删除解析器配置中的 .js 后缀
  • 当 Controller 提供 javascript View 名称时,该名称已包含 .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 :
    @Controller
    public class JavascriptController {
    
      @RequestMapping(method = RequestMethod.GET, value = "/js/test.js")
      public String testjs() {
        return "test.js";
      }
    }
    

    HTML View Controller 保持不变。

    关于spring-boot - 如何添加对多个 Thymeleaf 模板模式的支持,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40420963/

    相关文章:

    java - 如何在使用 Axon 框架时模拟 Spring Boot 存储库

    java - 为什么我在 Spring 中提交表单后得到 null 对象?

    java - 当我们使用 ITextRenderer 从 thymeleaf HTML 模板生成 PDF 时,如何设置 PDF 页面大小 A4?

    mysql - JDBC SQL 别名不起作用

    java - 在 thymeleaf 中使用 db 列作为 img src

    spring - 使用 AspectJ LTW 在非公共(public)方法的自调用和相关注意事项上允许 spring 代理功能

    spring - 如何测试 Spring @Conditional bean

    java - 尝试使用 Java Spring AOP 抛出 "org.springframework.beans.factory.BeanCreationException"

    java - 无法在网页中查看数据库中存储的记录

    java - Thymeleaf Spring MVC 中的输入字段显示为空白