Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >自定义注解判断参数为空

自定义注解判断参数为空

作者头像
@派大星
发布于 2023-06-28 06:58:52
发布于 2023-06-28 06:58:52
36100
代码可运行
举报
文章被收录于专栏:码上遇见你码上遇见你
运行总次数:0
代码可运行

最近在项目中遇到了一个小小的问题,和大家分享一下,简单的接口但是在不同的业务场景下需要有不同的校验逻辑,有的参数在特定的场景下需要校验,有的参数在另外的场景下则不需要校验。解决方案有很多种加上我当时是刚刚入职为了偷懒贪图省事,所以就写了一大堆的if/else。如下展示(由于业务原因,敏感字段已转换):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void checkParams(DTO dto) {
    if (ObjectUtils.isEmpty(dto.getParam())) {
        throw new ServiceException("Please fill in the param number");
    }
    if (ObjectUtils.isEmpty(dto.getParam())) {
        throw new ServiceException("Please fill in the param number");
    }
    if (ObjectUtils.isEmpty(dto.getParam())) {
        throw new ServiceException("Please fill in the param number");
    }
    if (ObjectUtils.isEmpty(dto.getParam())) {
        throw new ServiceException("Please fill in the param number");
    }
    if (ObjectUtils.isEmpty(dto.getParam())) {
        throw new ServiceException("Please fill in the param number");
    }
    if (ObjectUtils.isEmpty(dto.getParam())) {
        throw new ServiceException("Please fill in the param number");
    }
    if (ObjectUtils.isEmpty(dto.getParam())) {
        throw new ServiceException("Please fill in the param number");
    }

    ..............
}

为了方法的可读性吧,我还特意将检验参数的方法抽离出checkParams单独的方法。当时想这样应该也就可以了吧。万万没想到啊,我在编写完代码的时候在pull代码前的编译的时候,PMD检查没有过这个是把我给恶心到了当时报了一个错叫做什么 Avoid really long methods 和 GodClass这就让我很尴尬了,临门一脚给我拦住了很是郁闷。当时想我一个新来的需要抓紧把代码提上去不能拖延时间啊,接着我又开始了一系列的骚操作是你们不可能想到的。如下:

相比各位童鞋们看到参数的命名很无语吧,当时我也很无语其实我下意识是不想这么做的。但是没有办法,当时着急熟悉代码。以及完成工作没办法我还是硬着头皮把这个代码给改掉了。想着以后有时间改掉吧。天不遂人愿啊真的是。隔天我就经历了code review,各位你们可知道那种场合,我写的代码被斩首示众,我当时简直脚趾抠出来三室一厅的尴尬,好在是我leader明白我当时的困境理解我(此时我还是很庆幸的),说没事有时间改过来就好。cw一完事,我忙完自己手里的活,果断的偷偷的把这个低级错误给办了。利用了自定义注解的方式。废话不多说给大家看一下核心代码。

  • 首先我建立了一个注解类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.mb.rks.cases.common.annotation;

import java.lang.annotation.*;

/**
 * @author
 * <p>自定义注解校验参数<p>
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MetadataValidation {

    /**
     * 错误信息
     * @return
     */
    String message() default "参数不能为空";

    /**
     * 正则表达式
     * @return
     */
    String pattern() default "";

}

  • 然后利用反射写了一个验证器
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.mb.rks.cases.common.utils;

import com.mb.rks.cases.common.annotation.MetadataValidation;
import com.mb.rks.cases.common.exception.TipsValidationException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @author
 * <p>Validation验证器<p>
 * <p>
 * 对有自定义注解@Validation的参数进行校验
 */
@Slf4j
public final class ValidationCheckUtils {

    /**
     * 因为是工具类,所以不可以通过new的方式去创建,顾将其构造方法写成如下方式
  */
    protected ValidationCheckUtils(){}

    /**
     * 检验方法:
     * <p>扫描对象的属性,查看是否有@Validation注解,有注解的进行校验
     *
     * @param o 要校验的对象,入参对象
     */
    public static void check(Object o) {
        if (null == o) {
            return;
        }
        Class<?> clazz = o.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }

