首页 文章

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

提问于
浏览
1

我有一个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
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文件 . 如果我尝试了网址http://localhost:8080/test.js,它会按预期工作 . 但是,如果我尝试,例如,主URL(http://localhost:8080/)它失败并出现以下错误:

引起:java.io.FileNotFoundException:无法打开类路径资源[jstemplates / index.js],因为它不存在

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

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

1 回答

  • 3

    经过一些调试后我终于找到了解决方案 . 如果模板确实存在,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视图 .

    Edit

    为了解决最后一个问题,我在配置上做了一些改动:

    • 删除解析程序配置中的.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视图控制器保持不变 .

相关问题