当前位置: 首页 > 知识库问答 >
问题:

为什么没有找到Thymeleaf模板?

唐弘和
2023-03-14

我有一个Spring Boot 2.1.6应用程序(Spring 5),我想使用Thymeleaf作为我的模板引擎。我按照在线教程来设置我的项目,视图和控制器,当我想启动它时,我注意到Thymeleaf抱怨说它找不到任何模板:

2019-07-12T17:14:25,269 WARN  [main] o.s.b.a.t.ThymeleafAutoConfiguration$DefaultTemplateResolverConfiguration: Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)

我想我设置的项目,因为它应该是(至少根据教程和论坛,我可以找到):

src/main/
    java/
        a.b.c.MyController
        rest of the classes and packages
    resources/
        static/
            css/
                bootstrap.min.css
                main.css
            js/
                bootstrap.min.js
                jquery-3.4.1.min.js
                login.js
                main.js
        templates/
            login.html
            main.html

我的控制器如下所示:

@ApiOperation(value = "Get login page", nickname = "login", notes = "", tags = { "My App", })
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@GetMapping(value = { "/", "/login" })
@ResponseStatus(code = HttpStatus.OK)
public String login(Model model, String error, String logout) {
    if (error != null) {
        model.addAttribute("error", "Your username and/or password is invalid.");
    }

    if (logout != null) {
        model.addAttribute("message", "You have been logged out successfully.");
    }

    return "login";
}

login.html是这样的:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>My App :: Login</title>
        <link rel="stylesheet" type="text/css" href="@{/css/bootstrap.min.css}">
        <link rel="stylesheet" type="text/css" href="@{/css/main.css}">
    </head>
    <body>
        <h1>My App</h1>

        <div class="container">
            <form id="userform" method="post"  action="#" th:action="@{/authenticate}" th:object="${userForm}" class="form-signin">
                <h2 class="form-heading">Log In</h2>

                <span>${message}</span>

                <div class="form-group ${status.error ? 'has-error' : ''}">
                    <input type="text" class="form-control" placeholder="Username" autofocus th:field="*{username}"></input>
                </div>

                <input name="password" id="password" type="password" class="form-control" placeholder="Password" th:field="*{password}"/>

                <input type="hidden" th:name="${ _csrf.parameterName }" th:value="${ _csrf.token }"/>
                <button class="btn btn-lg btn-primary btn-block" type="submit">Log In</button>
            </form>
        </div>

        <script src="@{/js/jquery-3.4.1.min.js}"></script>
        <script src="@{/js/bootstrap.min.js}"></script>
        <script src="@{/js/login.js}"></script>
    </body>
</html>

当我打开登录页面时,我得到一个简单的超文本标记语言页面,正文中写着“登录”一词。

我发现这很奇怪,Thymeleaf正在“classpath:/templates/”中查找模板,这应该是正确的,因为我在应用程序中配置了log4j2 XML。属性作为“日志记录”。config=classpath:log4j2-${spring.profiles.active}。xml',该xml位于同一src/main/resources文件夹中。那么,在那里找不到templates文件夹的原因是什么呢?

更新:

我忘了提一下:我试图从Eclipse中运行它作为Spring Boot应用程序,也试图用Maven作为mvn Spring-boot: run运行它,结果相同。

