spring 放置在文件夹中时,找不到 MessageSource 的 ResourceBundle

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11150869/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:11:19  来源:igfitidea点击:

ResourceBundle not found for MessageSource when placed inside a folder

springspring-mvcresourcesresourcebundle

提问by Prasanth

I am trying to use resource bundles with Spring's Message Source. Here is the way I am doing it:

我正在尝试将资源包与 Spring 的消息源一起使用。这是我这样做的方式:

@Component
public class MessageResolver implements MessageSourceAware {

    @Autowired
    private MessageSource messageSource;

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

    public String getMessage(){
        return messageSource.getMessage("user.welcome", new Object[]{"Rama"} , Locale.US);
    }

}

And here is my folder structure:

这是我的文件夹结构:

enter image description here

在此处输入图片说明

messages_en_US.properties contains just one line:

messages_en_US.properties 仅包含一行:

user.welcome=Welcome {0}

Here is the xml configuration used:

这是使用的xml配置:

<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename">
        <value>resourcebundles/messages</value>
    </property>
</bean>

Here is the error I am getting:

这是我得到的错误:

WARNING: ResourceBundle [resourcebundles/messages] not found for MessageSource: Can't find bundle for base name resourcebundles/messages, locale en_US
Exception in thread "main" org.springframework.context.NoSuchMessageException: No message found under code 'user.welcome' for locale 'en_US'.

But if I move my resource bundle to directly under the resources folder, it is working fine. In this case, here is the xml configuration I am using:

但是如果我将我的资源包直接移到资源文件夹下,它工作正常。在这种情况下,这是我使用的 xml 配置:

<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
    <value>messages</value>
</property>

Is is that if I have to use ResourceBundleMessageSource, I should put my resource bundles directly under the resources? If i have to keep it in specified folder only, is there any other way to get this one work?

是说如果我必须使用ResourceBundleMessageSource,我应该将我的资源包直接放在资源下吗?如果我只能将它保存在指定的文件夹中,还有其他方法可以让这个工作吗?

Thanks!

谢谢!

回答by jis117

boy, maybe you can change the xml configuration as follows:

男孩,也许您可​​以按如下方式更改xml配置:

use

org.springframework.context.support.ReloadableResourceBundleMessageSource

instead of

代替

org.springframework.context.support.ResourceBundleMessageSource

all configuration like this:

所有的配置都是这样的:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:resourcebundles/messages" />
    <property name="useCodeAsDefaultMessage" value="true" />
</bean>

回答by Japan Trivedi

Change your configuration to the following for messageSource bean in your xml file.

将 xml 文件中 messageSource bean 的配置更改为以下内容。

<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> 
    <property name="basename"> 
        <value>classpath*:resourcebundles/messages</value> 
    </property> 
</bean>

Since all your properties files are in classpath of java you need to define the path with prefix classpath*:otherwise it will look into the web directory of your application.

由于您的所有属性文件都在 java 的类路径中,因此您需要使用前缀定义路径,classpath*:否则它将查看应用程序的 Web 目录。

Hope this helps you. Cheers.

希望这对你有帮助。干杯。

回答by Tom Silverman

It's nearly 2015 now and I'm using Spring 4.1.2.RELEASE and there's definitely a problem with the way the messageSource bean needs to be configured so it picks up the target resource bundle.

现在快到 2015 年了,我正在使用 Spring 4.1.2.RELEASE 并且需要配置 messageSource bean 以便它获取目标资源包的方式肯定存在问题。

1) If the messageSource bean is of type ReloadableResourceBundleMessageSourceit won't work:

1) 如果 messageSource bean 是ReloadableResourceBundleMessageSource类型,它将不起作用:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;

@Configuration
@ComponentScan(basePackages = { "com.intertech.service" })
//@ImportResource({"classpath:spring/applicationContext-i18n.xml"})
public class AppConfig {

  @Bean(name = "messageSource")
  public ReloadableResourceBundleMessageSource getMessageSource() {
      ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
      messageSource.setBasename("config/messages");
      messageSource.setDefaultEncoding("UTF-8");
      messageSource.setUseCodeAsDefaultMessage(true);
      return messageSource;
  }

//  @Bean(name = "messageSource")
//  public ResourceBundleMessageSource getMessageSource() {
//      ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
//      messageSource.setBasename("config/messages");
//      messageSource.setDefaultEncoding("UTF-8");
//      messageSource.setUseCodeAsDefaultMessage(true);
//      return messageSource;
//  }
}

2) If the messageSource bean is of type ResourceBundleMessageSourceit will work:

2) 如果 messageSource bean 是ResourceBundleMessageSource类型,它将起作用:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;

