记录一次工作中中使用反射

在很多的框架底层,都用到了java反射的原理,当初在学习java基础的时候,在反射这块,也只是稍稍的过了一下,因为一般只有需要写框架,或者去看框架的底层源码的时候,才会用到反射的知识点。
这次,工作中遇到一个问题,那就是需要使用java,充当一个中间商的角色,A服务调用我的java服务给我推送数据,我再通过公安提供的接口地址将数据推送给公安的服务,使用json格式来做中间数据的传输。但是,公安的接口文档中,所有的请求参数都是大写字母加下划线的格式,例如:

{ 
  "MJJCJLXXBZ":"门禁进出XXX",
  "GLDMJ_CJSBXXBZ":"关联的门禁采集XXX"
  ....
}

所有的接口的参数都是这种格式,大概有10几个接口,这些数据都是A服务推送给我的,所以就涉及到我这里需要写对应的Bean来接收这些参数,并将这些Bean转换成公安需要的json格式推送给公安。其实我完全可以用公安的这种数据格式,来声明一个个类,这样我就不用转换。

class Bean {
  private String MJJCJLXXBZ;
  private String GLDMJ_CJSBXXBZ;
  ....
}

这样做不是不可以,但是违反了java的小驼峰的命名方式,对于我这样有轻微洁癖的人是接受不了的,所以我将其换成常规的java小驼峰的命名格式。

class Bean {
  private String mjjcjlxxbz;
  private String gldmjCjsbxxbz;
  ....
}

这样A服务给我推送数据的时候,就采用这种小驼峰的格式,而我接收数据就使用这个bean来接收。但是我还需要将数据转换成公安接口需要的那种格式才能推送成功,传统办法是将bean里一个个字段都进行手动的转换,但是这样的方式并不可取,所以需要写一个通用的方法,进行操作,
此操作要具有通用性,所以我尝试使用泛型+反射来实现上述需求。
实现代码如下:


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 *
 *@classname RequestData
 *@author 刘岩松
 *@date 2020/6/23 16:31
 */
public class RequestData {

    private static Pattern AZ_PATTERN = Pattern.compile("[A-Z]");
    private static Pattern UNDERLINE_PATTERN = Pattern.compile("_([a-z])");

    public static  Map generation(T data) {
        Map result = new LinkedHashMap<>();
        Class clazz = data.getClass();
        try {
            for (Field field : clazz.getDeclaredFields()) {
                String key = underline(field.getName()).toUpperCase();
                //利用反射执行目标方法获取值
                Method method = clazz.getMethod("get" + field.getName().substring(0, 1).toUpperCase().concat(field.getName().substring(1)));
                String value = (String) method.invoke(data);
                result.put(key, value);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 将驼峰格式字符串转下划线格式
     *
     * @param str 待处理字符串
     * @author 刘岩松
     * @date 2020/6/23 16:55
     */
    private static String underline(String str) {
        //正则匹配大写字符转成小写并在前面加上下划线
        Matcher matcher = AZ_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer(str);
        if (matcher.find()) {
            sb = new StringBuffer();
            //将当前匹配的子串替换成指定字符串,
           //并且将替换后的子串及之前到上次匹配的子串之后的字符串添加到StringBuffer对象中
            //正则之前的字符和被替换的字符
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
            //把之后的字符串也添加到StringBuffer对象中
            matcher.appendTail(sb);
        } else {
            return sb.toString();
        }
        return underline(sb.toString());
    }

    /**
     *
     *将下划线格式字符串转驼峰格式
     *
     * @param str string 待处理字符串
     * @author 刘岩松
     * @date 2020/6/23 16:00
     */
    private static String camel(String str) {
        //正则匹配下划线及后一个字符,删除下划线并将匹配的字符转成大写
        Matcher matcher = UNDERLINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer(str);
        if (matcher.find()) {
            sb = new StringBuffer();
            //将当前匹配的子串替换成指定字符串,
            //并且将替换后的子串及之前到上次匹配的子串之后的字符串添加到StringBuffer对象中
            //正则之前的字符和被替换的字符
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
            //把之后的字符串也添加到StringBuffer对象中
            matcher.appendTail(sb);
        } else {
            return sb.toString();
        }
        return camel(sb.toString());
    }
}

你可能感兴趣的:(记录一次工作中中使用反射)