DTO日志打印统一脱敏

该博客介绍了Java中DTO(Data Transfer Object)类的实现,主要用于数据传输和序列化。文章详细展示了如何在DTO类中处理字段的访问控制,并且实现了自定义的toString方法,以避免相互引用导致的栈溢出。同时,文中还引入了一个名为`DesensitizationAnnotation`的注解,用于处理敏感信息的脱敏规则,确保在输出字符串时,符合特定的脱敏策略。
摘要由CSDN通过智能技术生成
package org.demo.spring.mysql.dto;

import org.springframework.beans.BeanUtils;

import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class BaseDTO implements Serializable {
    private static final long serialVersionUID = 25693154881567L;
    //访问控制器,序列化的时候,不做处理
    private transient ThreadLocal<BaseDTO> visitor = new ThreadLocal<BaseDTO>() {
        protected BaseDTO initialValue() {
            return null;
        }
    };
    private String simpleName = this.getClass().getSimpleName();

    public BaseDTO() {
    }

    /**
     * 重写String
     * 避免子类中相互引用引起输出toString时栈溢出
     *
     * @return
     */
    private String toStringO() {
        try {
            PropertyDescriptor[] props = BeanUtils.getPropertyDescriptors(this.getClass());
            Object[] params = new Object[0];
            boolean isFirst = true;
            StringBuilder strBuilder = new StringBuilder(512);
            strBuilder.append(this.getClass().getName()).append('{');
            PropertyDescriptor[] var9 = props;
            int var10 = props.length;

            for (int var11 = 0; var11 < var10; ++var11) {
                PropertyDescriptor descriptor = var9[var11];
                String filedName = descriptor.getName();
                if ("class".equals(filedName)) continue;
                Field field = this.getClass().getDeclaredField(descriptor.getName());
                if (field != null) {
                    boolean fieldAccessible = field.isAccessible();
                    if (!fieldAccessible) {
                        field.setAccessible(true);
                    }
                    // 获取get方法
                    Method m = descriptor.getReadMethod();
                    if (m != null) {
                        boolean accessible = m.isAccessible();
                        if (!accessible) {
                            m.setAccessible(true);
                        }
                        try {
                            Object result = m.invoke(this, params);
                            // 获取属性上的注解
                            DesensitizationAnnotation maskAnnotationFi = (DesensitizationAnnotation) field.getAnnotation(DesensitizationAnnotation.class);
                            // get方法上的注解
                            DesensitizationAnnotation maskAnnotationMeth = (DesensitizationAnnotation) m.getAnnotation(DesensitizationAnnotation.class);
                            if (maskAnnotationFi != null || maskAnnotationMeth != null) {
                                DesensitizationAnnotation maskAnnotation = maskAnnotationFi == null ? maskAnnotationMeth : maskAnnotationFi;
                                /**
                                 *   脱敏规则,默认***替换
                                 * 也可以加入正则,实际打个日志没必要那么复杂
                                 * 不过为了方便定位问题也不是不可以,
                                 * 定位问题好像也没那么巧单单依赖脱敏字段,所以还是偷点懒吧
                                 *
                                 */
                                result = maskAnnotation.desensitizationRule();
                            }

                            if (!isFirst) {
                                strBuilder.append(", ");
                            } else {
                                isFirst = false;
                            }

                            strBuilder.append(descriptor.getName()).append(": ");
                            if (result instanceof String) {
                                strBuilder.append('"');
                                strBuilder.append(result);
                                strBuilder.append('"');
                            } else {
                                strBuilder.append(result);
                            }
                        } catch (Exception var14) {
                        }

                        if (!accessible) {
                            m.setAccessible(false);
                        }
                    }
                }
            }
            strBuilder.append('}');
            return strBuilder.toString();
        } catch (Exception var15) {
            return super.toString();
        }
    }


    public String toString() {
        if (this.visitor.get() == null) {
            this.visitor.set(this);

            String var1;
            try {
                var1 = this.toStringO();
            } finally {
                this.visitor.set(null);
            }

            return var1;
        } else {
            return this.simpleName + "@" + Integer.toHexString(this.hashCode());
        }
    }
}
import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DesensitizationAnnotation {
    /**
     * 脱敏规则,默认***替换
     * @return
     */
    public String desensitizationRule() default "***";
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值