Thymeleaf模板引擎比较倾向于前端,了解过一点前端的人都会很快上手的。之所以不用JSP模板,是因为他还是原生的Java代码。换句话来说,就是Thymeleaf可以直接查看效果无需启动服务器,反之JSP就不行,必须依赖于服务器。这两种模板属于同一个方向,技术应用是要结合应用场景的。如果单纯从学习角度来看,学习哪个技术都没有错。但如果是要做产品,做项目,那技术选型就非常关键了。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>vip.wulang</groupId> <artifactId>thymeleaf</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <mysql.version>5.1.34</mysql.version> <spring.version>4.3.0.RELEASE</spring.version> <hibernate.version>5.1.0.Final</hibernate.version> <druid.version>1.1.10</druid.version> <jpa.version>1.10.4.RELEASE</jpa.version> <test.version>4.12</test.version> <common.version>3.3.2</common.version> <servlet.version>3.1.0</servlet.version> <fastjson.version>1.2.47</fastjson.version> <slf4j.version>1.7.25</slf4j.version> <aspectj.version>1.8.10</aspectj.version> <validation.version>6.0.13.Final</validation.version> <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version> </properties> <dependencies> <!-- Spring Framework start --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring Framework end --> <!-- Druid start --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- Druid end --> <!-- JPA start --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${jpa.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </exclusion> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> </exclusions> </dependency> <!-- JPA end --> <!-- Hibernate start --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <!-- Hibernate end --> <!-- Mysql start --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- Mysql end --> <!-- Test start --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${test.version}</version> <scope>test</scope> </dependency> <!-- Test end --> <!-- Common start --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${common.version}</version> </dependency> <!-- Common end --> <!-- Servlet start --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <!-- Servlet end --> <!-- FastJson start --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!-- FastJson end --> <!-- Slf4j start --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>${slf4j.version}</version> </dependency> <!-- Slf4j end --> <!-- Aspectj start --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> <!-- Aspectj end --> <!-- Validation start --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>${validation.version}</version> </dependency> <!-- Validation end --> <!-- Thymeleaf start --> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring4</artifactId> <version>${thymeleaf.version}</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>${thymeleaf.version}</version> </dependency> <!-- Thymeleaf end --> </dependencies> </project>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>vip.wulang.config.MyApplicationContext</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>IGTVGController</servlet-name> <servlet-class>vip.wulang.servlet.IGTVGController</servlet-class> </servlet> <servlet-mapping> <servlet-name>IGTVGController</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
package vip.wulang.config; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.web.context.ServletContextAware; import org.thymeleaf.ITemplateEngine; import org.thymeleaf.TemplateEngine; import org.thymeleaf.messageresolver.IMessageResolver; import org.thymeleaf.messageresolver.StandardMessageResolver; import org.thymeleaf.templatemode.TemplateMode; import org.thymeleaf.templateresolver.ITemplateResolver; import org.thymeleaf.templateresolver.ServletContextTemplateResolver; import javax.servlet.ServletContext; import java.io.IOException; import java.util.Properties; /** * @author CoolerWu on 2018/11/20. * @version 1.0 */ @Configuration @ComponentScan("vip.wulang") public class MyApplicationContext implements ApplicationContextAware, ServletContextAware { private static ApplicationContext applicationContext; private static ServletContext servletContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { MyApplicationContext.applicationContext = applicationContext; } public static ApplicationContext getApplicationContext() { return applicationContext; } @Override public void setServletContext(ServletContext servletContext) { MyApplicationContext.servletContext = servletContext; } public static ServletContext getServletContext() { return servletContext; } @Bean public ITemplateResolver templateResolver() { ServletContextTemplateResolver servletContextTemplateResolver = new ServletContextTemplateResolver(servletContext); servletContextTemplateResolver.setTemplateMode(TemplateMode.HTML); servletContextTemplateResolver.setPrefix("/WEB-INF/templates/"); servletContextTemplateResolver.setSuffix(".html"); servletContextTemplateResolver.setCacheTTLMs(3600000L); servletContextTemplateResolver.setCacheable(true); return servletContextTemplateResolver; } @Bean public IMessageResolver messageResolver() throws IOException { ClassPathResource classPathResource = new ClassPathResource("./home.properties"); Properties properties = new Properties(); properties.load(classPathResource.getInputStream()); StandardMessageResolver standardMessageResolver = new StandardMessageResolver(); standardMessageResolver.setDefaultMessages(properties); return standardMessageResolver; } @Bean public ITemplateEngine templateEngine(ITemplateResolver templateResolver, IMessageResolver messageResolver) { TemplateEngine templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(templateResolver); templateEngine.setMessageResolver(messageResolver); return templateEngine; } }
首先,笔者实现了两个接口 ApplicationContextAware、ServletContextAware,Spring启动时会自动注入 ApplicationContext、ServletContext。其次从官方文档来看,我们先要配置 ITemplateResolver Bean,其实就是模板解析器,ServletContextTemplateResolver 是该接口的实现类,并在其中设置前缀、后缀、模板类型、是否缓存、缓存多久等信息。再配置 IMessageResolver Bean,就是消息解析器,这个也可以不用配置。默认/WEB-INF/templates/home.html在同一文件夹中找到属性文件中的消息,并使用与模板相同的名称,例如:
而笔者则是设置的是在根目录中,"./home.properties"。然后就到了最重要的一个环节了,ITemplateEngine 这个接口,就是模板引擎,里面包含了之前了模板解析器、消息解析器等。至少需要配置模板解析器。以后要进行页面跳转也是通过模板引擎,我们可以当成模板引擎就是操作按钮,其他的解析器都是已经在模板引擎装配好了。
package vip.wulang.servlet; import org.thymeleaf.ITemplateEngine; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.WebContext; import vip.wulang.config.MyApplicationContext; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author CoolerWu on 2018/11/20. * @version 1.0 */ public class IGTVGController extends GenericServlet { @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; TemplateEngine templateEngine = ((TemplateEngine) MyApplicationContext.getApplicationContext().getBean(ITemplateEngine.class)); WebContext webContext = new WebContext(request, response, MyApplicationContext.getServletContext(), request.getLocale()); templateEngine.process("home", webContext, response.getWriter()); } }
官方文档介绍,Thymeleaf有一个上下文,这个上下文就是接口 IContext,而 IWebContext 扩展了该基础接口,WebContext 就是实现类。
WebContext ctx = new WebContext(request, response, servletContext, request.getLocale());
这四个构造函数参数中只有三个是必需的,因为如果没有指定系统,将使用系统的默认语言环境(尽管在实际应用程序中不应该发生这种情况)。准备好上下文对象后,现在我们可以告诉模板引擎使用上下文处理模板(通过其名称),并将响应编写器传递给它,以便可以将响应写入它:
templateEngine.process("home", webContext, response.getWriter());
home.welcome=Bienvenido a nuestra tienda de comestibles!!!!
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Good Thymes Virtual Grocery</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" type="text/css" media="all" href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" /> </head> <body> <p th:text="#{home.welcome}">Welcome to our grocery store!</p> </body> </html>
已经搭建完成了,不过需要注意的是:
<html xmlns:th="http://www.thymeleaf.org">
就是增加一个约束空间。只适用于html模板,也可以不可以不写约束语句,即:
<!DOCTYPE html> <html> <head> <title>Good Thymes Virtual Grocery</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" type="text/css" media="all" href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" /> </head> <body> <p data-th-text="#{home.welcome}">Welcome to our grocery store!</p> </body> </html>
这种语句通用于 Thymeleaf 的所有模板。看个人喜好。不启动服务器打开:
启动服务器打开:
更多详情,了解官方文档:https://www.thymeleaf.org/