使用spring boot通过自定义注解打印所需日志

spring boot自定义注解打印日志

在实际项目中可能需要监控每个接口的请求时间以及请求参数等相关信息,那么此时我们想到的就是两种实现方式,一种是通过拦截器实现,另一种则通过AOP自定义注解实现。

本文介绍自定义注解实现方式

自定义注解,四个元注解这次就不解释了。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WebLog {
    /**
     * 日志信息描述
     */
    String description() default "";
}

AOP实现:

1.@Order注解用来定义切面的执行顺序,数值越小优先级越高。

2.@Around环绕通知,我们可以自定义在什么时候执行@Before以及@After。

3.ThreadLocal针对每个线程都单独的记录。

@Aspect
@Component
public class WebLogAspect {
    private static ThreadLocal<ProceedingJoinPoint> td = new ThreadLocal<>();
    @Pointcut("@annotation(com.example.demo.annotation.WebLog)")
    @Order(1)
    public void webLog(){}
    @Before("webLog()")
    public void doBefor(JoinPoint point){
        System.out.println("***********method before执行************");
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        System.out.println("请求URL:"+request.getRequestURL());
        System.out.println("请求参数:"+ Arrays.toString(point.getArgs()));
        System.out.println("***********method before结束************");
    }
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        System.out.println("***********执行环绕方法开始************");
        td.set(point);
        long startTime = System.currentTimeMillis();
        ProceedingJoinPoint joinPoint = td.get();
        Object proceed = joinPoint.proceed();
        System.out.println("执行耗时毫秒:"+ (System.currentTimeMillis()-startTime));
        System.out.println("***********执行环绕方法结束************");
        return proceed;
    }
}

Controller

@RestController
public class LoginController {
    @PostMapping("/user/login")
    @WebLog(description = "用户登录接口")
    public UserForm login(@RequestBody UserForm user){
        return user;
    }
}

测试结果

通过自定义注解获取日志

1.定义一个注解

package com.hisense.demo02;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author : sunkepeng  E-mail : sunkepengouc@163.com
 * @date : 2020/8/8 20:09
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}

2.写一个测试用类,并使用注解

package com.hisense.demo02;

/**
 * @author : sunkepeng  E-mail : sunkepengouc@163.com
 * @date : 2020/8/8 20:04
 */
public class Calculator {
    @Check
    public void add(){
        System.out.println("1+0=" + (1+0));
    }
    @Check
    public void sub(){
        System.out.println("1-0=" + (1-0));
    }
    @Check
    public void mul(){
        System.out.println("1*0=" + (1*0));
    }
    @Check
    public void div(){
        System.out.println("1/0=" + (1/0));
    }
    public void show(){
        System.out.println("永无bug");
    }
}

3.使用注解,在测试类中输出log

package com.hisense.demo02;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * @author : sunkepeng  E-mail : sunkepengouc@163.com
 * @date : 2020/8/8 21:39
 */
public class TestCheck {
    public static void main(String[] args) throws IOException {
        Calculator calculator = new Calculator();
        Class calculatorClass = calculator.getClass();
        Method[] methods = calculatorClass.getMethods();
        int number =0;
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("bug.txt"));
        for (Method method : methods) {
            if (method.isAnnotationPresent(Check.class)){
                try {
                    method.invoke(calculator);
                } catch (Exception e) {
                    number++;
                    bufferedWriter.write(method.getName()+"出现异常");
                    bufferedWriter.newLine();
                    bufferedWriter.write("异常的名称:"+e.getCause().getClass().getSimpleName());
                    bufferedWriter.newLine();
                    bufferedWriter.write("异常的原因"+e.getCause().getMessage());
                    bufferedWriter.newLine();
                    bufferedWriter.write("-----------------");
                    bufferedWriter.newLine();
                }
            }
        }
        bufferedWriter.write("本次共出现:"+number+"次异常");
        bufferedWriter.flush();
        bufferedWriter.close();
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Springboot-注解-操作日志的实现方式

