【问题标题】:Spring - I18n - Access MessageSource over static class?Spring - I18n - 通过静态类访问 MessageSource?
【发布时间】:2016-01-11 07:06:46
【问题描述】:

我遵循了一些类似这样的教程:

http://www.concretepage.com/spring-4/spring-4-mvc-internationalization-i18n-and-localization-l10n-annotation-example

让 i18n 在我的 spring(boot) 项目中工作。 到目前为止它一直在工作,但我不喜欢总是将 MessageSource bean 自动连接到我当前的类,只是为了翻译一些 Strings。

我的想法是一个简单的包装类,带有像这样的静态调用

I18n.translate("some.identifier") 

I18n.translate("some.identifier",param,param,param...).

但是我不能将MessageSource 注入到 Spring 不处理的类中,对吧?

知道如何解决这个问题吗?

【问题讨论】:

  • 你为什么还需要MessageSource?当使用已与 I18N 集成的 JSP 或 Thymeleaf 时,对也集成的验证内容支持相同。那么你的用例是什么,为什么你仍然在一个普通的MessageSource 上操作。如果你正确使用框架,我会说你不需要那个 hack。
  • 我不使用 JSP,我使用的是 Vaadin。我非常愿意接受任何更好的方法来获得!使用方便 !! i18n 与 Vaadin。
  • 请将该特定部分添加到您的问题中,因为这对答案非常重要
  • 当使用 Spring Boot 和 vaadin 集成时,您可以让您的 van 组件由 Spring 管理,这应该允许您使用 MessageSource。还有 vaadin4spring 已经有类似的东西了。

标签: java spring internationalization vaadin


【解决方案1】:

你可以(不确定你是否应该)做这样的事情:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class StaticContextAccessor {

    private static StaticContextAccessor instance;

    @Autowired
    private ApplicationContext applicationContext;

    @PostConstruct
    public void registerInstance() {
        instance = this;
    }

    public static <T> T getBean(Class<T> clazz) {
        return instance.applicationContext.getBean(clazz);
    }

}

然后像这样使用它:

SomeOtherwiseAutowiredClass someObject = StaticContextAccessor.getBean(SomeOtherwiseAutowiredClass.class);

【讨论】:

    【解决方案2】:

    我的想法与使用 Vaadin 开发的想法相同,对我有用的解决方案是使用 StaticContextInitializer Bean。因此,请执行以下操作:

    首先将 Message 类的字段设为静态并提供 getter 和 setter 方法:

    private static MessageSource messageSource;
    
    private TextSource() {
    }
    
    public static String getText(String key, Locale locale) {
        return messageSource.getMessage(key,null, ensureLocale(locale));
    }
    
    
    
    public static String getText(String key, Locale locale, Object[] parameter) {
        return messageSource.getMessage(key, parameter, ensureLocale(locale));
    }
    
    private static Locale ensureLocale(Locale locale) {
        if (locale == null)
            locale = Locale.getDefault();
        return locale;
    }
    

    给类添加静态setter方法:

    public static void setMessageSource(MessageSource messageSource) {
        TextSource.messageSource = messageSource;
    }
    

    使用 @PostConstruct 注释编写您的 StaticInitializer Bean,并使用 @Autowired 注释注入 MessageSource。

    @Component
    public class FrontendStaticContextInitializer {
    
    @Autowired
    private MessageSource messageSource;
    
    @PostConstruct
    public void initialize() {
        TextSource.setMessageSource(messageSource);
    }
    }
    

    之后你就可以在你的视图中调用这个类:TextSource.getText("login.textfield.placeholder.benutzername", getLocale())

    【讨论】:

      【解决方案3】:

      你有两种可能:

      1. 静态属性/字段的非静态设置器;
      2. 使用org.springframework.beans.factory.config.MethodInvokingFactoryBean 调用静态设置器。

      您可以通过链接找到示例 How to make spring inject value into a static field

      附:将 MessageSource 自动装入 bean 有什么问题?

      【讨论】:

      • 嗯,也许我有点被宠坏了,但是为我用 Vaadin 编写的每个 GUI 组件设置一个 bean 真的很烦人。只是,.. 如果我愿意,.. 我必须将它自动连接到项目的大多数类... 那只是愚蠢和烦人。只要我再次回家,我会尝试你的暗示。thx
      【解决方案4】:

      创建一个静态消息源包装器,例如https://github.com/chelu/jdal/blob/master/core/src/main/java/org/jdal/beans/StaticMessageSource.java

      并在bean配置文件中声明:

      <!-- Message Source -->
      <bean id="messageSource"
              class="org.springframework.context.support.ResourceBundleMessageSource">
          <property name="basenames" value="i18n/jdal,i18n/i18n" />
      </bean>
      
      <bean id="staticMessageSource" class="org.jdal.beans.StaticMessageSource">
              <constructor-arg ref="messageSource" />
      </bean>
      

      请注意,如果您需要在其他 bean 之前实例化包装器,则可以使用 depend-on

      【讨论】:

        【解决方案5】:

        只需实现 MessageSourceAware 并将其设置为静态变量。 但是,它只有在 spring.main.lazyInitializationfalse 时才有效。

        @Component
        public final class MessageUtils implements MessageSourceAware {
        
            private static MessageSource messageSource;
        
            @Override
            public void setMessageSource(MessageSource messageSource) {
                MessageUtils.messageSource = messageSource;
            }
        
            public static String getMessage(String key, String... params) {
                return messageSource.getMessage(key, params, new Locale("PT", "br"));
            }
        
        }
        

        如果spring.main.lazyInitializationtrue,则需要强制注入:

        public class App {
        
            @Autowired
            private MessageUtils messageUtils;
        
            public static void main(String[] args) {
                SpringApplication.run(App .class, args);
            }
        
        }
        

        Spring会自动注入,见类:ApplicationContextAwareProcessor.invokeAwareInterfaces(Object bean)

        【讨论】:

          【解决方案6】:

          这里是一个示例 Utils,没有 DI 概念,没有 Bean 配置:

          import java.util.Locale;
          
          import org.apache.commons.lang3.Validate;
          import org.springframework.context.MessageSource;
          import org.springframework.context.support.ReloadableResourceBundleMessageSource;
          
          public class I18n {
              private static MessageSource MESSAGE_SOURCE;
              static {
                  I18nUtils.MESSAGE_SOURCE = messageSource();
              }
          
              public static String translate(Locale locale, String key, Object... args) {
                  Validate.notNull(locale, "locale require not null");
                  Validate.notEmpty(key, "key require not empty");
                  return MESSAGE_SOURCE.getMessage(key, args, locale);
              }
          
              private static MessageSource messageSource() {
                  ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
                  messageSource.addBasenames("classpath:Messages");
                  messageSource.setDefaultEncoding("UTF-8");
                  return messageSource;
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2017-07-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-30
            • 2011-04-17
            • 2016-11-06
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多