Spring Boot ReloadableResourceBundleMessageSource
更新i18n訊息message.properties
範例。
範例環境:
- Java 8
- Spring Boot 2.2.1.RELEASE
- Lombok
- Maven
建立Spring Boot專案(參考IntelliJ IDEA,Eclipse STS)。
Spring Boot預設使用ResourceBundleMessageSource
作為i18n訊息的配置,但這邊改用自訂的ReloadableResourceBundleMessageSource
bean來取得messages.properties
檔的訊息才能在程式執行期間(runtime)動態更新properties。
專案的application.properties
,僅配置應用程式路徑與port,所以應用程式本機路徑為http://localhost:8080/demo
application.properteis
#context path
server.servlet.context-path=/demo
#port
server.port=8080
i18n多語系訊息預設檔messages.properties
及中文訊息檔messages_zh_TW
。
messages.properties
demo.message=MessageSource config
demo.hello-world=Hello World
messages_zh_TW.properties
demo.message=MessageSource 配置
demo.hello-world=哈囉世界
ReloadableResourceBundleMessageSource
為Spring對MessageSource
的實作,與ResourceBundleMessageSource
的差別是ReloadableResourceBundleMessageSource
是以Resource
取得由Properties
包裝的訊息;而ResourceBundleMessageSource
則是以JDK的ResourceBundle
來獲取properties訊息。
由於ReloadableResourceBundleMessageSource
取得Properties
的方法為protected
,因此需要實作一個繼承類別來呼叫該方法,例如下面的DemoReloadableResourceBundleMessageSource
。
DemoReloadableResourceBundleMessageSource
package com.abc.demo.i18n;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Component;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
@Component
public class DemoReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource {
public Properties getPropertiesByFileName(String fileName) {
return getProperties(fileName).getProperties();
}
public Properties getProperties(Locale locale) {
return getMergedProperties(locale).getProperties();
}
public Set getPropertiesKeySet(Locale locale) {
return getProperties(locale).keySet().stream()
.map(Object::toString)
.collect(Collectors.toSet());
}
}
然後在Spring Boot配置類(本範例直接在@SpringBootApplication
類)設定上面的DemoReloadableResourceBundleMessageSource
為MessageSource
的bean。
注意setBasename()
的值前面要加上classpath:
才會從classpath(e.g. src/main/resources/
)讀取properties檔,且不用加副檔名.properties
。
DemoApplication
package com.abc.demo;
import com.abc.demo.i18n.DemoReloadableResourceBundleMessageSource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import java.nio.charset.StandardCharsets;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public MessageSource messageSource() {
DemoReloadableResourceBundleMessageSource messageSource = new DemoReloadableResourceBundleMessageSource();
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
messageSource.setBasename("classpath:messages");
return messageSource;
}
}
Controller DemoController
,定義API來測試properites值的更新效果。
呼叫/message
印出原本的properties值後重設properties值;
呼叫/message/new
印出重設的properties值。
DemoController
package com.abc.demo.controller;
import com.abc.demo.i18n.DemoReloadableResourceBundleMessageSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Locale;
import java.util.Properties;
@RestController
public class DemoController {
@Autowired
private DemoReloadableResourceBundleMessageSource messageSource;
@GetMapping("/message")
public void message() {
String s1 = messageSource.getMessage("demo.message", null, Locale.ENGLISH);
System.out.println(s1); // MessageSource config
String s2 = messageSource.getMessage("demo.message", null, Locale.TAIWAN);
System.out.println(s2); // MessageSource 配置
String s3 = messageSource.getMessage("demo.hello-world", null, Locale.ENGLISH);
System.out.println(s3); // Hello World
String s4 = messageSource.getMessage("demo.hello-world", null, Locale.TAIWAN);
System.out.println(s4); // 哈囉世界
messageSource.clearCache();
Properties messagesProperties = messageSource.getProperties(Locale.ENGLISH);
messagesProperties.setProperty("demo.message", "ReloadableResourceBundleMessageSource example");
Properties messagesZhTwProperties = messageSource.getProperties(Locale.TAIWAN);
messagesZhTwProperties.setProperty("demo.message", "ReloadableResourceBundleMessageSource 範例");
}
@GetMapping("/message/new")
public void newMessage() {
String s1 = messageSource.getMessage("demo.message", null, Locale.ENGLISH);
System.out.println(s1); // ReloadableResourceBundleMessageSource example
String s2 = messageSource.getMessage("demo.message", null, Locale.TAIWAN);
System.out.println(s2); // ReloadableResourceBundleMessageSource 範例
String s3 = messageSource.getMessage("demo.hello-world", null, Locale.ENGLISH);
System.out.println(s3); // Hello World
String s4 = messageSource.getMessage("demo.hello-world", null, Locale.TAIWAN);
System.out.println(s4); // 哈囉世界
}
}
完整程式碼請參考github。
沒有留言:
張貼留言