diff --git a/mybatis-spring-boot-autoconfigure/src/main/java/org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfiguration.java b/mybatis-spring-boot-autoconfigure/src/main/java/org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfiguration.java index d5fcf4f99..2324d681f 100644 --- a/mybatis-spring-boot-autoconfigure/src/main/java/org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfiguration.java +++ b/mybatis-spring-boot-autoconfigure/src/main/java/org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfiguration.java @@ -20,10 +20,10 @@ import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver; import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriverConfig; import org.mybatis.scripting.velocity.Driver; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -37,9 +37,11 @@ @ConditionalOnClass(LanguageDriver.class) public class MybatisLanguageDriverAutoConfiguration { + private static final String CONFIGURATION_PROPERTY_PREFIX = "mybatis.scripting-language-driver"; + @Configuration @ConditionalOnClass(FreeMarkerLanguageDriver.class) - static class FreeMarkerConfiguration { + public static class FreeMarkerConfiguration { @Bean @ConditionalOnMissingBean FreeMarkerLanguageDriver freeMarkerLanguageDriver() { @@ -49,7 +51,7 @@ FreeMarkerLanguageDriver freeMarkerLanguageDriver() { @Configuration @ConditionalOnClass(Driver.class) - static class VelocityConfiguration { + public static class VelocityConfiguration { @Bean @ConditionalOnMissingBean Driver velocityLanguageDriver() { @@ -59,11 +61,18 @@ Driver velocityLanguageDriver() { @Configuration @ConditionalOnClass(ThymeleafLanguageDriver.class) - static class ThymeleafConfiguration { + public static class ThymeleafConfiguration { + @Bean + @ConditionalOnMissingBean + ThymeleafLanguageDriver thymeleafLanguageDriver(ThymeleafLanguageDriverConfig config) { + return new ThymeleafLanguageDriver(config); + } + @Bean @ConditionalOnMissingBean - ThymeleafLanguageDriver thymeleafLanguageDriver(ObjectProvider configProvider) { - return new ThymeleafLanguageDriver(configProvider.getIfAvailable(ThymeleafLanguageDriverConfig::newInstance)); + @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".thymeleaf") + public ThymeleafLanguageDriverConfig thymeleafLanguageDriverConfig() { + return ThymeleafLanguageDriverConfig.newInstance(); } } diff --git a/mybatis-spring-boot-autoconfigure/src/site/xdoc/index.xml.vm b/mybatis-spring-boot-autoconfigure/src/site/xdoc/index.xml.vm index 6bb488b1d..f068d8bc6 100644 --- a/mybatis-spring-boot-autoconfigure/src/site/xdoc/index.xml.vm +++ b/mybatis-spring-boot-autoconfigure/src/site/xdoc/index.xml.vm @@ -317,13 +317,21 @@ public class CityDao { - configuration + configuration.* - A MyBatis Configuration bean. About available properties see the MyBatis reference page. + A MyBatis Configuration bean. About available nested properties see the MyBatis reference page. NOTE This property cannot be used at the same time with the config-location. + + + scripting-language-driver.thymeleaf.* + + + A MyBatis Thymeleaf Configuration bean. About available nested properties see the MyBatis Thymeleaf reference page. + + diff --git a/mybatis-spring-boot-autoconfigure/src/test/java/org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfigurationTest.java b/mybatis-spring-boot-autoconfigure/src/test/java/org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfigurationTest.java index 66b513d5c..5c448ba3b 100644 --- a/mybatis-spring-boot-autoconfigure/src/test/java/org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfigurationTest.java +++ b/mybatis-spring-boot-autoconfigure/src/test/java/org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfigurationTest.java @@ -15,6 +15,8 @@ */ package org.mybatis.spring.boot.autoconfigure; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Map; import org.apache.ibatis.mapping.BoundSql; @@ -25,6 +27,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver; +import org.mybatis.scripting.thymeleaf.TemplateEngineCustomizer; import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver; import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriverConfig; import org.mybatis.scripting.velocity.Driver; @@ -32,6 +35,7 @@ import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; +import org.thymeleaf.TemplateEngine; import static org.assertj.core.api.Assertions.assertThat; @@ -66,6 +70,17 @@ void testDefaultConfiguration() { assertThat(languageDriverBeans.get("freeMarkerLanguageDriver")).isInstanceOf(FreeMarkerLanguageDriver.class); assertThat(languageDriverBeans.get("velocityLanguageDriver")).isInstanceOf(Driver.class); assertThat(languageDriverBeans.get("thymeleafLanguageDriver")).isInstanceOf(ThymeleafLanguageDriver.class); + ThymeleafLanguageDriverConfig config = this.context.getBean(ThymeleafLanguageDriverConfig.class); + assertThat(config.isUse2way()).isEqualTo(true); + assertThat(config.getDialect().getPrefix()).isEqualTo("mb"); + assertThat(config.getDialect().getLikeAdditionalEscapeTargetChars()).isNull(); + assertThat(config.getDialect().getLikeEscapeChar()).isEqualTo('\\'); + assertThat(config.getDialect().getLikeEscapeClauseFormat()).isEqualTo("ESCAPE '%s'"); + assertThat(config.getTemplateFile().getBaseDir()).isEqualTo(""); + assertThat(config.getTemplateFile().getCacheTtl()).isNull(); + assertThat(config.getTemplateFile().getEncoding()).isEqualTo(StandardCharsets.UTF_8); + assertThat(config.getTemplateFile().getPatterns()).hasSize(1).contains("*.sql"); + assertThat(config.getCustomizer()).isNull(); } @Test @@ -89,6 +104,54 @@ void testCustomThymeleafConfig() { assertThat(boundSql.getParameterObject()).isEqualTo(10); assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id"); assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class); + ThymeleafLanguageDriverConfig config = this.context.getBean(ThymeleafLanguageDriverConfig.class); + assertThat(config.isUse2way()).isEqualTo(true); + assertThat(config.getDialect().getPrefix()).isEqualTo("m"); + assertThat(config.getDialect().getLikeAdditionalEscapeTargetChars()).isNull(); + assertThat(config.getDialect().getLikeEscapeChar()).isEqualTo('\\'); + assertThat(config.getDialect().getLikeEscapeClauseFormat()).isEqualTo("ESCAPE '%s'"); + assertThat(config.getTemplateFile().getBaseDir()).isEqualTo(""); + assertThat(config.getTemplateFile().getCacheTtl()).isNull(); + assertThat(config.getTemplateFile().getEncoding()).isEqualTo(StandardCharsets.UTF_8); + assertThat(config.getTemplateFile().getPatterns()).hasSize(1).contains("*.sql"); + assertThat(config.getCustomizer()).isNull(); + } + + @Test + void testCustomThymeleafConfigUsingConfigurationProperty() { + TestPropertyValues.of("mybatis.scripting-language-driver.thymeleaf.use2way=false", + "mybatis.scripting-language-driver.thymeleaf.dialect.like-additional-escape-target-chars=*,?", + "mybatis.scripting-language-driver.thymeleaf.dialect.like-escape-char=~", + "mybatis.scripting-language-driver.thymeleaf.dialect.like-escape-clause-format=escape '%s'", + "mybatis.scripting-language-driver.thymeleaf.dialect.prefix=mybatis", + "mybatis.scripting-language-driver.thymeleaf.template-file.base-dir=sqls", + "mybatis.scripting-language-driver.thymeleaf.template-file.cache-enabled=false", + "mybatis.scripting-language-driver.thymeleaf.template-file.cache-ttl=1234", + "mybatis.scripting-language-driver.thymeleaf.template-file.encoding=Windows-31J", + "mybatis.scripting-language-driver.thymeleaf.template-file.patterns=*.sql,*.sqlf", + "mybatis.scripting-language-driver.thymeleaf.customizer=org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfigurationTest$MyTemplateEngineCustomizer") + .applyTo(this.context); + this.context.register(MyAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class); + this.context.refresh(); + ThymeleafLanguageDriver driver = this.context.getBean(ThymeleafLanguageDriver.class); + SqlSource sqlSource = driver.createSqlSource(new Configuration(), + "SELECT * FROM users WHERE id = [# mybatis:p='id' /]", Integer.class); + BoundSql boundSql = sqlSource.getBoundSql(10); + assertThat(boundSql.getSql()).isEqualTo("SELECT * FROM users WHERE id = ?"); + assertThat(boundSql.getParameterObject()).isEqualTo(10); + assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id"); + assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class); + ThymeleafLanguageDriverConfig config = this.context.getBean(ThymeleafLanguageDriverConfig.class); + assertThat(config.isUse2way()).isEqualTo(false); + assertThat(config.getDialect().getPrefix()).isEqualTo("mybatis"); + assertThat(config.getDialect().getLikeAdditionalEscapeTargetChars()).hasSize(2).contains('*', '?'); + assertThat(config.getDialect().getLikeEscapeChar()).isEqualTo('~'); + assertThat(config.getDialect().getLikeEscapeClauseFormat()).isEqualTo("escape '%s'"); + assertThat(config.getTemplateFile().getBaseDir()).isEqualTo("sqls"); + assertThat(config.getTemplateFile().getCacheTtl()).isEqualTo(1234); + assertThat(config.getTemplateFile().getEncoding()).isEqualTo(Charset.forName("Windows-31J")); + assertThat(config.getTemplateFile().getPatterns()).hasSize(2).contains("*.sql", "*.sqlf"); + assertThat(config.getCustomizer()).isEqualTo(MyTemplateEngineCustomizer.class); } @Test @@ -129,4 +192,10 @@ ThymeleafLanguageDriverConfig thymeleafLanguageDriverConfig() { } } + public static class MyTemplateEngineCustomizer implements TemplateEngineCustomizer { + @Override + public void customize(TemplateEngine defaultTemplateEngine) { + } + } + }