spring - 如何在执行 JSR-303 验证之前将 PathVariable id 注入(inject) RequestBody?

标签 spring spring-mvc spring-boot bean-validation

我陷入了一个明显简单的问题:我想根据 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 注入(inject) RequestBody 对象 之前 执行bean验证?如果没有,什么是可行的解决方案?谢谢。

最佳答案

尝试将 httpServletRequest 注入(inject)自定义验证器

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;
    }
}

关于spring - 如何在执行 JSR-303 验证之前将 PathVariable id 注入(inject) RequestBody?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46617124/

相关文章:

java - Spring - 未创建 CrudRepository

spring-boot - 如何使用 OpenApi 自定义 swagger-ui.html url

java - 为什么 liquibase 总是使用自己的序列?

Java Spring - MySQL时间戳字段和毫秒精度

java - 在 Spring 中正确使用 Log4jConfigurer

Spring 上下文 :component-scan casting exception

spring-mvc - 使用功能性 Webflux 上传文件

java - 当 Spring Context 中所有 Controller 都准备就绪时,如何触发事件?

java - 原型(prototype) Bean 没有按预期 Autowiring

java - Spring MVC - 通过 Thymeleaf 访问静态页面