Spring Boot对Thymeleaf的支持

一 点睛

Spring Boot通过org.springframework.boot.autoconfigure.thymeleaf包对Thymeleaf进行自动配置,相关代码如下图所示:

通过ThymeleafAutoConfiguration类对集成所需要的Bean进行自动配置,包括TemplateResolver、TemplateEngine和thymeleafViewResolver的配置。

二 源码解读

1 ThymeleafProperties类

@ConfigurationProperties("spring.thymeleaf")
public class ThymeleafProperties {

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

    public static final String DEFAULT_SUFFIX = ".html";

    private boolean checkTemplateLocation = true;

    /**
     * 前缀设置,Spring Boot默认属性,放置在classpath:/templates/目录下
     */
    private String prefix = DEFAULT_PREFIX;

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

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

    /**
     * 模板的编码设置,默认为UTF-8
     */
    private String encoding = "UTF-8";

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

    private boolean cache = true;

    private String[] viewNames;

    private String[] excludedViewNames;

    private boolean enabled = true;
}

2 ThymeleafAutoConfiguration源码解读

package org.springframework.boot.autoconfigure.thymeleaf;
......

@Configuration
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass(SpringTemplateEngine.class)
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
public class ThymeleafAutoConfiguration {

    @Configuration
    @ConditionalOnMissingBean(name = "defaultTemplateResolver")
    public static class DefaultTemplateResolverConfiguration {

        @Autowired
        private ThymeleafProperties properties;

        @Autowired
        private ApplicationContext applicationContext;

        @PostConstruct
        public void checkTemplateLocationExists() {
            boolean checkTemplateLocation = this.properties.isCheckTemplateLocation();
            if (checkTemplateLocation) {
                TemplateLocation location = new TemplateLocation(
                        this.properties.getPrefix());
                Assert.state(location.exists(this.applicationContext),
                        "Cannot find template location: " + location
                                + " (please add some templates or check "
                                + "your Thymeleaf configuration)");
            }
        }

        @Bean
        public TemplateResolver defaultTemplateResolver() {
            TemplateResolver resolver = new TemplateResolver();
            resolver.setResourceResolver(thymeleafResourceResolver());
            resolver.setPrefix(this.properties.getPrefix());
            resolver.setSuffix(this.properties.getSuffix());
            resolver.setTemplateMode(this.properties.getMode());
            resolver.setCharacterEncoding(this.properties.getEncoding());
            resolver.setCacheable(this.properties.isCache());
            return resolver;
        }

        @Bean
        public SpringResourceResourceResolver thymeleafResourceResolver() {
            return new SpringResourceResourceResolver();
        }
    }

    @Configuration
    @ConditionalOnMissingBean(SpringTemplateEngine.class)
    protected static class ThymeleafDefaultConfiguration {

        @Autowired
        private final Collection<ITemplateResolver> templateResolvers = Collections
                .emptySet();

        @Autowired(required = false)
        private final Collection<IDialect> dialects = Collections.emptySet();

        @Bean
        public SpringTemplateEngine templateEngine() {
            SpringTemplateEngine engine = new SpringTemplateEngine();
            for (ITemplateResolver templateResolver : this.templateResolvers) {
                //将templateResolver加入到SpringTemplateEngine
                engine.addTemplateResolver(templateResolver);  
            }
            for (IDialect dialect : this.dialects) {
                engine.addDialect(dialect);
            }
            return engine;
        }

    }

    @Configuration
    @ConditionalOnClass(name = "nz.net.ultraq.thymeleaf.LayoutDialect")
    protected static class ThymeleafWebLayoutConfiguration {

        @Bean
        public LayoutDialect layoutDialect() {
            return new LayoutDialect();
        }

    }

    @Configuration
    @ConditionalOnClass(DataAttributeDialect.class)
    protected static class DataAttributeDialectConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public DataAttributeDialect dialect() {
            return new DataAttributeDialect();
        }

    }

    @Configuration
    @ConditionalOnClass({ SpringSecurityDialect.class })
    protected static class ThymeleafSecurityDialectConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public SpringSecurityDialect securityDialect() {
            return new SpringSecurityDialect();
        }

    }

    @Configuration
    @ConditionalOnClass(ConditionalCommentsDialect.class)
    protected static class ThymeleafConditionalCommentsDialectConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public ConditionalCommentsDialect conditionalCommentsDialect() {
            return new ConditionalCommentsDialect();
        }

    }

    @Configuration
    @ConditionalOnClass({ Servlet.class })
    @ConditionalOnWebApplication
    protected static class ThymeleafViewResolverConfiguration {

        //注入属性
        @Autowired
        private ThymeleafProperties properties;

        @Autowired
        private SpringTemplateEngine templateEngine;

        @Bean
        @ConditionalOnMissingBean(name = "thymeleafViewResolver")
        @ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
        public ThymeleafViewResolver thymeleafViewResolver() {
            ThymeleafViewResolver resolver = new ThymeleafViewResolver();
            resolver.setTemplateEngine(this.templateEngine);  //将SpringTemplateEngine加入到ThymeleafViewResolver
            resolver.setCharacterEncoding(this.properties.getEncoding());
            resolver.setContentType(appendCharset(this.properties.getContentType(),
                    resolver.getCharacterEncoding()));
            resolver.setExcludedViewNames(this.properties.getExcludedViewNames());
            resolver.setViewNames(this.properties.getViewNames());
            // This resolver acts as a fallback resolver (e.g. like a
            // InternalResourceViewResolver) so it needs to have low precedence
            resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5);
            return resolver;
        }

        private String appendCharset(String type, String charset) {
            if (type.contains("charset=")) {
                return type;
            }
            return type + ";charset=" + charset;
        }

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值