通过反射校验实体类中属性值是否符合要求

本文介绍了一种利用反射机制进行实体类字段校验的方法,避免了大量if-else判断,提高了代码的可读性和维护性。适用于保存或导入信息时的非空检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

业务逻辑中通常对于保存或者导入的信息需要进行校验,这时候我们如果通过后台校验可能需要大量的ifelse去判断,那不如通过一个反射写一个通用的校验,请看代码--》 


import org.apache.commons.lang3.ObjectUtils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @Author: yitianRen
 * @Date: 14:30 2020/8/1
 * @Description:
 * @Version v1.0
 */
public class CheckEntityFieldValueEmpty {

    //基本信息非空字段
    public static final String[] AM_HIGH_TALENT_INFO_FIELDS =
            {"name", "sex", "idNum", "orgFullName", "orgType", "adminPost", "pqLevel", "education", "mobile", "email", "address", "talenLevel","hightTalentType"};
    //高端会计人才非空字段
    public static final String[] AM_HIGH_TALENT_INFO_FIELDS_QGLJ =
            {"talentType", "year", "culStatus", "graDate"};
    //高端会计人才特殊支持计划非空字段
    public static final String[] AM_HIGH_TALENT_INFO_FIELDS_KJTSZCJH =
            {"year", "culStatus", "graDate"};
    //全国大中型企事业单位总会计师培养(高端班)非空字段
    public static final String[] AM_HIGH_TALENT_INFO_FIELDS_KJSPYG =
            {"talentType", "talentPeriod", "culStatus", "graDate"};

