Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性)
Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性)
前言:由于前段时间忙于写接口,在接口中需要做很多的参数校验,本着简洁、高效的原则,便写了这个小工具供自己使用(内容为缩减版,具体业务可自行扩展)
思路:使用Java反射机制,读取实体类属性头部注解,通过get方法获取参数值进行校验,如果为空则进行异常抛出。
CheckNull.java 类
package com.seesun2012.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解:校验非空字段
*
* @author seesun2012@163.com
*
*/
@Documented
@Inherited
// 接口、类、枚举、注解
@Target(ElementType.FIELD)
//只是在运行时通过反射机制来获取注解,然后自己写相应逻辑(所谓注解解析器)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckNull {
String message();
}
Userregister.java 类
package com.seesun2012.common.entity;
import java.io.Serializable;
import com.seesun2012.common.annotation.CheckNull;
/**
* 用户注册实体类
*
* @author seesun2012@163.com
*
*/
public class Userregister implements Serializable{
private static final long serialVersionUID = 1L;
//自定义注解
@CheckNull(message="用户名不能为空")
private String userAccount;
//自定义注解
@CheckNull(message="密码不能为空")
private String passWord;
public String getUserAccount() { return userAccount; }
public void setUserAccount(String userAccount) { this.userAccount = userAccount; }
public String getPassWord() { return passWord; }
public void setPassWord(String passWord) { this.passWord = passWord; }
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", userAccount=").append(userAccount);
sb.append(", passWord=").append(passWord);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}
CommonUtils.java 类
package com.seesun2012.common.utils;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import com.seesun2012.common.annotation.CheckNull;
import com.seesun2012.common.exception.CustBusinessException;
/**
* 公共工具类
*
* @author seesun2012@163.com
*
*/
public class CommonUtils{
/**
* 通过反射来获取javaBean上的注解信息,判断属性值信息,然后通过注解元数据来返回
*/
public static <T> boolean doValidator(T clas){
Class<?> clazz = clas.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
CheckNull checkNull = field.getDeclaredAnnotation(CheckNull.class);
if (null!=checkNull) {
Object value = getValue(clas, field.getName());
if (!notNull(value)) {
throwExcpetion(checkNull.message());
}
}
}
return true;
}
/**
* 获取当前fieldName对应的值
*
* @param clas 对应的bean对象
* @param fieldName bean中对应的属性名称
* @return
*/
public static <T> Object getValue(T clas,String fieldName){
Object value = null;
try {
BeanInfo beanInfo = Introspector.getBeanInfo(clas.getClass());
PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : props) {
if (fieldName.equals(property.getName())) {
Method method = property.getReadMethod();
value = method.invoke(clas, new Object[]{});
}
}
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
/**
* 非空校验
*
* @param value
* @return
*/
public static boolean notNull(Object value){
if(null==value){
return false;
}
if(value instanceof String && isEmpty((String)value)){
return false;
}
if(value instanceof List && isEmpty((List<?>)value)){
return false;
}
return null!=value;
}
public static boolean isEmpty(String str){
return null==str || str.isEmpty();
}
public static boolean isEmpty(List<?> list){
return null==list || list.isEmpty();
}
private static void throwExcpetion(String msg) {
if(null!=msg){
throw new CustBusinessException(msg);
}
}
}
Result.java 类
package com.seesun2012.common.entity;
import java.io.Serializable;
import java.util.HashMap;
public class Result extends HashMap<String, Object> implements Serializable {
private static final long serialVersionUID = 1L;
public static final Result SUCCEED = new Result(0, "操作成功");
public Result(int status, String massage) {
super();
this.put("status", status).put("message", massage);
}
public Result put(String key, Object value) {
super.put(key, value);
return this;
}
public static Result build(int i, String message) {
return new Result(i, message);
}
}
CustBusinessException.java 类
package com.seesun2012.common.exception;
/**
* 自定义异常类
*
* @author seesun2012@163.com
*
*/
public class CustBusinessException extends RuntimeException{
private static final long serialVersionUID = 1L;
public CustBusinessException(){
}
public CustBusinessException(String str){
super(str);
}
public CustBusinessException(Throwable throwable){
super(throwable);
}
public CustBusinessException(String str, Throwable throwable){
super(str, throwable);
}
}
TestUtils.java 类
package com.seesun2012.test.utils;
import com.seesun2012.common.entity.Result;
import com.seesun2012.common.entity.Userregister;
import com.seesun2012.common.utils.CommonUtils;
public class TestUtils{
public static void main(String[] args) {
Userregister sss = new Userregister();
sss.setUserAccount("asdflkjasokdfj");
System.out.println(insertUser(sss));
}
public static Result insertUser(Userregister param){
Result result = new Result(1, "新增失败");
try {
CommonUtils.doValidator(param);
result = Result.build(0, "新增成功");
} catch (Exception e) {
result = Result.build(1, e.getMessage());
}
return result;
}
}
结语:该用户暂未添加
Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性)的更多相关文章
- 【java集合框架源码剖析系列】java源码剖析之TreeSet
本博客将从源码的角度带领大家学习TreeSet相关的知识. 一TreeSet类的定义: public class TreeSet<E> extends AbstractSet<E&g ...
- 【java集合框架源码剖析系列】java源码剖析之HashSet
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于HashSet的知识. 一HashSet的定义: public class HashSet&l ...
- 【java集合框架源码剖析系列】java源码剖析之TreeMap
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于TreeMap的知识. 一TreeMap的定义: public class TreeMap&l ...
- 【java集合框架源码剖析系列】java源码剖析之ArrayList
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 本博客将从源码角度带领大家学习关于ArrayList的知识. 一ArrayList类的定义: public class Arr ...
- 【java集合框架源码剖析系列】java源码剖析之LinkedList
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 在实际项目中LinkedList也是使用频率非常高的一种集合,本博客将从源码角度带领大家学习关于LinkedList的知识. ...
- 【java集合框架源码剖析系列】java源码剖析之HashMap
前言:之所以打算写java集合框架源码剖析系列博客是因为自己反思了一下阿里内推一面的失败(估计没过,因为写此博客已距阿里巴巴一面一个星期),当时面试完之后感觉自己回答的挺好的,而且据面试官最后说的这几 ...
- 【java集合框架源码剖析系列】java源码剖析之java集合中的折半插入排序算法
注:关于排序算法,博主写过[数据结构排序算法系列]数据结构八大排序算法,基本上把所有的排序算法都详细的讲解过,而之所以单独将java集合中的排序算法拿出来讲解,是因为在阿里巴巴内推面试的时候面试官问过 ...
- Java并发包源码学习系列:阻塞队列BlockingQueue及实现原理分析
目录 本篇要点 什么是阻塞队列 阻塞队列提供的方法 阻塞队列的七种实现 TransferQueue和BlockingQueue的区别 1.ArrayBlockingQueue 2.LinkedBloc ...
- Spring Boot @Enable*注解源码解析及自定义@Enable*
Spring Boot 一个重要的特点就是自动配置,约定大于配置,几乎所有组件使用其本身约定好的默认配置就可以使用,大大减轻配置的麻烦.其实现自动配置一个方式就是使用@Enable*注解,见其名知 ...
随机推荐
- 《C#多线程编程实战》2.5 AutoResetEvent
这个有点像是缩小版的mutex 还是很好理解的 相对mutex 使用的范围可能比较小一点. class Program { static AutoResetEvent work = new AutoR ...
- 类4(可变数据成员/基于const的重载)
可变数据成员: 有时我们希望能修改某个类的数据成员,即使是在一个 const 成员函数内.可以通过在变量的声明中加入 mutable 关键字来声明一个可变数据成员.mutable 是为突破 const ...
- logging、hashlib、collections模块
一.hashlib模块(加密模块) 1.什么叫hash:hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 , ...
- P2252 取石子游戏 威佐夫博弈
$ \color{#0066ff}{ 题目描述 }$ 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆 ...
- P2561 [AHOI2002]黑白瓷砖
$ \color{#0066ff}{ 题目描述 }$ \(\color{#0066ff}{输入格式}\) 文件中以一行的形式存放一个正整数 n , n ≤ 20 . \(\color{#0066ff} ...
- IPython&Jupyter私房手册
Jupyter是以Ipython为基础,可以极大的方便开发,对于如何使用,网上的资料都不太全.因此决定自己编写一个私房手册方便随时查找. 1. 安装和配置 安装不多说,不想折腾直接安装anaconda ...
- Gym - 101908C 树状数组 逆序对
Grandpa Giuseppe won a professional pizza cutter, the kind of type reel and, to celebrate, baked a r ...
- Svn安装成功后的操作
一.服务器端创建目录 在Svn服务器端创建一个用来保存客户端提交文件的文件夹 (我的路径是d:/Svn/App/book) 首先将Svn的服务端安装目录/bin 进行环境配置,以下操作是在进行环境配置 ...
- struts2学习笔记(二)—— struts2的架构【转】
一.系统架构 Struts2的官方文档附带了Struts2的架构图. 从这张图能够非常好的去理解Struts2 关于图中的Key: Servlet Filters:过滤器链,client的全部请求 ...
- Android TCP协议的Socket通信
1.介绍 2.使用方法 3.java后台代码 服务器server package com.lucky.servertest; import java.io.BufferedReader; import ...