Spring Boot 和 Thymeleaf:找不到 HTML 模板 [英] Spring Boot and Thymeleaf: Can't find HTML templates

查看:49
本文介绍了Spring Boot 和 Thymeleaf:找不到 HTML 模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Thymeleaf 创建一个基于 Spring Boot 的应用程序.我使用 PetClinic 示例作为起点.我的应用程序找不到某些模板.

我的项目以标准方式设置:

/src/主/java/com.example我的Web应用程序主控制器.java/资源/静态/css/模板/片段布局.html主页.html应用程序属性

pom.xml

<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.1.RELEASE</version><relativePath/><!-- 从存储库中查找父级 --></父母><属性><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></属性><依赖项><依赖><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></依赖><依赖><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></依赖><依赖><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><范围>测试</范围></依赖><依赖><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></依赖></依赖项>

MyWebApplication.java

@SpringBootApplication公共类 MyWebApplication {公共静态无效主(字符串 [] args){SpringApplication.run(MyWebApplication.class, args);}}

HomeController.java

@Controller公共类 HomeController {@RequestMapping("/")公共字符串家(){返回家";}}

home.html

<html xmlns:th="http://www.thymeleaf.org"xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"th:replace="~{fragments/layout :: layout (~{::body},'home')}"><身体><h2 th:text="#{welcome}">欢迎</h2><div class="row">

</html>

layout.html

<!--定义整体布局的主要布局片段设置导航栏页面内容在主div中被替换--><html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"th:fragment="布局(模板,菜单)"><头><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><!-- <link rel="shortcut icon" type="image/x-icon" th:href="@{/images/favicon.png}">--><title>网络界面</title><link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"/><身体><!-- 导航栏--><nav class="navbar navbar-default" role="navigation"><div class="容器"><div class="navbar-header"><a class="navbar-brand glyphicon glyphicon-home" th:href="@{/}"></a><!-- 折叠小窗口上的菜单栏--><button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#main-navbar"><span class="sr-only">切换导航</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>

<!-- 导航栏项目--><div class="navbar-collapse collapse" id="main-navbar"><ul class="nav navbar-nav navbar-right"><!-- 为每个菜单项定义一个片段--><li th:fragment="menuItem (path, active, title, glyph, text)" th:class="${active==menu ? 'active' : ''}"><a th:href="@{__${path}__}" th:title=${title}><span th:class="'glyphicon glyphicon-'+${glyph}" class="glyphicon glyphicon-home" aria-hidden="true"></span><span th:text="${text}">模板</span></a><!-- 替换为片段--><li th:replace="::menuItem('/', 'home', 'home page', 'home', 'Home')"><span class="glyphicon glyphicon-home" aria-hidden="true"></span><跨度>主页</span>

</nav><!-- 主体--><div class="container-fluid"><div class="container xd-container"><div th:replace="${template}"></div>

<script th:src="@{/js/bootstrap.min.js}" type="text/javascript"></script></html>

application.properties 为空.

当我导航到 http://localhost:8080 时出现错误:

<块引用>

解析模板~{fragments/layout"时出错,模板可能不会存在或可能无法被任何配置的模板访问解析器(首页:5)

如果我从 home.html 中删除 'th:replace' 属性,它将显示欢迎消息.

浏览类似问题(例如这个),我看到其他人创建了 ThymeleafViewResolver bean.

问题:

  1. 为什么它找不到我的模板?
  2. 我需要创建模板解析器吗?如果是这样,为什么宠物诊所样本没有?它的模板解析器来自哪里?

据我所知,它的设置方式与宠物诊所样本相同,那么有什么区别?

解决方案

Spring boot 会自动为您执行一些内部工作,但要执行这些自动工作,您需要正确配置它.这是您的问题 2 的答案,如果配置正确,spring 会自动提供视图解析器.好的,现在让我们转到问题 1.

如果将 pom.xml 与 petclinic 的 pom.xml 进行比较,您会发现一些主要区别.

首先,根据 spring 官方文档 http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-build-systems.html#using-boot-maven,Maven 用户可以从 spring-boot-starter-parent 项目继承以获得合理的默认值.父项目提供了一些功能.要将项目配置为从 spring-boot-starter-parent 继承,只需在 pom.xml 中设置父项即可.

<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.1.RELEASE</version></父母>

通过该设置,您还可以通过覆盖自己项目中的属性来覆盖各个依赖项.例如,在 petclinic pom.xml 中,他们指定了您缺少的 thymeleaf 版本.

3.0.2.RELEASE

现在要正确设置 Thymeleaf 和 Thymeleaf 布局方言版本以及它们之间的兼容性,您需要从 spring-boot-starter-thymeleaf 中排除 thymeleaf-layout-dialect,bcz 将 thymeleaf 版本设置为 3.0.2.RELEASE 版本.

 <依赖><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><排除事项><排除><groupId>nz.net.ultraq.thymeleaf</groupId><artifactId>thymeleaf-layout-dialect</artifactId></排除></排除项></依赖>

I am trying to create a Spring Boot-based application with Thymeleaf. I am using the PetClinic sample as a starting point. My application can't find some of the templates.

My project is set up in the standard way:

/src
 /main
  /java
   /com.example
    MyWebApplication.java
    HomeController.java
  /resources
   /static
    /css
   /templates
    /fragments
     layout.html
    home.html
  application.properties

pom.xml

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

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>                   
</dependencies>

MyWebApplication.java

@SpringBootApplication
public class MyWebApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyWebApplication.class, args);
    }
}

