Spring Boot Actuator深度解析与实战

🧩 一、什么是 Spring Boot Actuator?

Actuator = "执行器" / "控制器"

它是 Spring Boot 提供的一个模块,用于:

  • 查看应用运行状态(如内存、线程、健康状况)
  • 监控性能指标(metrics)
  • 执行管理操作(如关闭应用、刷新配置)

这些功能通过一系列 HTTP 接口(称为"端点 endpoints") 暴露出来。

默认路径:/actuator

例如:

  • GET /actuator/health → 查看服务是否健康
  • GET /actuator/metrics → 获取 JVM 内存、CPU 使用率等
  • GET /actuator/env → 查看环境变量

🔍 分章节详解


✅ 6.2.5. Hypermedia for Actuator Web Endpoints(超媒体发现页)

核心意思:

提供一个"入口页面",列出所有可用的 Actuator 端点链接。

关键点解释:
内容 解释
/actuator 是"发现页" 访问这个 URL,会返回一个 JSON 列表,包含所有已启用的 endpoint 链接(比如 /health, /metrics)
自定义管理路径时自动迁移 如果你在 application.yml 中设置了 management.server.base-path=/manage,那么发现页就变成 /manage
设置为 / 时禁用 如果把 management context path 设成根路径 /,为了避免和其他接口冲突,发现页会被关闭

📌 示例:

访问 http://localhost:8080/actuator 得到如下结果(部分):

json 复制代码
{
  "_links": {
    "self": { "href": "/actuator" },
    "health": { "href": "/actuator/health" },
    "metrics": { "href": "/actuator/metrics" },
    "env": { "href": "/actuator/env" }
  }
}

👉 这叫 HATEOAS 风格(Hypermedia as the Engine of Application State),即"通过链接导航系统"。


✅ 6.2.6. CORS Support(跨域支持)

核心意思:

允许浏览器从其他域名访问 Actuator 的 API(比如前端管理系统调用后端的 /actuator/health)。

默认情况:

❌ CORS 被禁用

只有当你显式配置了 allowed-origins,才开启。

示例配置(application.yml):
yaml 复制代码
management:
  endpoints:
    web:
      cors:
        allowed-origins: https://example.com
        allowed-methods: GET,POST
        allowed-headers: "*"
        max-age: 3600

这表示:

  • 允许来自 https://example.com 的请求
  • 只能使用 GET 和 POST 方法
  • 支持任意 header
  • 缓存预检请求 1 小时

💡 注意:需要 Spring MVC 或 WebFlux 才能生效。


✅ 6.2.7. Implementing Custom Endpoints(实现自定义端点)

你可以自己写代码来添加新的监控接口!

方法一:通用端点 @Endpoint(推荐 ✅)
java 复制代码
@Component
@Endpoint(id = "custom")
public class CustomEndpoint {

    @ReadOperation
    public CustomData getData() {
        return new CustomData("test", 5);
    }

    @WriteOperation
    public void updateData(String name, int counter) {
        // 处理更新逻辑
    }
}

✅ 特点:

  • 同时暴露在 JMX 和 HTTP 上
  • 技术无关(不依赖 Spring MVC/Jersey)
  • 推荐用于通用场景
注解 对应 HTTP 方法 场景
@ReadOperation GET 查询数据
@WriteOperation POST 修改数据
@DeleteOperation DELETE 删除数据

方法二:Web 专属端点(@WebEndpoint)
java 复制代码
@WebEndpoint(id = "webonly")
public class WebOnlyEndpoint {
    @ReadOperation
    public String status() {
        return "OK";
    }
}

⚠️ 特点:

  • 只暴露在 HTTP 上
  • 不出现在 JMX 中
  • 更轻量,适合只做 Web 监控

方法三:增强已有端点(@EndpointWebExtension)

你想给现有的 health 端点加个额外的 Web 功能?可以用这个。

java 复制代码
@EndpointWebExtension(endpoint = HealthEndpoint.class)
public class CustomHealthWebExtension {

