SpringBoot メッセージのDB化

前回、SpringBootのメッセージをロケール対応できるように設定しました。
今回は、前回のを発展させてメッセージをローカルのDBで一元管理できるようにしましょう。
何でこんな事をするかというと、ローカライズの手間をなくすため、オフショアで最初に英語版で作ってコストを下げる為などいろいろ考えられます。

[ソース](https://github.com/MariMurotani/SpringDemo/blob/5_messaging/)

###1.Messageモデルの作成
MongoDB用のデータアクセスモデル

###2.MyMessageService サービスの作成
@Serviceアノテーションを使ってサービスとして作成する
こうする事で、Controllerからも直接呼び出し可能

###3.MyMessageSource コンポーネントの作成
MessageSourceを継承したコンポーネントを作成

###4.MyMessageResolver コンポーネントの作成
AbstractMessageResolverを継承したコンポーネントを作成

###５.メッセージリゾルバの設定
`emplateEngine.setMessageResolver((IMessageResolver) context.getBean(MyMessageResolver.class));`
今回は、AutowiredなどSpring独自のアノテーションを利用しているので、new MyMessageResolver()ではなく、beanとして生成するのがポイント

###6.テンプレートファイルとコントローラーに記述

```teplate.html
<div th:text="#{parse.index.titile(${userName})}"></div>
<div th:text="#{user.welcome(${userAttiribute})}"></div>`
```
```java:XX.java
@EnableAutoConfiguration
@EnableConfigurationProperties
@Controller
@RequestMapping("/XX")
public class XXController {
	@Autowired
	private ApplicationContext context;
	
	@RequestMapping(value="index",method=RequestMethod.GET)
	public String index(Model model) {
		System.out.println(LocaleContextHolder.getLocale());
		
		model.addAttribute("userName",new String[]{"Mari-san","Yoshi-san"});
		model.addAttribute("userAttiribute","PratinumUser");
		model.addAttribute("tree", "");
		return "parse/index";
	}
}
```

***7.データの用意***

```messages_en_us.properties
user.welcome=Welcome {0}
```
```db.Message
{
    "_id" : ObjectId("55ffe15ed9b583a6817f3a6b"),
    "code" : "parse.index.titile",
    "locale" : "ja.*|en.*",
    "value" : "ハロー22 {0} ,{1}",
    "update_time" : Timestamp(1416472648, 1)
}
```

```java:Message.java
@Getter
@Setter
@Document(collection="Message")
public class Message {
	@Id
	private String id;
	private String code;
	private String locale;
	private String value;
	private org.bson.types.BSONTimestamp update_time;
	
	public Message(String locale, String value) {
		super();
		this.locale = (locale == null)?"ja":locale;
		this.value = (value == null)?"":value;
		
	}
	public Message() {
		super();
	}
}
```

```java:MyMessageService.java
@Service
public class MyMessageService extends ServiceBase {
	
	public MyMessageService() {
		super();
	}
	
	 public String GetMessage(String code,String locale){
		String result = "";
		 
		Query searchUserQuery = this.GetSaerchQuery(code, locale);
		List<Message> messages = mongoOperation.find(searchUserQuery, Message.class);
		Iterator iterator = messages.iterator();
		while(iterator.hasNext()) {
			Message message = (Message)iterator.next();
			String localereg = message.getLocale();
			if(localereg != null && localereg  != ""){
				Pattern p = Pattern.compile(localereg);
				Matcher m = p.matcher(locale);
				if(m.matches()){
					result = message.getValue() == null?result:message.getValue();
					break;
				}
			}
		}
		
		return result;
    }
	 
    private Query GetSaerchQuery(String code,String locale){
    	Query searchMessageQuery = new Query(Criteria.where("code").is(code));
    	searchMessageQuery.with(new Sort(Sort.Direction.DESC, "update_time"));
			
		System.out.println(searchMessageQuery.toString());;
		return searchMessageQuery;
    	
    }
}
```

```java:MyMessageSource.java
@Component
public class MyMessageSource implements MessageSource{
	@Autowired
	MyMessageService messageService;

	@Autowired
	MessageSource messageSource;
	
	@Override
	public String getMessage(String code, Object[] args,String defaultMessage, Locale locale) {
		return this.getMessage(code,args,"",locale);
	}
	
	@Override
	public String getMessage(String code, Object[] args, Locale locale) {
		String sMess = messageService.GetMessage(code, locale.toString());
		
		if(sMess == null | sMess == ""){
			sMess = messageSource.getMessage(code,args,locale) ;
		}
		if(sMess == null){
			sMess = ConstError.MESSAGE_NON_EXIST_ERR;
		}
		
		return sMess;
	}
	
	@Override
	public String getMessage(MessageSourceResolvable resolvable, Locale locale) {
		String sMess = messageSource.getMessage(resolvable,locale);
		return sMess;
	}

}
```
```java:MyMessageResolver.java

@Component
public class MyMessageResolver extends AbstractMessageResolver {//StandardMessageResolver

	@Autowired
	MyMessageSource messageSource;
		
	@Autowired
	ApplicationContext context;
	
	public void setMessageSource(MyMessageSource messageSource) {
	    this.messageSource = messageSource;
	}
	
	@Override
	public MessageResolution resolveMessage(Arguments arguments, String key,Object[] messageParameters) {
		String sMess = this.messageSource.getMessage(key.toString(), null,LocaleContextHolder.getLocale());
		//super.checkInitialized();
		
		if(!(messageParameters[0] instanceof String)){
			
			for(int i = 0; i < ((Object[])messageParameters[0]).length ; i++){
				sMess = sMess.replace("{" +String.valueOf(i)+ "}",String.valueOf(((Object[])messageParameters[0])[i]));
			}
		}else{
			for(int i = 0; i < messageParameters.length ; i++){
				System.out.println(messageParameters[i]);
				sMess = sMess.replace("{" +String.valueOf(i)+ "}",String.valueOf(messageParameters[i]));
			}
		}
		MessageResolution resolution = new MessageResolution(sMess);
		return resolution;
	}
}
```
```java:ThymeleafConfig.java
@Configuration
public class ThymeleafConfig extends WebMvcConfigurerAdapter {
		@Autowired
	    private ApplicationContext context;
	
	    @Value("${lang.default.lang}")
		private String defLang;
	    @Value("${lang.default.locale}")
		private String defLocale;
	
	    
	    @Override 
	    public void addInterceptors(InterceptorRegistry registry) { 
	            registry.addInterceptor(localeChangeInterceptor()); 
	    } 
	
	    @Bean 
	    public LocaleChangeInterceptor localeChangeInterceptor() { 
	            LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); 
	            localeChangeInterceptor.setParamName("language"); 
	            return localeChangeInterceptor; 
	    } 
	
	    @Bean 
	    public CookieLocaleResolver localeResolver() { 
	            CookieLocaleResolver localeResolver = new CookieLocaleResolver(); 
	            Locale defaultLocale = new Locale(defLang + "_" + defLocale); 
	            localeResolver.setDefaultLocale(defaultLocale); 
	            return localeResolver; 
	    }
	    
	    @Bean 
	    public ReloadableResourceBundleMessageSource messageSource() { 
	    	ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); 
	        messageSource.setBasename("classpath:messages/messages"); 
	        return messageSource; 
	    }
	    
	    @Override
	    public void addResourceHandlers(ResourceHandlerRegistry registry) {
	        registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
	    }
    
	
		ServletContextTemplateResolver   not working
	
		@Bean
		public ClassLoaderTemplateResolver templateResolver() {
			ClassLoaderTemplateResolver classLoaderTemplateResolver = new ClassLoaderTemplateResolver();
			classLoaderTemplateResolver.setCacheable(false);
			classLoaderTemplateResolver.setPrefix("templates/");
			classLoaderTemplateResolver.setSuffix(".html");
			classLoaderTemplateResolver.setTemplateMode("HTML5");
			classLoaderTemplateResolver.setCacheable(false);
			//classLoaderTemplateResolver.setResourceResolver(resourceResolver);
			return classLoaderTemplateResolver;
		}
	
        @Bean
	    public SpringTemplateEngine templateEngine() {
	        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
	        templateEngine.setTemplateResolver(templateResolver());
	        templateEngine.addDialect(new ThymeleafDialect());
	        templateEngine.setMessageResolver((IMessageResolver) context.getBean(MyMessageResolver.class));
	        return templateEngine;
	    }
	    
        @Bean
	    public ThymeleafViewResolver viewResolver() {
	        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
	        viewResolver.setTemplateEngine(templateEngine());
	        return viewResolver;
	    }
	    


}
```