【问题标题】:Springboot - Thymeleaf tries to resolve files it should notSpringboot - Thymeleaf 尝试解析它不应该解析的文件
【发布时间】:2017-11-05 00:39:25
【问题描述】:

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

我在 JUnit 中添加了一些使用 SpringBoot 的集成测试。在这些测试中,我得到了 thymeleaf 现在正在尝试解析任何目录中的任何页面的问题。 JSF 被完全忽略了,因此我的一大堆 JUnit 测试都失败了。 thymeleaf 忽略它的配置并想要解析所有文件有什么意义吗? 这是我完整的 thymeleaf 配置,正如我所说,如果我将它部署在独立的 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 boot 将其加载到上下文中......我刚刚删除了我的 ThymeleafConfig 类用于测试目的,但 thymeleaf 仍然试图解析 JSF 页面......(是的我在执行测试之前做了 maven clean)

编辑 2

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

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

上面已经添加了我的 ThymeleafConfig 类。

【问题讨论】:

    标签: spring spring-boot thymeleaf


    【解决方案1】:

    将 thymeleaf 的依赖项添加到我的 pom.xml 中似乎足以让 Spring Boot 将其加载到上下文中......

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

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

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

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

    【讨论】:

      【解决方案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 配置错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多