How to Monitor Spring Boot HTTP Requests with Actuator: A Step‑by‑Step Guide
This article explains why monitoring HTTP requests in Spring Boot is essential for stability, performance, debugging, user analysis, and security, and provides a complete hands‑on tutorial using Actuator to record, view, customize, and persist request‑response data.
Environment: SpringBoot 2.7.18
1. Introduction
Monitoring interface request information is crucial for system stability, performance optimization, rapid issue location, and data security. It supports problem tracing, performance tuning, user behavior analysis, and security auditing.
2. Practical Example
2.1 Add Dependency & Configuration
<code><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency></code>Register an HttpTraceRepository bean; Actuator provides an in‑memory implementation by default.
<code>@Configuration
public class HttpActuatorConfig {
@Bean
InMemoryHttpTraceRepository inMemoryHttpTraceRepository() {
return new InMemoryHttpTraceRepository();
}
}</code>Enable the httptrace endpoint.
<code>management:
endpoints:
web:
exposure:
include: httptrace</code>Visit /actuator to verify the endpoint is active.
2.2 Test Endpoints
<code>@RestController
@RequestMapping("/users")
public class UserController {
private static List<User> DATAS = new ArrayList<>();
static {
DATAS.add(new User(1L, "张三", 22));
DATAS.add(new User(2L, "李四", 32));
// ... other sample users ...
}
@PostMapping("")
public ResponseEntity<Void> save(@RequestBody User user) {
DATAS.add(user);
return ResponseEntity.created(URI.create(String.format("/users/%s", user.getId()))).build();
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable("id") Long id) {
DATAS.removeIf(u -> u.getId() == id);
return ResponseEntity.noContent().build();
}
@PutMapping("")
public ResponseEntity<Void> update(@RequestBody User user) {
DATAS.stream()
.filter(u -> u.getId() == user.getId())
.findFirst()
.ifPresent(u -> {
u.setAge(user.getAge());
u.setName(user.getName());
});
return ResponseEntity.noContent().build();
}
@GetMapping("")
public ResponseEntity<List<User>> list() {
return ResponseEntity.ok(DATAS);
}
@GetMapping("/{id}")
public ResponseEntity<User> get(@PathVariable("id") Long id) {
return ResponseEntity.ok(DATAS.stream()
.filter(u -> u.getId() == id)
.findFirst().orElse(null));
}
// Test exception
@GetMapping("/exception")
public ResponseEntity<Void> exce() {
System.out.println(1 / 0);
return ResponseEntity.noContent().build();
}
}</code>All operations use an in‑memory list for simplicity.
2.3 View Recorded Requests
Call /actuator/httptrace to see each request’s URL, headers, response status, and the timeTaken attribute (milliseconds).
2.4 Customize Recorded Information
<code>management:
trace:
http:
include:
- time-taken
- response-headers</code>In SpringBoot 3 the configuration changed to:
<code>management:
httpexchanges:
recording:
include:
- time-taken</code>2.5 Manually Retrieve Request‑Response Data
<code>private final HttpTraceRepository httpTraceRepository;
public HttpController(HttpTraceRepository httpTraceRepository) {
this.httpTraceRepository = httpTraceRepository;
}
@GetMapping("/{status}")
public Object info(@PathVariable("status") Integer status) {
return httpTraceRepository.findAll()
.stream()
.filter(trace -> trace.getResponse().getStatus() == status)
.collect(Collectors.toList());
}</code>This endpoint filters stored traces by HTTP status code.
2.6 Custom Storage
<code>@Component
public class PackHttpTraceRepository implements HttpTraceRepository {
private static final String HTTP_TRACE_KEY = "http_request_response";
private final StringRedisTemplate stringRedisTemplate;
public PackHttpTraceRepository(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
@Override
public List<HttpTrace> findAll() {
return stringRedisTemplate.opsForList()
.range(HTTP_TRACE_KEY, 0, -1)
.stream()
.map(json -> {
try {
return objectMapper.readValue(json, HttpTrace.class);
} catch (Exception e) {
return null;
}
})
.collect(Collectors.toList());
}
@Override
public void add(HttpTrace trace) {
try {
String json = objectMapper.writeValueAsString(trace);
stringRedisTemplate.opsForList().leftPush(HTTP_TRACE_KEY, json);
} catch (Exception ignored) {}
}
}</code>Persist traces to Redis (or Elasticsearch) for production use; dedicated tracing systems such as Zipkin or SkyWalking are recommended.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.