另外,我正在使用Java12。我的pom。xml如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>my.groupid</groupId>
    <artifactId>my.artifactid</artifactId>
    <packaging>war</packaging>
    <name>MyApp</name>
    <version>${baseversion}.${gitcommitcount}.${buildnumber}</version>
    <description>My App</description>

    <properties>
        <baseversion>1.0.0</baseversion>
        <java.version>12</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <springfox-version>2.9.2</springfox-version>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>

        <buildnumber>0</buildnumber>
        <gitcommitcount>0</gitcommitcount>
    </properties>

    <distributionManagement>
        <repository>
            <id>id</id>
            <name>Internal Local Releases</name>
            <url>http://x.x.x.x:xxxx/repository/local_release/</url>
        </repository>
        <snapshotRepository>
            <id>id</id>
            <name>Internal Local Snapshots</name>
            <url>http://x.x.x.x:xxxx/repository/local_snapshot/</url>
        </snapshotRepository>
    </distributionManagement>

    <repositories>
        <repository>
            <id>id</id>
            <url>x.x.x.x:xxxx/repository/local_group/</url>
        </repository>
    </repositories>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <build>
        <finalName>${project.name}</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <excludes>
                    <!--
                    Will need to be excluded from final WAR
                    <exclude>*.properties</exclude>
                    <exclude>*.xml</exclude>
                    -->
                </excludes>
                <includes>
                    <!-- Include is only for running locally -->
                    <include>*.properties</include>
                    <include>*.xml</include>
                </includes>
            </resource>
        </resources>
        <sourceDirectory>src/main/java</sourceDirectory>

        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <release>12</release>
                    <compilerArgs>
                        <arg>--enable-preview</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <argLine>--enable-preview</argLine>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <configuration>
                    <argLine>--enable-preview</argLine>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                            <goal>build-info</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <jvmArguments>--enable-preview</jvmArguments>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <archiveClasses>false</archiveClasses>
                    <warSourceDirectory>WebContent</warSourceDirectory>
                    <archive>
                        <manifestEntries>
                            <Built-On>${maven.build.timestamp} UTC</Built-On>
                            <ModuleName>${project.name}</ModuleName>
                            <ModuleVersion>${project.version}</ModuleVersion>
                        </manifestEntries>
                        <manifestSections>
                            <manifestSection>
                                <name>Release section</name>
                                <manifestEntries>
                                    <BaseVersion>${baseversion}</BaseVersion>
                                    <BuildNumber>${buildnumber}</BuildNumber>
                                    <GITRevision>${gitrevision}</GITRevision>
                                </manifestEntries>
                            </manifestSection>
                        </manifestSections>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>rename-wars</id>
                        <phase>install</phase>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <executable>scripts/rename-wars.bat</executable>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- Logging -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <!--SpringFox dependencies -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${springfox-version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${springfox-version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.joschi.jackson</groupId>
            <artifactId>jackson-datatype-threetenbp</artifactId>
            <version>2.6.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- JWT -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.10.6</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.10.6</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.10.6</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- Commons HttpClient -->
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <!-- Commons IO -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <!-- Oracle JDBC -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc8</artifactId>
            <version>12.2.0.1.0</version>
        </dependency>
        <!-- CSV parsing -->
        <dependency>
            <groupId>com.opencsv</groupId>
            <artifactId>opencsv</artifactId>
            <version>4.6</version>
        </dependency>
        <!-- Javax Mail for email validation -->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>
        <!-- Configuration -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- Actuator to gather metrics and health -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- JSON -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20180813</version>
        </dependency>
        <!-- Testing dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>com.vaadin.external.google</groupId>
                    <artifactId>android-json</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.restdocs</groupId>
            <artifactId>spring-restdocs-mockmvc</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

更新2:application.properties

server.port=9080
spring.profiles.active=dev
spring.jackson.date-format=a.b.c.RFC3339DateFormat
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
logging.config=classpath:log4j2-${spring.profiles.active}.xml

# Setting session timeout
server.servlet.session.timeout=10m

# ThymeLeaf settings
spring.thymeleaf.cache=false
spring.thymeleaf.check-template=true
spring.thymeleaf.check-template-location=true
spring.thymeleaf.enabled=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

# dbcp2 settings
spring.datasource.dbcp2.test-while-idle=true
spring.datasource.dbcp2.test-on-borrow=true
spring.datasource.dbcp2.test-on-return=false
spring.datasource.dbcp2.validation-query=select 1 from dual
spring.datasource.dbcp2.validation-query-timeout=30000
spring.datasource.dbcp2.time-between-eviction-runs-millis=30000
spring.datasource.dbcp2.min-evictable-idle-time-millis=30000
spring.datasource.dbcp2.initial-size=10
spring.datasource.dbcp2.max-total=20
spring.datasource.dbcp2.pool-prepared-statements=true
spring.datasource.dbcp2.log-abandoned=true
spring.datasource.dbcp2.log-expired-connections=true
spring.datasource.dbcp2.max-wait-millis=1000
spring.datasource.dbcp2.remove-abandoned-on-borrow=true
spring.datasource.dbcp2.remove-abandoned-on-maintenance=true
spring.datasource.dbcp2.remove-abandoned-timeout=60
spring.datasource.dbcp2.num-tests-per-eviction-run=3
spring.datasource.dbcp2.default-auto-commit=true

# File upload settings
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1

# Actuator settings

# Actuator endpoint settings
management.endpoint.shutdown.enabled=true
management.endpoint.health.enabled=true
management.endpoint.health.show-details=always
management.endpoint.metrics.enabled=true
management.endpoint.loggers.enabled=true
management.endpoint.info.enabled=true
management.endpoints.web.exposure.include=health,metrics,loggers,info
management.health.cassandra.enabled=false
management.health.couchbase.enabled=false
management.health.db.enabled=true
management.health.diskspace.enabled=true
management.health.diskspace.path=/
management.health.elasticsearch.enabled=false
management.health.influxdb.enabled=false
management.health.ldap.enabled=false
management.health.mail.enabled=false
management.health.mongo.enabled=false
management.health.neo4j.enabled=false
management.health.rabbit.enabled=false
management.health.redis.enabled=false
management.health.solr.enabled=false

# App info for actuator
info.app.name=My App
info.app.description=My App
info.app.version=1.0.0
info.customer=My App

更新3:添加了模板和视图解析程序,如下所示:

@Configuration
public class TemplateBeans implements WebMvcConfigurer {

    @Autowired
    private ServletContext servletContext;

    @Bean
    @Description("Thymeleaf template resolver serving HTML5")
    public ServletContextTemplateResolver templateResolver() {
        ServletContextTemplateResolver servletContextTemplateResolver = new ServletContextTemplateResolver(
                servletContext);

        servletContextTemplateResolver.setPrefix("classpath:/templates/");
        servletContextTemplateResolver.setCacheable(false);
        servletContextTemplateResolver.setSuffix(".html");
        servletContextTemplateResolver.setTemplateMode("HTML5");
        servletContextTemplateResolver.setCharacterEncoding("UTF-8");

        return servletContextTemplateResolver;
    }

    @Bean
    @Description("Thymeleaf template engine with Spring integration")
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();

        springTemplateEngine.setTemplateResolver(templateResolver());

        return springTemplateEngine;
    }

    @Bean
    @Description("Thymeleaf view resolver")
    public ViewResolver viewResolver() {
        ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();

        thymeleafViewResolver.setTemplateEngine(templateEngine());
        thymeleafViewResolver.setCharacterEncoding("UTF-8");

        return thymeleafViewResolver;
    }
}

有了这个,我得到例外:

2019-07-15T14:43:21,382 DEBUG [http-nio-9080-exec-3] o.s.w.s.FrameworkServlet: Failed to complete request: org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "/classpath:/templates/login.html")
2019-07-15T14:43:21,389 ERROR [http-nio-9080-exec-3] o.a.j.l.DirectJDKLog: Servlet.service() for servlet [dispatcherServlet] in context with path [/AICGDPR] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "/classpath:/templates/login.html")] with root cause
java.io.FileNotFoundException: ServletContext resource "/classpath:/templates/login.html" does not exist

