【问题标题】:spring-data-rest: Validator not being invokedspring-data-rest:验证器未被调用
【发布时间】:2018-06-06 19:36:36
【问题描述】:

我正在使用带有 spring-data-rest 的 springboot 2.0.1.RELEASE 并遵循此处提到的解决方法,但我的验证器仍未被调用。以下是详细信息:

ValidatorRegistrar:Workaround for a bug

@Configuration
public class ValidatorRegistrar implements InitializingBean {

    private static final List<String> EVENTS;
    static {
        List<String> events = new ArrayList<String>();
        events.add("beforeCreate");
        events.add("afterCreate");
        events.add("beforeSave");
        events.add("afterSave");
        events.add("beforeLinkSave");
        events.add("afterLinkSave");
        events.add("beforeDelete");
        events.add("afterDelete");
        EVENTS = Collections.unmodifiableList(events);
    }

    @Autowired
    ListableBeanFactory beanFactory;

    @Autowired
    ValidatingRepositoryEventListener validatingRepositoryEventListener;

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, Validator> validators = beanFactory.getBeansOfType(Validator.class);
        for (Map.Entry<String, Validator> entry : validators.entrySet()) {
            EVENTS.stream().filter(p -> entry.getKey().startsWith(p)).findFirst()
                    .ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue()));
        }
    }
}

验证器类:

@Component("beforeSaveBidValidator")
public class BeforeSaveBidValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return Bid.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        Bid bid = (Bid)target;
        if (!bid.getAddendaAcknowledged()) {
            errors.rejectValue("addendaAcknowledged", 
                "addendaAcknowledged is not true");
        }
    }
}

用于出价的自定义 RestController:

@RestController
@RequestMapping(path = "/bids")
public class BidController {

    private BidRepository bidRepository;

    @Autowired
    public BidController(
        BidRepository bidRepository) {
        this.bidRepository = bidRepository;
    }

    @PutMapping("{id}")
    public Bid update(@RequestBody @Valid Bid bid) {
        return bidRepository.save(bid);
    }
}

Rest 客户端测试代码:

Bid bid = new Bid()
...
bid.setAddendaAcknowledged(false)

Map<String, String> uriVariables = new HashMap<String, String>()
uriVariables.put("id", bid.id)

HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
HttpEntity<Bid> entity = new HttpEntity<>(bid, headers)
ResponseEntity<String> response = restTemplate.exchange(
        "/bids/{id}", HttpMethod.PUT, entity, Bid.class, bid.id)

// Expected: response.statusCode == HttpStatus.BAD_REQUEST
// Found: response.statusCode == HttpStatus.OK
// Debugger showed that Validator was never invoked.

知道我错过了什么吗?

【问题讨论】:

    标签: spring-boot spring-data-rest


    【解决方案1】:

    您正在尝试将验证器与自定义控制器一起使用,而不是 SDR 控制器。在这种情况下,您可以使用 @InitBinder 注释将其添加到您的控制器中:

    @RestController
    @RequestMapping("/bids")
    public class BidController {
    
        //...
    
        @InitBinder("bid") // add this parameter to apply this binder only to request parameters with this name
        protected void bidValidator(WebDataBinder binder) {
            binder.addValidators(new BidValidator());
        }
    
        @PutMapping("/{id}")
        public Bid update(@RequestBody @Valid Bid bid) {
            return bidRepository.save(bid);
        }
    }
    

    验证器上的@Component 注释不是必需的,ValidatorRegistrar 类也是如此。


    如何将验证器与 SDR 控制器一起使用,您可以在我的另一个 answer 中阅读。

    【讨论】:

    • @FarrukhNajmi 不客气!请不要忘记接受答案...)
    猜你喜欢
    • 2014-08-10
    • 2016-12-01
    • 2016-03-02
    • 2016-05-21
    • 2020-05-13
    • 1970-01-01
    • 2018-08-22
    • 2014-10-20
    相关资源
    最近更新 更多