该文章将编写一个自定义注解,检测前端传入的json格式字符串是否包含某些字段
基本语法:
- 元注解
- @Target:限定注解应用范围,value可以为数组
TYPE
、FIELD
、METHOD
、PARAMETER
、CONSTRUCTOR
、LOCAL_VARIABLE
、ANNOTATION_TYPE
、PACKAGE
- @Retention:修饰注解的生命力(
SOURCE
、CLASS
、RUNTIME
) - @Documented:注解随着被定义的java文件生成到JavaDoc文档当中。
- @Inherited:类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解。
只在@Target被定义为TYPE时起作用
- @Target:限定注解应用范围,value可以为数组
- 使用@interface修饰类
- 注解类型元素
- 注解类型元素必须为public,不写默认为public
- 类型只能是基本数据类型、String、Class、枚举、注解或者以上类型的数组
- 只有一个value元素时,使用注解时可以省略value=, 即
@JsonParamsError(value = "hahah") === @JsonParamsError("hahah")
没有元素时,使用注解时可以省略(), 即@JsonParamsErro() === @JsonParamsErro
数组类型元素只需要填一个值时可以省略{}, 即@JsonParamsError(arr = {"hahah"}) === @JsonParamsError(arr = "hahah")
- default代表默认值,如果没有指定默认值,那么使用的时候必须显示指定
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonParamsError{
String desc() default "";
String[] params();
}
通过aop实现注解功能:
- 声明切入点
- 将Signature强转为MethodSignature获取Method,通过Method获取对应注解
- 获取方法的参数,执行相应逻辑
- 执行方法
@Slf4j
@Component
@Aspect
public class JsonParamsAspect {
//定义注解的切入点
@Pointcut("@annotation(com.example.commondframe.annotation.JsonParamsError)")
public void caughtJsonParseError(){}
//使用环绕通知的方式
// ProceedingJoinPoint 是使用Around特有的,该类比JoinPoint多了方法的执行
@Around(value = "caughtJsonParseError()")
public Object jsonParseErrorAround(ProceedingJoinPoint joinPoint) throws Throwable {
Signature signature = joinPoint.getSignature(); //获取方法签名
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
JsonParamsError jsonParamsError = method.getAnnotation(JsonParamsError.class); //获取方法修饰的JsonParamsError注解
String desc = jsonParamsError.desc(); //获取JsonParamsError注解的desc属性
String[] params = jsonParamsError.params(); //获取JsonParamsError注解的params属性
Object o = joinPoint.getArgs()[0]; //获取方法的第一个参数
JSONObject data = null;
if( o instanceof JSONObject ){ //如果是JSONObject实例, 强转为JSONObject
data = (JSONObject) o;
}else if( o instanceof String ){ //如果是String类型,转换为JSONObject
data = JSON.parseObject((String)o);
}else{ //否则为错误类型
log.error("{}, 方法{}, 错误参数类型", desc, method.getName());
return Error.error("参数有误!");
}
for(String param : params){ //遍历传入的params属性,判断是否都在JSONObject中存在
if( !data.containsKey(param) ){
log.error("{}, 方法{}, 参数{}不存在", desc, method.getName(), param);
return Error.error("参数有误!");
}
}
return joinPoint.proceed(); //执行方法
}
}