springboot自定义注解-实现记录交易日志

springboot自定义注解连载目录

引入注解

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

创建日志注解

创建@AuditLog注解,作用与方法,生命周期存在于vm运行

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuditLog {
    String method() default "";

    String methodDescription() default "";

    String httpMethod() default "";

    String[] storageMode() default {"file"};
}

为@AuditLog注解声明切面

/*
声明切面
 */
@Aspect
@Component
@Slf4j
public class AuditLogAspect {

    /*
    定义切点,标记方法
     */
    @Pointcut("@annotation(com.study.customannotation.aspect.annotation.AuditLog)")
    public void operationLog() {
    }

    /**
     *
     *环绕增强,相当于MethodInterceptor
     *
     * @param joinPoint
     * @param auditLog
     * @return
     */
    @Around("operationLog()  && @annotation(auditLog)")
    public Object arround(ProceedingJoinPoint joinPoint, AuditLog auditLog){
        long beginTime = System.currentTimeMillis();
        boolean result = true;
        Object res = null;
        try {
            res = joinPoint.proceed();
        } catch (Throwable throwable) {
            result = false;
            throwable.printStackTrace();
        }finally {

        }

        long endTime = System.currentTimeMillis();
        long requestTime = endTime - beginTime;

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String[] storageMode = auditLog.storageMode();
        if (ArrayUtils.contains(storageMode, "file")) {
            info_aop("", "", joinPoint.getSignature().getDeclaringTypeName(), auditLog.httpMethod(), joinPoint.getSignature().getName(), auditLog.method(), auditLog.methodDescription(), this.getIpAddr(request), ZonedDateTime.ofInstant(Instant.ofEpochMilli(beginTime), ZoneId.systemDefault()).format(DateTimeFormatter.ISO_INSTANT), ZonedDateTime.ofInstant(Instant.ofEpochMilli(endTime), ZoneId.systemDefault()).format(DateTimeFormatter.ISO_INSTANT), (double)requestTime, result);
        }


        return res;
    }

    public static void info_aop(final String userId, final String tenantCode, final String className, final String httpMethod, final String method, final String api, final String methodDescription, final String requestIp, final String startTime, final String endTime, final double duration, final boolean result) {
        String logReturnMsg = "{\"startTime\":\"{}\",\"endTime\":\"{}\",\"userId\":\"{}\",\"tenantCode\":\"{}\",\"package\":\"{}\",\"method\":\"{}\",\"httpMethod\":\"{}\",\"api\":\"{}\",\"methodDescription\":\"{}\",\"requestIp\":\"{}\",\"duration\":\"{}\",\"result\":\"{}\"}";
        log.info(logReturnMsg, new Object[]{startTime, endTime, userId, tenantCode, className, method, httpMethod, api, methodDescription, requestIp, duration, result});
    }

    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-DictClient-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-DictClient-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        return StringUtils.substringBefore(ip, ",");
    }


    @Before("operationLog()")
    public void doBeforeAdvice(JoinPoint joinPoint){
        System.out.println("进入方法前执行.....");

    }

    /**
     * 处理完请求,返回内容
     * @param ret
     */
    @AfterReturning(returning = "ret", pointcut = "operationLog()")
    public void doAfterReturning(Object ret) {
        System.out.println("方法的返回值 : " + ret);
    }

    /**
     * 后置异常处理
     * @param joinPoint
     */
    @AfterThrowing("operationLog()")
    public void throwss(JoinPoint joinPoint){
        System.out.println("方法异常时执行.....");
    }

    /**
     * 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
     *
     * @param jp
     */
    @After("operationLog()")
    public void after(JoinPoint jp){
        System.out.println("方法最后执行.....");
    }

}

在Controller的方法上添加@AuditLog注解

当执行到方法时,就会执行切面中的方法,通过java反射机制记录交易的日志,如:交易时间,交易ip,执行的类,指定的方法,参数,交易用时,交易结果等等

  @GetMapping("/BloodDonation/page")
    @AuditLog(method = "/api/BloodDonation/page", methodDescription = "献血列表(分页)", httpMethod = "GET")
    @ApiOperation(value = "献血列表(分页)")
    public ResponseEntity<ReturnResultDTO<?>> findBloodDonationPage(QueryUpbdBloodDonationRecordEntityDTO upbdBloodDonationRecordEntityDTO, Page page) {
        return prepareReturnResult(ReturnCode.SUCCESS.getCode(), upbdBloodDonationService.findBloodDonation(page,upbdBloodDonationRecordEntityDTO));
    }

git项目demo
https://gitee.com/ding-dawei/custom-annotation.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SpringBoot中可以自定义注解实现特定的功能。自定义注解的步骤如下: 1. 使用`@interface`关键字来定义注解,可以在注解中设置属性。 2. 可以通过注解的属性来传递参数,比如设置注解中的属性值。 3. 可以通过判断某个类是否有特定注解来进行相应的操作。 在SpringBoot中,自定义注解可以用于实现日志记录、定时器等功能。通过使用注解,可以简化代码,并提高开发效率。同时,自定义注解也是Spring框架中广泛应用的一种方式,可以在SpringMVC框架中使用注解来配置各种功能。而在SpringBoot框架中,更是将注解的使用推向了极致,几乎将传统的XML配置都替换为了注解。因此,对于SpringBoot来说,自定义注解是非常重要的一部分。123 #### 引用[.reference_title] - *1* *3* [springboot 自定义注解(含源码)](https://blog.csdn.net/yb546822612/article/details/88116654)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] - *2* [SpringBoot-自定义注解](https://blog.csdn.net/weixin_44809337/article/details/124366325)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大佬腿好粗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值