spring-data-rest:未调用验证器
spring-data-rest: Validator not being invoked
我正在使用 springboot 2.0.1.RELEASE 和 spring-data-rest 并遵循此处提到的解决方法,但我的验证器仍未被调用。详情如下:
验证者注册商: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()));
}
}
}
验证者class:
@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);
}
}
休息客户端测试代码:
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.
知道我错过了什么吗?
您正在尝试将您的验证器与自定义控制器一起使用,而不是 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
class.
一样没有必要
如何将验证器与 SDR 控制器一起使用,您可以在我的另一篇文章中阅读 answer。
我正在使用 springboot 2.0.1.RELEASE 和 spring-data-rest 并遵循此处提到的解决方法,但我的验证器仍未被调用。详情如下:
验证者注册商: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()));
}
}
}
验证者class:
@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);
}
}
休息客户端测试代码:
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.
知道我错过了什么吗?
您正在尝试将您的验证器与自定义控制器一起使用,而不是 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
class.
如何将验证器与 SDR 控制器一起使用,您可以在我的另一篇文章中阅读 answer。