基于JavaBean编辑器读取peroperties文件
引言
最近在重读《精通Spring+4.x++企业应用开发实战》这本书,看到了有关JavaBean编辑器的部分,了解到PropertyEditor和BeanInfo的使用。不得不说,BeanInfo是一个很强大的东西,Java中的内省也与之有一点点小关联。
JavaBean、PropertyEditor与BeanInfo
JavaBean简单介绍
JavaBean是一种Java写成的可重用组件,本质上还是一个Java类,但是与一般的Java类不同,JavaBean必须有一个无参的构造函数,其字段必须私有化,并提供set、get方法供外界使用。根据书中所介绍,Sun所制定的JavaBean规范很大程度山是为了IDE准备的--它让IDE能够以可视化的方式设置JavaBean的属性。
PropertyEditor接口
PropertyEditor是属性编辑器的接口,其作用是将一个String类型的值转换为JavaBean的属性。Java为PropertyEditor提供了一个默认的实现类PropertyEditorSupport。
BeanInfo接口
BeanInfo用于描述JavaBean哪些属性可以编辑及对应属性编辑器。Java为BeanInfo也提供了一个默认实现--SimpleBeanInfo。
其他
更多有关JavaBean以及这两个接口的知识,可以购买这本书《精通Spring+4.x++企业应用开发实战》,或者看我的Copy
一个小例子
在《精通Spring+4.x++企业应用开发实战》中使用的例子是根据《Core Java II》的一个例子改变而成,但是有一个小缺点,该例子使用到了Swing,演示时需要将代码打成JAR包,使用IDE组件扩展管理功能注册到IDE中,不太方便,因此我特意尝试用JavaBean编辑器读取properties文件作为一个小例子。
定义一个JavaBean
我们先定义一个Person类,用作JavaBean
/**
* 一个简单的JavaBean
* @author aming
*
*/
public class Person implements Serializable {
private static final long serialVersionUID = 6366021085463785872L;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private int age;
/**
* 性别
*/
private Gender gender;
/**
* 生日
*/
private Date birthday;
/**
* 是否结婚
*/
private boolean married;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public boolean isMarried() {
return married;
}
public void setMarried(boolean married) {
this.married = married;
}
public Person() {
super();
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", gender=" + gender + ", birthday=" + birthday + ", married="
+ married + "]";
}
}
其中Gender是我自定义的枚举,其代码如下:
/**
* 表示性别的枚举类
* @author aming
*
*/
public enum Gender {
M(1,"男"),F(2,"女");
private int id;
private String genderName;
public String getGenderName() {
return genderName;
}
Gender(int id,String genderName){
this.id = id;
this.genderName = genderName;
}
public static Gender getGender(int id) {
for(Gender gender:values()) {
if(gender.id == id) {
return gender;
}
}
return M;
}
public static Gender getGender(String genderName) {
for(Gender gender:values()) {
if(gender.genderName == genderName) {
return gender;
}
}
return M;
}
}
实现PropertyEditor
Person类中有5个字段,分别使用String、int、Gender、Date和boolean这5中类型,其中对String类型变量name我们使用PropertyEditorSupport这个默认实现就可以了,其他的类型我们需要自定义去实现PropertyEditor接口--int对应IntegerPropertyEditor、Gender对应GenderPropertyEditor、Date对应DatePropertyEditor以及boolean对应BooleanPropertyEditor。
IntegerPropertyEditor
IntegerPropertyEditor类继承了PropertyEditorSupport类和实现PropertyEditor接口(个人习惯实现接口的时候同时继承一个默认实现,这样我可以只关心我所需要实现的方法,当然,这个默认实现最好是一个抽象类),重写了getAsText()方法和setAsText(String text),其代码如下:
@Override
public String getAsText() {
return String.valueOf((int)getValue());
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
try {
setValue(Integer.parseInt(text));
} catch(NumberFormatException e) {
throw new IllegalArgumentException(e);
}
}
GenderPropertyEditor
GenderPropertyEditor主要是将外部获得到的字符串去转换为Gender,其实现思路是,先尝试将该字符串转换为Integer类型,如果转换成功则将转换得到Integer值通过Gender枚举的静态方法getGender(int id)获取Gender类型的变量;如果转换失败,则将该字符串看作genderName,再去获取Gender。至于Gender到字符串,直接返回genderName就可以了。主要代码如下:
@Override
public String getAsText() {
Gender value = (Gender)getValue();
return value.getGenderName();
}
@Override
public void setAsText(String value) throws IllegalArgumentException {
try {
setValue(Gender.getGender(Integer.valueOf(value)));
}catch(NumberFormatException ex) {
setValue(Gender.getGender(value));
}
}
DatePropertyEditor
DatePropertyEditor的思路和GenderPropertyEditor相似,其核心代码献上:
private DateFormat df;
@Override
public String getAsText() {
Date date = (Date)getValue();
return df.format(date);
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
try {
setValue(df.parse(text));
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
public DatePropertyEditor() {
super();
this.df = new SimpleDateFormat("yyyy-MM-dd");
}
BooleanPropertyEditor
BooleanPropertyEditor与IntegerPropertyEditor一样,实现非常类似:
@Override
public String getAsText() {
return String.valueOf((boolean)getValue());
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(Boolean.valueOf(text));
}
自定义BeanInfo
定义PersonBeanInfo类,用于描述Person属性和相对应的PropertyEditor。代码如下:
public class PersonBeanInfo extends SimpleBeanInfo implements BeanInfo {
@Override
public PropertyDescriptor[] getPropertyDescriptors() {
List<PropertyDescriptor> list = new ArrayList<>();
try {
// 将Person中name与PropertyEditorSupport绑定
PropertyDescriptor namePropertyDescriptor = new PropertyDescriptor("name",Person.class);
namePropertyDescriptor.setPropertyEditorClass(PropertyEditorSupport.class);
// 将Person中age与IntegerPropertyEditor绑定
PropertyDescriptor agePropertyDescriptor = new PropertyDescriptor("age",Person.class);
agePropertyDescriptor.setPropertyEditorClass(IntegerPropertyEditor.class);
// 将Person中gender与GenderPropertyEditor绑定
PropertyDescriptor genderPropertyDescriptor = new PropertyDescriptor("gender", Person.class);
genderPropertyDescriptor.setPropertyEditorClass(GenderPropertyEditor.class);
// 将Person中birthday与DatePropertyEditor绑定
PropertyDescriptor birthdayPropertyDescriptor = new PropertyDescriptor("birthday",Person.class);
birthdayPropertyDescriptor.setPropertyEditorClass(DatePropertyEditor.class);
// 将Person中married与BooleanPropertyEditor绑定
PropertyDescriptor marriedPropertyDescriptor = new PropertyDescriptor("married",Person.class);
marriedPropertyDescriptor.setPropertyEditorClass(BooleanPropertyEditor.class);
list.add(namePropertyDescriptor);
list.add(agePropertyDescriptor);
list.add(genderPropertyDescriptor);
list.add(birthdayPropertyDescriptor);
list.add(marriedPropertyDescriptor);
return list.toArray(new PropertyDescriptor[list.size()]);
} catch (IntrospectionException ex) {
ex.printStackTrace();
}
return null;
}
}
创建配置文件
因为我创建的是一个普通的Java项目,因此我选择在src目录下创建person.properites文件,文件内容如下:
name=arthurming
age=18
gender=1
birthday=2017-10-24
married=true
测试
测试代码
@Test
public void test() throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
Properties p = new Properties();
InputStream is =this.getClass().getClassLoader().getResourceAsStream("person.properties");
p.load(is);
BeanInfo beanInfo = new PersonBeanInfo();
PropertyDescriptor[] propertyDescriptoies = beanInfo.getPropertyDescriptors();
Person person = new Person();
for(PropertyDescriptor propertyDescriptor : propertyDescriptoies) {
String key = propertyDescriptor.getName();
String value = p.getProperty(key);
Method method = propertyDescriptor.getWriteMethod();
PropertyEditor pe = (PropertyEditor) propertyDescriptor.getPropertyEditorClass().newInstance();
if(pe.getClass() == PropertyEditorSupport.class) { //①
pe.setValue(value);
} else {
pe.setAsText(value);
}
method.invoke(person,pe.getValue());
}
System.out.println(person);
}
说明:代码①表示当pe类型是PropertyEditorSupport,而不是我所定义PropertyEdtior,应该使用setValue方法而不是setAsText方法。
因为在PropertyEditorSupport中,其setAsText()方法为:
public void setAsText(String text) throws java.lang.IllegalArgumentException {
if (value instanceof String) {
setValue(text);
return;
}
throw new java.lang.IllegalArgumentException(text);
}
如果使用setAsText()方法,那么由于value不是String类型,将会抛出IllegalArgumentException。不过很遗憾我搞明白value到底实际上什么类型......
测试结果
Person [name=arthurming, age=18, gender=M, birthday=Tue Oct 24 00:00:00 CST 2017, married=true]
小结
感觉您能容忍我拙劣的文笔看到现在,也希望你在读《精通Spring+4.x++企业应用开发实战》这本书时,看到有关JavaBean编辑器的知识,我的这个例子可以对你有所帮助。
补充
1024,节日快乐
基于JavaBean编辑器读取peroperties文件的更多相关文章
- 项目一:第四天 1、快递员的条件分页查询-noSession,条件查询 2、快递员删除(逻辑删除) 3、基于Apache POI实现批量导入区域数据 a)Jquery OCUpload上传文件插件使用 b)Apache POI读取excel文件数据
1. 快递员的条件分页查询-noSession,条件查询 2. 快递员删除(逻辑删除) 3. 基于Apache POI实现批量导入区域数据 a) Jquery OCUpload上传文件插件使用 b) ...
- 基于.NET的程序读取Excel文件的解决方案
目录 0. 前言 1. 使用NPOI库读取Excel文件 2. 使用OleDbConnection 3. 相关参考 shanzm-2020年12月8日 23:48:11 0. 前言 以前基于 .NET ...
- 基于GDAL库,读取.nc文件(以海洋表温数据为例)C++版
对于做海洋数据处理的同学,会经常遇到nc格式的文件,nc文件的格式全称是NetCDF,具体的详细解释请查询官网[https://www.unidata.ucar.edu/software/netcdf ...
- 读取指定文件夹下的全部文件,可通过正则进行过滤,返回文件路径数组 -- 基于node的一个函数
var fs = require('fs'); // 模板文件夹路径 var templateDirectory = '../src'; //相对于当前文件的相对路径 //var templateDi ...
- 基于Java+Selenium的WebUI自动化测试框架(十)-----读取Excel文件(JXL)
之前,我们使用了读取XML文件的方式来实现页面元素的读取,并做成了基础页面类.下面,我们来进行一些扩展,通过Excel来读取页面元素. Excel的使用,大多数人应该都不陌生.那么Java读取Exce ...
- 基于GDAL库,读取.grd文件(以海洋地形数据为例)C++版
技术背景 海洋地形数据主要是通过美国全球地形起伏数据(GMT)获得,数据格式为grd(GSBG)二进制数据,打开软件通过是Surfer软件,surfer软件可进行数据的编辑处理,以及进一步的可视化表达 ...
- Javascript写入txt和读取txt文件的方法
文章主要介绍了Javascript写入txt和读取txt文件的方法,需要的朋友可以参考下1. 写入 FileSystemObject可以将文件翻译成文件流. 第一步: 例: 复制代码 代码如下: Va ...
- .Net读取Excel文件时丢失数据的问题 (转载)
相信很多人都试过通过OleDB读取Excel文件,这种方法效率十分高,只是有一点会让人十分头痛,就是当一列中既有混合型数据,又有纯数据时,往往容易丢失数据. 百度过后,改连接字符串 “HDR=YES; ...
- Resumable.js – 基于 HTML5 File API 的文件上传
Resumable.js 是一个 JavaScript 库,通过 HTML5 文件 API 提供,稳定和可恢复的批量上传功能.在上传大文件的时候通过每个文件分割成小块,每块在上传失败的时候,上传会不断 ...
随机推荐
- Rigidbody(刚体) and Collider(碰撞器)
关于刚体Rigidbody,手册上是这么描述的: Control of an object's position through physics simulation. 通过物理模拟控制一个物体的位置 ...
- temp-成都农商行路径
route add 30.3.4.0 mask 255.255.255.0 30.3.12.254 route add 30.3.12.0 mask 255.255.255.0 30.3.12.254 ...
- Apache Spark 2.2.0 中文文档 - Spark RDD(Resilient Distributed Datasets)论文 | ApacheCN
Spark RDD(Resilient Distributed Datasets)论文 概要 1: 介绍 2: Resilient Distributed Datasets(RDDs) 2.1 RDD ...
- 谈谈IT界8大恐怖预言!
IT界的8大恐怖预言 本文字数:3276 建议阅读时间:你开心就好 第三次科技革命已经进入白热化阶段———信息技术革命作为其中最主要的一环已经奠定了其基本格局和趋势.OK大势已定,根据目前的形势,小编 ...
- 【】小技巧】CSS文字两端对齐
需求如下,红框所在的文字有四个字的.三个字的.两个字的,如果不两端对齐可以选择居中对齐,或者右对齐.但是如果要像下面这样两端对齐呢? 我相信以前很多人都这么干过:两个字中间使用 来隔开达到四个字的宽度 ...
- JAVA多线程---volatile关键字
加锁机制既可以确保可见性又可以保证原子性,而volatile变量只能确保可见性. 当把变量声明为volatile时候 编译器与运行时都会注意到这个变量是共享的,不会将该变量上的操作与其他内存操作一起重 ...
- 深入理解计算机系统chapter1
---恢复内容开始--- 预处理器+编译器+汇编器+链接器=编译系统 运行hello程序 操作系统: 无论是在单核还是多核系统中,一个CPU看上去都在并发的执行多个进程,这是通过处理器在进程间切换来实 ...
- M方法
ThinkPHP函数详解:M方法 M方法用于实例化一个基础模型类,和D方法的区别在于:1.不需要自定义模型类,减少IO加载,性能较好:2.实例化后只能调用基础模型类(默认是Model类)中的方法:3. ...
- Python网络编程socket练习(TCP)
服务器端:server.py # -*- coding: utf-8 -*- from socket import * HOST='' PORT=5000 BUFF_SIZE=1024 ADDR=(H ...
- 初入APP(结合mui框架进行页面搭建)
前 言 博主最近在接触移动APP,学习了几个小技巧,和大家分享一下. 1. 状态栏设置 现在打开绝大多数APP,状态栏都是与APP一体,不仅美观,而且与整体协调.博主是个中度强迫症患者,顶部那个 ...