SpringBoot记录请求体日志

SpringBoot记录请求体日志

有时经常会遇到将请求体记录到日志的需求。由于请求体是个流,读取完后不能再次被读取,用拦截器等方法不太合适;使用AOP对controller做代理的方式也不可取,因为这样记录的是反序列化成java对象,属性顺序可能会与真实的请求体有所偏差。但SpringBoot提供了RequestBodyAdvice接口,可以方便的记录真实的请求体,又不影响后续请求体的读取。
首先,创建一个实体类。

import lombok.Data;

@Data
public class Person {
    private Integer age;
    private String name;
}

接着,自定义一个注解


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface BodyLog {
}

然后实现RequestBodyAdvice接口,此Advice会对标记了BodyLog注解的Controller,并且使用了@RequestBody的方法进行拦截。beforeBodyRead方法中先将请求体读取,然后将读取的内容记录后又写入了body中。

@Slf4j
@ControllerAdvice(annotations = BodyLog.class)
public class BodyLogRequestAdvice implements RequestBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        String bodyString = IoUtil.read(inputMessage.getBody(), StandardCharsets.UTF_8);
        log.info("请求体:{}", bodyString);
        return new HttpInputMessage() {
            @Override
            public ByteArrayInputStream getBody() {
                return new ByteArrayInputStream(bodyString.getBytes(StandardCharsets.UTF_8));
            }

            @Override
            public HttpHeaders getHeaders() {
                return inputMessage.getHeaders();
            }
        };
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return null;
    }
}

最后,我们创建一个controller,模拟测试一下。


import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/person")
@BodyLog
public class PersonController {
    @PostMapping("save")
    public String save(@RequestBody Person person) {
        return "ok";
    }
}

接着我们调用接口

在这里插入图片描述
控制台打印出请求体信息。
在这里插入图片描述

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot中,你可以使用AOP(面向切面编程)来实现计时器。首先,你需要定义一个切面类,在这个类中,你可以定义一个@Before注解的方法,在这个方法中获取请求的开始时间。然后,你可以定义一个@After注解的方法,在这个方法中获取请求的结束时间,并计算请求处理的时间。下面是一个简单的示例代码: ```java @Aspect @Component public class TimingAspect { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Before("execution(* com.example.controller.*.*(..))") public void logRequestStartTime(JoinPoint joinPoint) { logger.info("Request started at: {}", System.currentTimeMillis()); } @After("execution(* com.example.controller.*.*(..))") public void logRequestEndTime(JoinPoint joinPoint) { logger.info("Request ended at: {}", System.currentTimeMillis()); } } ``` 在上面的代码中,@Aspect注解用于声明这个类是一个切面类,@Component注解用于让Spring Boot自动扫描和注入这个类。@Before注解用于指定一个方法在被切入的方法执行前执行,@After注解用于指定一个方法在被切入的方法执行后执行。在这个示例代码中,我们使用了JoinPoint对象来获取被切入的方法的信息,通过Logger对象来记录日志。 最后,你需要在Spring Boot的配置文件中开启AOP: ```yaml spring: aop: auto: true ``` 这样,当Spring Boot收到请求时,AOP会自动执行切面类中的方法,并记录请求处理的时间。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值