- 浏览: 375119 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
真的全站唯一:
描述的能不能准确一点,我也以为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 2044近期做了好长时间的 ... -
【java规范】Java spi机制浅谈
2012-04-24 23:04 45718最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现 ... -
【maven】多子模块maven模板工程archetype创建过程
2012-04-02 20:55 17576最近项目里需要创建一 ... -
【java基础】如何设计java应用程序的平滑停止
2012-03-05 23:44 10925java应用程序退出的触发机制有: 1.自动结束:应用没有存 ... -
【java并发】juc Executor框架详解
2012-02-26 13:55 12378Executor 框架是 juc 里提供的线程池的实现。 ... -
【java并发】juc高级锁机制探讨
2012-02-23 00:52 8511最近在看一些j ... -
【java并发】基于JUC CAS原理,自己实现简单独占锁
2012-02-14 13:47 7768synchronized的基本原理回 ... -
[NoSQL]MongoDB初体验
2012-01-05 16:06 3926因为未来业务发展的一 ... -
【JVM】HotSpot JVM内存管理和GC策略总结
2011-12-13 22:05 15879JVM的相关知识是学习java ... -
32位机器下的一个java.lang.OutOfMemoryError错误分析
2011-10-17 11:19 2548昨天在本人windows机器( ... -
【Spring】IOC核心源码学习(三):bean标签和自定义标签实现原理
2011-09-25 11:13 9619接上文: 【Spring】IOC核心源码学习(二):容器初始 ... -
【Spring】IOC核心源码学习(二):容器初始化过程
2011-09-21 21:03 23509接上文 啃啃老菜: Spring IOC核心源码学习(一 ... -
[监控]Btrace监控简单笔记
2011-09-09 10:57 4904前阵子看了公司网站的一个cache 命中率统计的btrace监 ... -
【设计】一个有意思的服务方法入参设计
2011-09-01 22:40 1980今天晚上和项目组的几 ... -
DBCP数据源配置项记录
2011-09-01 20:22 2934网站最近发生了数据库连接爆掉的问题。排查了下各个应用存在 ... -
【性能】Java BigDecimal和double性能比较
2011-08-28 20:06 14111我们知道 java 里面有个 BigDecimal ... -
【Spring】IOC容器并发条件下,可能发生死锁
2011-08-28 17:07 68341.背景 上周在生产环境应用启 ... -
JDK7 AIO 初体验
2011-08-17 19:20 2535JDK7 AIO初体验 JDK7已经releas ... -
啃啃老菜:Spring IOC核心源码学习(一)
2011-08-14 13:57 7446啃啃老菜: Spring IOC核心源码 ... -
如果要用java实现算法,一定慎用递归
2011-04-06 20:41 12825现象 : 递归是我们很经典的一种算法实现,可以很好的 ...
相关推荐
国际化插件-ResourceBundle Editor
ResourceBundle Editor (eclipse-rbe)是一个用于编辑本地化的属性文件(localized properties files)。它让你通一个屏幕就能够同时管理所有相关联属性文件中的key/value信息。它所具有的功能包括:自动为Keys分类,...
这是一个简单实现读取properties、xml格式的配置文件的小案例。虽然实际项目中可能不是这样实现的。作为了解也是不错的。 一、读取properties类型文件 方法一:java.util.ResourceBundle读取properties类型文件; ...
这里面有详细的处理maven项目中resources目录下的资源文件,方便快捷的得到或设置资源文件中的内容,本人亲测,里面还有示例
下面小编就为大家带来一篇ResourceBundle类在jsp中的国际化实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
java.util.ResourceBundle使用详解
ResourceBundle:资源包,包括图片源代码
j18n替代了java.util.ResourceBundle以支持Unicode属性文件。 您可以将UTF8字符放入* .properties中,唯一的代码更改是将“ ResourceBundle.getBundle(..)”替换为“ J18n.getBundle(..)”。
ResourceBundle rb = ResourceBundle.getBundle(name, Locale.getDefault()); 3。使用java.util.PropertyResourceBundle类的构造函数 示例: InputStream in = new BufferedInputStream(new FileInputStream...
此实现仅为开发环境开发,不应在生产环境中运行。 开发它是为了简化创建 ResourceBundle 源的过程,而不必每次使用 genrb 重新编译源文件。 这个项目既不是真正的一部分,也不是。 用法 : 测试文件 <?php use...
资源包 ResourceBundle 是一个固执的 Symfony 包... 该包需要资源(实体)来实现非常简单的ResourceInterface 。 这些示例假设您使用的是 Doctrine,但该包与 ORM 无关。 首先,让我们创建一个简单的资源。 <?php
NULL 博文链接:https://leiwuluan.iteye.com/blog/369909
可视化的插件编写,也可以转化国际化语言,挺不错的小工具
private ResourceBundle resourceBundle; public CommonParam() { propertyFileName = "com/test/dao/SysConfig"; resourceBundle = ResourceBundle.getBundle(propertyFileName); } public String ...
ResourceBundleEditor 资源文件编辑器 eclipse的资源文件编辑插件 经常在做国际化的时候编辑properties文件。转换文件字符总是让人比较繁琐。有了这个插件所见即所得。我们输入中文的时候自动就转换完毕了。...
resourcebundleeditor在eclipse里面的设置和使用
在Maven2中实现了传递依赖,如此对于Hibernate所依赖的包,Maven2会自动下载,开发人员只需关心Hibernate即可。 注意:只有得到Maven支持的依赖,通常是plugin形式出现,才能获得这个特性。而且对于一些老的plugin,...