Spring Boot ~ Thymeleaf。
Spring Boot 默认不支持 jsp。
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
- 自动装配。
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties
关键信息。
public static final String DEFAULT_PREFIX = “classpath:/templates/”;
public static final String DEFAULT_SUFFIX = “.html”;
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.boot.autoconfigure.thymeleaf;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.http.MediaType;
import org.springframework.util.MimeType;
import org.springframework.util.unit.DataSize;
@ConfigurationProperties(
prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
private Charset encoding;
private boolean cache;
private Integer templateResolverOrder;
private String[] viewNames;
private String[] excludedViewNames;
private boolean enableSpringElCompiler;
private boolean renderHiddenMarkersBeforeCheckboxes;
private boolean enabled;
private final ThymeleafProperties.Servlet servlet;
private final ThymeleafProperties.Reactive reactive;
public ThymeleafProperties() {
this.encoding = DEFAULT_ENCODING;
this.cache = true;
this.renderHiddenMarkersBeforeCheckboxes = false;
this.enabled = true;
this.servlet = new ThymeleafProperties.Servlet();
this.reactive = new ThymeleafProperties.Reactive();
}
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 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;
}
public boolean isEnableSpringElCompiler() {
return this.enableSpringElCompiler;
}
public void setEnableSpringElCompiler(boolean enableSpringElCompiler) {
this.enableSpringElCompiler = enableSpringElCompiler;
}
public boolean isRenderHiddenMarkersBeforeCheckboxes() {
return this.renderHiddenMarkersBeforeCheckboxes;
}
public void setRenderHiddenMarkersBeforeCheckboxes(boolean renderHiddenMarkersBeforeCheckboxes) {
this.renderHiddenMarkersBeforeCheckboxes = renderHiddenMarkersBeforeCheckboxes;
}
public ThymeleafProperties.Reactive getReactive() {
return this.reactive;
}
public ThymeleafProperties.Servlet getServlet() {
return this.servlet;
}
static {
DEFAULT_ENCODING = StandardCharsets.UTF_8;
}
public static class Reactive {
private DataSize maxChunkSize = DataSize.ofBytes(0L);
private List<MediaType> mediaTypes;
private String[] fullModeViewNames;
private String[] chunkedModeViewNames;
public Reactive() {
}
public List<MediaType> getMediaTypes() {
return this.mediaTypes;
}
public void setMediaTypes(List<MediaType> mediaTypes) {
this.mediaTypes = mediaTypes;
}
public DataSize getMaxChunkSize() {
return this.maxChunkSize;
}
public void setMaxChunkSize(DataSize maxChunkSize) {
this.maxChunkSize = maxChunkSize;
}
public String[] getFullModeViewNames() {
return this.fullModeViewNames;
}
public void setFullModeViewNames(String[] fullModeViewNames) {
this.fullModeViewNames = fullModeViewNames;
}
public String[] getChunkedModeViewNames() {
return this.chunkedModeViewNames;
}
public void setChunkedModeViewNames(String[] chunkedModeViewNames) {
this.chunkedModeViewNames = chunkedModeViewNames;
}
}
public static class Servlet {
private MimeType contentType = MimeType.valueOf("text/html");
private boolean producePartialOutputWhileProcessing = true;
public Servlet() {
}
public MimeType getContentType() {
return this.contentType;
}
public void setContentType(MimeType contentType) {
this.contentType = contentType;
}
public boolean isProducePartialOutputWhileProcessing() {
return this.producePartialOutputWhileProcessing;
}
public void setProducePartialOutputWhileProcessing(boolean producePartialOutputWhileProcessing) {
this.producePartialOutputWhileProcessing = producePartialOutputWhileProcessing;
}
}
}
- namespace。
<html xmlns:th="http://www.thymeleaf.org">
- controller。
package com.geek.demothymeleaf.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map;
@Controller
public class BootController {
@RequestMapping("/welcome")
public String request(Map<String, Object> map) {
// 给 thymeleaf 准备数据。
map.put("welcome", "welcome, Thymeleaf.");
return "result";
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:id="${welcome}" th:text="${welcome}">Welcome to our grocery store!</p>
</body>
</html>
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#attribute-precedence
th:text # <h1>hello</h1> // 转义。
th:utext # <h1>hello</h1> // 不转义。原样输出。
- 符号。
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#standard-expression-syntax
Simple expressions:
Variable Expressions: ${...}
Selection Variable Expressions: *{...}
Message Expressions: #{...}
Link URL Expressions: @{...}
Fragment Expressions: ~{...}
- 遍历。
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#iteration
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:id="${welcome}" th:text="${welcome}">Welcome to our grocery store!</p>
<table>
<tr>
<th>NAME</th>
<th>PRICE</th>
<th>IN STOCK</th>
</tr>
<tr th:each="prod : ${prods}">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<!--<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>-->
</tr>
</table>
</body>
</html>
package com.geek.demothymeleaf.controller;
import com.geek.demothymeleaf.entity.Product;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Controller
public class BootController {
@RequestMapping("/welcome")
public String request(Map<String, Object> map) {
// 给 thymeleaf 准备数据。
map.put("welcome", "welcome, Thymeleaf.");
List<Product> prods = new ArrayList<>();
prods.add(new Product("a", 100, 10));
prods.add(new Product("b", 200, 20));
prods.add(new Product("c", 200, 30));
map.put("prods", prods);
return "result";
}
}
Spring Boot 默认不支持 jsp。
Spring Boot 默认自带一个内置的 Tomcat,不需要打 war 包,直接打 jar 包就可以运行。
但如果要整合 jsp 开发,就需要单独配置一个外置的 Tomcat,需要打 war 包。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
provided:将项目打包时,不需要将内置的 Tomcat 一起打包。
package com.geek.springbootjsp;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class SpringBootStartApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
// return super.configure(builder);
return builder.sources(SpringbootJspApplication.class);
}
}
- application.properties。
spring.mvc.view.prefix=/WEB/INF/
spring.mvc.view.suffix=.jsp
controller。
package com.geek.springbootjsp.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map;
@Controller
public class WebController {
@RequestMapping("/hello")
public String welcome(Map<String, Object> map) {
map.put("name", "geek");
return "index";
}
}
如果是 Spring Boot 项目,在启动 Tomcat 服务器时,会自动调用 com.geek.springbootjsp.ServletInitializer 类中的 configure(); 方法。
package com.geek.springbootjsp;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringbootJspApplication.class);
}
}
会启动 Spring Boot。