好的,下面是一个真实的 Spring Boot 示例,展示如何使用 AOP 和自定义注解来记录请求参数、响应和耗时。
### 假设场景
我们构建一个简单的用户服务,包括用户的创建和获取。我们将在这两个方法上使用 AOP 来记录日志。
### 1. 创建自定义注解
首先,创建自定义注解 `@LogRequestResponse`。
```java
package com.example.demo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogRequestResponse {
}
```
### 2. 创建 AOP 切面
接下来,创建一个切面类,处理日志逻辑。
```java
package com.example.demo.aspect;
import com.example.demo.annotation.LogRequestResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Aspect
@Component
public class LoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
@Around("@annotation(LogRequestResponse)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
// 记录请求参数
Object[] args = joinPoint.getArgs();
logger.info("Request Parameters: {}", Arrays.toString(args));
// 记录开始时间
long startTime = System.currentTimeMillis();
// 执行目标方法
Object proceed = joinPoint.proceed();
// 记录结束时间
long endTime = System.currentTimeMillis();
// 记录响应
logger.info("Response: {}", proceed);
// 记录耗时
logger.info("Execution time: {} ms", (endTime - startTime));
return proceed;
}
}
```
### 3. 创建用户服务
实现一个简单的`UserService`,包含创建和获取用户的方法。
```java
package com.example.demo.service;
import com.example.demo.annotation.LogRequestResponse;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class UserService {
private Map<Long, String> userDatabase = new HashMap<>();
private long userIdCounter = 1;
@LogRequestResponse
public Long createUser(String userName) {
Long userId = userIdCounter++;
userDatabase.put(userId, userName);
return userId;
}
@LogRequestResponse
public String getUser(Long userId) {
return userDatabase.get(userId);
}
}
```
### 4. 创建控制器
创建控制器来调用用户服务。
```java
package com.example.demo.controller;
import com.example.demo.service.UserService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping
public Long createUser(@RequestBody String userName) {
return userService.createUser(userName);
}
@GetMapping("/{id}")
public String getUser(@PathVariable Long id) {
return userService.getUser(id);
}
}
```
### 5. 配置 Spring Boot
确保您的 `pom.xml` 中包含 Spring AOP 依赖。
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
```
### 6. 启动应用
您可以使用以下代码块在 `DemoApplication` 类中启动 Spring Boot 应用。
```java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
### 7. 测试应用
启动应用后,您可以使用 Postman 或 CURL 测试 API。
#### 创建用户
```bash
curl -X POST -H "Content-Type: application/json" -d "John Doe" http://localhost:8080/users
```
#### 获取用户
```bash
curl http://localhost:8080/users/1
```
### 8. 日志输出示例
在控制台中,您应该能看到类似以下的输出:
```
2023-10-01 00:00:00 INFO Request Parameters: [John Doe]
2023-10-01 00:00:01 INFO Response: 1
2023-10-01 00:00:01 INFO Execution time: 5 ms
2023-10-01 00:00:02 INFO Request Parameters: [1]
2023-10-01 00:00:02 INFO Response: John Doe
2023-10-01 00:00:02 INFO Execution time: 1 ms
```
### 注意事项
1. **异常处理**:您可以扩展 AOP 来捕获异常并记录错误信息。
2. **敏感数据**:在处理请求时,确保不在日志中记录敏感信息。
3. **性能**:定期检查日志的生成,确认不会影响系统性能。
通过这种实现方式,您可以便捷地记录请求和响应的参数以及处理时间,有效提高系统的可监控性和调试能力。