You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java嵌套DTO生成可持久化哈希:支持注解排除字段的库推荐

适合嵌套DTO哈希生成的Java库方案

下面推荐几个能满足需求的Java库,支持自定义注解排除字段、处理嵌套对象,生成整数或字符串哈希用于持久化:


1. Apache Commons Lang3(HashCodeBuilder)

这个库是Java开发中的常用工具,结合反射可以轻松实现带注解过滤的嵌套对象哈希生成,返回整数哈希值,也可转成十六进制字符串。

实现步骤

  1. 定义自定义排除注解(你已经有了,这里再明确下):
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcludeField {}
  1. 编写哈希生成工具类,递归遍历对象字段,跳过带@ExcludeField的字段:
import org.apache.commons.lang3.builder.HashCodeBuilder;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class HashGenerator {
    public static int generateIntHash(Object obj) throws IllegalAccessException {
        if (obj == null) return 0;
        HashCodeBuilder hcb = new HashCodeBuilder();
        processNestedObject(obj, hcb);
        return hcb.toHashCode();
    }

    public static String generateStringHash(Object obj) throws IllegalAccessException {
        int intHash = generateIntHash(obj);
        return Integer.toHexString(intHash);
    }

    private static void processNestedObject(Object obj, HashCodeBuilder hcb) throws IllegalAccessException {
        Class<?> clazz = obj.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            // 跳过静态字段和带排除注解的字段
            if (Modifier.isStatic(field.getModifiers()) || field.isAnnotationPresent(ExcludeField.class)) {
                continue;
            }
            field.setAccessible(true);
            Object value = field.get(obj);
            if (value != null && !isBasicType(value.getClass())) {
                // 递归处理嵌套对象
                processNestedObject(value, hcb);
            } else {
                hcb.append(value);
            }
        }
    }

    // 判断是否是基础类型或其包装类、字符串
    private static boolean isBasicType(Class<?> clazz) {
        return clazz.isPrimitive()
                || clazz.equals(Integer.class) || clazz.equals(Long.class)
                || clazz.equals(Float.class) || clazz.equals(Double.class)
                || clazz.equals(Boolean.class) || clazz.equals(String.class);
    }
}
  1. 直接使用:
Car car = new Car();
car.setModelYear(2024);
car.setColor("red");
TyreClass tyre = new TyreClass();
tyre.setRadius(18.5f);
tyre.setColour("black");
tyre.setWidth(225.0);
car.setTyre(tyre);

// 生成整数哈希
int intHash = HashGenerator.generateIntHash(car);
// 生成字符串哈希
String strHash = HashGenerator.generateStringHash(car);

2. Jackson(序列化JSON后哈希)

如果你的项目已经引入Jackson(很多Web项目都会用),可以通过序列化对象为JSON(自动过滤带注解的字段),再对JSON字符串生成哈希,返回字符串类型(如SHA-256)。

实现步骤

  1. 复用你的@ExcludeField注解,配置Jackson识别该注解为忽略字段:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.AnnotationIntrospector;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;

public class JsonHashGenerator {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        // 让Jackson识别@ExcludeField为忽略字段
        objectMapper.setAnnotationIntrospector(new AnnotationIntrospector() {
            private final AnnotationIntrospector delegate = objectMapper.getSerializationConfig().getAnnotationIntrospector();

            @Override
            public boolean hasIgnoreMarker(AnnotatedMember member) {
                return member.hasAnnotation(ExcludeField.class) || delegate.hasIgnoreMarker(member);
            }
        });
    }

    // 生成SHA-256字符串哈希
    public static String generateSha256Hash(Object obj) throws Exception {
        String json = objectMapper.writeValueAsString(obj);
        java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-256");
        byte[] hashBytes = digest.digest(json.getBytes());
        StringBuilder hexStr = new StringBuilder();
        for (byte b : hashBytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexStr.append('0');
            hexStr.append(hex);
        }
        return hexStr.toString();
    }
}
  1. 使用示例:
String sha256Hash = JsonHashGenerator.generateSha256Hash(car);

3. Google Guava(HashCode)

Guava提供了丰富的哈希算法支持,结合反射可以实现类似的嵌套对象哈希生成,返回字符串哈希值。

实现步骤

import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;

public class GuavaHashGenerator {
    private static final HashFunction SHA256 = Hashing.sha256();

    public static String generateHash(Object obj) throws IllegalAccessException {
        if (obj == null) return SHA256.hashString("", StandardCharsets.UTF_8).toString();
        com.google.common.hash.Hasher hasher = SHA256.newHasher();
        processNested(obj, hasher);
        return hasher.hash().toString();
    }

    private static void processNested(Object obj, com.google.common.hash.Hasher hasher) throws IllegalAccessException {
        Class<?> clazz = obj.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            if (Modifier.isStatic(field.getModifiers()) || field.isAnnotationPresent(ExcludeField.class)) {
                continue;
            }
            field.setAccessible(true);
            Object value = field.get(obj);
            if (value == null) {
                hasher.putString("null", StandardCharsets.UTF_8);
                continue;
            }
            Class<?> valueClazz = value.getClass();
            // 处理基础类型和包装类
            if (valueClazz == int.class || valueClazz == Integer.class) {
                hasher.putInt((Integer) value);
            } else if (valueClazz == float.class || valueClazz == Float.class) {
                hasher.putFloat((Float) value);
            } else if (valueClazz == double.class || valueClazz == Double.class) {
                hasher.putDouble((Double) value);
            } else if (valueClazz == String.class) {
                hasher.putString((String) value, StandardCharsets.UTF_8);
            } else {
                // 递归处理嵌套对象
                processNested(value, hasher);
            }
        }
    }
}

使用示例:

String guavaHash = GuavaHashGenerator.generateHash(car);

各方案对比

  • Apache Commons Lang3:轻量依赖,生成整数哈希,适合不需要长哈希的场景,代码直观易维护。
  • Jackson:依赖Jackson(多数项目已引入),序列化逻辑成熟,自动处理复杂嵌套,生成的字符串哈希长度固定,适合持久化存储。
  • Google Guava:哈希算法丰富,代码风格简洁,适合本身就用Guava的项目。

内容的提问来源于stack exchange,提问作者user1416932

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 07:35:20