在Spring boot中,官方默认采用的是Thymeleaf模块引擎,通过org.springframework.boot.autoconfigure.thymeleaf包对Thymeleaf进行了自动配置。

通过Thymeleaf2Configuration类对集成所需要的Bean进行自动配置,包括templateResolver、templateViewResolver 和templateEngine 的配置。

通过ThymeleafProperties来配置Thymeleaf,在application.properties中以 spring.thymeleaf开头来配置,通过查看ThymeleafProperties的主要源码,可以看出如何设置属性及默认配置:

/*
 * Copyright 2012-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure.thymeleaf;

import java.nio.charset.Charset;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.MimeType;

/**
 * Properties for Thymeleaf.
 *
 * @author Stephane Nicoll
 * @since 1.2.0
 */
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

	private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");

	private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");

	public static final String DEFAULT_PREFIX = "classpath:/templates/";

	public static final String DEFAULT_SUFFIX = ".html";

	/**
	 * 在渲染之前检查模板是否存在(Thymeleaf 3+)。
	 */
	private boolean checkTemplate = true;

	/**
	 * 检查模板位置是否存在。
	 */
	private boolean checkTemplateLocation = true;

	/**
	 * Spring boot 默认模板路径,默认在classpath:/templates/目录下
	 */
	private String prefix = DEFAULT_PREFIX;

	/**
	 * 后缀设置,默认为html.
	 */
	private String suffix = DEFAULT_SUFFIX;

	/**
	 * 模板模式设置,默认为html5
	 */
	private String mode = "HTML5";

	/**
	 * 模板的编码设置,默认UTF-8
	 */
	private Charset encoding = DEFAULT_ENCODING;

	/**
	 * 模板的媒体类型设置,默认为text/html
	 */
	private MimeType contentType = DEFAULT_CONTENT_TYPE;

	/**
	 * 是否开启模板缓存,默认是开启的,开发时建议关闭
	 */
	private boolean cache = true;

	/**
	 * Order of the template resolver in the chain. By default, the template resolver is
	 * first in the chain. Order start at 1 and should only be set if you have defined
	 * additional "TemplateResolver" beans.
	 */
	private Integer templateResolverOrder;

	/**
	 * Comma-separated list of view names that can be resolved.
	 */
	private String[] viewNames;

	/**
	 * Comma-separated list of view names that should be excluded from resolution.
	 */
	private String[] excludedViewNames;

	/**
	 * Enable MVC Thymeleaf view resolution.
	 */
	private boolean enabled = true;

	public boolean isEnabled() {
		return this.enabled;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public boolean isCheckTemplate() {
		return this.checkTemplate;
	}

	public void setCheckTemplate(boolean checkTemplate) {
		this.checkTemplate = checkTemplate;
	}

	public boolean isCheckTemplateLocation() {
		return this.checkTemplateLocation;
	}

	public void setCheckTemplateLocation(boolean checkTemplateLocation) {
		this.checkTemplateLocation = checkTemplateLocation;
	}

	public String getPrefix() {
		return this.prefix;
	}

	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	public String getSuffix() {
		return this.suffix;
	}

	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}

	public String getMode() {
		return this.mode;
	}

	public void setMode(String mode) {
		this.mode = mode;
	}

	public Charset getEncoding() {
		return this.encoding;
	}

	public void setEncoding(Charset encoding) {
		this.encoding = encoding;
	}

	public MimeType getContentType() {
		return this.contentType;
	}

	public void setContentType(MimeType contentType) {
		this.contentType = contentType;
	}

	public boolean isCache() {
		return this.cache;
	}

	public void setCache(boolean cache) {
		this.cache = cache;
	}

	public Integer getTemplateResolverOrder() {
		return this.templateResolverOrder;
	}

	public void setTemplateResolverOrder(Integer templateResolverOrder) {
		this.templateResolverOrder = templateResolverOrder;
	}

	public String[] getExcludedViewNames() {
		return this.excludedViewNames;
	}

	public void setExcludedViewNames(String[] excludedViewNames) {
		this.excludedViewNames = excludedViewNames;
	}

	public String[] getViewNames() {
		return this.viewNames;
	}

	public void setViewNames(String[] viewNames) {
		this.viewNames = viewNames;
	}

}

以上关于ThymeleafProperties类的中文注释,为个人根据代码理解及其原代码英文注释而来。

在spring boot中整合Thymeleaf需要加入对Thymeleaf的依赖:

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

创建一个HelloController 类,通过spring mvc 返回页面,来通过Thymeleaf渲染一个页面。

import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping(value = "/hello")
    public String hello(ModelMap map){
        // 加入一个属性,用来在模板中读取
        map.addAttribute("host", "http://www.baikeyang.com");
        // return模板文件的名称,对应src/main/resources/templates/index.html
        return "index";
    }

}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
    <meta charset="UTF-8" >
    <title></title>
</head>
<body>
<h1 th:text="${host}">Hello World</h1>
<br/>
</body>
</html>

直接打开html页面展现Hello World,但是启动程序后,访问http://localhost:8080/hello,则是展示Controller中host的值:http://www.baikeyang.com,做到了不破坏HTML自身内容的数据逻辑分离。

#Thymeleaf配置

#Thymeleaf模板模式
spring.thymeleaf.mode = HTML5
#Thymeleaf 编码
spring.thymeleaf.encoding = UTF-8
#模板缓存(热部署静态文件)
spring.thymeleaf.cache = false
#spring.thymeleaf.prefix=classpath:/templates/:指定Thymeleaf的页面文件放置的位置(也就是页面文件的前缀),这里的classpath:/templates/指的目录就是src/resources/templates,所以需要创建templates这个目录(默认是没有这个目录的)
spring.thymeleaf.prefix = classpath:/templates/
#检查模板位置是否存在
spring.thymeleaf.check-template-location = true
#指定页面文件的后缀,这里配置所有页面文件都是.html的文件
spring.thymeleaf.suffix = .html
#内容类型
spring.thymeleaf.content-type = text/html

启动项目,直接访问,会有一个异常抛出:

org.xml.sax.SAXParseException: 元素类型 "meta" 必须由匹配的结束标记 "</meta>" 终止。

spring.thymeleaf.mode的默认值是HTML5,其实是一个很严格的检查,对.html的内容要求很严格,比如<meta charset="UTF-8" />,如果少最后的标签封闭符号/,就会报错而转到错误页。也比如你在使用<br/>、<link>、<meta>这样的html标签,也会被thymeleaf认为不符合要求而抛出错误。

因为,我可以调整spring.thymeleaf.mode,改为LEGACYHTML5可以得到一个可能更友好亲切的格式要求。

需要注意的是,LEGACYHTML5需要搭配一个额外的库NekoHTML才可用。需要给项目添加NekoHTML的依赖:

<dependency>
	<groupId>net.sourceforge.nekohtml</groupId>
	<artifactId>nekohtml</artifactId>
	<version>1.9.22</version>
</dependency>

最后重启项目就可以感受到不那么严格的thymeleaf了,访问正常。

 

 

标签: Spring Boot, Thymeleaf, Spring Boot 之 Thymeleaf 篇

添加新评论