当前位置: 首页 > news >正文

自定义异常注解处理框架

首先我们定义两个用于检验string和List的注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author caiyi.yu* 自定义非空判断*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface StringNotBlank {String message() default "该字段不能为空";String name() default "";
}

package com.mija.tpa.platform.api.myannotate;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author caiyi.yu*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ListNotEmpty {String message() default "list不能为空";
}

接下来,我们可以定义一个validateHelper,用于通过反射使用我们自定义注解校验规则

import com.mija.tpa.platform.api.myannotate.ListNotEmpty;
import com.mija.tpa.platform.api.myannotate.StringNotBlank;
import lombok.extern.slf4j.Slf4j;import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.function.BiConsumer;/*** @author caiyi.yu<br>* <b>ValidateHelper </b>用于验证对象字段 <br>* 使用方式:手动调用validate,这是验证参数的入口<br>* 已经支持的类型:String、List<br>* 如果需要添加需要支持的其他类型的验证,请在HANDLERS中添加一个合适的处理器并在这个类中实现他<br>*/
@Slf4j
public class ValidateHelper {@FunctionalInterfacepublic interface ThrowingBiConsumer<T, U> {void accept(T t, U u) throws Exception;}private static <T, U> BiConsumer<T, U> wrapException(ThrowingBiConsumer<T, U> throwingBiConsumer) {return (t, u) -> {try {throwingBiConsumer.accept(t, u);} catch (Exception e) {throw new RuntimeException(e);  // 将异常统一化抛出}};}private static final HashMap<Class<?>, BiConsumer<Object, Field>> HANDLERS = new HashMap<>();static {HANDLERS.put(String.class, wrapException(ValidateHelper::validateString));HANDLERS.put(List.class, wrapException(ValidateHelper::validateList));}/*** 校验入参的字段*/public static void validate(Object obj) throws IllegalAccessException {if (obj == null){return;}Class<?> clazz = obj.getClass();for (Field field : clazz.getDeclaredFields()) {BiConsumer<Object, Field> handler = HANDLERS.getOrDefault(field.getType(), ValidateHelper::defaultHandler);handler.accept(obj, field);}}/*** 校验 String 类型的字段是否为空*/private static void validateString(Object obj, Field field) throws IllegalAccessException {if (field.isAnnotationPresent(StringNotBlank.class)) {field.setAccessible(true);String value =(String) field.get(obj);if (value == null || value.isEmpty()) {StringNotBlank fieldAnnotation = field.getAnnotation(StringNotBlank.class);throw new IllegalArgumentException(field.getName() + ":" + fieldAnnotation.message());}}}/*** 校验 List 类型的字段是否为空*/private static void validateList(Object obj, Field field) throws IllegalAccessException {if (field.isAnnotationPresent(ListNotEmpty.class)) {field.setAccessible(true);List<?> value =(List<?>) field.get(obj);if (value == null || value.isEmpty()) {ListNotEmpty fieldAnnotation = field.getAnnotation(ListNotEmpty.class);throw new IllegalArgumentException(field.getName() + ":" + fieldAnnotation.message());}else {// 遍历列表中的每个元素进行校验for (Object item : value) {validate(item);}}}//对集合元素的深入处理else {field.setAccessible(true);List<?> value =(List<?>) field.get(obj);if (value != null && !value.isEmpty()){for (Object item : value) {validate(item);}}}}/*** 默认处理器,当没有找到对应的字段类型处理器时调用*/private static void defaultHandler(Object obj, Field field) {log.warn("【ValidateHelper】未定义的校验类型!字段类型:" + field.getType());}
}

相关文章:

自定义异常注解处理框架

首先我们定义两个用于检验string和List的注解 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** author caiyi.yu* 自定义非空判断*/ Target(Elemen…...

【小程序】微信小程序课程 -3 快速上手之常用方法

目录 1、 对话框 1.1 模态对话框 1.2 消息对话框 2、 存储 2.1 同步 2.1.1 同步保存数据 2.1.2 同步获取数据 2.1.3 同步删除数据 2.1.4 同步清空数据 2.2 异步 2.2.1 异步保存数据 2.2.2 异步获取数据 2.2.3 异步删除数据 2.2.4 异步清空数据 3、 上拉加载更多…...

iOS 小组件

基本知识 时间轴 小组件通过AppIntentTimelineProvider进行 UI 刷新 struct Provider: AppIntentTimelineProvider {func placeholder(in context: Context) -> SimpleEntry {// 添加占位的&#xff08;选择添加的时候使用&#xff09;// todo}func snapshot(for configu…...

【2.使用VBA自动填充Excel工作表】

目录 前言什么是VBA如何使用Excel中的VBA简单基础入门控制台输出信息定义过程&#xff08;功能&#xff09;定义变量常用的数据类型Set循环For To 我的需求开发过程效果演示文件情况测试填充源文件测试填充目标文件 全部完整的代码sheet1中的代码&#xff0c;对应A公司工作表Us…...

算法记录——链表

2.链表 2.1判断是否是回文链表 1.方法一&#xff1a;利用栈反转链表 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode…...

EasyExcel实现百万数据批量导出

当数据量比较大时&#xff0c;例如数据量达到百万级&#xff0c;传统的一次读取到内存中在写入excel文件的方法便不再适用了&#xff0c;可能会导致内存溢出&#xff1b;而且一次性将数据写入一张sheet工作表也不太好。 但我们可以选择数据分片的方式批量写入多个工作表。 测试…...

兆易GD32E508的SHRTIM配置 主从定时器 产生2对相位可调互补PWM 带死区

如有技术问题及技术需求请加作者微信! GD32E5系列MCU是基于Arm Cortex-M33处理器的32位通用微控制器。Cortex-M33处理器基于Armv8架构,处理器主频最高可达180MHz,支持强大的可扩展指令集,包括通用数据处理I/O控制任务、增强的数据处理位域操作、DSP和浮点运算器(FPU)。 GD…...

数据归组工具

利用C#将数据 [ {"name":"A","fzh":1}, {"name":"A","fzh":2}, {"name":"A","fzh":3}, {"name":"B","fzh":4}, {"name":"B",&…...

JavaScript 中的闭包的形成及使用场景

JavaScript 中的闭包 闭包&#xff08;Closure&#xff09; 是 JavaScript 中一个非常重要且独特的概念&#xff0c;它指的是 函数能够记住并访问其词法作用域内的变量&#xff0c;即使这个函数在其词法作用域之外执行。 通俗地说&#xff0c;闭包是 一个函数可以“记住”它在…...

后端返回内容有换行标识,前端如何识别换行

<br/>的话 用 v-html \n 可以用css样式 white-space: pre-wrap 后端返回结果 前端...

服务器被挂马,导致网站首页被更改怎么解决

当服务器被挂马并导致网站首页被篡改时&#xff0c;说明服务器或网站的安全性遭到破坏。为了修复并防止未来的攻击&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. 立即下线网站 目的&#xff1a;防止恶意软件进一步传播&#xff0c;保护用户数据和防止攻击者继续对网…...

Android 利用OSMdroid开发GIS

1、地址 Github地址&#xff1a;https://gitee.com/mirrors/osmdroid Git地址&#xff1a; GitCode - 全球开发者的开源社区,开源代码托管平台 Git下载包地址&#xff1a;Releases osmdroid/osmdroid GitHub 新建项目 osmdroid在线&#xff1a; &#xff08;1&#xff09…...

一文上手skywalking【上】

一、skywalking预览 1.1 skywalking 概述 ​ Apache SkyWalking, 适用于分布式系统的应用程序性能监控工具&#xff0c;专为微服务、云原生和基于容器的 &#xff08;Kubernetes&#xff09; 架构而设计。官方地址: https://skywalking.apache.org/ 适用于分布式系统的应用程…...

【JavaScript】JQuery基础知识及应用

一、JQuery的导入方法 https://editor.csdn.net/md/?articleId132214798 二、JQuery介绍 JQuery(JQ)&#xff1a;JS的一个类库&#xff08;方法库&#xff1a;包含了大量的、有助于项目开发的属性和方法&#xff09; 第一代版本1.xx.xx: 1.11.3 兼容所有浏览器的&#xff0…...

初始爬虫9

1.元素定位后的操作 “find_element“仅仅能够获取元素&#xff0c;不能够直接获取其中的数据&#xff0c;如果需要获取数据需要使用以下方法”。下面列出了两个方法&#xff1a; 获取文本 element.text 通过定位获取的标签对象的 text 属性&#xff0c;获取文本内容 获取属性…...

从细胞到临床:表观组学分析技术在精准医疗中的角色

中国科学院等科研院所的顶尖人才发起&#xff0c;专注于多组学、互作组、生物医学等领域的研究与服务。在Nature等国际知名期刊发表多篇论文&#xff0c;提供实验整体打包、免费SCI论文润色等四大优势服务。在表观组学分析技术方面&#xff0c;提供DAP-seq、ATAC-seq、H3K4me3 …...

带你0到1之QT编程:二十、QT与MySQL喜结连理,构建数据库应用开发

此为QT编程的第二十谈&#xff01;关注我&#xff0c;带你快速学习QT编程的学习路线&#xff01; 每一篇的技术点都是很很重要&#xff01;很重要&#xff01;很重要&#xff01;但不冗余&#xff01; 我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点&#xff01; …...

梯度下降法及其性能评估

梯度下降法 梯度下降法是一种一阶迭代优化算法&#xff0c;用于寻找函数的局部最小值。在机器学习中&#xff0c;它通常用来最小化损失函数&#xff08;也称为成本函数或误差函数&#xff09;&#xff0c;以提高模型对数据的拟合程度。梯度下降法的基本思想是沿着目标函数当前…...

906. 超级回文数

1. 题目 906. 超级回文数 2. 解题思路 题目意思很简单&#xff0c;在给定范围中找到所有满足&#xff0c;它本身是回文&#xff0c;且它的平方也是回文的数字个数。 这题需要注意题目给定的范围&#xff0c;后面很有用&#xff1a; 因为回文范围是有限的&#xff0c;那么我…...

代码随想录算法训练营||二叉树

前/中/后序遍历 递归方式 参考文章 题目 思路&#xff1a;其实递归方式的前中后序遍历的方式都差不多&#xff0c;区别是在父节点的遍历时间。 前序代码 class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result new…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...