springboot 自定义注解-常规实现方式

通常springboot的应用场景为:

  • 日志记录: 记录请求信息的日志, 以便进行信息监控, 信息统计, 计算PV(page View)等
  • 性能监控;
  • 权限检查;
  • 通用行为

0. pom引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

1. 自定义注解的范式

  • @Target 注解
    主要说明注解的使用范围,主要包括以下几种类型:
TYPE:类,接口或者枚举
FIELD:域,包含枚举常量
METHOD:方法
PARAMETER:参数
CONSTRUCTOR:构造方法
LOCAL_VARIABLE:局部变量
ANNOTATION_TYPE:注解类型
PACKAGE:
  • @Retention 注解
    主要说明注解的生命周期,主要包含以下几种类型:
SOURCE:源码级别保留,编译后即丢弃
CLASS:编译级别保留,编译后的class文件中存在,在jvm运行时丢弃,这是默认值。
RUNTIME: 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。
  • @Documented 注解
    主要指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值

2. 具体实现

现在我们自定义一个注解,实现的功能是当系统执行某个函数时,我们打印请求头和登录人的相关信息。

2.1 定义接口

@Target(ElementType.METHOD)  //在方法上使用
@Retention(RetentionPolicy.RUNTIME)   //运行级别保留
public @interface DetailRequest {
    String value() default "";    //使用注解的时候传递,默认为""
}

2.2 切面编程

@Component     
@Aspect
@Slf4j
public class MyAspect {
    
    ThreadLocal<Long> currentTime = new ThreadLocal<>();
    
    public MyAspect() {   //验证是否启动时加载
        System.out.println("==========MyAspect start=======================");
    }

    /**
     * 配置切入点
     */
    @Pointcut("@annotation(me.zhengjie.annotation.DetailRequest)")   //此处对应之前我们定义的接口
    public void detailPointcut() {
        // 该方法无方法体,主要为了让同类中其他方法使用此切入点
    }


    /**
     * 配置环绕通知,使用在方法logPointcut()上注册的切入点
     *
     * @param joinPoint join point for advice
     */
    @Around("detailPointcut()")
    public Object detailAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result;
        currentTime.set(System.currentTimeMillis());      //保存当前时间
        result = joinPoint.proceed();                     //获得函数运行结果

        //操作时长
        Long time=System.currentTimeMillis() - currentTime.get();
        System.out.println("操作时长:"+time +" 毫秒" );

        HttpServletRequest request = RequestHolder.getHttpServletRequest();  
        //获取ip值
        String ip=request.getRemoteAddr();
        System.out.println("ip:"+ ip );
        //获得浏览器类型
        String browser= StringUtils.getBrowser(request);    //getBrowser()方法见下面
        System.out.println("浏览器类型:"+ browser );
        //获取操作时间
        Time t =new Time(System.currentTimeMillis());
        LocalTime localTime = t.toLocalTime();
        String st = localTime.toString();                  //获取当前时间(毫秒)转化为标准时间显示
        System.out.println("当前操作时间:"+ st );           

        //获取操作人
        String currentUsername = SecurityUtils.getCurrentUsername();    //获取系统登录用户,从cookie或reids中取
        System.out.println("当前操作人:"+ currentUsername );
        //获取方法名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();    
        String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
        System.out.println("当前具体操作方法:"+ methodName );
        //获取描述
        Method method = signature.getMethod();
        DetailRequest annotation = method.getAnnotation(DetailRequest.class);
        String value = annotation.value();
        System.out.println("当前具体操作注解名:"+ value );         //获取注解中传递的参数
        return result;
    }
}

其中所用到的工具类RequestHolder,其定义为

public class RequestHolder {

    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes)Objects.
        			requireNonNull(RequestContextHolder.
        			getRequestAttributes())).getRequest();
    }
}

StringUtils.getBrowser()方法定义如下:

    public static String getBrowser(HttpServletRequest request) {
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        Browser browser = userAgent.getBrowser();
        return browser.getName();
    }

2.3 自定义注解的使用

该函数功能为查询指定表格的所有数据

    @GetMapping
    @DetailRequest("自定义测试")    //传递"自定义测试"字符串
    public ResponseEntity<Object> query(MyJobQueryCriteria criteria,Pageable pageable){
        return new ResponseEntity<>(myJobService.queryAll(criteria,pageable),HttpStatus.OK);
    }

2.4 启动类上添加注解

@EnableAspectJAutoProxy

2.5 观察结果

系统启动时(使用的是eladmin开源框架,具体使用见我的博客):
在这里插入图片描述
可以看到已经成功加载自定义注解
接下来,进入指定页面,加载public ResponseEntity query(MyJobQueryCriteria criteria,Pageable pageable),可以看到输出结果:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值