        // 对象的所有属性
        fieldList.forEach(field -> {
            ReflectionUtils.makeAccessible(field);

            try {
                // 获取属性值
                MetadataValidation annotation = field.getAnnotation(MetadataValidation.class);
                // 没有注解则不做处理
                if (null == annotation) {
                    return;
                }
                // 获取指定对象o上此 Field 表示的字段的值
                Object value = field.get(o);
                checkNotNull(value, annotation);
                checkPattern(value, annotation);
            } catch (IllegalAccessException e) {
                log.error("Validation验证起数据解析失败:{}", e.getMessage());
            }
        });
    }


    /**
     * 非空判断
     *
     * @param value      属性值
     * @param annotation 注解信息
     */
    private static void checkNotNull(Object value, MetadataValidation annotation) {
        log.info("开始非空校验");
        if (annotation != null && ObjectUtils.isEmpty(value)) {
            throw new RuntimeException(annotation.message());
        }
    }

    /**
     * 正则校验
     *
     * @param value      属性值
     * @param annotation 注解信息
     */
    private static void checkPattern(Object value, MetadataValidation annotation) {
        // 存在正则表达式
        if (null != annotation.pattern() && annotation.pattern().length() > 0) {
            Pattern pattern = Pattern.compile(annotation.pattern());
            // 以pattern的规则匹配value的值
            Matcher matcher = pattern.matcher(value.toString());
            // 属性值不符合正则表达式所制定的格式,抛出异常
            if (!matcher.matches()) {
                throw new RuntimeException(annotation.message());
            }
        }
    }


}

  • 在需要调用校验参数的地方可以加上这样一串代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 点击发送之前的参数校验
ValidationCheckUtils.check(dto);

