工作场景中,参数校验必不可少,最近利用自定义注解实现入参参数校验,在入参校验方面,有不错的扩展性,可重用性。
接口调用,如果入参是实体类,就在实体类的变量上方标记。
实体类例子
返回结果
先自定义一个注解,用来标记需要校验的参数。
@Target({
ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.CONSTRUCTOR, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Examine {
String value() default "isNull";
}
利用注解的标记,定义一个aop,实现对参数的获取和校验
@Component
@Aspect
public class ExamineAop {
@Around("@annotation(examine)")
public Object paramCheck(ProceedingJoinPoint joinPoint, Examine examine) throws Throwable {
//获取方法传入参数数组
Object[] args = joinPoint.getArgs();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Parameter[] parameters = signature.getMethod().getParameters();
//循环数组
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
//处理类似String Integer的类
if (isPrimite(parameter.getType())) {
//获取参数上是否带有自定义注解,不为空则代表有
Examine annotation = parameter.getAnnotation(Examine.class);
if (annotation == null) {
continue;
}
//判断传入参数是否为null
if (args[i] == null) {
//抛出自定义异常,会被我的全局异常处理捕获,返回固定的返回体
throw new ExamineException();
}
//利用反射,调用自定义注解中的参数方法
Method verificationUtil = VerificationUtil.class.getMethod(annotation.value(), Object.class);
Object invoke = verificationUtil.invoke(null, args[i]);
if (invoke.equals(false)) {
throw new ExamineException();
}
continue;
}
//处理自定义实体类中带有自定义注解的成员变量,验证方法相同
Class<?> paramClazz = parameter.getType();
Object arg = Arrays.stream(args).filter(ar -> paramClazz.isAssignableFrom(ar.getClass())).findFirst().get();
Field[] declaredFields = paramClazz.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
Examine annotation = field.getAnnotation(Examine.class);
if (annotation == null) {
continue;
}
if (args[i] == null) {
throw new ExamineException();
}
Method verificationUtil = VerificationUtil.class.getMethod(annotation.value(), Object.class);
Object invoke = verificationUtil.invoke(null, field.get(arg));
if (invoke.equals(false)) {
throw new ExamineException();
}
continue;
}
}
return joinPoint.proceed();
}
/**
* 判断是否为基本类型:包括String
*
* @param clazz clazz
* @return true:是; false:不是
*/
private boolean isPrimite(Class<?> clazz) {
return clazz.isPrimitive() || clazz == String.class;
}
}
验证工具类,在aop实现类中利用反射调用,在本类中可以添加自己的验证,在注解中,传入方法名字,即可调用方法来验证参数,如(Examine(isPhone)String phone)。
public class VerificationUtil {
/**
* 验证是否手机号
*
* @param phone
* @return
*/
public static Boolean isPhone(Object phone) {
String pattern = "^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1}))+\\d{8})?$";
return phone.toString().matches(pattern);
}
/**
* 验证是否为空
*
* @param value
* @return
*/
public static Boolean isNull(Object value) {
return value != null || String.valueOf(value).length() > 0;
}
}
在本程序中还有异常类和全局捕获异常没有写出,百度一大堆。
如有错误和bug,欢迎指正。
文章浏览阅读655次。SIT2596 封装形式包括标准的 5 脚 TO-220 封装(DIP)和 5 脚 TO-263 表贴封装(SMD)。输出电压,电压输出范围在 1.2V-37V,输入电压最高可达 40V,输出电流可达 3A;SIT2596 是一款降压型开关电压调节芯片,可固定输出 3.3V、5V、12V,也可根据需要调节。准电感,这更优化了 SIT2596 的使用,极大地简化了开关电源电路的设计,节约了外围的成本。可选固定输出 3.3V、5V、12V 电压或输出电压可调;优异的线性调整率和负载调整率;_替代lm2596
文章浏览阅读973次。接收端的本振信号与发射端射频载波相差一个中频,接收端收到的宽带射。波形相乘,得到复合信号,实现信号频谱的展宽,展宽后的信号再调制射频载波发送出去。一般扩频调制时一个信息码包含一个周期的伪码,用扩频后的复合信号对载波进。在发端输入的信息与扩频码发生器产生的伪随机码序列(这里使用的是 m 序列)进行。直接序列扩频,就是直接用高码率的扩频码序列在发端去扩展信号的频谱,在收端用相。的扩频码序列进行波形相乘,实现相关解扩,再经信息解调,恢复出原始信号。同的扩频码去解扩,把展宽的扩频信号还原成原始的基带信号。_直接序列扩频码本的概念
文章浏览阅读2.4k次。现在到了TVR和CVM Results部分了。TVR是Terminal Verification Results,也就是终端验证的结果,包括了脱机数据认证,持卡人认证,处理限制等等是否成功。所以只要交易结果不是我们期望的,我们总是先拿TVR出来看看是哪里出了问题。CVM Results是持卡人认证结果,针对CVM。一. TVRtag:‘95’ length:5 bytes第..._9f34 emv tag
文章浏览阅读845次,点赞25次,收藏30次。还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!【完整版领取方式在文末!!
文章浏览阅读436次。注:阿里云网站申请需要进行IPC备案,如果不通过备案仅可本机IP地址访问,其它IP地址访问失败或是提示未进行备案。解决办法:开始菜单-服务器管理器-管理(M)-添加角色和功能-按步骤添加Web服务器(IIs)注:云服务器选择的阿里云windows系统,同时使用的是IIS进行服务器配置。解决办法:清理浏览器缓存后刷新,或是更换成其它浏览器。问题2:关于更改网站内容,刷新仍然保存旧界面。问题1:关于云服务器中没有IIS管理器。_阿里云服务器部署iis
文章浏览阅读1.9k次,点赞4次,收藏2次。最近在使用VS Code遇到了 OmniSharp 的各种报错导致没有了代码提示。这个问题是由于本身C#的更新版本造成的。1.在设置里搜索 Use Modern Net,取消勾选,重启 VS Code!2.改了依然有错误,提示或Could not locate MSBuild instance to register with OmniSharp.C# extension插件回到1.24.4,同时把Visual Studio Code Editor包升级到1.2.5又可以了。_vs code没有c#的提示
文章浏览阅读1.1k次。 可能需要的环境: Python 3.6官网下载 需要下载的第三方库:requests 其余为python自带不需要下载 首先看下效果图具体写作过程参考b站视频传送门:GUI天气预报接下来实现过程,首先创建窗口,设置标题,布局窗口,设置标签,按钮,就直接粘贴代码:如果对创建窗口的函数不熟悉:请点击python中tkinter的使用(控件整理)(一..._tkinter显示爬虫七天天气折线图
文章浏览阅读638次,点赞12次,收藏28次。优点:实现比较简单,执行环境相对单纯缺点:只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段 Javascript 代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。为了解决这个问题,JavaScript 语言将任务的执行模式分为两种:同步和异步。
文章浏览阅读271次。目前为止,我总结了Python的知识体系,并且暂时包括了十五章内容。 Python简介 基础知识 列表和元祖 字符串 字典 条件、循环和其他语句 抽象 更加抽象 异常 魔法方法、属性和迭代器 模块 文件和流 图形用户界面 数据库支持 网络编程 ...
文章浏览阅读640次。define("god","123",true);// 定义常量(true 为不区分大小写)constant("god")."";//输出常量echo (define("god").""); //输出常量是否被定义 预定义变量echo $_SERVER["SERVER_ADDR"];//服务器ip地址 echo $_SERVER["SERVER_NAME"];//
文章浏览阅读6.3k次。反常积分与暇点反常积分又叫广义积分,是对普通定积分的推广,指含有无穷上限/下限,或者被积函数含有瑕点的积分,前者称为无穷限广义积分,后者称为瑕积分(又称无界函数的反常积分)。如果函数f(x)在点a的一个邻域内无界,那么点a称为函数f(x)的瑕点(也称无界间断点)。无界函数的反常积分又称为瑕积分。反常积分的敛散性参考:https://zhuanlan.zhihu.com/p/101310338..._反常积分发散
文章浏览阅读2.1k次。---------------------JavaEE+Android开发、Java培训、期待与您交流! ---------------------- 交通灯管理系统一.交通灯管理项目的需求 模拟实现十字路口的交通灯管理系_城市道路十字路口信号灯控制系统,模拟实现十字路口的信号控制功能。要实现基