来自 RESTful 网络服务的响应中字段的动态过滤指出 returns 域对象列表
Dynamic filtering of a field in the response from a RESTful webservice enpoint that returns a List of domain objects
鉴于使用 Spring 启动框架开发的 RESTful Web 服务,我想要一种方法来抑制响应中所有用户的 birthDate
。这是我在四处寻找解决方案后实施的:
@RestController
public class UserResource {
@Autowired
private UserDAOservice userDAOService;
@GetMapping("/users")
public MappingJacksonValue users() {
List<User> users = userDAOService.findAll();
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter
.filterOutAllExcept("id", "name");
FilterProvider filters = new SimpleFilterProvider().addFilter(
"UserBirthDateFilter", filter);
MappingJacksonValue mapping = new MappingJacksonValue(users);
mapping.setFilters(filters);
return mapping;
}
}
但是,当我在浏览器中点击 rest 端点时,我仍然可以在响应中看到用户的出生日期:
{
"id": 1,
"name": "Adam",
"birthDate": "1980-03-31T16:56:28.926+0000"
}
问题 1:我可以使用什么 API 来实现我的 objective?
接下来,假设我想结合过滤来遵守 HATEOAS,我该怎么做呢?我无法弄清楚可用于同时使用这两个功能的 APIs :
@GetMapping("/users/{id}")
public EntityModel<User> users(@PathVariable Integer id) {
User user = userDAOService.findById(id);
if (user == null) {
throw new ResourceNotFoundException("id-" + id);
}
EntityModel<User> model = new EntityModel<>(user);
WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).users());
model.add(linkTo.withRel("all-users"));
//how do I combine EntityModel with filtering?
return model;
}
问题 2 : 如何将 EntityModel
与 MappingJacksonValue
合并?
注: 我知道 @JsonIgnore
注释,但它会对使用该域的所有端点应用过滤器;但是,我只想将过滤限制在上面的两个端点。
有一种更简单的方法可以做到这一点,在您的传输对象(您发送回客户端的 class)上,您可以简单地使用 @JsonIgnore 注释来确保该字段未被序列化,因此发送给客户端。因此,只需在您的用户 class 中为您的生日字段添加 @JsonIgnore。
您还可以在此处阅读有关此方法的更多信息:
https://www.baeldung.com/jackson-ignore-properties-on-serialization
如果您需要 return 不同的对象用于不同的端点(在您的情况下没有 birthDay 的用户,仅针对特定的),您应该创建单独的传输对象并将它们用于各自的端点。您可以将构造函数中的原始实体(用户)传递给那些 classes 并复制所有需要的字段。
您可以使用 Jackson 的@JsonView 功能。有了这个,您可以告诉某个请求映射生成具有选定属性集的序列化 JSON。
public class View {
interface UserDetails {}
}
public class User {
@JsonView(View.UserDetails.class)
private Long id;
@JsonView(View.UserDetails.class)
private String name;
private String birthdate;
}
控制器就像
@JsonView(View.UserDetails.class)
@GetMapping("/users")
public MappingJacksonValue users() {
....
}
原来为了这个工作,我必须在 DTO 上方添加 @JsonFilter
注释并提供在创建 SimpleFilterProvider
.
时使用的相同名称
@JsonFilter("UserBirthDateFilter")
public class User {
private Integer id;
@Size(min=2, message="user name must be atleast 2 characters")
@ApiModelProperty(notes="user name must be atleast 2 characters")
private String name;
@Past
@ApiModelProperty(notes="birth date cannot be in the past")
private Date birthDate;
//other methods
}
对于问题 2,我遇到了与您完全相同的问题,这就是我所做的。它似乎在工作:
@GetMapping(path = "/users/{id}")
public MappingJacksonValue retrieveUser(@PathVariable int id){
User user = service.findOne(id);
if(user==null){
throw new UserNotFoundException("id-"+id);
}
//"all-users", SERVER_PATH + "/users"
EntityModel<User> resource = EntityModel.of(user);
WebMvcLinkBuilder linkTo =
linkTo(methodOn(this.getClass()).retrieveAllUsers());
resource.add(linkTo.withRel("all-users"));
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept("id");
FilterProvider filters = new SimpleFilterProvider().addFilter("UserFilter",filter);
MappingJacksonValue mapping = new MappingJacksonValue(resource);
mapping.setFilters(filters);
return mapping;
}
响应 HTTP GET localhost:8080/users/1
{
"id": 1,
"links": [
{
"rel": "all-users",
"href": "http://localhost:8080/users"
}
]}
鉴于使用 Spring 启动框架开发的 RESTful Web 服务,我想要一种方法来抑制响应中所有用户的 birthDate
。这是我在四处寻找解决方案后实施的:
@RestController
public class UserResource {
@Autowired
private UserDAOservice userDAOService;
@GetMapping("/users")
public MappingJacksonValue users() {
List<User> users = userDAOService.findAll();
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter
.filterOutAllExcept("id", "name");
FilterProvider filters = new SimpleFilterProvider().addFilter(
"UserBirthDateFilter", filter);
MappingJacksonValue mapping = new MappingJacksonValue(users);
mapping.setFilters(filters);
return mapping;
}
}
但是,当我在浏览器中点击 rest 端点时,我仍然可以在响应中看到用户的出生日期:
{
"id": 1,
"name": "Adam",
"birthDate": "1980-03-31T16:56:28.926+0000"
}
问题 1:我可以使用什么 API 来实现我的 objective?
接下来,假设我想结合过滤来遵守 HATEOAS,我该怎么做呢?我无法弄清楚可用于同时使用这两个功能的 APIs :
@GetMapping("/users/{id}")
public EntityModel<User> users(@PathVariable Integer id) {
User user = userDAOService.findById(id);
if (user == null) {
throw new ResourceNotFoundException("id-" + id);
}
EntityModel<User> model = new EntityModel<>(user);
WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).users());
model.add(linkTo.withRel("all-users"));
//how do I combine EntityModel with filtering?
return model;
}
问题 2 : 如何将 EntityModel
与 MappingJacksonValue
合并?
注: 我知道 @JsonIgnore
注释,但它会对使用该域的所有端点应用过滤器;但是,我只想将过滤限制在上面的两个端点。
有一种更简单的方法可以做到这一点,在您的传输对象(您发送回客户端的 class)上,您可以简单地使用 @JsonIgnore 注释来确保该字段未被序列化,因此发送给客户端。因此,只需在您的用户 class 中为您的生日字段添加 @JsonIgnore。
您还可以在此处阅读有关此方法的更多信息:
https://www.baeldung.com/jackson-ignore-properties-on-serialization
如果您需要 return 不同的对象用于不同的端点(在您的情况下没有 birthDay 的用户,仅针对特定的),您应该创建单独的传输对象并将它们用于各自的端点。您可以将构造函数中的原始实体(用户)传递给那些 classes 并复制所有需要的字段。
您可以使用 Jackson 的@JsonView 功能。有了这个,您可以告诉某个请求映射生成具有选定属性集的序列化 JSON。
public class View {
interface UserDetails {}
}
public class User {
@JsonView(View.UserDetails.class)
private Long id;
@JsonView(View.UserDetails.class)
private String name;
private String birthdate;
}
控制器就像
@JsonView(View.UserDetails.class)
@GetMapping("/users")
public MappingJacksonValue users() {
....
}
原来为了这个工作,我必须在 DTO 上方添加 @JsonFilter
注释并提供在创建 SimpleFilterProvider
.
@JsonFilter("UserBirthDateFilter")
public class User {
private Integer id;
@Size(min=2, message="user name must be atleast 2 characters")
@ApiModelProperty(notes="user name must be atleast 2 characters")
private String name;
@Past
@ApiModelProperty(notes="birth date cannot be in the past")
private Date birthDate;
//other methods
}
对于问题 2,我遇到了与您完全相同的问题,这就是我所做的。它似乎在工作:
@GetMapping(path = "/users/{id}")
public MappingJacksonValue retrieveUser(@PathVariable int id){
User user = service.findOne(id);
if(user==null){
throw new UserNotFoundException("id-"+id);
}
//"all-users", SERVER_PATH + "/users"
EntityModel<User> resource = EntityModel.of(user);
WebMvcLinkBuilder linkTo =
linkTo(methodOn(this.getClass()).retrieveAllUsers());
resource.add(linkTo.withRel("all-users"));
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept("id");
FilterProvider filters = new SimpleFilterProvider().addFilter("UserFilter",filter);
MappingJacksonValue mapping = new MappingJacksonValue(resource);
mapping.setFilters(filters);
return mapping;
}
响应 HTTP GET localhost:8080/users/1
{
"id": 1,
"links": [
{
"rel": "all-users",
"href": "http://localhost:8080/users"
}
]}