    此组件解决的问题是: 「谁」在「什么时间」对「什么」做了「什么事」 本组件目前针对 Spring-boot 做了 Autoconfig,如果是 SpringMVC,也可自己在 xml 初始化 bean 使用方式 基本使用 maven依赖添加SDK依赖 <dependency> <groupId>io.github.mouzt</groupId> <artifactId>bizlog-sdk</artifactId> <version>

  • springboot通过注解、接口创建定时任务详解

    目录 springboot中定时任务的创建 springboot通过注解创建定时任务 首先引入pom 直接上代码来一个栗子 @Scheduled注解的各个参数 springboot通过注接口创建定时任务 实现接口SchedulingConfigurer 主要方法 总结 项目中经常会用到定时任务,有的人在用quartz,有的人可能自己搭建了一套调度平台,springboot对于定任务的支持,让定时任务的创建变得简单,今天来说说springboot中定时任务的创建. springboot中定时任务的

  • 使用Springboot注解形式进行模糊查询

    Springboot注解形式进行模糊查询 需求: 功能需要按照商户名字做模糊查询,sql我们项目中使用的是mybatis封装好的一些常见增删改查方法(通用sql需要在pom.xml文件中加入依赖): <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter --> <dependency> <groupId>tk.mybatis</groupId> <ar

  • 解决springboot中@DynamicUpdate注解无效的问题

    springboot 中 @DynamicUpdate 注解无效解决方案 遇到的问题 项目中使用 jpa,以前没用过,所以踩坑在所难免. 在使用过程中,要更新一条记录的某个字段,更新成功以后,发现整条记录只剩下我更新的那个字段,其他的全部为空了. 瞬间明白,这种更新是全覆盖,针对每个字段 update,实体类没赋值的字段,也直接将空值 set 过去了. 寻求解决方案 正在庆幸这么容易就解决,突然发现并没有这么简单. 群众的力量是无穷大的,我立刻就明白这个注解为什么无效,原来是搞错了它的用途. 一

  • Springboot+mybatis-plus+注解实现数据权限隔离

