Spring boot:thymeleaf 没有正确渲染片段

Posted

技术标签:

【中文标题】Spring boot:thymeleaf 没有正确渲染片段【英文标题】:Spring boot: thymeleaf is not rendering fragments correctly 【发布时间】:2017-08-17 04:26:02 【问题描述】:

我正在创建 Spring Boot Web 应用程序。出于模板目的,我使用的是百里香。我正在创建单独的 html 页面片段,并从这些片段中创建两个不同的布局。但是,当我连接内容页面时,我没有得到正确的输出。

请检查代码sn-ps/

查看解析器

@Configuration
@EnableAutoConfiguration
@PropertySource("classpath:application.properties")
public class WebConfig extends WebMvcConfigurerAdapter 

@Bean
public TemplateResolver templateResolver() 
    ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
    templateResolver.setPrefix("/WEB-INF/views/");
    templateResolver.setSuffix(".html");
    templateResolver.setTemplateMode("html5");
    return templateResolver;


@Bean
public SpringTemplateEngine setTemplateEngine() 
    SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
    springTemplateEngine.setTemplateResolver(templateResolver());
    return springTemplateEngine;


@Bean
public ViewResolver viewResolver()
    ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
    viewResolver.setTemplateEngine(setTemplateEngine());
    viewResolver.setOrder(1);
    return viewResolver;

目录结构

src/
  main/
    webapp/
        WEB-INF/
            views/
                fragments/
                         header.html
                         footer.html
                         navBar.html
                layouts/
                         appLayout.html
                         baseLayout.html
                 welcome.html

appLayout.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

<head>
</head>
<body>

<div th:replace="/fragments/header :: header"></div>
<div th:replace="/fragments/navbar :: navbar"></div>
<div class="container">
    <div layout:fragment="content">
    <p>Content goes here...</p>
    </div>
    <footer>
    <div th:replace="/fragments/footer :: footer"></div>
    </footer>
</div>
</body>
</html>

页脚片段footer.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
    <div th:fragment="footer">
    Footer
    </div>
</body>
</html>

使用此方法创建不同的片段。

主方法类又名启动

@ComponentScan(basePackages="xyz.abc")
@SpringBootApplication
public class AppApplication 

    public static void main(String[] args) 
        System.out.println("Started");
        SpringApplication.run(AppApplication.class, args);
    

welcome.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~layouts/appLayout">

<head>
</head>

<body>
<th:block layout:fragment="content">
    <div class="hero-unit">
    <h1>My Content</h1>
    </div>
</th:block>
</body>
</html>

现在当我访问服务器时,我只得到welcome.html 而没有从appLayoutfragments 得到任何东西

我错过了什么? 还有一个问题,我经历了许多项目,其中一些将views 保留在src/main/resource 之下,而我将其保留在src/main/web/WEB-INF 之下这两种方法有什么区别?

【问题讨论】:

第二个问题请看this。 非常感谢。 您是否已将LayoutDialect 添加到SpringTemplateEngine 中? 没有。它是什么?以及如何/为什么要写它? 尝试删除片段路径中的正斜杠 【参考方案1】:

这是一个完整的例子。

Gradle 依赖:

compile('org.springframework.boot:spring-boot-starter-thymeleaf')

如果你想使用 spring-security dialect [optional] 添加这个:

  compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.2.RELEASE")

在 SpringBoot 上,您不需要视图配置,所有视图都应该转到: src/resources/templates

这是否意味着模板目录下的所有视图都是公开的?不。

我应该将可公开访问的静态文件(js 和 css)放在哪里?src/resources/templates/static

如何创建布局?

在 Thymleaf 中,很容易处理垂直和水平视图片段关系。

1。垂直布局关系:

假设您有一个母版页 包括所有常见的 js 和 css 文件、侧导航、应用栏导航 ..等等。几乎所有的人都会垂直继承这种观点 视图,因此在这种情况下,您希望以某种方式嵌入所有视图 在您的母版页中。假设您有employee_list 页面;当用户请求employee_list 页面时,employee_list 页面将被插入到您的主布局中,并且用户将看到employee_list 页面+ 母版页面元素。

母版页: 在此页面上,您只需添加layout:fragment="content"content 是将嵌入此页面的子视图片段的名称。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      xmlns:sec="http://www.w3.org/1999/xhtml">
<head>

</head>

<body>

    <div id = "page_wrapper">

        <div id="side_menu">
            <!--side menu content-->
        </div>


        <div id="content_wrapper">

            <!--page content-->
            <div layout:fragment="content">

            </div>

        </div>

        <script type="text/javascript" th:inline="javascript">

           //common js here

            /* ]]> */

        </script>

    </div>