@Configuration
@ComponentScan(basePackages = { "com.intertech.service" })
//@ImportResource({"classpath:spring/applicationContext-i18n.xml"})
public class AppConfig {

//  @Bean(name = "messageSource")
//  public ReloadableResourceBundleMessageSource getMessageSource() {
//      ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
//      messageSource.setBasename("config/messages");
//      messageSource.setDefaultEncoding("UTF-8");
//      messageSource.setUseCodeAsDefaultMessage(true);
//      return messageSource;
//  }

  @Bean(name = "messageSource")
  public ResourceBundleMessageSource getMessageSource() {
      ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
      messageSource.setBasename("config/messages");
      messageSource.setDefaultEncoding("UTF-8");
      messageSource.setUseCodeAsDefaultMessage(true);
      return messageSource;
  }
}

3) If you're using an XML configuration file combined with a configuration class - it will work (notice how the base bundle is configured in a class like qualification manner i.e. 'config.messages' not 'config/messages'): (applicationContext-i18n.xml)

3)如果您使用与配置类结合的 XML 配置文件 - 它会起作用(注意基本包是如何以类资格方式配置的,即“config.messages”而不是“config/messages”):(applicationContext -i18n.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource"
        p:basename="config.messages"
        p:useCodeAsDefaultMessage="true"/>

    <!-- This will not work -->
    <!--
    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
        p:basename="config/messages"
        p:useCodeAsDefaultMessage="true"/>
     -->
</beans>

and:

和:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ComponentScan(basePackages = { "com.intertech.service" })
@ImportResource({"classpath:spring/applicationContext-i18n.xml"})
public class AppConfig {

//  @Bean(name = "messageSource")
//  public ReloadableResourceBundleMessageSource getMessageSource() {
//      ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
//      messageSource.setBasename("config/messages");
//      messageSource.setDefaultEncoding("UTF-8");
//      messageSource.setUseCodeAsDefaultMessage(true);
//      return messageSource;
//  }

//  @Bean(name = "messageSource")
//  public ResourceBundleMessageSource getMessageSource() {
//      ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
//      messageSource.setBasename("config/messages");
//      messageSource.setDefaultEncoding("UTF-8");
//      messageSource.setUseCodeAsDefaultMessage(true);
//      return messageSource;
//  }
}

4) Most importantly... if you're using a WebApplicationInitializer(no web.xml), you've got to register the configuration class that defines the 'messageSource' bean in the root context, not in the dispatcher servlet's context:

4) 最重要的是...如果您使用的是WebApplicationInitializer(没有 web.xml),您必须注册在根上下文中定义“messageSource”bean 的配置类,而不是在调度程序 servlet 的上下文中:

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
    // Create the 'root' Spring application context
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    rootContext.register(AppConfig.class);
    // Manage the lifecycle of the root application context
    container.addListener(new ContextLoaderListener(rootContext));
    // Create the dispatcher servlet's Spring application context
    AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
    dispatcherServlet.register(MvcConfig.class);
    // Register and map the dispatcher servlet
    ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(
            dispatcherServlet));
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("*.htm");
    }
}

回答by Timothy Anyona

In my case, using Spring 4.3.2.RELEASEand java configand a ReloadableResourceBundleMessageSource, I had to define my template engine as a bean otherwise my messages were not getting resolved.

在我的情况下,使用Spring 4.3.2.RELEASEJava的配置ReloadableResourceBundleMessageSource,我不得不定义我的模板引擎作为一个bean,否则我的消息并没有得到解决。

Here's a sample of a working configuration.

这是一个工作配置的示例。

AppConfig.java

应用程序配置文件

import java.util.concurrent.TimeUnit;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;

@Configuration
@EnableWebMvc
@ComponentScan("myapp")
public class AppConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {

private ApplicationContext applicationContext;

private static final boolean CACHE_THYMELEAF_TEMPLATES = false;
private final String UTF8_ENCODING = "UTF-8";

@Override
public void setApplicationContext(ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
}

@Bean
public ViewResolver viewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(templateEngine());
    resolver.setCharacterEncoding(UTF8_ENCODING);
    resolver.setCache(CACHE_THYMELEAF_TEMPLATES);
    return resolver;
}

@Bean
public TemplateEngine templateEngine() {
    //this method must be defined as a bean otherwise i18n messages are not found
    //if method defined as private TemplateEngine templateEngine() messages are not found
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setEnableSpringELCompiler(true);
    engine.addTemplateResolver(templateResolver());
    return engine;
}

private ITemplateResolver templateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("/WEB-INF/thymeleaf/");
    resolver.setTemplateMode(TemplateMode.HTML);
    resolver.setSuffix(".html");
    resolver.setCacheable(CACHE_THYMELEAF_TEMPLATES);
    resolver.setCharacterEncoding(UTF8_ENCODING);
    return resolver;
}   

@Bean
public MessageSource messageSource() {
    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasenames("WEB-INF/i18n/messages");
    messageSource.setUseCodeAsDefaultMessage(true);
    messageSource.setDefaultEncoding(UTF8_ENCODING);
    messageSource.setFallbackToSystemLocale(false);
    messageSource.setCacheSeconds((int)TimeUnit.HOURS.toSeconds(1));
    return messageSource;
}

}