    //校验保存或者导入实体类中不能为空值的项
    /**
     *@Author: yitianRen
     *@Date: 17:12 2020/8/1
     *@Description:
     * @param isList 提示语
     * @param listIndex 第几项
     * @param notEmptyStrs 不能为空的字段值
     * @param obj 实体
     *@Version v1.0
     */
    public static List<Map<String,String>> checkEntity(String[] notEmptyStrs, Object obj,int isList,int listIndex){
        List<Map<String,String>> resutList = new LinkedList<>();
       /* for (int i = 0; i < checkList.size(); i++) {
            Object obj = checkList.get(i);*/
            Field[] fields = obj.getClass().getDeclaredFields();
            Map<String,String> map = new HashMap<>();
            StringBuffer sb =new StringBuffer();
            if(isList == -1){
                sb.append("当前单据中基础项");
            }else if(isList == -3){
                sb.append("第"+(listIndex+1)+"列中基础项");
            }else if(isList == -2){
                sb.append("当前单据中锁定项");
            }
            else if(isList == -4){
                sb.append("第"+(listIndex+1)+"列中锁定项");
            }
            Boolean isEmpty = false;
            for (Field f:fields) {
                try {
                    //校验是否是需要校验字段
                    if (Arrays.asList(notEmptyStrs).contains(f.getName())) {
                        f.setAccessible(true);
                        Object value = f.get(obj);
                        String str = ObjectUtils.toString(value, "");
                        if (StringUtil.isEmpty(str)) {
                            isEmpty = true;
                            sb.append(getName(f.getName()));
                        }
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            sb.append("项不能为空!");
            map.put("emptyField",sb.toString());
            if(isEmpty){
                resutList.add(map);
            }
        //}
        return resutList;
    }

    private static String getName(String name) {
        Map<String,String> nameMap = new HashMap<>();
        nameMap.put("name","姓名");
        nameMap.put("sex","性别");
        nameMap.put("idNum","身份证号");
        nameMap.put("orgFullName","工作单位全称");
        nameMap.put("orgType","工作单位类别");
        nameMap.put("adminPost","会计人员职务");
        nameMap.put("pqLevel","职称");
        nameMap.put("education","学历");
        nameMap.put("mobile","手机号");
        nameMap.put("email","电子邮箱");
        nameMap.put("address","通讯地址");
        nameMap.put("talenLevel","高端会计人才级别");
        nameMap.put("hightTalentType","会计人才类型");
        nameMap.put("talentType","高端会计人才类别");
        nameMap.put("year","年度");
        nameMap.put("hightClassType","高端班类别");
        nameMap.put("talentPeriod","期次");
        nameMap.put("culStatus","培养状态");
        nameMap.put("graDate","毕业年度");
        return "【"+nameMap.get(name)+"】";
    }

}

参考使用:

CheckEntityFieldValueEmpty.checkEntity(CheckEntityFieldValueEmpty.AM_HIGH_TALENT_INFO_FIELDS,highTalentInfoVo,-1,0);

 

<think>好的,用户的问题是关于在Spring Boot中使用反射获取字段注解的示例。我需要先理清楚用户的需求,然后结合提供的引用内容来构建答案。 首先,用户可能是在开发Spring Boot应用时,遇到了需要动态处理字段注解的情况。例如,自定义注解,然后通过反射读取注解的,进行一些业务逻辑处理,比如数据校验、动态配置等。根据引用[1],Spring本身大量使用反射来管理Bean,比如动态创建实例、依赖注入和AOP。因此,用户的问题属于如何在自己的代码中利用反射机制,类似于Spring容器内部的操作。 接下来,我需要回忆反射的基本步骤。获取字段的注解通常涉及以下几个步骤:获取类的Class对象,通过Class对象获取字段,然后从字段上获取注解实例,最后读取注解的属性值。同时,需要处理可能的异常,比如NoSuchFieldException,以及确保注解的保留策略是RUNTIME,这样才能在运行时通过反射获取,如引用[4]中的@JasyptField注解,确实使用了@Retention(RetentionPolicy.RUNTIME),这样是正确的。 然后,结合用户提供的引用内容,特别是引用[4]中的自定义注解示例,可以构建一个类似的例子。比如,用户可能定义了一个注解,比如@CustomAnnotation,然后需要读取该注解的。需要确保在示例代码中正确使用反射API,如getDeclaredField获取字段,再getAnnotation获取注解实例。 另外,考虑到Spring Boot的环境,可能需要获取Spring管理的Bean中的字段注解,这时候可能需要结合ApplicationContext来获取Bean实例,再对其进行反射操作。不过用户的问题更偏向于普通的反射操作,不需要涉及Spring容器获取Bean的过程,所以示例中可以简化,直接使用一个普通对象。 还需要考虑代码的完整性,比如异常处理,是否需要遍历所有字段,或者如何集成到Spring Boot的服务中。例如,可能在一个服务类中编写工具方法,处理特定对象的字段注解。 最后,根据用户提供的引用[3],Spring Boot的参数校验使用@Valid和异常处理,可能在示例中提到类似的应用场景,比如自定义校验注解,通过反射读取注解进行校验,但用户的问题更侧重于如何获取注解,而不是校验本身,所以示例应重点展示反射获取的过程。 总结步骤: 1. 创建自定义注解,并确保保留策略为RUNTIME。 2. 在实体类的字段上使用该注解。 3. 编写工具类方法,使用反射获取字段的注解实例。 4. 读取注解的属性值,并处理可能的异常。 需要检查示例代码是否符合这些步骤,并确保语法正确。同时,参考引用中的代码结构,比如引用[4]的注解定义,引用[1]中提到的反射应用场景,确保回答的准确性和相关性。</think>在Spring Boot中,通过反射获取字段注解的实现步骤如下(结合代码示例说明): --- ### 1. 定义自定义注解 首先创建作用在字段上的注解,注意必须设置`@Retention(RetentionPolicy.RUNTIME)`以保证运行时可见: ```java @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface CustomAnnotation { String value() default ""; int priority() default 0; } ``` --- ### 2. 在实体类中使用注解 在需要处理的字段上添加注解并赋: ```java public class User { @CustomAnnotation(value = "username", priority = 1) private String name; @CustomAnnotation(value = "userAge", priority = 2) private int age; } ``` --- ### 3. 反射获取注解 通过反射API获取字段及其注解信息: ```java public class AnnotationProcessor { public static void processAnnotations(Object obj) { Class<?> clazz = obj.getClass(); for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(CustomAnnotation.class)) { CustomAnnotation annotation = field.getAnnotation(CustomAnnotation.class); System.out.println("字段名: " + field.getName()); System.out.println("注解: " + annotation.value()); System.out.println("优先级: " + annotation.priority()); } } } } ``` --- ### 4. 在Spring Boot中集成使用 结合Spring容器调用示例: ```java @Service public class UserService { public void validateUser(User user) { AnnotationProcessor.processAnnotations(user); // 触发注解处理 } } ``` --- ### 关键点解析 - **反射操作入口**:通过`Class.getDeclaredFields()`获取所有字段,遍历后检查注解存在性 - **注解生命周期**:必须使用`@Retention(RetentionPolicy.RUNTIME)`才能使注解在运行时可见[^4] - **访问私有字段**:若需要访问私有字段,需调用`field.setAccessible(true)` - **性能优化**:反射操作成本较高,建议缓存`Class`对象和`Field`信息 --- ### 典型应用场景 1. **动态配置解析**:根据注解生成字段映射关系 2. **数据校验扩展**:自定义校验规则注解(类似@Valid的扩展实现)[^3] 3. **序列化控制**:根据注解决定字段序列化方式 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值