    目录 1.创建注解 2. 具体实现 1.创建注解 当此注解打在类上,不需要传参,该类下所有查询接口开启数据隔离:打在方法上默认开启数据隔离,传参为false则该方法关闭验证 /** * 数据权限验证注解 * @author xiaohua * @date 2021/6/23 */ @Documented @Target({METHOD, ANNOTATION_TYPE, TYPE}) @Retention(RUNTIME) public @interface DataPermission { /

  • 解决SpringBoot @value注解取不到值的问题

    关于@value的springapplication容器的问题 1.在src/main/resources下创建stu.properties文件 ## student.name=Tom student.age=22 student.birthday=1996/01/10 student.sex=true student.hobbies[0]=swimming student.hobbies[1]=basketball student.skills[0]=programming student.s

  • SpringBoot使用@SpringBootTest注解开发单元测试教程

    概述 @SpringBootTest注解是SpringBoot自1.4.0版本开始引入的一个用于测试的注解.基本用法如下: 1.添加依赖: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.

  • 使用spring boot通过自定义注解打印所需日志

    spring boot自定义注解打印日志 在实际项目中可能需要监控每个接口的请求时间以及请求参数等相关信息,那么此时我们想到的就是两种实现方式,一种是通过拦截器实现,另一种则通过AOP自定义注解实现. 本文介绍自定义注解实现方式 自定义注解,四个元注解这次就不解释了. @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface WebLog { /** * 日志信息描述 */ String d

  • Spring Boot中自定义注解结合AOP实现主备库切换问题

    摘要:本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的压力,在本篇文章中主要记录在Spring Boot中通过自定义注解结合AOP实现直接连接备库查询. 一.通过AOP 自定义注解实现主库到备库的切换 1.1 自定义注解 自定义注解如下代码所示 import java.lang.annotation.ElementType; import java.la

  • 详解spring boot mybatis全注解化

    本文重点给大家介绍spring boot mybatis 注解化的实例代码,具体内容大家参考下本文: pom.xml <!-- 引入mybatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version

  • Spring Boot Web 开发注解篇

    一.spring-boot-starter-web 依赖概述 在 Spring Boot 快速入门中,只要在 pom.xml 加入了 spring-boot-starter-web 依赖,即可快速开发 web 应用.可见,Spring Boot 极大地简化了 Spring 应用从搭建到开发的过程,做到了「开箱即用」的方式.Spring Boot 已经提供很多「开箱即用」的依赖,如上面开发 web 应用使用的 spring-boot-starter-web ,都是以 spring-boot-sta

  • spring boot使用自定义的线程池执行Async任务

    在前面的博客中,//www.jb51.net/article/134866.htm 我们使用了spring boot的异步操作,当时,我们使用的是默认的线程池,但是,如果我们想根据项目来定制自己的线程池了,下面就来说说,如何定制线程池! 一.增加配置属性类 package com.chhliu.springboot.async.configuration; import org.springframework.boot.context.properties.ConfigurationProper

  • Spring AOP 实现自定义注解的示例

    自工作后,除了一些小项目配置事务使用过 AOP,真正自己写 AOP 机会很少,另一方面在工作后还没有写过自定义注解,一直很好奇注解是怎么实现他想要的功能的,刚好做项目的时候,经常有人日志打得不够全,经常出现问题了,查日志的才发现忘记打了,所以趁此机会,搜了一些资料,用 AOP + 自定义注解,实现请求拦截,自定义打日志,玩一下这两个东西,以下是自己完的一个小例子,也供需要的同学参考. 1. 注解如下: package cn.bridgeli.demo.annotation;   import j

  • Spring Boot读取自定义配置文件

    @Value 首先,会想到使用@Value注解,该注解只能去解析yaml文件中的简单类型,并绑定到对象属性中去. felord:   phone: 182******32   def:     name: 码农小胖哥     blog: felord.cn     we-chat: MSW_623   dev:     name: 码农小胖哥     blog: felord.cn     we-chat: MSW_623   type: JUEJIN 对于上面的yaml配置,如果我们使用@Va

  • spring boot使用@Async注解解决异步多线程入库的问题

    目录 前言 项目实况介绍 第一种方式 第二种方式 这里有个坑! 这里有两个坑! 总结 前言 在开发过程中,我们会遇到很多使用线程池的业务场景,例如定时任务使用的就是ScheduledThreadPoolExecutor.而有些时候使用线程池的场景就是会将一些可以进行异步操作的业务放在线程池中去完成,例如在生成订单的时候给用户发送短信,生成订单的结果不应该被发送短信的成功与否所左右,也就是说生成订单这个主操作是不依赖于发送短信这个操作,所以我们就可以把发送短信这个操作置为异步操作.而要想完成异步操

  • spring boot 的常用注解使用小结

    @RestController和@RequestMapping注解 4.0重要的一个新的改进是@RestController注解,它继承自@Controller注解.4.0之前的版本,Spring MVC的组件都使用@Controller来标识当前类是一个控制器servlet.使用这个特性,我们可以开发REST服务的时候不需要使用@Controller而专门的@RestController. 当你实现一个RESTful web services的时候,response将一直通过response

  • Spring Boot 如何自定义返回错误码错误信息

     说明 •在实际的开发过程中,很多时候要定义符合自己业务的错误码和错误信息,而不是统一的而不是统一的下面这种格式返回到调用端 INTERNAL_SERVER_ERROR(500, "Internal Server Error"), 下面我们来看看如何将我们自定义的错误码和错误信息返回到调用端. 1 自定义错误码 •首先我们要定义一个枚举类 public enum ErrorEnum { /* * 错误信息 * */ E_20011(20011, "缺少必填参数"),

随机推荐