Java Preferences类做本地存储
1. Preferences使用场景
Preferences类可以用在项目中做一个本地小存储。比如小型的一些软件配置项目,内部存储时会以key/value的形式存储。但是最终的本地存储方式会被序列化为xml。在不同的系统下Preferences有其不同的实现。
2. 场景示例
最近正好做了一个springboot web项目,需要做一个软件授权证书,由我们生成证书给到客户,客户需要导入证书才能获得系统使用的授权。证书有有效期限限制。
找了一个开源工具truelicense-core,看了源码后发现它使用了Preferences来保存最终生成的证书key。于是学习了一下Preferences类。
3. Preferences在truelicense-core中的作用
truelicense-core在项目中安装证书时,会最终把加密的key通过Preferences写入,由于证书和授权本身并没有类似数据库这样的持久化存储做支持,所以当客户使用证书安装授权后,在授权期内需要能够保存用户的授权状态,否则项目每次重启都会进行一次授权。这是不合理的。而truelicense-core正是通过Preferences类存储了安装的key
4. Preferences写入的数据在哪里
Preferences本身是个抽象类,它有三个不同的工厂类,可以根据不同平台生产对应的Preferences类。Java源码如下
// 3. Use platform-specific system-wide default String osName = System.getProperty("os.name"); String platformFactory; if (osName.startsWith("Windows")) { platformFactory = "java.util.prefs.WindowsPreferencesFactory"; } else if (osName.contains("OS X")) { platformFactory = "java.util.prefs.MacOSXPreferencesFactory"; } else { platformFactory = "java.util.prefs.FileSystemPreferencesFactory"; }
源码可以看出Preferences支持:windows、os x、和其他类unix平台
在windows下,Preferences类最终将数据保存在系统的注册表中。通常我们使用Preferences会使用userNodeForPackage方法获取,而不会获取系统的节点
例如如下的代码:
Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class);
这样获取到的Preferences最终会写入 HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs 这个注册表节点,写入的节点层级是LicenseVerify所在的包路径,假设LicenseVerify在com.abc包路径下,则完整的注册表层级为:HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs\com.abc这个节点下。
在linux平台因为并没有注册表的存在,Java使用文件系统做存储。存储的路径是在:
new File(System.getProperty("java.util.prefs.userRoot",System.getProperty("user.home")), ".java/.userPrefs");
如果user.home指向app用户的家目录,则存储的完整路径为:/home/app/.java/userPrefs/com/abc。在linux上存储直接被存为xml文件,可以打开查看。而windows下需要程序读取导出xml。