自定义注解+反射实现需求


背景

接到一个需求一个员工有诸多信息 现在要记录修改时哪些信息被修改了并需要记录这些信息在一个字段中,同时后台又需要支持按照修改内容进行多选搜索。


一、分析思路

要记录每一个字段是否修改,按照常规写法会产生大量ifelse 同时代码可读性差 并且代码也不好维护 所以我使用了自定义注解+反射来解决问题

二、实现步骤

首先写一个自定义注解来标记字段的描述

package cn.nineox.health.common.annotation;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Description {
  /**
   * 字段描述
   */
  public String filedName();


}

然后需要将源对象要和修改后的对象进行比对 需要遍历对象 这里我用到了反射

 /**
   * 信息修改组装字符串
   *
   * @param sourceBean
   * @param targetBean
   * @return
   */
  public static String editContent(Object sourceBean, Object targetBean) {
    Class sourceBeanClass = sourceBean.getClass();
    Class targetBeanClass = targetBean.getClass();

    // 获取对象的所有字段并存入字段集合中
    Field[] sourceFields = sourceBeanClass.getDeclaredFields();
    Field[] targetFields = targetBeanClass.getDeclaredFields();
    StringBuffer stringBuffer = new StringBuffer();
    for (int i = 0; i < sourceFields.length; i++) {
      Field sourceField = sourceFields[i];
      Field targetField = targetFields[i];
      // 没有注解的字段不处理
      Description description = sourceField.getAnnotation(Description.class);
      if (description == null) {
        continue;
      }
      // 设置私有变量也可访问
      sourceField.setAccessible(true);
      targetField.setAccessible(true);
      try {
        // 获取简单名称 比如java.lang.String 的简单名称就是String
        String fieldTypeName = sourceField.getType().getSimpleName();
        // 信息修改的类型暂时只有Integer和String 后续有新的再增加
        if (StringUtils.equals("String", fieldTypeName)) {
          String sourceValue = (String) sourceField.get(sourceBean);
          String targetValue = (String) targetField.get(targetBean);
          // 不相等则证明是修改
          if (!StringUtils.equalsIgnoreCase(sourceValue, targetValue)
              && (StringUtils.isNotEmpty(targetValue) || StringUtils.isNotEmpty(sourceValue))) {
            // 将注解中的描述信息拼接到字符串中
            stringBuffer.append(sourceField.getAnnotation(Description.class).filedName()).append(',');
          }
        }

        if (StringUtils.equals("Integer", fieldTypeName)) {
          Integer sourceValue = (Integer) sourceField.get(sourceBean);
          Integer targetValue = (Integer) targetField.get(targetBean);
          // 不相等则证明是修改
          if (!ObjectUtil.equal(sourceValue, targetValue)) {
            // 将注解中的描述信息拼接到字符串中
            stringBuffer.append(sourceField.getAnnotation(Description.class).filedName()).append(',');
          }
        }
      } catch (IllegalArgumentException | IllegalAccessException e) {
        e.printStackTrace();
      }
    }
    if (stringBuffer.length() > 0) {
      stringBuffer.deleteCharAt(stringBuffer.length() - 1);
    }
    return stringBuffer.toString();
  }

然后实现多选的筛选操作
这里我用到了mysql中的FIND_IN_SET(a,b)函数 他能判断a是否在b中存在 其中b是用逗号分割的

   <if test="query.editContentList  != null and query.editContentList.size() > 0">
      and (
      <foreach collection="query.editContentList" item="item" open="(" close=")" separator="or">
        FIND_IN_SET(#{item}, c.editContent)
      </foreach>
      )
    </if>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值