</body>

</html>

员工列表页面: 要将employee_list 页面放入主页面,您只需将layout:decorator="layouts/master" 添加到页面的html 标记。我已将所有布局放在 src/resources/templates/layouts 目录下,这就是为什么我使用 layouts/master 而只是说 master。还要注意layout:fragment="content"属性;此属性表示此视图中的任何内容都将嵌入到母版页中。

 <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org"
          xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
          layout:decorator="layouts/master">

    <body>

        <div id = "content" class = "content layout-list" layout:fragment="content">

            <div>

               <table>

              </table>

            </div>

        </div>

    </body>

    </html>

结果:


横向布局关系:

如果您想包含一个通用视图而不是像我们在前面的示例中那样垂直继承它怎么办?在上面的例子中说你想在你的employee_list 页面上包含一个分页视图;在这种情况下,关系变成水平的。

分页片段: 顺便说一句,这是一个工作示例; Page 类是我自己创建的自定义类,用于包装分页响应。这是一个非常简单的课程,我所做的只是将响应列表和分页信息放入其中。 片段名称使用th:fragment="pagination" 表示

<div th:if = "$page.totalNumberOfItems > 0 and page.numberOfItems > 0" class = "pagination-wrapper" th:fragment="pagination" xmlns:th="http://www.thymeleaf.org">

    <div class = "valign-wrapper right">

        <div id = "items_per_page_wrapper">

            <div class="valign-wrapper">

                <span  th:text="#ui.pagination.rows.per.page.label" style="padding-right: 10px">Rows per page:</span>

                <select  id="items_per_page_select" name = "itemsPerPage">
                    <option th:each="items_per_page : $page.ITEMS_PER_PAGE_OPTIONS_LIST" th:text="$items_per_page" th:value = "$items_per_page" th:selected="$items_per_page == $page.itemsPerPage">10</option>
                </select>

            </div>

        </div>

        <label  class="current_page_info"
                th:text="#ui.pagination.current.page.info($page.currentPageFirstItemNumber, $page.currentPageLastItemNumber, $page.totalNumberOfItems)"></label>

        <ul class="pagination right">

            <li th:classappend="$page.pageNumber > 0  ? '' : 'disabled'">
                <a id="previous_page_link" href="javascript:void(0)">
                    <i class="material-icons">navigate_before</i>
                </a>
            </li>

            <li th:classappend="$page.currentPageLastItemNumber == page.totalNumberOfItems ? 'disabled' : ''">
                <a id="next_page_link"  href="javascript:void(0)">
                    <i class="material-icons">navigate_next</i>
                </a>
            </li>
        </ul>

    </div>

</div>

员工列表页面: 在 table 标签下添加这个 sn-p。

  <div th:replace="common/pagination :: pagination">
        <!--pagination content-->
    </div>

结果:

【讨论】:

你是如何使用外部jsCSS文件的? 和往常一样,你把 test.csd 放到资源/静态目录中。要包含它,您将使用路径 /test.css。 Js 文件也是如此。希望能帮助到你。抱歉,我现在不在笔记本电脑旁。【参考方案2】:

如果您使用的是 Spring Boot,则无需定义视图解析器来呈现 html 页面。

@SpringBootApplication 注解等效于使用@Configuration、@EnableAutoConfiguration 和@ComponentScan。所以你可能不需要定义@ComponentScan。

我还看到,如果您使用的是 Spring Boot,则不需要定义这些 bean。资源下的模板目录可以直接访问,无需定义 bean。因此,通过使用 thymeleaf,您可以轻松地从控制器返回视图。

视图保存在 spring mvc 中的 src/main/web/WEB-INF 下。但是在 Spring Boot 上,视图保存在模板目录下,可以从控制器返回,而无需进行任何视图解析器配置。

对于您的百里香叶问题,您可以在 github 上查看。

https://github.com/sagar1limbu/bookstore

【讨论】:

但在 WEB-INF 下保持视图将保护直接访问。 ***.com/questions/19786142/…

以上是关于Spring boot:thymeleaf 没有正确渲染片段的主要内容,如果未能解决你的问题,请参考以下文章

没有 Thymeleaf 的 Spring Boot 安全性

i18n 在 spring-boot / thymeleaf 项目中它没有检索本地化消息

Spring Boot 仅针对没有 thymeleaf 登录的用户显示注销按钮

Spring Boot:在没有控制器的情况下使用 thymeleaf 处理 html 文件

Spring Boot 最佳实践模板引擎Thymeleaf集成

Spring Boot 最佳实践模板引擎Thymeleaf集成