如何在执行 JSR-303 验证之前*将 PathVariable id 注入 RequestBody?
How to inject PathVariable id into RequestBody *before* JSR-303 validation is executed?
我遇到了一个看似简单的问题:我想根据 PUT 请求中的对象 ID 执行一些自定义验证。
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public ResponseEntity<Void> update(@Valid @RequestBody ClientDTO objDto, @PathVariable Integer id) {
Client obj = service.fromDTO(objDto);
service.update(obj);
return ResponseEntity.noContent().build();
}
我想创建一个自定义验证器来输出自定义消息,以防我更新的某些字段不能与数据库中的另一个对象相同。像这样:
public class ClientUpdateValidator implements ConstraintValidator<ClientUpdate, ClientDTO> {
@Autowired
private ClientRepository repo;
@Override
public void initialize(ClientInsert ann) {
}
@Override
public boolean isValid(ClientDTO objDto, ConstraintValidatorContext context) {
Client aux = repo.findByName(objDto.getName());
if (aux != null && !aux.getId().equals(objDto.getId())) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Already exists")
.addPropertyNode("name").addConstraintViolation();
return false;
}
return true;
}
}
但是,对象id来自@PathVariable,而不是来自@RequestBody。我不能像上面那样调用 "objDto.getId()"。
另一方面,在请求体中强制填写对象id没有多大意义,因为这样路径变量将变得毫无意义。
我该如何解决这个问题?有没有办法将 PathVariable 中的 id 注入 RequestBody 对象 before 执行 bean 验证?如果不是,什么是可行的解决方案?谢谢
尝试将 httpServletRequest 注入自定义验证器
public class ClientUpdateValidator implements ConstraintValidator<ClientUpdate, ClientDTO> {
@Autowired
private HttpServletRequest request;
@Autowired
private ClientRepository repo;
@Override
public void initialize(ClientInsert ann) {
}
@Override
public boolean isValid(ClientDTO objDto, ConstraintValidatorContext context) {
// for example your path to put endpoint is /client/{id}
Map map = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
String id = map.get("id");
Client aux = repo.findByName(objDto.getName());
if (aux != null && !aux.getId().equals(id)) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Already exists")
.addPropertyNode("name").addConstraintViolation();
return false;
}
return true;
}
}
我遇到了一个看似简单的问题:我想根据 PUT 请求中的对象 ID 执行一些自定义验证。
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public ResponseEntity<Void> update(@Valid @RequestBody ClientDTO objDto, @PathVariable Integer id) {
Client obj = service.fromDTO(objDto);
service.update(obj);
return ResponseEntity.noContent().build();
}
我想创建一个自定义验证器来输出自定义消息,以防我更新的某些字段不能与数据库中的另一个对象相同。像这样:
public class ClientUpdateValidator implements ConstraintValidator<ClientUpdate, ClientDTO> {
@Autowired
private ClientRepository repo;
@Override
public void initialize(ClientInsert ann) {
}
@Override
public boolean isValid(ClientDTO objDto, ConstraintValidatorContext context) {
Client aux = repo.findByName(objDto.getName());
if (aux != null && !aux.getId().equals(objDto.getId())) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Already exists")
.addPropertyNode("name").addConstraintViolation();
return false;
}
return true;
}
}
但是,对象id来自@PathVariable,而不是来自@RequestBody。我不能像上面那样调用 "objDto.getId()"。
另一方面,在请求体中强制填写对象id没有多大意义,因为这样路径变量将变得毫无意义。
我该如何解决这个问题?有没有办法将 PathVariable 中的 id 注入 RequestBody 对象 before 执行 bean 验证?如果不是,什么是可行的解决方案?谢谢
尝试将 httpServletRequest 注入自定义验证器
public class ClientUpdateValidator implements ConstraintValidator<ClientUpdate, ClientDTO> {
@Autowired
private HttpServletRequest request;
@Autowired
private ClientRepository repo;
@Override
public void initialize(ClientInsert ann) {
}
@Override
public boolean isValid(ClientDTO objDto, ConstraintValidatorContext context) {
// for example your path to put endpoint is /client/{id}
Map map = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
String id = map.get("id");
Client aux = repo.findByName(objDto.getName());
if (aux != null && !aux.getId().equals(id)) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Already exists")
.addPropertyNode("name").addConstraintViolation();
return false;
}
return true;
}
}