如何在执行*JSR-303验证之前将PathVariable id注入RequestBody*?

Nel*_*ves 7 spring spring-mvc bean-validation spring-boot

我陷入了一个看似简单的问题:我想根据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();
}
Run Code Online (Sandbox Code Playgroud)

我想创建一个自定义验证器来输出自定义消息,以防我更新一些不能与我的数据库中的另一个对象相同的字段.像这样的东西:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,对象id来自@PathVariable,而不是来自@RequestBody.我不能像上面那样调用"objDto.getId()".

另一方面,强制要求填充请求体中的对象id没有多大意义,因为这样路径变量将变得无意义.

我怎么解决这个问题?有没有办法执行bean验证之前将PathVariable中的id注入RequestBody对象?如果没有,那么什么是可行的解决方案?谢谢.

Chi*_*Dov 5

尝试将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;
    }
}
Run Code Online (Sandbox Code Playgroud)