我还尝试使用ClassLoaderTemplateResolver而不是ServletContextTemplateResolver,但得到了一个稍微不同的异常:

2019-07-15T14:48:54,208 DEBUG [http-nio-9080-exec-1] o.s.w.s.FrameworkServlet: Failed to complete request: org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "classpath:/templates/login.html")
2019-07-15T14:48:54,217 ERROR [http-nio-9080-exec-1] o.a.j.l.DirectJDKLog: Servlet.service() for servlet [dispatcherServlet] in context with path [/AICGDPR] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "classpath:/templates/login.html")] with root cause
java.io.FileNotFoundException: ClassLoader resource "classpath:/templates/login.html" could not be resolved

共有3个答案

燕涵容
2023-03-14

最终使用了JSP。第一次尝试时效果完美。

薛华奥
2023-03-14

嘿,我也有同样的问题。过了很长时间,我发现我缺少类级映射。例如,我正在为我的案例编写以下代码:

@Controller
public class ProviderController {
    @GetMapping(value = "providers")
    public String getAllProviders(Model model){
        model.addAttribute("roomReservations", null);
        return "provider";
    }

而且Eyleaf没有发现我的观点。我使用以下代码解决了这个问题:

@RequestMapping(value = "providers")
@Controller
public class ProviderController {
@GetMapping
    public String getAllProviders(Model model){
        model.addAttribute("roomReservations", null);
        return "provider";
    }

我希望它也能解决你的问题。

孙海
2023-03-14

将登录页面的位置更改为静态而不是模板。应该是如下,

resources/static/login。html而不是资源/模板/登录。html

不要忘记在控制器中指定扩展名,return“login.html”

(希望您已经配置了视图解析器,否则您的endpoint将返回字符串“login.html”)

 类似资料:
  • 我正在jsf应用程序(使用JBoss 7)中使用Apache FOP 2.0来创建pdf文件。但是如果我想包含 svg,我会收到以下错误: 图像不可用。URI:image/svg.svg。原因:org.apache.xmlgraphics.image.loader。ImageException:不支持该文件格式。未找到image/svg的ImagePreloader。svg(无可用上下文信息):o

  • 问题内容: 我刚刚安装并测试了elasticsearch,它看起来很棒,我需要知道一些东西,我有一个配置文件 在目录中 并且我插入了一个包含一个单词的文档,如果我搜索关键字, 它说什么也没找到… 在索引之前它不会干或我在配置中错过了一些东西.... 问题答案: 您的查询看起来如何? 您的配置看起来不太好。尝试:

  • 这个问题解决了。请看下面的核对答案。 注入点有以下注释:-@org.springframework.beans.factory.annotation.autowired(required=true) 行动: 考虑在您的配置中定义一个类型为'DAO.UserRepository'的bean。 进程结束,退出代码为%1

  • 控制台中出现以下错误: 我的文件夹文件: 那么,虽然存在,但为什么我会出现错误呢?

  • 展示了如何调试问题,即PHP模块没有加载到PHP中。 我使用OpenSUSEV42。2个Linux操作系统,带有Apache Web服务器,PHP v7。1、Mysql。 因为它不提供PHPV7。1我需要,我构建了PHPV7。1来源。使用PHP-FPM。 我把它安装到 php.ini在: 我发现,opcache安装到 我编辑了php。ini并添加了以下行: 重新启动: 但我还是得到了以下结果: [

  • 我使用MVC页面中的Kendo DatePicker值构建了一个模型: 但是,如果我输入值,而不是单击日历并选择日期,它在这里不会得到值。我怎样才能得到这个数据?