回答by Babi

Is is that if I have to use ResourceBundleMessageSource, I should put my resource bundles directly under the resources? If i have to keep it in specified folder only, is there any other way to get this one work?

是说如果我必须使用ResourceBundleMessageSource,我应该将我的资源包直接放在资源下吗?如果我只能将它保存在指定的文件夹中,还有其他方法可以让这个工作吗?

You can define your messages in your own package, it does not need to be located in the resources folder.

您可以在您自己的包中定义您的消息,它不需要位于资源文件夹中。

Using Spring 5.2.2.RELEASE versioned components, this is the way I managed to make it work:

使用 Spring 5.2.2.RELEASE 版本化组件,这是我设法使其工作的方式:

The qualified name of the file would be:

文件的限定名称将是:

/tutproject/src/com/tutproject/app/messages/messages.properties

The bean is defined like this in the my Spring Bean Configuration File (XML):

bean 在我的 Spring Bean 配置文件 (XML) 中是这样定义的:

<bean id="messageSource"
    class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename"
    value="/com/tutproject/app/messages/messages">
</property>
</bean>

The Java build path includes tutproject/src, this is the part of the location omitted in the XML definition.

Java 构建路径包括tutproject/src,这是 XML 定义中省略的位置部分。

Some additional useful information from the ResourceBundleMessageSource class:

ResourceBundleMessageSource 类中的一些其他有用信息:

  • The basenames follow {@link java.util.ResourceBundle} conventions: essentially, * a fully-qualified classpath location. If it doesn't contain a package qualifier * (such as {@code org.mypackage}), it will be resolved from the classpath root. * Note that the JDK's standard ResourceBundle treats dots as package separators: * This means that "test.theme" is effectively equivalent to "test/theme".

  • 基本名称遵循 {@link java.util.ResourceBundle} 约定:本质上,* 一个完全限定的类路径位置。如果它不包含包限定符 *(例如 {@code org.mypackage}),它将从类路径根目录解析。* 请注意,JDK 的标准 ResourceBundle 将点视为包分隔符: *这意味着 "test.theme" 实际上等效于 "test/theme"

回答by Aliis

In Spring Boot 2.2.5 things have slightly changed. Classpath is not needed anymore.

在 Spring Boot 2.2.5 中,情况略有变化。不再需要类路径。

    @Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("messages");
    messageSource.setDefaultEncoding("UTF-8");
    return messageSource;
}

回答by Santhosh Hirekerur

I strongly suggest to keep property files out side of project so that we don't need to compile code for every property change.

我强烈建议将属性文件保留在项目之外,这样我们就不需要为每个属性更改编译代码。

Below configuration we are using in live project. setting property.location value in application.properties file

我们在实时项目中使用的配置如下。在 application.properties 文件中设置 property.location 值

@Configuration
public class LocalizationConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(LocalizationConfiguration.class);

    @Value("${property.location}")
    private String propertyLocation;

    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(Locale.ENGLISH); // change this
        return localeResolver;
    }

    @Bean
    public ReloadableResourceBundleMessageSource messageSource() {
        ReloadableResourceBundleMessageSource  resource = new ReloadableResourceBundleMessageSource();
        String messageFolderPath = propertyLocation + "/" + "i18n";
        resource.setBasename("file:"+messageFolderPath+"/messages");
        resource.setDefaultEncoding("UTF-8");
        resource.setCacheSeconds(10);
        return resource;
    }

    @Bean
    public LocalValidatorFactoryBean validatorFactoryBean() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }

}

回答by Siddharth

What worked for me was something really simple.

对我有用的是一些非常简单的事情。

It was

它是

<property name="basename">
            <value>locale\messages</value>
        </property>

I changed it to

我把它改成

<property name="basename">
            <value>locale/messages</value>
        </property>

Just a \ to / change fixed it for me. I am using a MAC.

只是一个 \ to / change 为我修复了它。我正在使用 MAC。

I have not tried *classpath, that may not have worked for me.

我没有尝试过*classpath,这可能对我不起作用。

回答by Ganesh Teltia

I have used following configuration and it is working fine in my project. My messages.properties is in below path: ..\WebContent\WEB-INF\resources

我使用了以下配置,它在我的项目中运行良好。我的messages.properties 位于以下路径:..\WebContent\WEB-INF\resources

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:WEB-INF/resources/messages" />
    <property name="useCodeAsDefaultMessage" value="true" />
</bean>

回答by Shekhar Jagadale

I have used following configuration and it is working fine in my project.

我使用了以下配置,它在我的项目中运行良好。

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:configurations/messages" />
    <property name="useCodeAsDefaultMessage" value="true" />
</bean>

location: src\main\resources\configurations\messages_en.properties

地点: src\main\resources\configurations\messages_en.properties