huryer 2019-06-26
本文主要研究下webflux如何进行参数校验
import javax.validation.constraints.Min; import javax.validation.constraints.NotEmpty; public class User { @Min(1) private long id; @NotEmpty private String name; @Min(20) private int age; //... }
/** * curl -i -X POST -d 'id=-1&name=a&age=10' http://localhost:8080/user/validate-mono * * curl -i -X POST -d 'id=2&name=a&age=10' http://localhost:8080/user/validate-mono * * curl -i -X POST -d 'id=2&name=a&age=30' http://localhost:8080/user/validate-mono * @param user * @return */ @PostMapping("/validate-mono") public Mono<String> formValidate(@Validated Mono<User> user) { return user .map(u -> "Hello " + u.getName()) .onErrorResume(WebExchangeBindException.class, e -> Mono.just(bindingResult2String(e.getBindingResult()))); }
/** * curl -i -H "Content-Type: application/json" -X POST -d '{"id":-11,"name":"a"}' http://localhost:8080/user/validate-mono-json-body * * curl -i -H "Content-Type: application/json" -X POST -d '{"id":12,"name":"a","age":30}' http://localhost:8080/user/validate-mono-json-body * @param user * @return */ @PostMapping(value = "/validate-mono-json-body",produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody public Mono<String> requestBodyValidate(@Validated @RequestBody Mono<User> user) { return user .map(u -> "Hello " + u.getName()) .onErrorResume(WebExchangeBindException.class, e -> Mono.just(bindingResult2String(e.getBindingResult()))); }注意这里catch住WebExchangeBindException
@ExceptionHandler(WebExchangeBindException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseBody public String handleBindException(WebExchangeBindException bindException) { return bindingResult2String(bindException.getBindingResult()); }
/** * curl -i -X POST -d 'id=-1&name=a&age=10' http://localhost:8080/user/validate-mono * * curl -i -X POST -d 'id=2&name=a&age=10' http://localhost:8080/user/validate-mono * * curl -i -X POST -d 'id=2&name=a&age=30' http://localhost:8080/user/validate-mono * @param user * @return */ @PostMapping(value = "/validate-mono",produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public Mono<String> formValidate(@Validated Mono<User> user) { return user .map(u -> "Hello " + u.getName()); }注意这里要标注produces = MediaType.APPLICATION_JSON_UTF8_VALUE,否则报406 Not Acceptable
/** * curl -i -H "Content-Type: application/json" -X POST -d '{"id":-11,"name":"a"}' http://localhost:8080/user/validate-mono-json-body * * curl -i -H "Content-Type: application/json" -X POST -d '{"id":12,"name":"a","age":30}' http://localhost:8080/user/validate-mono-json-body * @param user * @return */ @PostMapping(value = "/validate-mono-json-body",produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody public Mono<String> requestBodyValidate(@Validated @RequestBody Mono<User> user) { return user .map(u -> "Hello " + u.getName()); }注意这里没有使用onErrorResume来处理WebExchangeBindException,而是交给ExceptionHandler处理
javax.validation虽然是方便,但是具体业务场景非常复杂,不是简单的单个字段校验就完事的,有的需要关联校验,这个时候javax.validation就无能为力了。这个时候可能就需要手工来写校验。
/** * curl -i -X POST -d 'id=-1&name=a&age=10' http://localhost:8080/user/manual-validate * * curl -i -X POST -d 'id=2&name=a&age=-1' http://localhost:8080/user/manual-validate * @param user * @return */ @PostMapping(value = "/manual-validate",produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public Mono<String> manualValidate(Mono<User> user){ return user.flatMap(u -> { if(u.getAge() < 0){ return Mono.error(new RuntimeException("age < 0")); }else{ return Mono.just("success"); } }); }
通过使用javax.validation自动校验及Mono.error手工校验,基本可以处理大多数webflux参数校验场景。