【问题标题】:Internationalized drop downs using Spring 3使用 Spring 3 的国际化下拉菜单
【发布时间】:2012-01-13 20:18:04
【问题描述】:

故事

我有一个代表用户访问级别的选择控件。我正在寻找一种使其国际化的方法。标签应该从消息资源中加载,并且值应该按原样使用。我使用具有标签和值属性的简单 SelectOption 类在控制器中准备所有下拉列表。这样,我的选择在所有 jsp 中看起来都是一致的。

问题

我找到了一些示例,但它们是基于 jsp 中的逻辑。开发人员遍历他的标签并使用消息资源手动构造选项标签。虽然这可行,但必须有更好的方法。我还发现 Spring 3 将支持国际化选项标签的一些 cmets,但我找不到任何具体的内容。

控制器逻辑

Collection<SelectOption> optionList = new ArrayList<SelectOption>();
optionList.add(new SelectOption("-SELECT-", "-"));  
optionList.add(new SelectOption("Administrator", "ADMIN"));
optionList.add(new SelectOption("Editor", "EDIT"));
bean.setFilterUserAccessLevelOptionList(optionList);

JSP 逻辑

<form:select path="filterUserAccessLevel"  items="${bean.filterUserAccessLevelOptionList}" itemLabel="label" itemValue="value"/>

问题

  1. 我想以这种方式在我的控制器中添加选项: optionList.add(new SelectOption("userAccessLevelAdministratorLabel", "ADMIN"));并让 Spring 将 userAccessLevelAdministratorLabel 转换为消息资源中的值。这可能吗?
  2. 如果 Spring 3 不能为我做到这一点,如果不在 jsp 中手动构造选项标签,那如何实现呢?

=== 2012-01-15 ==================================== ===========================

仍在尝试使用 aweigold 的想法制定解决方案。

控制器

@Controller
public class UserController {
@Autowired
private UserService userService;

@Autowired
SelectOptionListBuilder listBuilder;

    @RequestMapping("/userIndex/{pageNumber}")
public ModelAndView getUserList(@PathVariable Integer pageNumber, @ModelAttribute("userIndexBean") UserIndexBean phantomBean, Locale locale, Model model) {

    UserIndexBean bean = new UserIndexBean();

    // prepare filter form
    Collection<SelectOption> optionList = listBuilder.getUserAccessLevelOptionList(true, SortOrder.NONE, locale);
    bean.setFilterUserAccessLevelOptionList(optionList);

SelectOptionListBuilderImpl

@Component
public class SelectOptionListBuilderImpl implements SelectOptionListBuilder, MessageSourceAware {

private MessageSource messageSource;

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


@Override
public List<SelectOption> getUserAccessLevelOptionList(boolean addSelectPrompt, SortOrder sortOrder, Locale locale) {
    List<SelectOption> optionList = new ArrayList<SelectOption>();

    if(addSelectPrompt) {
        optionList.add(new SelectOption(messageSource.getMessage("common.selectPromptLabel", null, locale), "-"));
    }

消息源映射

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">    
<property name="basename" value="/WEB-INF/i18n/messages" />
<property name="defaultEncoding" value="UTF-8"/>
<property name="UseCodeAsDefaultMessage" value="true"/>
</bean>

例外

org.springframework.context.NoSuchMessageException: No message found under code 'common.selectPromptLabel' for locale 'en_CA'

【问题讨论】:

    标签: spring select internationalization


    【解决方案1】:

    当我需要在 jsp 之外的 Controller 中执行此类操作时,我一直在制作我的 Controllers MessageSourceAware。然后,Spring 将在交换它们时注入一个新的 MessageSource,您可以像 Spring 一样询问它。在您的示例中,您将执行以下操作:

    @Controller
    public class someController implements MessageSourceAware {
        private MessageSource messageSource;
    
        @Override
        public void setMessageSource(MessageSource messageSource) {
            this.messageSource = messageSource;
        }
    
        @RequestMapping
        // Pass in the locale from the LocaleResolver
        public void someMapping(Locale locale){
            optionList.add(new SelectOption(
               messageSource.getMessage("userAccessLevelAdministratorLabel", null, locale),
               "ADMIN"))
        }
    }
    

    【讨论】:

    • 我正在尝试你的想法。 messageSource 不知道我的消息包。我尝试使用与我的列表无关但使用 spring:message 显示正常的条目。同样的“没有这样的消息”错误。在调试器中,父消息源为空。此外,我找不到将语言环境注入我的列表构建器的方法。将它作为参数传递是我能够连接各个部分的唯一方法。
    • 这可能是因为您的消息包未添加到您的消息源。查看 ReloadableResourceBendleMessageSource 或 ResourceMessageBundleSource 类。将其中一个实例化为 bean,并使用您的消息包进行配置。另外,考虑制作组件 MessageSourceAware,这样 Spring 上下文可以将其换成新的。
    • 我已将我的 messageSource 映射添加到帖子中。此映射有效,因为我的 &lt;spring:message 标记工作正常。你能想到我的SelectOptionListBuilderImpl 中的messageSource 没有连接到捆绑包的任何其他原因吗?另外,您介意解释一下您评论中的最后一句话吗?
    • 尝试使用 MessageSourceAware 接口(请参阅我的原始帖子中的代码)。 Spring 提供了在运行时更改 MessageSource 对象的能力,并且它使用该接口来更新直接询问它的任何人。
    • 我已经实现了该界面并使用我最新版本的列表生成器更新了帖子。我仍然遇到异常。 messageSource 是用 XmlWebApplicationContext 类型的对象设置的。该对象有一个 configLocations 列表,其中包含应用程序上下文和我的 spring 安全性的条目,但它没有定义消息源的 spring-servlet.xml 条目。
    【解决方案2】:

    看看 spring roo 项目。他们通过创建tagx 标签来解决此类问题。这个标签做你已经描述的事情(它包含一个从资源加载消息并构建选项标签的小逻辑)。但是因为逻辑是一次性的,你可以在jspx文件中像普通标签一样使用这个标签,感觉就像一个标签可以做你想做的事。

    【讨论】:

    • 谢谢,拉尔夫。我的清单上有 Spring Roo,但我试图一次解决一件事。我老了,我需要慢慢来。 :)
    • @jacekn:只是为了澄清我的意思:我并不是说你应该使用 ROO,我的意思是你应该创建一个 ROO 项目,看看他们是如何做的 tagx (input.tagx例如)
    • 感谢您的澄清,拉尔夫。我实际上又开始阅读关于 roo 本身的内容。在利弊方面得到了侧面跟踪。我知道你只是指标签。现在,我还在玩,所以我会继续前进。但坦率地说,我不喜欢我的 java 类获取语言相关值的事实。它有效,但对我来说,标签绝对是处理这个问题的更好地方。当我从事一个实际项目时,我一定会剖析那个 tagx 库。
    猜你喜欢
    • 1970-01-01
    • 2013-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 2011-10-13
    • 1970-01-01
    相关资源
    最近更新 更多