巴拉巴拉
小魔仙

自动将properties属性赋值到类中的静态变量

最近写了一个开源github项目,是一个纯Java项目,用来检测指定的一个服务器是否正常运行可访问。如果发生异常可以发送邮件,并可能的话可以尝试重启tomcat服务器。如果您感兴趣可以访问 serverfly 谢谢大家,安利完毕

现在开始正式介绍本文章,因为写这个自动反序列化properteis工具也是因为上面这个项目我才编写了这个工具类。可能这个项目里面也就这个工具类写的最多吧。

例如:config.properties中:

key1=123
key2=中文
key3=false

Const.java:

public static int key1;
public static String key2;
public static boolean key3;

使用工具类:

PropertiesAutoSerialize.init("/config.properties",Const.class);

看上去使用方式好像很简单,其实是真的很简单!这是真的!


实现原理

  • 从properties文件中获取所有的key
  • 遍历这些key去找类中的同名静态字段
  • 字段仅支持boolean,byte,char,short,int,long,float,double,String
  • properties需要使用UTF-8编码,否则中文乱码

献上工具类代码:PropertiesAutoSerialize.java

package com.againfly.util;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Properties;

/**
 * Created by wangankang on 16/8/28.
 * 该类用于将Properties文件中的参数,自动的设置到类同名字段中,前提是字段为静态的.
 */
public class PropertiesAutoSerialize implements Serializable {
    /**
     * 待反序列化的类
     */
    private Class clazz;

    /**
     * 待反序列化的Properties文件输入流
     */
    private InputStream propertiesFile;

    /**
     * Properties操作对象
     */
    private Properties p = new Properties();

    /**
     * 私有的构造方法
     * 用于获取Properties文件流和设置待转对象
     *
     * @param path  用于指定Properties文件路径,例如"/config.properties"
     * @param clazz 待反序列化的类
     */
    private PropertiesAutoSerialize(String path, Class clazz) {
        this.propertiesFile = PropertiesAutoSerialize.class.getResourceAsStream(path);
        InputStreamReader isr = null;
        try {
            isr = new InputStreamReader(propertiesFile, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        this.clazz = clazz;
        try {
            p.load(isr);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取指定key的value值
     *
     * @param key 用于指定获取Properties中的key
     * @return 用于返回Properties中指定key的value
     */
    private String readProperty(String key) {
        if (null == key || "".equals(key.trim())) return null;
        return p.getProperty(key);
    }

    /**
     * PropertiesAutoSerialize.init("/config.properties",Const.class);
     *
     * @param path  properties路径名
     * @param clazz 需要反序列化的类
     */
    public static void init(String path, Class clazz) {
        new PropertiesAutoSerialize(path, clazz).serializeProperties();
    }

    /**
     * 转换实现原理:
     * 获取Properties中所有的key,并遍历
     * 获取该key对应的value,如果value为空字符串,则跳过
     * 去取待转类中的同名字段,如果没有则跳过
     * 判断这个字段是否是静态字段,如果不是则跳过
     * 判断这个字段是否是final,如果是则跳过
     * 设置该字段为可见
     * 获取Properties中指定的value并trim
     * 执行setField方法,对指定的字段进行设置值
     */
    private void serializeProperties() {
        try {
            Iterator iterator = p.keySet().iterator();
            while (iterator.hasNext()) {
                Object obj = iterator.next();
                if (!(obj instanceof String)) {
                    continue;
                }
                String key = ((String) obj).trim();
                String value = readProperty(key).trim();
                if (StringUtil.isEmpty(value)) {
                    continue;
                }
                Field field;
                if (null == (field = getField(key))) {
                    continue;
                }
                if (!Modifier.isStatic(field.getModifiers())) {
                    continue;
                }
                if (Modifier.isFinal(field.getModifiers())) {
                    continue;
                }
                field.setAccessible(true);
                this.setField(field, value);
            }
        } finally {
            try {
                if (null != propertiesFile)
                    propertiesFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 通过反射获取待转类clazz中指定字段名的字段,如果字段不存在则返回null
     *
     * @param fieldName 去查找待转类中的指定字段
     * @return 返回指定的字段
     */
    private Field getField(String fieldName) {
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (Exception ignored) {
        }
        return null;
    }

    /**
     * 对指定的字段进行设置值,目前仅支持字段类型:
     * String,boolean,byte,char,short,int,long,float,double
     *
     * @param field 指定的字段
     * @param value 设置值
     */
    private void setField(Field field, String value) {
        Class type = field.getType();
        Object par = null;
        try {
            if (String.class.equals(field.getType())) {
                par = value;
            } else if (int.class.equals(type) || Integer.class.equals(type)) {
                par = Integer.valueOf(value);
            } else if (boolean.class.equals(type) || Boolean.class.equals(type)) {
                par = Boolean.valueOf(value);
            } else if (long.class.equals(type) || Long.class.equals(type)) {
                par = Long.valueOf(value);
            } else if (double.class.equals(type) || Double.class.equals(type)) {
                par = Double.valueOf(value);
            } else if (float.class.equals(type) || Float.class.equals(type)) {
                par = Float.valueOf(value);
            } else if (short.class.equals(type) || Short.class.equals(type)) {
                par = Short.valueOf(value);
            } else if (byte.class.equals(type) || Byte.class.equals(type)) {
                par = Byte.valueOf(value);
            } else if (char.class.equals(type)) {
                par = value.charAt(0);
            }
            if (null != par) {
                field.set(null, par);
            } else {
                throw new RuntimeException("Properties转换异常:Class(字段类型不是'八大基本类型和String'):" + clazz.getName() + ",字段名:" + field.getName() + ",字段类型:" + field.getType() + ",value:" + value);
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Properties转换异常:Class(IllegalAccessException):" + clazz.getName() + ",字段名:" + field.getName() + ",字段类型:" + field.getType() + ",value:" + value);
        } catch (NumberFormatException e){
            throw new RuntimeException("Properties转换异常:Class(NumberFormatException):" + clazz.getName() + ",字段名:" + field.getName() + ",字段类型:" + field.getType() + ",value:" + value);
        }
    }

}

 

赞(0) 打赏
如果文章对你有帮助,欢迎你来评价反馈。AgainFly » 自动将properties属性赋值到类中的静态变量

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  • Q Q(选填)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