基于Spring Boot+JsonView实现多客户端接口字段动态控制
实现基于请求头自动匹配JsonView的方案
1. 定义客户端与JsonView的映射关系
先创建枚举类,将请求头中的客户端标识与对应的JsonView视图类绑定,同时提供默认视图兜底:
public enum ClientViewMapping { CLIENT_A("client-a", ClientAView.class), CLIENT_B("client-b", ClientBView.class), DEFAULT("default", DefaultView.class); private final String clientId; private final Class<?> viewClass; ClientViewMapping(String clientId, Class<?> viewClass) { this.clientId = clientId; this.viewClass = viewClass; } public static Class<?> getViewByClientId(String clientId) { for (ClientViewMapping mapping : values()) { if (mapping.clientId.equals(clientId)) { return mapping.viewClass; } } return DEFAULT.viewClass; } }
2. 自定义ResponseBodyAdvice动态切换视图
利用Spring的ResponseBodyAdvice拦截响应,根据请求头获取对应视图并设置到Jackson序列化配置中:
@ControllerAdvice public class DynamicJsonViewAdvice implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { // 仅处理Jackson格式的响应转换器 return MappingJackson2HttpMessageConverter.class.isAssignableFrom(converterType); } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { // 从请求头提取客户端标识 String clientId = request.getHeaders().getFirst("X-Client-Id"); Class<?> targetView = ClientViewMapping.getViewByClientId(clientId); // 将响应包装为MappingJacksonValue并设置视图 if (body instanceof MappingJacksonValue) { ((MappingJacksonValue) body).setSerializationView(targetView); return body; } else { MappingJacksonValue container = new MappingJacksonValue(body); container.setSerializationView(targetView); return container; } } }
3. 控制器与实体类配置
控制器无需手动指定@JsonView,直接返回实体即可:
@RestController @RequestMapping("/api/data") public class DataController { @GetMapping public DataEntity getData() { DataEntity entity = new DataEntity(); // 填充业务数据 return entity; } }
实体类保留@JsonView注解,对应各客户端视图:
public class DataEntity { @JsonView({DefaultView.class, ClientAView.class, ClientBView.class}) private String id; @JsonView({DefaultView.class, ClientAView.class}) private String commonField; @JsonView(ClientAView.class) private String clientAField; @JsonView(ClientBView.class) private String clientBField; // getter、setter方法 } // 视图类定义(可通过继承复用字段规则) public class DefaultView {} public class ClientAView extends DefaultView {} public class ClientBView extends DefaultView {}
4. 验证逻辑
- 客户端请求时添加请求头
X-Client-Id: client-a,将返回包含id、commonField、clientAField的响应 - 添加请求头
X-Client-Id: client-b,将返回包含id、commonField、clientBField的响应 - 无该请求头时,默认返回
id、commonField字段
内容的提问来源于stack exchange,提问作者Kenany
相关产品推荐
相关产品推荐

