Spring Boot Admin使用InstanceExchangeFilterFunction实现下划线转驼峰适配UI咨询
问题原因分析
你的问题核心是全局ObjectMapper配置被业务绑定为下划线命名策略,而SBA UI只能识别驼峰格式的actuator接口返回值,你之前的两种方案分别踩了两个坑:
- 直接修改全局
MappingJackson2HttpMessageConverter会同时影响业务接口和SBA逻辑,所以出现SBA正常但业务前端崩溃的问题 - 定义的
InstanceExchangeFilterFunction是空实现,没有对响应内容做实际的格式转换,所以不生效
正确实现方案
核心思路是完全不触碰全局业务的ObjectMapper配置,单独给SBA请求做响应转换:通过InstanceExchangeFilterFunction拦截SBA Server和被监控实例之间的请求,拿到下划线格式的响应后,单独转换为驼峰格式再返回给SBA UI,全程和业务配置隔离。
完整配置代码
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import de.codecentric.boot.admin.server.web.client.InstanceExchangeFilterFunction; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import reactor.core.publisher.Mono; import java.util.Iterator; import java.util.Map; @Configuration public class SbaSpecialConfig { // 单独定义SBA专用ObjectMapper,和业务使用的全局ObjectMapper完全隔离 private final ObjectMapper sbaObjectMapper = new ObjectMapper(); @Bean public InstanceExchangeFilterFunction snakeToCamelFilter() { return (instance, request, next) -> next.exchange(request) .flatMap(response -> { // 仅处理JSON格式的响应 if (response.headers().contentType().isPresent() && response.headers().contentType().get().includes(MediaType.APPLICATION_JSON)) { return response.bodyToMono(String.class) .map(body -> { try { JsonNode rootNode = sbaObjectMapper.readTree(body); // 递归转换所有下划线key为驼峰 convertKeyToCamel(rootNode); return sbaObjectMapper.writeValueAsString(rootNode); } catch (Exception e) { // 转换失败直接返回原响应避免异常 return body; } }) .map(camelBody -> response.mutate().body(camelBody).build()); } // 非JSON响应直接透传 return Mono.just(response); }); } // 下划线转驼峰工具方法 private void convertKeyToCamel(JsonNode node) { if (node.isObject()) { Iterator<Map.Entry<String, JsonNode>> fields = node.fields(); while (fields.hasNext()) { Map.Entry<String, JsonNode> field = fields.next(); String oldKey = field.getKey(); String newKey = snakeToCamel(oldKey); if (!oldKey.equals(newKey)) { fields.remove(); ((ObjectNode) node).set(newKey, field.getValue()); } convertKeyToCamel(field.getValue()); } } else if (node.isArray()) { for (JsonNode child : node) { convertKeyToCamel(child); } } } private String snakeToCamel(String snakeStr) { StringBuilder sb = new StringBuilder(); boolean upperCaseNext = false; for (char c : snakeStr.toCharArray()) { if (c == '_') { upperCaseNext = true; } else { sb.append(upperCaseNext ? Character.toUpperCase(c) : c); upperCaseNext = false; } } return sb.toString(); } }
验证说明
- 保留你原有业务的全局ObjectMapper下划线配置不需要修改,业务接口不受任何影响
- 重启SBA服务后访问metrics、env等功能,页面可以正常加载数据
- 如果需要只适配特定接口,可以在过滤器中增加请求路径判断,只处理指定的actuator接口即可
内容的提问来源于stack exchange,提问作者Sonny
相关产品推荐
相关产品推荐

