自定义注解实例

1.创建自定义注解
@Target({ElementType.METHOD , ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestDecrypt {
boolean value() default true;
}
说明:
1.)@Retention – 定义该注解的生命周期
● RetentionPolicy.SOURCE : 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
● RetentionPolicy.CLASS : 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式
● RetentionPolicy.RUNTIME : 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。

2.)Target – 表示该注解用于什么地方。默认值为任何元素,表示该注解用于什么地方。可用的ElementType 参数包括
● ElementType.CONSTRUCTOR: 用于描述构造器
● ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
● ElementType.LOCAL_VARIABLE: 用于描述局部变量
● ElementType.METHOD: 用于描述方法
● ElementType.PACKAGE: 用于描述包
● ElementType.PARAMETER: 用于描述参数
● ElementType.TYPE: 用于描述类、接口(包括注解类型) 或enum声明
2.自定义注解处理方法
public class NeedCrypto {

public static boolean needEncrypt(MethodParameter returnType) {
    boolean encrypt = false;
    boolean classPresentAnno = returnType.getContainingClass().isAnnotationPresent(ResponseEncrypt.class);
    boolean methodPresentAnno = Objects.requireNonNull(returnType.getMethod()).isAnnotationPresent(ResponseEncrypt.class);
    if (classPresentAnno) {
        encrypt = returnType.getContainingClass().getAnnotation(ResponseEncrypt.class).value();
        if (!encrypt) return false;
    }
    if (methodPresentAnno) encrypt = returnType.getMethod().getAnnotation(ResponseEncrypt.class).value();
    return encrypt;
}

public static boolean needDecrypt(MethodParameter parameter) {
    boolean decrypt = false;
    boolean classPresentAnno = parameter.getContainingClass().isAnnotationPresent(RequestDecrypt.class);
    boolean methodPresentAnno = Objects.requireNonNull(parameter.getMethod()).isAnnotationPresent(RequestDecrypt.class);
    if (classPresentAnno) {
        decrypt = parameter.getContainingClass().getAnnotation(RequestDecrypt.class).value();
        if (!decrypt) return false;
    }
    if (methodPresentAnno) decrypt = parameter.getMethod().getAnnotation(RequestDecrypt.class).value();
    return decrypt;
}

}
说明:
//判断类上是否有该注解
boolean classPresentAnno = returnType.getContainingClass().isAnnotationPresent(ResponseEncrypt.class);
//判断方法上是否有该注解
boolean methodPresentAnno = Objects.requireNonNull(returnType.getMethod()).isAnnotationPresent(ResponseEncrypt.class);
if (classPresentAnno) {
//获取类上注解的值
encrypt = returnType.getContainingClass().getAnnotation(ResponseEncrypt.class).value();
if (!encrypt) return false;
}
//获取方法上注解的值
if (methodPresentAnno) encrypt = returnType.getMethod().getAnnotation(ResponseEncrypt.class).value();

3.配套RequestDecryptAdvice使用
@Slf4j
@RestControllerAdvice
public class RequestDecryptAdvice implements RequestBodyAdvice {
@Override
public boolean supports(@NonNull MethodParameter methodParameter,
@NonNull Type type,
@NonNull Class<? extends HttpMessageConverter<?>> aClass) {
//return false;
//log.info(“supports >> methodParameter={},type={},aClass={}”, methodParameter, type, aClass.getSimpleName());
return true;
}

@Override
public @NonNull
HttpInputMessage beforeBodyRead(@NonNull HttpInputMessage httpInputMessage,
                                @NonNull MethodParameter methodParameter,
                                @NonNull Type type,
                                @NonNull Class<? extends HttpMessageConverter<?>> aClass) {
    //return null;
    if (NeedCrypto.needDecrypt(methodParameter)) {
        //log.info("type={},aClass={}",type,aClass);
        //log.info("**************************我是RequestDecryptAdvice解密操作**************************");
        return new HttpInputMessage() {
            @Override
            public @NonNull
            InputStream getBody() throws IOException {
                String bodyStr = IOUtils.toString(httpInputMessage.getBody(), StandardCharsets.UTF_8);
                String newBodyStr=null;
                try {
                    newBodyStr = AES.decrypt(bodyStr);
                    log.debug("请求密文={}",bodyStr);
                    log.info("请求明文={}",newBodyStr);
                } catch (Exception exception) {
                    log.error("bodyStr={},newBodyStr={}",bodyStr,newBodyStr);
                    log.error(exception.getLocalizedMessage(),exception);
                    throw new IOException(exception.getMessage(),exception);
                }
                //log.info("bodyStr={},newBodyStr={}",bodyStr,newBodyStr);
                return IOUtils.toInputStream(newBodyStr,StandardCharsets.UTF_8);
            }
            @Override
            public @NonNull
            HttpHeaders getHeaders() {
                return httpInputMessage.getHeaders();
            }
        };
    }
    return httpInputMessage;
}

@Override
public @NonNull
Object afterBodyRead(@NonNull Object o,
                     @NonNull HttpInputMessage httpInputMessage,
                     @NonNull MethodParameter methodParameter,
                     @NonNull Type type,
                     @NonNull Class<? extends HttpMessageConverter<?>> aClass) {
    //return null;
    //log.info("afterBodyRead >> object={},httpInputMessage={},methodParameter={},type={},aClass={}", o, httpInputMessage, methodParameter, type, aClass.getSimpleName());
    return o;
}

@Override
public Object handleEmptyBody(Object o,
                              @NonNull HttpInputMessage httpInputMessage,
                              @NonNull MethodParameter methodParameter,
                              @NonNull Type type,
                              @NonNull Class<? extends HttpMessageConverter<?>> aClass) {
    //return null;
    //log.info("handleEmptyBody >> object={},httpInputMessage={},methodParameter={},type={},aClass={}", o, httpInputMessage, methodParameter, type, aClass.getSimpleName());
    return o;
}

}

4.加在类上或者方法上

@RequestDecrypt
@ResponseEncrypt
@CrossOrigin(origins = {""}, allowCredentials = “true”, allowedHeaders = {""})
public class AppAlarmCenterController {}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值