JsonView注解

通过 @JsonView 注解, 指定对应对象在对应控制器的不同返回内容.

JsonView以接口作为区分组, 不同的接口作为其参数可以针对不同类型进行分类区分.
我们有一个 User 对象, 它有username和password属性, 然后对应两个控制器userList和getUserInfo, 我想在在userList接口时只返回用户的名称列表, 在getUserInfo时,将用户名和密码一起返回。那么可以通过定义两个接口:UserSimpleView和UserDetailView, UserDetailView继承自UserSimpleView,根据Java的继承关系也不难理解,就是当有simple的时候, 是独立的, 当有detail的时候, 会将simple注解了的参数一并展示,描述的可能不是特别好,可以通过代码得到更好的展示。

首先,我们在User类中,定义两个接口。分别代表两种展示类别,然后再username字段加上simple接口参数,在password字段加上detail接口参数。

@Data
@Accessors(chain = true)
public class User implements Serializable {

    public interface UserSimpleView {}
    public interface UserDetailView extends UserSimpleView {}

    @JsonView(UserSimpleView.class)
    private String username;
    @JsonView(UserDetailView.class)
    private String password;
}

然后再对应的两个控制器,通过 @JsonView 注解,和对应对象的属性绑定起来。
可以看到,我们在getUserList方法上配置了simple接口,代表着它的参数返回中,只会包括usename字段属性值。
在getInfo方法上,通过配置detail接口,代表着它的返回值中可以包括 User 对象中的所有使用了 Detail 接口以及其父接口的参数.

@RestController
@RequestMapping("user")
public class UserController {

    @GetMapping
    @JsonView(User.UserSimpleView.class)
    public List<User> getUserList(UserQueryCondition condition,
                              @PageableDefault(size = 20, page = 1, sort = "username,asc") Pageable pageable) {

        System.out.println(ReflectionToStringBuilder.toString(condition, ToStringStyle.MULTI_LINE_STYLE));
        System.out.println(pageable);

        return Collections.singletonList(new User().setUsername("yzt").setPassword("xxx"));
    }

    @GetMapping("{id:\\d+}")
    @JsonView(User.UserDetailView.class)
    public User getInfo(@PathVariable String id) {

        System.out.println(id);

        User user = new User();
        user.setUsername("tom").setPassword("xxx");
        return user;
    }
}

接下来通过单元测试的返回值,具体的来看一下效果。

@SpringBootTest
@RunWith(SpringRunner.class)
public class UserControllerTest {

    @Autowired
    private WebApplicationContext wac;
    private MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @Test
    public void whenQuerySuccess() throws Exception {
        String contentAsString = mockMvc.perform(get("/user")
                .param("username", "yzt")
                .param("age", "20")
                .param("ageTo", "30")
                .param("page", "2")
                .param("size", "10")
                .param("sort", "age,desc")
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.length()").value(1))
                .andReturn()
                .getResponse()
                .getContentAsString();
        System.out.println(contentAsString);

    }


    @Test
    public void whenGetInfoSuccess() throws Exception {
        String content = mockMvc.perform(get("/user/1")
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.username").value("tom"))
                .andReturn()
                .getResponse()
                .getContentAsString();
        System.out.println(content);
    }
}

对应的返回值如下:
whenQuerySuccess接口返回值, 只看到了username参数。

top.imyzt.learning.security.demo.dto.UserQueryCondition@67b560fe[
  username=yzt
  age=20
  ageTo=30
]
Page request [number: 2, size 10, sort: age: DESC]
[{"username":"yzt"}]

whenGetInfoSuccess接口返回值,可以看到了password参数。

{"username":"tom","password":"xxx"}

至此,博客结束了。有多学了一个骚操作。