    @ReadOperation
    public Map<String, Object> customHealthInfo() {
        return Collections.singletonMap("custom", "info");
    }
}

这样就在原有 /actuator/health 基础上增加了新能力。


方法四:完全自由控制(@ControllerEndpoint / @RestControllerEndpoint)

如果你非要使用 Spring MVC 的注解(如 @GetMapping, @RequestBody),可以这么做:

java 复制代码
@RestControllerEndpoint(id = "admin")
public class AdminController {

    @GetMapping("/pause")
    public String pauseApp() {
        // 暂停应用逻辑
        return "paused";
    }
}

⚠️ 缺点:

  • ❌ 不能用于 JMX
  • ❌ 不能用于 Jersey 或非 Spring Web 框架
  • ❌ 可移植性差

👉 所以官方建议:优先使用 @Endpoint,除非必须用 MVC 注解。


🔁 输入参数处理(Receiving Input)

如何接收参数?

无论是 GET 参数还是 POST JSON,都可以直接作为方法参数注入。

示例:
java 复制代码
@WriteOperation
public void updateUser(String name, int age) {
    // name 来自 query 参数或 JSON 字段
    // age 同理
}
请求示例:
http 复制代码
POST /actuator/custom?name=Tom
Content-Type: application/json

{
  "age": 25
}

→ name="Tom" 来自 URL 参数

→ age=25 来自 JSON body

✅ 自动拼接!

注意事项:
  • 默认参数是必填的
  • 加 @Nullable 表示可选
  • 方法签名只能用基本类型或简单对象字段映射(不能传整个复杂对象)
  • Java 编译需加 -parameters(Maven/Gradle 插件默认已开启)

⚙️ Web Endpoint Request Predicates(请求匹配规则)

每个端点的操作都会自动生成一个"请求匹配器"。

1. 路径(Path)

格式:/{base-path}/{endpoint-id}

默认 base-path = /actuator

例子:

  • 端点 ID 是 sessions → 路径是 /actuator/sessions
  • 如果加了 @Selector:
java 复制代码
@ReadOperation
public Session getSession(@Selector String id) {
    // ...
}

→ 路径变成 /actuator/sessions/{id}

支持通配符:

java 复制代码
@ReadOperation
public List<String> list(@Selector(match = ALL_REMAINING) String[] parts) {
    // 匹配 /actuator/path/to/file
}

2. HTTP 方法映射

Operation HTTP Method
@ReadOperation GET
@WriteOperation POST
@DeleteOperation DELETE

3. Content-Type(Consumes)

操作类型 consumes 类型
@WriteOperation(带 body) application/vnd.spring-boot.actuator.v2+json, application/json
其他操作 空(不限制)

👉 支持版本化媒体类型,便于未来升级协议。


4. 返回类型(Produces)

根据返回值决定响应类型:

返回值 Produces
void / Void (无 content-type)
Resource(文件) application/octet-stream
其他对象 application/vnd.spring-boot.actuator.v2+json, application/json

5. 响应状态码(Status Code)

情况 HTTP Status
@ReadOperation 返回值 200 OK
@ReadOperation 无返回值 404 Not Found
@WriteOperation / @DeleteOperation 有返回值 200 OK
@WriteOperation / @DeleteOperation 无返回值 204 No Content
缺少必要参数 or 类型转换失败 400 Bad Request

6. Range 请求(断点续传)

如果返回的是 Resource(比如日志文件),并且使用的是 Spring MVC 或 WebFlux,则支持 HTTP Range 请求(可用于下载大文件的部分内容)。

🚫 不支持 Jersey。


7. 安全控制(Security)

可以在方法参数中获取当前用户信息:

java 复制代码
@ReadOperation
public String secureData(Principal principal) {
    if (principal == null) {
        return "anonymous";
    }
    return "Hello " + principal.getName();
}

// 或者更强大的权限判断
@ReadOperation
public boolean isAdmin(SecurityContext securityContext) {
    return securityContext.isUserInRole("ADMIN");
}

