开发学院

您的位置:首页>教程>正文

教程正文

Thymeleaf 3.0教程:2 虚拟杂货店的例子

  本指南中显示的示例以及本指南未来章节的源代码可以在https://github.com/thymeleaf/thymeleafexamples-gtvg中找到。

2.1 一个杂货店的网站

  为了更好地解释Thymeleaf处理模板所涉及的概念,本教程将使用一个演示应用程序,您可以从项目的网站上下载。

  这个应用程序是一个杂货店的网站,将为我们提供许多场景来展示Thymeleaf的许多特性。

  首先,我们需要一组简单的应用模型实体:通过创建订单销售给客户的产品。我们还将管理对这些产品的评论:

gtvg-model.png

  我们的应用程序还将有一个非常简单的服务层,由包含如下方法的服务对象组成:

public class ProductService {

    ...

    public List<Product> findAll() {
        return ProductRepository.getInstance().findAll();
    }

    public Product findById(Integer id) {
        return ProductRepository.getInstance().findById(id);
    }
    
}

  在网络层,应用程序有一个过滤器,根据请求网址将执行委托给hymeleaf-enabled的命令:

private boolean process(HttpServletRequest request, HttpServletResponse response)
        throws ServletException {
    
    try {

        // This prevents triggering engine executions for resource URLs
        if (request.getRequestURI().startsWith("/css") ||
                request.getRequestURI().startsWith("/images") ||
                request.getRequestURI().startsWith("/favicon")) {
            return false;
        }

        
        /*
         * Query controller/URL mapping and obtain the controller
         * that will process the request. If no controller is available,
         * return false and let other filters/servlets process the request.
         */
        IGTVGController controller = this.application.resolveControllerForRequest(request);
        if (controller == null) {
            return false;
        }

        /*
         * Obtain the TemplateEngine instance.
         */
        ITemplateEngine templateEngine = this.application.getTemplateEngine();

        /*
         * Write the response headers
         */
        response.setContentType("text/html;charset=UTF-8");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        /*
         * Execute the controller and process view template,
         * writing the results to the response writer. 
         */
        controller.process(
                request, response, this.servletContext, templateEngine);
        
        return true;
        
    } catch (Exception e) {
        try {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } catch (final IOException ignored) {
            // Just ignore this
        }
        throw new ServletException(e);
    }
    
}

  这是IGTVGController接口

public interface IGTVGController {

    public void process(
            HttpServletRequest request, HttpServletResponse response,
            ServletContext servletContext, ITemplateEngine templateEngine);    
}

  我们现在要做的就是创建IGTVGController接口的实现,从服务中检索数据,并使用ITemplateEngine对象处理模板。

  最终,它会是这样的:

gtvg-view.png

  但是首先让我们看看模板引擎是如何初始化的。

2.2 创建和配置模板引擎

  过滤器中的process(…)方法包含以下行:

ITemplateEngine templateEngine = this.application.getTemplateEngine();

  这意味着GTVGApplication类负责创建和配置Thymeleaf应用程序中最重要的对象之一:模板引擎实例(ITemplateEngine接口的实现)。

  org.thymeleaf.TemplateEngine 对象是这样初始化的:

public class GTVGApplication {
  
    
    ...
    private final TemplateEngine templateEngine;
    ...
    
    
    public GTVGApplication(final ServletContext servletContext) {

        super();

        ServletContextTemplateResolver templateResolver = 
                new ServletContextTemplateResolver(servletContext);
        
        // HTML is the default mode, but we set it anyway for better understanding of code
        templateResolver.setTemplateMode(TemplateMode.HTML);
        // This will convert "home" to "/WEB-INF/templates/home.html"
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        // Template cache TTL=1h. If not set, entries would be cached until expelled
        templateResolver.setCacheTTLMs(Long.valueOf(3600000L));
        
        // Cache is set to true by default. Set to false if you want templates to
        // be automatically updated when modified.
        templateResolver.setCacheable(true);
        
        this.templateEngine = new TemplateEngine();
        this.templateEngine.setTemplateResolver(templateResolver);
        
        ...

    }

}

  配置TemplateEngine对象的方法有很多,但目前这几行代码将教会我们足够多的必要步骤。

模板解析器

  让我们从模板解析器开始:

ServletContextTemplateResolver templateResolver = 
        new ServletContextTemplateResolver(servletContext);
Template Resolvers are objects that implement an interface from the Thymeleaf API called org.thymeleaf.templateresolver.ITemplateResolver:

public interface ITemplateResolver {

    ...
  
    /*
     * Templates are resolved by their name (or content) and also (optionally) their 
     * owner template in case we are trying to resolve a fragment for another template.
     * Will return null if template cannot be handled by this template resolver.
     */
    public TemplateResolution resolveTemplate(
            final IEngineConfiguration configuration,
            final String ownerTemplate, final String template,
            final Map<String, Object> templateResolutionAttributes);
}

  这些对象负责决定如何访问我们的模板,在这个GTVG应用程序中,org.thymeleaf.templateresolver.ServletContextTemplateResolver意味着我们将从Servlet上下文中检索模板文件作为资源:一个存在于每个Java网络应用程序中的应用程序范围的javax.servlet.ServletContext对象,它解析来自网络应用程序根的资源。

  但这不是我们能说的关于模板解析器的全部,因为我们可以在它上面设置一些配置参数。首先,模板模式:

templateResolver.setTemplateMode(TemplateMode.HTML);

  HTML是ServletContextTemplateResolver的默认模板模式,但是最好还是建立它,以便我们的代码清楚地记录正在发生的事情。

templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");

  前缀和后缀修改模板名称,我们将传递给引擎以获得要使用的真实资源名称。

  使用此配置,模板名称“product/list”将对应于:

servletContext.getResourceAsStream("/WEB-INF/templates/product/list.html")

  或者,在模板解析器中,通过cacheTTLMs属性配置解析后的模板在缓存中的驻留时间:

templateResolver.setCacheTTLMs(3600000L);

  如果达到最大缓存大小,并且模板是当前缓存的最早条目,则在达到TTL之前,仍可以将其从缓存中排除。

  缓存行为和大小可以由用户通过实现ICacheManager接口或通过修改StandardCacheManager对象来管理默认缓存来定义。

  关于模板解析器还有很多要学习的,但是现在让我们来看看模板引擎对象的创建。

模板引擎

  模板引擎对象是org.thymeleaf.ITemplateEngine接口的实现。Thymeleaf核心:org.thymeleaf.TemplateEngine提供了其中的一个实现,我们在这里创建了一个实例:

templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);

  相当简单,不是吗?我们只需要创建一个实例,并为其设置模板解析器。

  模板解析器是模板引擎唯一需要的参数,尽管后面还会介绍许多其他参数(消息解析器、缓存大小等)。目前,这就是我们所需要的。

  我们的模板引擎现在准备好了,我们可以开始使用Thymeleaf创建我们的页面。