- 浏览: 378122 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
真的全站唯一:
描述的能不能准确一点,我也以为bigDecimal性能比dou ...
【性能】Java BigDecimal和double性能比较 -
zhanggang807:
学习到了。。以后会考虑往这方面设计
【java规范】Java spi机制浅谈 -
Xiong506:
xiyuan1025 写道你这是在linux下吗,我在linu ...
[监控]Btrace监控简单笔记 -
Xiong506:
xiyuan1025 写道你这是在linux下吗,我在linu ...
[监控]Btrace监控简单笔记 -
Bll:
找不到实现类
【java规范】Java spi机制浅谈
ResourceBundle主要是用于和本地语言环境相关的一些资源绑定。特别是String资源。
从国际化的设计角度看,一般在代码里不编写和语言环境相关的东西。比如在代码里编写和语言环境相关的错误提示或信息。
以下面枚举为例:
public enum WeekdayEnum { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday; }
如果期望在不同的weekday的心情,不同语言环境输出不同的信息,如中文环境希望这样输出:
Monday:星期一郁闷 Tuesday:星期二忐忑 Wednesday:星期三难熬 Thursday:星期四期待 Friday星期五激动 Saturday:星期六高兴 Sunday:星期天担忧
这时我们需要定义资源文件,为不同的语言环境制定不同的资源文件,同时支持占位符,可以通过动态传入字符串替换占位符。
JDK自带的ResourceBundle支持properties文件作为资源文件绑定。而我们有的时候希望更习惯于xml的文件定义。这时可以基于JDK ResourceBundl扩展,实现基于XML的ResourceBundl资源绑定。
我们公司里面的二方库有一套xml resourcebundle的实现,但是该实现需要依赖一些外部的jar包,如xml解析等等。
有时候,这种基础功能基于原生实现更方便,不要去依赖其他的二方库,所以实现了一套完全基于JDK的实现。
1.定义资源文件 WeekDayEnum.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="Monday">星期一郁闷</entry> <entry key="Tuesday">星期二忐忑</entry> <entry key="Wednesday">星期三难熬</entry> <entry key="Thursday">星期四期待</entry> <entry key="Friday">星期五激动</entry> <entry key="Saturday">星期六高兴</entry> <entry key="Sunday">星期天担忧</entry> </properties>
2.编写代码实现
2.1.XmlResourceFactory
public class XmlResourceBundleFactory { private static XMLResourceBundleControl DEFAULT_CONTROL = new XMLResourceBundleControl(null,true); private final static String POINT_REGEX = "\\."; /** * 通过默认的XMLResourceBundleControl获取资源Bundle * * <pre> * 默认的XMLResourceBundleControl实现,就在classpath的跟目录下查找资源文件。 * </pre> * * @param fileName * @return */ public static ResourceBundle getBundle(String fileName) { return ResourceBundle.getBundle(fileName, DEFAULT_CONTROL); } /** * 通过指定path的XMLResourceBundleControl获取资源Bundle * * <pre> * 指定path的XMLResourceBundleControl实现,会在指定的classpath目录下查找资源文件。 * </pre> * * @param fileName * @param classpath * @return */ public static ResourceBundle getBundle(String classpath, String fileName) { XMLResourceBundleControl xmlResourceBundleControl = new XMLResourceBundleControl(classpath,true); return ResourceBundle.getBundle(fileName, xmlResourceBundleControl); } public static class XMLResourceBundleControl extends ResourceBundle.Control { private String resourcePath; // 資源的classpath路径 private boolean seprateDotPrefix; // 用于标识是否把包含点的baseName前缀过滤掉。 XMLResourceBundleControl(String resourcePath, boolean seprateDotPrefix){ this.resourcePath = resourcePath; this.seprateDotPrefix = seprateDotPrefix; } public List<String> getFormats(String baseName) { return Collections.singletonList("xml"); } public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException { if ((baseName == null) || (locale == null) || (format == null) || (loader == null)) { throw new NullPointerException(); } ResourceBundle bundle = null; if (!format.equals("xml")) { return null; } if (seprateDotPrefix) { if (baseName.indexOf(".") > 0) { String array[] = baseName.split(POINT_REGEX); baseName = array[array.length - 1]; } } String bundleName = toBundleName(baseName, locale); String resourceName = toResourceName(bundleName, format); String resourceFullName = resourceName; if (resourcePath != null && !"".equals(resourcePath.trim())) {// baseName可能包含包命前綴,把包命前綴去除 resourceFullName = resourcePath + "/" + resourceName; } URL url = loader.getResource(resourceFullName); if (url == null) { return null; } URLConnection connection = url.openConnection(); if (connection == null) { return null; } if (reload) { connection.setUseCaches(false); } InputStream stream = connection.getInputStream(); if (stream == null) { return null; } BufferedInputStream bis = new BufferedInputStream(stream); bundle = new XMLResourceBundle(bis); bis.close(); return bundle; } } static class XMLResourceBundle extends ResourceBundle { private Properties props; XMLResourceBundle(InputStream stream) throws IOException{ props = new Properties(); props.loadFromXML(stream); } protected Object handleGetObject(String key) { return props.getProperty(key); } public Enumeration<String> getKeys() { Set<String> handleKeys = props.stringPropertyNames(); return Collections.enumeration(handleKeys); } } }
2.2 CodeMessageHolder
public class CodeMessageHolder { private Class<?> type; private String resourcePath; private ResourceBundle resourceBundle; /** * 从指定路径加载resource * * @param type * @param classpath */ private CodeMessageHolder(Class<?> type, String classpath){ this.type = type; this.resourcePath = classpath; loadBundleBySpecialPath(); } /** * 从默认路径加载resource * * @param type */ private CodeMessageHolder(Class<?> type){ this.type = type; loadBundleByDefault(); } protected static CodeMessageHolder newDefaultMessageHolder(Class<?> type) { return new CodeMessageHolder(type); } protected static CodeMessageHolder newSpecialPathMessageHolder(Class<?> type,String classpath) { return new CodeMessageHolder(type,classpath); } private void loadBundleByDefault() { resourceBundle = XmlResourceBundleFactory.getBundle(type.getName()); } private void loadBundleBySpecialPath() { resourceBundle = XmlResourceBundleFactory.getBundle(resourcePath, type.getName()); } public String getMessage(Enum<?> e) { if (resourceBundle == null) { return null; } return resourceBundle.getString(e.name()); } public String getMessage(String key) { if (resourceBundle == null) { return null; } return resourceBundle.getString(key); } public String getMessage(Enum<?> e, String... param) { String s = getMessage(e); if (s == null) { return null; } return MessageFormat.format(s, (Object[]) param); } public String getMessage(String key, String... param) { String s = getMessage(key); if (s == null) { return null; } return MessageFormat.format(s, (Object[]) param); } }
3.编写枚举测试类,测试绑定
public enum WeekdayEnum { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday; private static CodeMessageHolder messageHolder = CodeMessageHolder.newDefaultMessageHolder(WeekdayEnum.class); public String getMessage() { return messageHolder.getMessage(this); } public String getMessage(String... params) { return messageHolder.getMessage(this, params); } public static void main(String[] args) { for (WeekdayEnum w : WeekdayEnum.values()) { System.out.println(w.getMessage()); } } }
关于resourcebundle内部实现,JDK是基于cache来做的,不需要每次都去装载资源文件。内部实现看源码即可明白,这里不过多解释。
附件附上源码实现,刚好看到这个且有兴趣的,欢迎一起交流或提供建议。
- xmlresourcebundle.rar (3.7 KB)
- 下载次数: 21
评论
5 楼
singleant
2012-05-07
laiweiweihi 写道
楼主,可以用绝对路径代替 ClassPath 么?资源文件非要放在 ClassPath 下么?
这个用绝对路径不是太好吧?classpath自包含比较好。
绝对路径可以做,不过就意味着和环境绑定在一起了,这个绝对路径就需要一个可配置的入口。
4 楼
san_yun
2012-05-06
javaeye 太恶心了,这也要通知我。。。。。
3 楼
laiweiweihi
2012-05-06
楼主,可以用绝对路径代替 ClassPath 么?资源文件非要放在 ClassPath 下么?
2 楼
singleant
2012-04-24
san_yun 写道
上次你提到可增量的倒排序索引来解决标签问题,什么时候分享下这方面的心得吧?
我只是觉得技术上可行呀 具体场景上我也没用过
1 楼
san_yun
2012-04-21
上次你提到可增量的倒排序索引来解决标签问题,什么时候分享下这方面的心得吧?
发表评论
-
【总结】近期的几点技术心得总结
2012-09-09 09:29 2079近期做了好长时间的 ... -
【java规范】Java spi机制浅谈
2012-04-24 23:04 45838最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现 ... -
【maven】多子模块maven模板工程archetype创建过程
2012-04-02 20:55 17652最近项目里需要创建一 ... -
【java基础】如何设计java应用程序的平滑停止
2012-03-05 23:44 10998java应用程序退出的触发机制有: 1.自动结束:应用没有存 ... -
【java并发】juc Executor框架详解
2012-02-26 13:55 12493Executor 框架是 juc 里提供的线程池的实现。 ... -
【java并发】juc高级锁机制探讨
2012-02-23 00:52 8692最近在看一些j ... -
【java并发】基于JUC CAS原理,自己实现简单独占锁
2012-02-14 13:47 7847synchronized的基本原理回 ... -
[NoSQL]MongoDB初体验
2012-01-05 16:06 3964因为未来业务发展的一 ... -
【JVM】HotSpot JVM内存管理和GC策略总结
2011-12-13 22:05 15952JVM的相关知识是学习java ... -
32位机器下的一个java.lang.OutOfMemoryError错误分析
2011-10-17 11:19 2595昨天在本人windows机器( ... -
【Spring】IOC核心源码学习(三):bean标签和自定义标签实现原理
2011-09-25 11:13 9684接上文: 【Spring】IOC核心源码学习(二):容器初始 ... -
【Spring】IOC核心源码学习(二):容器初始化过程
2011-09-21 21:03 23645接上文 啃啃老菜: Spring IOC核心源码学习(一 ... -
[监控]Btrace监控简单笔记
2011-09-09 10:57 5036前阵子看了公司网站的一个cache 命中率统计的btrace监 ... -
【设计】一个有意思的服务方法入参设计
2011-09-01 22:40 2021今天晚上和项目组的几 ... -
DBCP数据源配置项记录
2011-09-01 20:22 2994网站最近发生了数据库连接爆掉的问题。排查了下各个应用存在 ... -
【性能】Java BigDecimal和double性能比较
2011-08-28 20:06 14247我们知道 java 里面有个 BigDecimal ... -
【Spring】IOC容器并发条件下,可能发生死锁
2011-08-28 17:07 69211.背景 上周在生产环境应用启 ... -
JDK7 AIO 初体验
2011-08-17 19:20 2578JDK7 AIO初体验 JDK7已经releas ... -
啃啃老菜:Spring IOC核心源码学习(一)
2011-08-14 13:57 7521啃啃老菜: Spring IOC核心源码 ... -
如果要用java实现算法,一定慎用递归
2011-04-06 20:41 12947现象 : 递归是我们很经典的一种算法实现,可以很好的 ...
相关推荐
这是一个简单实现读取properties、xml格式的配置文件的小案例。虽然实际项目中可能不是这样实现的。作为了解也是不错的。 一、读取properties类型文件 方法一:java.util.ResourceBundle读取properties类型文件; ...
1. **资源文件的创建与编辑**:用户可以直接在Eclipse环境中创建新的`ResourceBundle`文件,无需手动编写XML或Properties文件。编辑界面支持实时预览,可以方便地添加、删除或修改键值对,同时提供错误检查,确保...
一个简单的XML示例如下: ```xml 首页" action="home.action"/> 产品" action="product_list.action"> 新产品" action="new_product.action"/> 热销产品" action="hot_product.action"/> 联系我们" action=...
ResourceBundle是Java中用于实现国际化的基本工具类,它允许开发者为不同的语言环境创建不同的资源文件。例如,对于英文环境,我们可以创建一个名为`messages_en.properties`的文件,对于中文环境,则创建`messages_...
这通常通过在Action类或者配置文件中设置`ResourceBundle`来实现。在Action类中,我们可以声明一个成员变量来持有资源包,并在构造函数或初始化方法中加载: ```java private ResourceBundle resourceBundle; ...
本篇文章将深入探讨如何在Struts2中实现简单语言包的国际化。 首先,我们需要了解什么是i18n。这里的数字"18"代表了从"i"到"n"之间有18个字母,"i18n"是"internationalization"的缩写。国际化是一种设计和实现软件...
4. **简单程序实现**: - 创建Action类,实现业务逻辑,可能需要继承自`org.apache.struts.action.Action`。 - 编写ActionForm,对应用户输入的数据,并进行数据校验。 - 配置struts-config.xml文件,定义...
这通常在`web.xml`配置文件中完成,或者使用`ResourceBundle`类动态加载。 3. **自定义标签**:创建一个自定义标签类,该类负责从资源文件中获取相应的文本。标签类需要知道如何根据当前用户的语言环境选择正确的...
9. **国际化**:通过ResourceBundle和MessageSource,Spring MVC可以轻松实现多语言支持。 10. **AOP(面向切面编程)**:Spring MVC可以与Spring的AOP模块集成,实现日志记录、事务管理等功能。 在"spring mvc...
本示例将详细介绍如何在Struts2框架下通过struts2.xml配置文件和.properties资源文件实现国际化功能。 首先,我们需要了解什么是国际化。国际化是一种设计方法,使得软件可以适应不同国家和地区的文化差异,包括...
通过这个简单的示例,我们可以看到 FXML 在创建复杂的用户界面时的强大功能和灵活性。此外,由于 FXML 与 JavaFX 的紧密集成,使得开发者可以轻松地实现动态和交互式用户界面。无论是初学者还是有经验的开发者,都...
SwingQQ是一个基于Java Swing库实现的桌面应用,旨在模仿QQ的基本功能,提供用户一个简易的聊天体验。这个项目展示了如何使用Swing构建GUI界面,实现用户交互,并且包括了添加、删除和修改联系人与群组的功能。下面...
- **IoC容器**:Spring的核心,管理对象的生命周期和依赖关系,通过XML或注解配置实现bean的声明式装配。 - **AOP**:提供面向切面编程,用于日志记录、事务管理、权限控制等跨切面关注点的处理。 - **数据访问**...
Tomcat提供了一个简单的JNDI(Java Naming and Directory Interface)实现,允许在Web应用程序中查找和绑定资源。 9. **国际化与本地化**: Tomcat支持多语言环境,通过`ResourceBundle`来实现。 10. **日志系统...
Java平台为实现国际化提供了基础支持,包括使用Unicode编码和Locale类来处理多语言环境,以及ResourceBundle类来加载和管理不同地区的资源文件。例如,创建一个名为`applicationResource.properties`的主资源文件,...
Java提供了多种API来处理XML,如DOM(文档对象模型)、SAX(简单API for XML)和StAX(流式API for XML)。DOM一次性加载整个XML文档,适合小型文件;SAX是事件驱动的,适用于大文件;StAX允许用户以迭代方式读写XML...
- **让Struts拦截用户请求:** 通过配置`struts-config.xml`文件实现。 - **控制器部分:** `ActionServlet`作为核心控制器,负责调度请求。 - **配置Action:** 在`struts-config.xml`文件中定义Action。 - **...
SpringMVC可以通过ResourceBundle和MessageSource实现国际化,通过ThemeResolver实现主题切换,提供不同语言和风格的用户界面。 9. **SpringMVC与Spring Boot的整合** Spring Boot简化了Spring应用的启动和配置,...
为了实现国际化,JasperReport支持使用资源文件(`.properties`)来定义不同语言的文本。在报表模板中,使用`$R{}`引用这些资源文件中的文本,然后在服务器端根据用户选择的语言加载相应的资源文件。 ```xml ...