Springboot - Thymeleaf尝试解析它不应该的文件

时间:2017-06-03 21:15:43

标签: spring spring-boot thymeleaf

您好我目前正在开发一个使用百里香和JSF的网络项目(它是一个遗留系统,我们只能慢慢迁移到百里香,这就是为什么JSF仍然在那里并且不能从一天到另一天被移除,因为这是一个工作繁重)。 Thymeleaf配置为解析位于“thymeleaf”目录下的webapp目录中的视图。如果我直接在tomcat服务器上部署应用程序,这非常有效。此外,来自其他目录的页面,然后“thymeleaf”目录也由JSF框架解析。

我在JUnit中添加了一些使用SpringBoot的集成测试。在这些测试中,我遇到了问题,百里香现在正试图解决任何目录中的任何页面。 JSF完全被忽略了,因此我得到了一大堆JUnit测试失败。有没有必要为什么百万美元忽略了它的配置并希望解决所有文件? 这是我完整的百万美元配置,正如我所说,如果我将它部署在一个独立的tomcat上,这将完美地运行。

private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
  this.applicationContext = applicationContext;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
  String imagesPattern = "/images/**";
  String imagesLocation = basePath() + "resources/images/";
  registry.addResourceHandler(imagesPattern).addResourceLocations(imagesLocation);
  log.info("added resourceHandler (pathPattern: '{}'), (resourceLocation: '{}')",
           imagesPattern,
           imagesLocation);

  String cssPattern = "/css/**";
  String cssLocation = basePath() + "resources/css/";
  registry.addResourceHandler(cssPattern).addResourceLocations(cssLocation);
  log.info("added resourceHandler (pathPattern: '{}'), (resourceLocation: '{}')", cssPattern, cssLocation);
}

@Bean(name = "basepath")
public String basePath()
{
  String basepath = "";

  File file = new File(Optional.ofNullable(System.getenv("THYMELEAF_APP_RESOURCES"))
                               .orElse("thymeleaf-resources/"));
  if (file.exists())
  {
    basepath = "file:" + file.getAbsolutePath();
  }
  if (!basepath.endsWith("/"))
  {
    basepath += "/";
  }
  log.info("basepath: {}", basepath);
  return basepath;
}

@Bean
@Description("Thymeleaf View Resolver")
public ThymeleafViewResolver viewResolver(String basePath)
{
  log.info("setting up Thymeleaf view resolver");
  ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
  viewResolver.setTemplateEngine(templateEngine(basePath));
  viewResolver.setCharacterEncoding("UTF-8");
  viewResolver.setCache(true);
  return viewResolver;
}

public SpringTemplateEngine templateEngine(String basePath)
{
  log.info("setting up Thymeleaf template engine.");
  SpringTemplateEngine templateEngine = new SpringTemplateEngine();
  templateEngine.setTemplateResolver(templateResolver(basePath));
  templateEngine.setEnableSpringELCompiler(true);
  return templateEngine;
}

private ITemplateResolver templateResolver(String basePath)
{
  log.info("setting up Thymeleaf template resolver");
  SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
  resolver.setApplicationContext(applicationContext);
  resolver.setPrefix(basePath + "thymeleaf/views/");
  resolver.setSuffix(".html");
  resolver.setTemplateMode(TemplateMode.HTML);
  resolver.setCacheable(false);
  return resolver;
}

@Bean
public IMessageResolver thymeleafMessageSource(MessageSource messageSource)
{
  SpringMessageResolver springMessageResolver = new SpringMessageResolver();
  springMessageResolver.setMessageSource(messageSource);
  return springMessageResolver;
}

修改

我刚刚发现问题似乎更深层次。将thymeleaf的依赖项添加到我的pom.xml中似乎足以让spring引导将其加载到上下文中...我刚刚删除了我的ThymeleafConfig类用于测试目的,而且仍然是thymeleaf尝试解析JSF页面...(是的在执行测试之前我做了maven clean)

编辑2

我现在读了它并试图排除ThymeleafAutoConfiguration类,但它没有帮助。我的配置仍然被覆盖。到目前为止,这是我的配置。 (是的,这是整个项目中唯一的EnableAutoConfiguration注释)

    @Configuration
    @EnableAutoConfiguration(exclude = {ThymeleafAutoConfiguration.class})
    @Import({WebAppConfig.class, ThymeleafConfig.class})
    public class SpringBootInitializer extends SpringBootServletInitializer

我的ThymeleafConfig课程已在上面添加。

2 个答案:

答案 0 :(得分:2)

  

将mymeleaf的依赖项添加到我的pom.xml中似乎足以让spring boot加载到上下文中......

如果这让您感到惊讶,那么我建议您花些时间退一步,了解Spring Boot的工作原理,特别是它的自动配置功能。 This section参考文档是一个很好的起点。

简而言之,Spring Boot采用约定优于配置方法。如果依赖关系在类路径上,则Spring Boot假定您要使用它,并使用合理的默认值对其进行配置。这就是它与Thymeleaf一起做的事情。您可以使用excludes上的@SpringBootApplication属性为特定依赖项禁用此自动配置:

@SpringBootApplication(exclude={ThymeleafAutoConfiguration.class})
public class ExampleApplication {

}

您还可以使用spring.autoconfigure.exclude属性提供要排除的逗号分隔的自动配置类列表。列表中的每个条目都应该是auto-configuration class的完全限定名称。您可以将此属性与@TestPropertySource一起使用,以逐个测试地禁用自动配置。

答案 1 :(得分:2)

几个小时来,我一直在努力解决类似问题,终于找到了根本原因。 如果您对pom中的* -data-rest有依赖性,例如:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>

即使您在其他地方都使用另一个模板引擎(Freemarker,JSP等),也必须将Thymeleaf添加到pom中。 原因:将JpaRepository作为休息服务公开Spring Boot需要Thymeleaf。我不明白为什么不将其定义为spring-boot-starter-data-rest的依赖项,以便Maven自动解决它。 我认为这是一个Spring Boot配置错误。