Spring Boot与Thymeleaf集成

JSP在内嵌Servlet容器上运行有些问题(内嵌Tomcate、Jetty不支持以jar的形式运行JSP,Undertow不支持JSP)。

Spring Boot 默认使用Thymeleaf模板,因为Thymeleaf模板提供了完美的Spring MVC支持,可以完全替代JSP。

1 Thymeleaf基础知识

Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点:

  1. Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
  2. Thymeleaf 开箱即用的特性。它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
  3. Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。

Thymeleaf 是一个Java类库,它是一个xml/xhtml/html5的模板引擎,可以作为MVC的Web应用的View层。

示例

<html xmlns:th="http://www.thymeleaf.org"><!-- 通过这个命名空间将静态视图转换成动态的,需要动态的处理的元素前面加上th: -->
  <head>
  	 <meta content="text/html;charset=UTF-8"/>
  	 <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
     <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <link th:href="@{bootstrap/css/bootstrap.min.css}" rel="stylesheet"/> <!-- 通过@{}来对静态资源的引用 -->
    <link th:href="@{bootstrap/css/bootstrap-theme.min.css}" rel="stylesheet"/>
  </head>
  <body>
  
  <div class="panel panel-primary">
    <div class="panel-heading">
        <h3 class="panel-title">访问model</h3>
    </div>
    <div class="panel-body">
    		<!-- ${}访问Mode中的属性(注解要加上th: 前缀) -->
        	<span th:text="${singlePerson.name}"></span> 
    </div>
  </div>
  
  <div th:if="${not #lists.isEmpty(people)}"> <!-- if判断(<、>、<=、>=、==、 !=、也支持SpringEL) -->
	  <div class="panel panel-primary">
	    <div class="panel-heading">
	        <h3 class="panel-title">列表</h3>
	    </div>
	    <div class="panel-body">
	        <ul class="list-group">
	        	<!-- 迭代 -->
				<li class="list-group-item" th:each="person:${people}">
				    <span th:text="${person.name}"></span>
				   	<span th:text="${person.age}"></span>
				   	<button class="btn" th:onclick="'getName(\'' + ${person.name} + '\');'">获得名字</button>
				</li>
	        </ul>
	    </div>
	 </div>
 </div>
  
  <script th:src="@{jquery-1.10.2.min.js}" type="text/javascript"></script><!-- 2 -->
  <script th:src="@{bootstrap/js/bootstrap.min.js}"></script><!-- 2 -->
  
  <script th:inline="javascript"> // th:inline="javascript" 添加到script标签可以访问mdel中的属性
  	var single = [[${singlePerson}]];
  	console.log(single.name+"/"+single.age)
  	
  	function getName(name){
  		console.log(name);
  	}
  </script>
  
  </body>
 </html>

2 与Spring MVC的集成

在Spring MVC中我们如果要集成一个模板引擎的话,需要定义ViewResolver,而ViewResolver需要定义一个View,如我们为jsp定义的ViewResolver:

@Bean
public InternalResourceViewResolver viewResolver() {
	InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
	viewResolver.setPrefix("/WEB-INF/classes/views/");// 运行时代码会将页面自动编译到/WEB-INF/classes/views/下
	viewResolver.setSuffix(".jsp");
	viewResolver.setViewClass(JstlView.class);
	return viewResolver;
}

使用JstlView定义了一个InternalResourceViewResolver。所以使用Thymeleaf作为我的模板也需要做类似的定义。Thymeleaf为我们提供了org.thymeleaf.spring4.view.ThymeleafView和org.thymeleaf.spring4.view.ThymeleafViewResolver(默认使用ThymeleafView作为View)。Thymeleaf为我们提供了SpringTemplateEngine类,用来驱动在Spring MVC下使用Thymeleaf模板引擎,另外还提供了一个TemplateResolver类来设置通用的模板引擎(前缀、后缀等)。如下:

@Bean
public TemplateResolver templateResolver() {
	TemplateResolver templateResolver = new ServletContextTemplateResolver();
	templateResolver.setPrefix("/WEB-INF/templates/");
	templateResolver.setSuffix(".html");
	templateResolver.setTemplateMode("HTML5");
	return templateResolver;
}

@Bean
public SpringTemplateEngine templateEngine() {
	SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
	springTemplateEngine.setTemplateResolver(templateResolver());
	return springTemplateEngine;
}

