在现在的项目开发中,经常会用到注解,比如Spring的@Autowired
,SpringMVC的@Controller
,@RequestMapping
等等,大部分人只知道用,不知道这些注解的怎么发挥作用。有没有想过手动写一个注解,完成参数校验呢?
简介
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
作用分类:
①编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
② 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
③编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】
分类
Java注解根据标记位置分为三类。
- 标记在类上
- 标记在变量上
- 标记在方法上
注解类上需要加入:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
依次是,标记的位置,注解生存周期。
标记在方法上
运行时有效
实战
在编写注解之前需要了解,你的参数校验需要做哪些工作。
此次校验是标记在变量上的,主要功能包括:
- 非空校验
- 长度校验
- 正则校验
这几条包含了大部分的数据校验的功能。
开始
编写注解:Validation.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Validation {
//校验失败报错信息
String value();
//最大值
String max();
//最小值
String min();
//正则表达式
String pattern();
}
编写校验代码:
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;
public class Check {
public static void check(Object o) {
if (null == o) {
return;
}
Class clazz = o.getClass();
List<Field> fieldList = new ArrayList<Field>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
fieldList.forEach(field -> {
field.setAccessible(true);
try {
Object value = field.get(o);
Validation annotation = field.getAnnotation(Validation.class);
if (null == annotation) {
return;
}
checkNotNull(value, annotation);
checkPattern(value, annotation);
checkMax(value, annotation);
checkMin(value, annotation);
} catch (IllegalArgumentException e) {
e.printStackTrace();
//数据解析失败
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
}
private static double objectToDubule(Object o) {
return Double.valueOf(o.toString());
}
private static void checkNotNull(Object value, Validation validation) {
if (validation.notNull() && value == null) {
throw new RuntimeException(validation.value());
}
}
private static void checkPattern(Object value, Validation validation) {
if (null != validation.pattern() && validation.pattern().length() > 0) {
Pattern p = Pattern.compile(validation.pattern());
Matcher m = p.matcher(value.toString());
if (!m.matches()) {
throw new RuntimeException(validation.value());
}
}
}
private static void checkMax(Object value, Validation validation) {
if (validation.max() > 0) {
if (value instanceof String) {
if (value.toString().length() < validation.max()) {
throw new RuntimeException(validation.value());
}
} else {
if (objectToDubule(value) > validation.max()) {
throw new RuntimeException(validation.value());
}
}
}
}
private static void checkMin(Object value, Validation validation) {
if (validation.max() >= 0) {
if (value instanceof String) {
if (value.toString().length() > validation.min()) {
throw new RuntimeException(validation.value());
}
} else {
if (objectToDubule(value) < validation.min()) {
throw new RuntimeException(validation.value());
}
}
}
}
}
测试
编写CheckTest.java
import org.junit.Test;
public class CheckTest {
@Test
public void check() {
TestData data = new TestData();
data.arg = 20;
data.setMobile("1368989889");
data.setName("test");
Check.check(data);
System.out.println("校验通过");
}
class TestData {
@Validation(value = "名称校验失败", notNull = true)
private String name;
@Validation(value = "手机号校验失败", notNull = true, pattern = "^1(3[0-9]|4[0-9]|5[0-35-9]|8[0-9]|7[0-9]|6[0-9]|9[0-9])\\d{8}$")
private String mobile;
@Validation(value = "年龄校验失败", notNull = true, max = 60, min = 18)
private Integer arg;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public Integer getArg() {
return arg;
}
public void setArg(Integer arg) {
this.arg = arg;
}
}
}
运行截图:
手机号错误
数据正确
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