前往小程序,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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
实习第十一周,第十二周
title属性是必须的,用来指定通知的标题,格式为字符串。options属性是可选的,格式为一个对象,用来设定各种设置
治电小白菜
2020/08/25
7150
实习第十一周,第十二周
📃前端导出Excel实践:探索xlsl的实现方式
使用XLSX库,你可以读取现有的Excel文件,提取其中的数据和元数据。例如,假设你有一个名为"data.xlsx"的Excel文件,你可以通过以下方式读取它:
linwu
2023/07/27
1.3K0
如何使用JavaScript实现前端导入和导出excel文件(H5编辑器实战复盘)
最近笔者终于把H5-Dooring的后台管理系统初步搭建完成, 有了初步的数据采集和数据分析能力, 接下来我们就复盘一下其中涉及的几个知识点,并一一阐述其在Dooring H5可视化编辑器中的解决方案. 笔者将分成3篇文章来复盘, 主要解决场景如下:
徐小夕
2020/10/30
3.2K0
如何使用JavaScript实现前端导入和导出excel文件(H5编辑器实战复盘)
excel 导出json_导出的数据格式不对
但是用这种方式会出现一种问题,就是当你的table有分页的情况下,只能抓取当前分页的数据。
全栈程序员站长
2022/09/20
1.4K0
excel 导出json_导出的数据格式不对
前端: 如何让你的Table组件无限可能
一般我们渲染表格, 大多数是预先将表格结构写好, 比先定义好columns再向后端请求数据填充表格, 如下:
徐小夕
2021/02/05
1.8K0
Rust赋能前端: 纯血前端将 Table 导出 Excel
大家好,我是柒八九。一个专注于前端开发技术/Rust及AI应用知识分享的Coder
前端柒八九
2025/01/03
1700
Rust赋能前端: 纯血前端将 Table 导出 Excel
Node.js + Vue 实现 Excel 导出与保存
https://juejin.cn/post/6953882449235410951
@超人
2021/05/24
3.7K0
Node.js + Vue 实现 Excel 导出与保存
Ant Design实现Excel导入导出
最近公司的公众号管理系统需要添加Excel导入与导出功能,考虑到需要多个地方引用,所以开发了一个组件,下面把代码分享出来给大家。
越陌度阡
2022/05/06
1.5K0
前端复杂表格导出excel,一键导出 Antd Table 看这篇就够了(附源码)
前端导出 excel 的需求很多,但市面上好用的库并不多,讲明白复杂使用场景的文章更少。
solocoder
2022/03/31
12.3K1
前端复杂表格导出excel,一键导出 Antd Table 看这篇就够了(附源码)
前后端分离导出Excel
正常导出Excel确实很简单, 前端请求接口,接口处理数据,数据处理完按成之后自动生成Excel保存到指定目录,api把文件名称,文件路径返回给前端,前端一个a标签超链接就可以下载,然而在本地开发是可以直接下载的,但是在服务器上通过链接,直接就打开了文件流,并没有下载,这下就需要前端请求文件链接,下载数据流。
Wyc
2021/07/01
1.5K0
前后端分离导出Excel
Ant Design
提交表单可以直接用回调函数里面的values获取值 重置表单数据 form.resetFields()
P轴
2022/11/18
2.9K0
Ant Design
爱不释手的Excel导出工具类
最近了不起做的需求中有一个需求是要求导出Excel表格,有大约十几张表需要导出吧。
灬沙师弟
2023/09/29
3630
爱不释手的Excel导出工具类
使用ant design开发完整的后台系统
这里要说的是ant design的vue版和react版本的使用。这里不考虑到两种框架vue和react的底层。
Jimmy_is_jimmy
2020/06/09
2.6K0
使用ant design开发完整的后台系统
React后台管理前端系统(基于开源框架开发)起步式
这个系统的搭建背景是这样的,有一个朋友想看到现有系统中的一些,用户数据,新闻数据,只需要看到,短期不需要增删改功能,让我搭建一个简单的后台系统给他看.接到任务作为一个有四年开发经验的人来说这也太简单了吧,开始干吧,最简单的办法是直接使用开源项目https://github.com/PanJiaChen/vue-element-admin 下载下来,把不要的路由去掉,新建几个表格路由,页面直接复制过来就用了.
拿我格子衫来
2022/01/24
2.1K0
React后台管理前端系统(基于开源框架开发)起步式
十分钟上手 xlsx,4 种方法实现 Excel 导入导出
如果你和我一样经常和管理页面打交道,那么 Excel导入数据 和 数据导出Excel 这两个需求一定是逃不掉的。
写代码的海怪
2022/03/30
3K0
十分钟上手 xlsx,4 种方法实现 Excel 导入导出
记录解决几个前端小问题的过程
今天的主要工作都在用react.js写一些前端界面,中间遇到了一些问题,这里解决这些问题的过程记录一下。 使用echarts图表组件 由于项目比较老旧,并没有使用webpack、gulp之类的前端编译工具进行编译,而是直接将依赖的javascript库引入,如下所示: <body> <div id="reactHolder"></div> <script type="text/javascript" src="${ctx}/script/lodash/lodash.min.js"></script> <sc
jeremyxu
2018/05/10
2.4K0
JAVA导出EXCEL实现
##JAVA导出EXCEL实现的多种方式 java导出Excel的方法有多种,最为常用的方式就是使用第三方jar包,目前POI和JXL是最常用的二方包了,也推荐使用这两种。 ###POI实现 POI这里不详细解释,可参考徐老师发的博客:http://blog.csdn.net/evangel_z/article/details/7332535,他利用开源组件POI3.0.2动态导出EXCEL文档的通用处理类ExportExcel,详细使用方法下载最新代码看看就可以里,徐老师写的很明了!总之思路就是用Servlet接受post、get请求,获取文件导出路径,然后将测试数据封装好调用通用处理类导出Excel,然后再下载刚导出的Excel,会自动在浏览器弹出选择保存路径的弹出框,这样就达到里大家常见的文件导出下载的功能!当然,真正的项目里不可能把文件导出到本地,肯定是先吧文件导出到服务器上,再去服务器下载,对于用户来说就感觉好像直接就导出了! 这种实现逻辑也可以修改,就是把通用处理类ExportExcel从void改为返回read好数据的InputStream,而不要直接就去write,然后调用下载的方法downLoad使用HttpServletResponse.getOutputStream()所得到的输出流来write数据,然后调用flush()时就会在页面弹出选择路径的弹出框,选择好后数据就真正从缓存输出到了Excel中,这样就省去里中间先要导出一次的步骤了。 ###JXL实现 我这里讲一下JXL,其实和POI差不多,就是调用的组件不同,引入的jar包不同了,整个Excel导出下载的逻辑还是一样的。好了,直接上代码,都是通用代码,以后都能用的上。 先是几个mode类封装了在处理过程中会用到的模型。 ExcelColMode 主要封装的是Map中的key或者dto中实现get方法的字段名,其实就是表格的标题的属性名。
全栈程序员站长
2022/09/07
2.5K0
Vue+Element前端导入导出Excel(实践)
arr就是我们要的结果,是一个数组。每一个值是个对象,包含了code type两个属性。
coder_koala
2020/03/06
4.5K1
Vue+Element前端导入导出Excel(实践)
又快又美又好用的前端框架 Ant Design Pro V5 发布了
距离上次 Pro 发布已经过去了两年,这两年间前端的生态也发生了一些变化, Low-Code 大行其道,Bundleless 也随着 Snowpack,Vite 的发布越来越火热,前端在国际化,权限,数据流和布局方面已经有了最佳实践。 Ant Design Pro 致力于提升中后台的开发体验,在这些领域我们也提出了自己的解决方案。 ​
用户8639654
2021/07/16
1.4K0
Npoi导入导出Excel操作
    之前公司的一个物流商系统需要实现对订单的批量导入和导出,翻阅了一些资料,最后考虑使用NPOI实现这个需求。 在winform上面实现excel操作:http://www.cnblogs.com/CallmeYhz/p/4920293.html,NPOI的主页:http://npoi.codeplex.com/ 简介 NPOI 是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目, 使用 NPOI 你就可以在没有安装 Office 或者相应
用户1055830
2018/01/18
3.8K2
Npoi导入导出Excel操作
推荐阅读
相关推荐
实习第十一周,第十二周
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验