HomeController.java

@Controller
public class HomeController {

    @RequestMapping("/")
    public String home() {
        return "home";
    }
}

home.html

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org" 
      xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
     th:replace="~{fragments/layout :: layout (~{::body},'home')}">
<body>
    <h2 th:text="#{welcome}">Welcome</h2>
        <div class="row">
        </div>
</body>

</html>

layout.html

<!DOCTYPE html>

<!-- 
    The main layout fragment that defines the overall layout
    Sets up the navigation bar
    The page contents are replaced in the main div
 -->
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
        th:fragment="layout (template, menu)">

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- <link rel="shortcut icon" type="image/x-icon" th:href="@{/images/favicon.png}"> -->  

  <title>Web Interface</title>

  <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" />

</head>

<body>

  <!-- Navigation Bar -->
  <nav class="navbar navbar-default" role="navigation">
    <div class="container">
      <div class="navbar-header">
        <a class="navbar-brand glyphicon glyphicon-home" th:href="@{/}"></a>

      <!-- Collapse the menu bar on small windows -->
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#main-navbar">
                  <span class="sr-only">Toggle navigation</span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>         
        </button>      
      </div>

      <!-- The Navbar items -->
      <div class="navbar-collapse collapse" id="main-navbar">
        <ul class="nav navbar-nav navbar-right">

          <!-- Define a fragment for each menu item -->
          <li th:fragment="menuItem (path, active, title, glyph, text)" th:class="${active==menu ? 'active' : ''}">
            <a th:href="@{__${path}__}" th:title=${title}>
              <span th:class="'glyphicon glyphicon-'+${glyph}" class="glyphicon glyphicon-home" aria-hidden="true"></span>
              <span th:text="${text}">Template</span>
            </a>
          </li>

          <!-- Replace with the fragment -->
          <li th:replace="::menuItem ('/', 'home', 'home page', 'home', 'Home')">
            <span class="glyphicon glyphicon-home" aria-hidden="true"></span>
            <span> Home</span>
          </li>                   
        </ul>
      </div>
    </div>
  </nav>

  <!-- Main body -->
  <div class="container-fluid">
    <div class="container xd-container">
      <div th:replace="${template}"></div>
    </div>

  </div>

  <script th:src="@{/js/bootstrap.min.js}" type="text/javascript"></script>

</body>

</html>

application.properties is empty.

When I navigate to http://localhost:8080 I get the error:

Error resolving template "~{fragments/layout", template might not exist or might not be accessible by any of the configured Template Resolvers (home:5)

If I remove the 'th:replace' attribute from home.html, it will display the welcome message.

Browsing similar questions (e.g. this one), I see other people create ThymeleafViewResolver bean.

Questions:

  1. Why can't it find my templates?
  2. Do I need to create a template resolver? If so, how come the pet clinic sample doesn't? Where does its template resolver come from?

As far as I can see it's set up the same way as the pet clinic sample, so what's the difference?

解决方案

Spring boot does some internal works automagically for you, but to do that automagical work you need to configure it properly. This is the answer for your question 2, spring automagically provides the view resolver if configuration is right. Ok, now lets move to question 1.

If you compare your pom.xml with that of petclinic, You'll see some key differences.

At first, According to spring official doc http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-build-systems.html#using-boot-maven, Maven users can inherit from the spring-boot-starter-parent project to obtain sensible defaults. The parent project provides some features. To configure your project to inherit from the spring-boot-starter-parent simply set the parent in your pom.xml.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.1.RELEASE</version>
</parent>

With that setup, you can also override individual dependencies by overriding a property in your own project. For instance, in petclinic pom.xml, they specified the thymeleaf version which is missing in yours.

<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>

Now to properly setup Thymeleaf and Thymeleaf layout dialect version with compatibility between them you need to exclude thymeleaf-layout-dialect from spring-boot-starter-thymeleaf, bcz of setting thymeleaf version to 3.0.2.RELEASE version.

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
      <exclusions>
        <exclusion>
            <groupId>nz.net.ultraq.thymeleaf</groupId>
            <artifactId>thymeleaf-layout-dialect</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

这篇关于Spring Boot 和 Thymeleaf:找不到 HTML 模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