利用注解和反射解决代码冗余问题(改进版)

在优化代码的时候发现,传参存在着高度冗余,如果后面需要改参数,很不方便。

 String pam1 = "id=" + appKey + "&sign=" + sign + "&method=" + method + "&access_token=" + token + "&timestamp="
                + timestamp + "&projectCode=" + projectCode;

参考网上的方法,自己创建注解类,利用反射注入参数并实现。
在这里插入图片描述
在这里插入图片描述
这里解释一下注解。

  1. @Retention修饰注解,用来表示注解的生命周期
    在这里插入图片描述
    上面三种类型生命周期:SOURCE<CLASS<RUNTIME,使用RUNTIME会包含前面两个生命周期
    那怎么来选择合适的注解生命周期呢?
    首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要 在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife) ,就用 CLASS注解;如果 只是做一些检查性的操作,比如 @Override 和@SuppressWarnings,则 可选用 SOURCE 注解。
    RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
  2. @Target:注解的作用目标
    @Target(ElementType.TYPE)——接口、类、枚举、注解@Target(ElementType.FIELD)——字段、枚举的常量
    @Target(ElementType.METHOD)——方法
    @Target(ElementType.PARAMETER)——方法参数
    @Target(ElementType.CONSTRUCTOR) ——构造函数
    @Target(ElementType.LOCAL_VARIABLE)——局部变量
    @Target(ElementType.ANNOTATION_TYPE)——注解
    @Target(ElementType.PACKAGE)——包
  3. @Inherited:说明子类可以继承父类中的该注解
  4. @Document 是 java 在生成文档,是否显示注解的开关

第二步是创建实体类,并导入注解,定义导出时的字段名(name)和拼接顺序(order)
在这里插入图片描述
第三步就是写出拼接的方法

public class UrlUtil {

    public static String createURL(DeviceDTO deviceDTO){
    deviceUrl deviceUrl = deviceDTO.getClass().getAnnotation(deviceUrl.class);
    StringBuilder stringBuilder = new StringBuilder(deviceUrl.url());
    Arrays.stream(deviceDTO.getClass().getDeclaredFields())
            .filter(x -> x.isAnnotationPresent(deviceField.class))
            .sorted(Comparator.comparing(x -> x.getAnnotation(deviceField.class).order()))
            .peek(x -> x.setAccessible(true))
            .forEach(field -> {
                deviceField flightQueryField = field.getAnnotation(deviceField.class);
        Object value = "";
        try {
            value = field.get(deviceDTO);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if (flightQueryField.order() == 1) {
            stringBuilder.append("?").append(flightQueryField.name() + "=" + value).append("&");
        } else {
            stringBuilder.append(flightQueryField.name() + "=" + value).append("&");
        }
    });
    return stringBuilder.toString().substring(0, stringBuilder.toString().length() - 1);
    }
}

如果需要实现传入任意类型的类,可以这样实现:
这里,我的url拼接,不需要?,我把append(?)去掉了,若需要自己加上

 public static <T> String createURL(Class<T> tClass,T cla){
        //将传过来的对象进行赋值处理
        T u = tClass.cast(cla);
        //以下是验证此示意中实体类可被操作了
		//getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
		//.getClass()是一个对象实例的方法,只有对象实例才有这个方法,具体的类是没有的

        for (Field declaredField : u.getClass().getDeclaredFields()) {
            //允许获取实体类private的参数信息
            declaredField.setAccessible(true);
        }
        deviceUrl deviceUrl = cla.getClass().getAnnotation(deviceUrl.class);
        StringBuilder stringBuilder = new StringBuilder(deviceUrl.url());
        //通过自定义注解deviceField获取实体类的字段值和属性值
        Arrays.stream(cla.getClass().getDeclaredFields())
                .filter(x -> x.isAnnotationPresent(deviceField.class))
                .sorted(Comparator.comparing(x -> x.getAnnotation(deviceField.class).order()))
                .peek(x -> x.setAccessible(true))
                .forEach(field -> {
                    deviceField flightQueryField = field.getAnnotation(deviceField.class);
            Object value = "";
            try {
                value = field.get(cla);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if (flightQueryField.order() == 1) {
                stringBuilder.append(flightQueryField.name() + "=" + value).append("&");
            } else {
                stringBuilder.append(flightQueryField.name() + "=" + value).append("&");
            }
        });
        return stringBuilder.toString().substring(0, stringBuilder.toString().length() - 1);
        }

传参的话是这样的
在这里插入图片描述

进行测试
在这里插入图片描述
结果
在这里插入图片描述
这里我没有加前置的url,在实体类的注解里url加上就好了

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值