好了上面所有的核心代码快已经贴出来了,希望能够帮助到小伙伴们。 其实看到这里的小伙伴们免不了会说上一句使用Spring的 @Valid和@Validated不好嘛,干嘛要自己造轮子呢,多次一举,其实不是这样的这种想法我在编写代码的时候就想到了。但是在我们的业务场景中多个参数接口使用的参数类是同一个,所以使用Spring的@Valid和@Validated自然是不行了。其实换种想法也不是不可以那就是检验参数的再新建一个类,我觉得完全没必要,因为这样很容易就造成类爆炸。不知你是怎么样呢。欢迎评论。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-10-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上遇见你 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
SpringBoot系列之自定义枚举类的数据校验注解
SpringBoot系列之自定义枚举类的数据校验注解 业务场景:数据校验,需要对枚举类型的数据传参,进行数据校验,不能随便传参。拓展,支持多个参数的枚举数据校验
SmileNicky
2021/12/17
3.3K1
SpringBoot系列之自定义枚举类的数据校验注解
简单实现自定义注解
在Java中创建自定义注解 创建自定义注解与编写接口很相似,除了它的接口关键字前有个@符号。 注意以下几点: ·注解方法不能有参数。 ·注解方法的返回类型局限于原始类型,字符串,枚举,注解,或以上类型构成的数组。 ·注解方法可以包含默认值。 ·注解可以包含与其绑定的元注解,元注解为注解提供信息,有四种元注解类型: @Documented – 表示使用该注解的元素应被javadoc或类似工具文档化,它应用于类型声明,类型声明的注解会影响客户端对注解元素的使用。如果一个类型声明添加了Documented注解
dalaoyang
2018/04/28
6860
简单实现自定义注解
Spring 自定义注解你了解过吗?
https://juejin.im/post/5cf376e16fb9a07eee5eb6eb
南风
2020/09/11
5820
自定义注解
代码逻辑: 访问get接口,接口通过并返回一个参数key-value设置到request中去, 同时也会往session中设置一个相同的key-value, 前台拿到这个key-value,然后存储到form表单中,post提交表单时,会将这个key-value提交, 后台校验此key-value和session中的key-value是否一致
在下是首席架构师
2022/08/18
3170
2 手写实现SpringMVC,第二节:自定义注解及反射赋值
可以发现,这里面使用了大量的自定义注解,并且还有autuwire的属性也需要被赋值(Spring的IOC功能)。
天涯泪小武
2019/01/17
1K0
自定义注解实现参数验证与业务代码解耦
核心依赖 <!-- aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId>
Meet相识
2018/09/12
1.3K0
利用Java的注解实现自定义校验器
Java的注解是一种可用于将元数据信息与程序源代码中的各个部分进行关联的机制。而校验器则是在开发过程中必不可少的一部分,它可以用来保证系统或者接口输入参数的有效性和准确性。利用Java的注解实现自定义校验器可以提高开发效率,减少代码维护的工作量,并且能够更加规范化地管理项目代码。
用户1289394
2023/12/19
3170
利用Java的注解实现自定义校验器
总说自定义注解,可是自定义注解到底该怎么用?
在项目中新建Java文件是选择Annotation类型则会为我们创建一个注解文件。关于注解的详细介绍可以看之前写的注解详解文章。
我的小熊不见了丶
2019/05/22
1.2K0
一篇文章,全面掌握Java自定义注解(Annontation)
注解(Annontation),Java5引入的新特性,位于java.lang.annotation包中。提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。是一种说明、配置、描述性的信息,与具体业务无关,也不会影响正常的业务逻辑。但我们可以用反射机制来进行校验、赋值等操作。
程序新视界
2022/05/09
4.5K0
022.自定义注解
注解是Jdk1.5新增新技术。很多框架为了简化代码,都会提供有些注解。 可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在代码上插入了一个插件。 注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。
qubianzhong
2018/12/14
4320
Java Bean Validation自定义注解
前面介绍了Java Bean Validation的使用,本文进一步介绍一下当标准的校验注解不满足要求时,可以自定义校验注解满足特定需求。比如@In,要求参数数据某个固定的集合(类似于枚举值) 自定义注解 @In import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Retention
十毛
2019/05/14
2.7K0
java自定义注解怎么实现注解(怎么获取自定义注解内的值)
10@Repeatable(LearnRepeatableAnnotation.class)
全栈程序员站长
2022/07/28
1.5K0
【Java 注解】自定义注解 ( 使用注解实现简单测试框架 )
在 【Java 注解】自定义注解 ( 注解属性定义与赋值 ) 博客中讲解了 注解属性 ;
韩曙亮
2023/03/29
4420
【Java 注解】自定义注解 ( 使用注解实现简单测试框架 )
Java实现自定义注解,实现不需要token 验证就可以访问接口
一个springboot 项目,需要token 验证,前端传过来token ,我们一般在项目全局写一个过滤器,去验证前端传过来的token ,如果有哪些接口不需要token验证,那么就排除这些接口,这个也需要配置。
一写代码就开心
2024/05/25
1.2K0
Java实现自定义注解,实现不需要token 验证就可以访问接口
MybatisPlus不好用?帅小伙一气之下写了个MybatisPlusPro
即使在 CRUD,只要你肯思变,抽离出一套轮子,也是轻而易举的事。下面我们就一起来让 CRUD 自动化。
java思维导图
2023/12/13
3731
MybatisPlus不好用?帅小伙一气之下写了个MybatisPlusPro
注解 & 自定义注解
一般我们把元注解理解为描述注解的注解,元数据理解为描述数据的数据,元类理解为描述类的类…
收心
2022/01/17
4530
java自定义注解的使用
不曾想,每个人都是这样经历过来的,不知你是否还记得在spring的xml配置文件里如何配置对象的场景?或许依然记忆犹新,或许早已抛开在脑后,等等吧。后面spring出现了通过注解的方式去注入一个实例,这或许解放了很多我这样的码农双手,坏笑。
码农王同学
2019/11/26
6860
Java 注解 —— 注解的理解、注解的使用与自定义注解
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ajianyingxiaoqinghan/article/details/81436118
剑影啸清寒
2019/05/26
3.3K0
java自定义注解和使用[通俗易懂]
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/129174.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/29
2470
springboot使用jpa 自定义注解进行校验
最近在看jpa的时候,想起来,要是自己写一个自定义的注解作用在entity上面应该怎么使用啊。 这里要使用到了@EntityListeners 这是一个实体的监听器
分享干货的你
2021/04/06
1.2K0
推荐阅读
相关推荐
SpringBoot系列之自定义枚举类的数据校验注解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档