Spring boot 小ネタ

こんにちわ、猫好きリーマンのほげPGです。
今回は 以下の小ネタを紹介します。
・別名の設定ファイルを読み込ませる
・設定値一覧を表示する
・velocityをテンプレートエンジンで使う
・thymeleafをViewとは別のテンプレートエンジンでも使う
・DataSource名がぶつかるのを回避する設定
・Tomcat起動バッチ
1、別名の設定ファイルを読み込ませる
環境変数 spring.config.name に application,env と指定すれば、application.properties(yml)以外にenv.properties(yml) も読み込んでくれます。
WebApp.java
@EnableAutoConfiguration
@ComponentScan()
@Slf4j
public class WebApp extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
log.info("called.");
return application.sources(WebApp.class)
.properties("spring.config.name=application,env");
}
public static void main(String[] args) throws ClassNotFoundException {
log.info("called. {}", Arrays.deepToString(args));
new SpringApplicationBuilder(WebApp.class)
.properties("spring.config.name=application,env")
.run(args);
}
}
※tomcatでも動くようにしてみました。同じコードなのがいまいちなのですが、わざわざstaticメソッドを作るのもいやなので妥協しました。
実際にenv.ymlに以下を定義して実行すると、読み込まれたのが確認出来ます。
env: local
HogeConfig.java
@Configuration
@Slf4j
public class HogeConfig {
@Value("${env}")
String env;
@PostConstruct
public void init() {
log.info("env: {}", env);
}
}
2、設定値一覧を表示する
StandardEnvironmentから気合で取れました。
@Configuration
@Slf4j
public class HogeConfig {
@Autowired
StandardEnvironment environment;
@PostConstruct
public void init() {
MutablePropertySources sources = environment.getPropertySources();
for (PropertySource<?> p : sources) {
String name = p.getName();
Object source = p.getSource();
if (source instanceof Map) {
Map<?, ?> map = (Map<?, ?>) source;
log.debug("{}: {}, {}", name, source.getClass(), map.size());
for (Map.Entry<?, ?> entry : map.entrySet()) {
log.debug(" {}: {}", entry.getKey(), entry.getValue());
}
} else {
log.debug("{}: {}", name, source.getClass());
}
}
}
}
※actuatorを使えば簡単に確認できます。
Pom.xml に以下を指定
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.yml に以下を設定
management.endpoints.web.exposure.include: "*"
webアプリを起動したら、以下のURL(上:設定、下:bean)をpostmanやcurlで呼出、jsonを整形。
http://localhost:8080/hoge/actuator/env
http://localhost:8080/hoge/actuator/beans
3、velocityをテンプレートエンジンで使う
Spring boot 2 だと自動で設定してくれないので自前で設定する必要があります。
Pom.xml
<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency>
application.yml
mail.velocity: resource.loader: class class.resource.loader.class: org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader input.encoding: UTF-8 output.encoding: UTF-8
※prefixやsuffixを設定する機能はClasspathResourceLoaderには用意されていません。
HogeConfig.java
@Configuration
@Slf4j
public class HogeConfig {
@Bean("velocityProperties")
@ConfigurationProperties(prefix = "mail.velocity")
public Properties velocityProperties() {
return new Properties();
}
@Bean
public VelocityEngine velocityEngine(@Qualifier("velocityProperties") Properties props) {
log.debug("props: {}", props);
VelocityEngine velocityEngine = new VelocityEngine(props);
velocityEngine.init();
return velocityEngine;
}
}
テンプレート src/main/resources/mail/hoge.vm
ほげ(velocity):$now
使用サンプル
@Autowired
VelocityEngine velocityEngine;
public String hoge2(…) throws IOException {
…
StringWriter writer = new StringWriter();
VelocityContext ctx = new VelocityContext();
ctx.put("now", new Date());
Template template = velocityEngine.getTemplate("mail/hoge.vm");
template.merge(ctx, writer);
String body = writer.toString();
log.debug("body: {}", body);
…
}
実行結果
2019-12-23 15:43:21 DEBUG xec-1 (HogeController.java:53) hoge2 - body: ほげ(velocity):Mon Dec 23 15:43:21 JST 2019
4、thymeleafをViewとは別のテンプレートエンジンでも使う
Webのviewerでも使いたいので、TemplateEngineはnewせず、TemplateResolverをいい感じに生成するだけになります。
application.yml
mail.thymeleaf: prefix: /mail/ suffix: .txt templateMode: TEXT characterEncoding: utf-8 cacheable:: false order: 1 check-existence: true
※重要なのはorderでリゾルバの順序を指定するのとcheck-existenceをtrueにしてテンプレートが見つからなかった場合に例外にしないことです
HogeConfig.java
@Configuration
@Slf4j
public class HogeConfig {
@Bean("thymeleaf-resolver")
@ConfigurationProperties(prefix = "mail.thymeleaf")
public ClassLoaderTemplateResolver mailThymeleafResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
return templateResolver;
}
}
テンプレート src/main/resources/mail/hoge-body.txt
ほげ(thymeleaf):[[${now}]]
使用サンプル
@Autowired
TemplateEngine mailTemplateEngine;
public String hoge3(…) throws IOException {
…
Context ctx = new Context(Locale.JAPANESE);
ctx.setVariable("now", new Date());
String body = mailTemplateEngine.process("hoge-body", ctx);
log.debug("body: {}", body);
…
}
実行結果
2019-12-23 15:55:53 DEBUG xec-1 (HogeController.java:70) hoge3 - body: ほげ(thymeleaf):Mon Dec 23 15:55:52 JST 2019
WebView が機能することも確認。
ブラウザからほげる

ログ
2019-12-23 16:57:47 DEBUG xec-1 (HogeController.java:65) hoge3 - called. 2019-12-23 16:57:48 DEBUG xec-1 (HogeController.java:70) hoge3 - body: ほげ(thymeleaf):Mon Dec 23 16:57:47 JST 2019
5、DataSource名がぶつかるのを回避する設定
DataSourceをデフォルト設定で使っているWebアプリが2つ以上動作しようとすると、起動時に以下の例外が出ます。
Unable to register MBean [HikariDataSource (null)] with key ‘dataSource’; nested exception is javax.management.InstanceAlreadyExistsException: com.zaxxer.hikari:name=dataSource,type=HikariDataSource
これを回避する設定は以下となります。
spring.jmx.default-domain: hoge-web
※hoge-webは自分自身のアプリ名など
6、Tomcat起動バッチ
環境変数設定やサービス設定をしたくないので、以下のバッチをTomcatフォルダに置いて起動させています。なんとなく紹介します。
TOMCAT_START.bat
set CATALINA_HOME=. set JAVA_HOME=C:\java\pleiades-2019-06\java\8 set path=%path%;%JAVA_HOME%\bin bin\startup.bat
プロジェクト一式
今回はここまで。