👉 可与 Spring Security 集成,做细粒度权限控制。


8. Servlet 端点(@ServletEndpoint)

如果你想封装一个已有的 Servlet 作为监控端点:

java 复制代码
@ServletEndpoint(id = "my-servlet")
public class MyServletEndpoint implements Supplier<EndpointServlet> {
    @Override
    public EndpointServlet get() {
        return new EndpointServlet(MyLegacyServlet.class);
    }
}

⚠️ 局限性强,仅限 Servlet 容器使用。


✅ 总结:四种创建端点的方式对比

方式 注解 是否支持 JMX 是否支持 Web 是否可移植 推荐程度
通用端点 @Endpoint ✅ ✅ ✅ 最高 ⭐⭐⭐⭐⭐
Web 专属 @WebEndpoint ❌ ✅ ✅ ⭐⭐⭐⭐
扩展已有端点 @EndpointWebExtension ❌ ✅ ✅ ⭐⭐⭐⭐
MVC 控制器风格 @ControllerEndpoint ❌ ✅(仅 Spring Web) ❌ ⭐⭐

💡 实际应用场景举例

场景 1:做一个"清理缓存"的管理接口

java 复制代码
@Endpoint(id = "clearcache")
public class ClearCacheEndpoint {

    @Autowired
    private CacheManager cacheManager;

    @WriteOperation
    public String clearAllCaches() {
        cacheManager.getCacheNames().forEach(name ->
            cacheManager.getCache(name).clear()
        );
        return "All caches cleared.";
    }
}

访问:POST /actuator/clearcache


场景 2:查看某个任务的状态(带 ID)

java 复制代码
@Endpoint(id = "tasks")
public class TaskEndpoint {

    @ReadOperation
    public TaskStatus getStatus(@Selector String taskId) {
        return taskService.getStatus(taskId);
    }
}

访问:GET /actuator/tasks/login-job


✅ 最佳实践建议

  1. 优先使用 @Endpoint + @ReadOperation/@WriteOperation
  2. 避免使用 @ControllerEndpoint,除非必须用 @RequestBody 等高级特性
  3. 编译时确保开启 -parameters(Spring Boot 默认已开)
  4. 敏感端点要加安全认证(配合 Spring Security)
  5. 生产环境不要暴露所有端点!
yaml 复制代码
# application-prod.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info

📚 学习资源


✅ 一句话总结:

这段文档讲的是:如何通过标准和自定义方式,在 Spring Boot 中暴露监控接口,并精确控制它们的路径、参数、安全性、输出格式等行为。

如果你正在开发微服务监控平台、内部运维工具或需要深度集成健康检查系统,这部分知识非常关键!

需要我给你写一个完整的自定义 Actuator 端点示例吗?包括 Maven 配置、Java 代码、测试请求等。

相关推荐
zhoujungis5 分钟前
登录态 1 小时就掉?Django + Vue 双 Token 认证实战 | 尘世栈帧
后端
Félix25111 分钟前
Nacos学习笔记(SpringBoot/SpringCloud)
java·spring boot·spring
文丑颜不良啊15 分钟前
LeetCode1581~1600题目解析
java·leetcode
香蕉大香蕉(06敬畏市场)16 分钟前
MySQL 单点详解(06)
java·数据库·mysql·博客·实习
武子康25 分钟前
同一台 ESP32,GSM 能消回声,VoIP 为什么不行?
人工智能·后端·agent
用户693717500138428 分钟前
AI 能写代码,但工程架构还是应该由人来定
前端·后端
lqbzlll29 分钟前
Spring Boot 开启虚拟线程后接口反而变慢了?4 个排查方向和对应修法
java·spring boot·后端
七夜zippoe34 分钟前
LangChain4j vs Spring AI:Java AI 框架怎么选(对比表)
java·人工智能·spring·ai·langchain4j
悠仁さん39 分钟前
【C++】set map 使用
java·前端·c++
回家路上绕了弯42 分钟前
让 AI 成为团队的共同能力
后端