@Bean
public ThymeleafViewResolver thymeleafViewEngine() {
	ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
	thymeleafViewResolver.setTemplateEngine(templateEngine());
	// thymeleafViewResolver.setViewClass(ThymeleafView.class);
	return thymeleafViewResolver;
}

3 Spring Boot对Thymeleaf的支持

Spring Boot通过org.springframework.boot.autoconfigure.thymeleaf包对thymeleaf进行自动配置。如图:

image

通过ThymeleafAutoConfiguration对集成所需的Bean进行自动配置,包括templateResolver、templateEngine和thymeleafResolver的配置。

通过ThymeleafProperties配置Thymeleaf,再application.properties文件中以spring.thymeleaf开头,通过源码我们可以看出如何设置属性和默认值:

package org.springframework.boot.autoconfigure.thymeleaf;

import java.nio.charset.Charset;

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

@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";

	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;

	/**
	 * 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;

	...

}

3.1 示例Bean

package com.chenfeng.xiaolyuh.entity;

public class Person {
	private String name;
	private Integer age;
	
	public Person() {
		super();
	}
	public Person(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}

}

3.2 脚本样式静态文件

静态资源放在/src/main/resources/static目录下,如图:

image

3.3 演示页面 页面默认放在/src/main/resources/templates,在该文件下建立index.html文件:

image

代码如下:

<html xmlns:th="http://www.thymeleaf.org"><!-- 通过这个命名空间将静态视图转换成动态的,需要动态的处理的元素前面加上th: -->
  <head>
  	 <meta content="text/html;charset=UTF-8"/>
  	 <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
     <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <link th:href="@{bootstrap/css/bootstrap.min.css}" rel="stylesheet"/> <!-- 通过@{}来对静态资源的引用 -->
    <link th:href="@{bootstrap/css/bootstrap-theme.min.css}" rel="stylesheet"/>
  </head>
  <body>
  
  <div class="panel panel-primary">
    <div class="panel-heading">
        <h3 class="panel-title">访问model</h3>
    </div>
    <div class="panel-body">
    		<!-- ${}访问Mode中的属性(注解要加上th: 前缀) -->
        	<span th:text="${singlePerson.name}"></span> 
    </div>
  </div>
  
  <div th:if="${not #lists.isEmpty(people)}">
	  <div class="panel panel-primary">
	    <div class="panel-heading">
	        <h3 class="panel-title">列表</h3>
	    </div>
	    <div class="panel-body">
	        <ul class="list-group">
	        	<!-- 迭代 -->
				<li class="list-group-item" th:each="person:${people}">
				    <span th:text="${person.name}"></span>
				   	<span th:text="${person.age}"></span>
				   	<button class="btn" th:onclick="'getName(\'' + ${person.name} + '\');'">获得名字</button>
				</li>
	        </ul>
	    </div>
	 </div>
 </div>
  
  <script th:src="@{jquery-1.10.2.min.js}" type="text/javascript"></script><!-- 2 -->
  <script th:src="@{bootstrap/js/bootstrap.min.js}"></script><!-- 2 -->
  
  <script th:inline="javascript"> // th:inline="javascript" 添加到script标签可以访问mdel中的属性
  	var single = [[${singlePerson}]];
  	console.log(single.name+"/"+single.age)
  	
  	function getName(name){
  		console.log(name);
  	}
  </script>
  
  </body>
</html>

3.4 控制层代码

package com.chenfeng.xiaolyuh;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.chenfeng.xiaolyuh.entity.Person;
import com.chenfeng.xiaolyuh.properties.AuthorSettings;

@SpringBootApplication
@Controller
public class SpringBootStudentApplication {
	
	@RequestMapping("index")
	public String index(Model model){
		Person single = new Person("aa",11);
		
		List<Person> people = new ArrayList<Person>();
		Person p1 = new Person("xx",11);
		Person p2 = new Person("yy",22);
		Person p3 = new Person("zz",33);
		people.add(p1);
		people.add(p2);
		people.add(p3);
		
		model.addAttribute("singlePerson", single);
		model.addAttribute("people", people);
		
		return "index";
	}

	// 标准的JAVA应用main方法,主要作用作为项目启动的入口
	public static void main(String[] args) {
		SpringApplication.run(SpringBootStudentApplication.class, args);
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值