
痛点一个接口N套VO作为后端开发你一定遇到过这样的场景同一个用户列表接口不同角色看到的字段完全不一样。管理员能看到用户的手机号、薪资等敏感信息普通用户只能看到昵称和头像。于是代码变成了这样// 管理员看到的 {id: 1, name: 张三, phone: 13800138000, salary: 15000} // 普通用户看到的 {id: 1, name: 张三}你开始写多套VOAdminUserVO、NormalUserVO、PublicUserVO……三个角色还好五个角色就完全失控了。每个接口都要写if-else判断返回哪个VO代码臃肿不堪维护成本飙升。解决方案JsonView 一劳永逸其实Spring Boot的Jackson库早就为我们准备好了解决方案——JsonView注解。第一步定义视图接口public class Views { // 最基础的公开信息 public interface Public {} // 普通用户包含公开信息 普通用户可见字段 public interface Normal extends Public {} // 管理员包含所有字段 public interface Admin extends Normal {} }通过继承关系Admin自动拥有Normal和Public的所有字段Normal自动拥有Public的所有字段。第二步实体类标注视图public class UserVO { JsonView(Views.Public.class) private Long id; JsonView(Views.Public.class) private String name; JsonView(Views.Normal.class) private String phone; JsonView(Views.Admin.class) private BigDecimal salary; // 省略getter/setter }每个字段属于哪个视图组一目了然。第三步动态切换视图关键来了——如何根据当前登录用户角色动态切换视图RestControllerAdvice public class JsonViewAdvice extends AbstractMappingJacksonResponseBodyAdvice { Override protected void beforeBodyWriteInternal(MappingJacksonValue body, MediaType contentType, MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) { // 根据当前用户角色动态设置视图 Class? view resolveViewByRole(); if (view ! null) { body.setSerializationView(view); } } private Class? resolveViewByRole() { LoginUser user SecurityUtils.getLoginUser(); if (user null) return Views.Public.class; if (user.isAdmin()) return Views.Admin.class; return Views.Normal.class; } }这样一来Controller层完全不用改动GetMapping(/list) public RListUserVO list() { return R.ok(userService.list()); }同一个接口管理员请求返回全部字段普通用户请求只返回公开字段。进阶技巧1. 方法级别的视图覆盖如果某个接口需要特殊处理可以直接在方法上指定视图GetMapping(/detail) JsonView(Views.Admin.class) public RUserVO detail(PathVariable Long id) { return R.ok(userService.getById(id)); }方法上的JsonView会覆盖全局拦截器的设置。2. 嵌套对象的视图控制如果VO中有嵌套对象同样可以标注视图public class OrderVO { JsonView(Views.Public.class) private Long orderId; JsonView(Views.Normal.class) private UserVO user; // UserVO中的字段也会受视图控制 }优缺点分析优点代码复用一套VO、一套Controller告别多套VO的维护噩梦扩展简单新增角色只需在resolveViewByRole()中添加一个分支声明式编程字段归属清晰一目了然缺点继承层次控制角色层次太多时视图接口的继承树会变得复杂建议控制在4层以内细粒度不足如果需求是A角色看phoneB角色看emailC角色两个都看JsonView就力不从心了适合你的场景吗如果你的项目满足以下条件JsonView方案非常适合你角色之间有清晰的层级关系Admin → Manager → Normal → Public每个角色的字段是上一层级的超集角色数量在5个以内如果你的场景是角色之间字段互有交叉没有清晰的层级关系需要精细化控制每个字段对每个角色的可见性角色数量超过10个那么建议考虑自定义注解 序列化器的方案在序列化时逐字段判断权限。总结JsonView是处理多角色字段返回的优雅方案它让代码更简洁、更易维护。核心思路是定义视图接口通过继承表达角色层级标注字段归属用JsonView标记每个字段属于哪个视图动态切换视图通过ResponseBodyAdvice拦截响应根据当前用户角色动态设置序列化视图下次遇到多角色字段返回的需求不妨试试这个方案让你的代码更加优雅。