序
本文主要研究下webflux如何进行参数校验
使用javax.validation
domain
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;
//...
}
通过onErrorResume处理异常
- form表单提交
/**
* 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 formValidate(@Validated Mono user) {
return user
.map(u -> "Hello " + u.getName())
.onErrorResume(WebExchangeBindException.class, e -> Mono.just(bindingResult2String(e.getBindingResult())));
}
- post json
/**
* 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 requestBodyValidate(@Validated @RequestBody Mono user) {
return user
.map(u -> "Hello " + u.getName())
.onErrorResume(WebExchangeBindException.class, e -> Mono.just(bindingResult2String(e.getBindingResult())));
}
注意这里catch住WebExchangeBindException
通过ExceptionHandler处理WebExchangeBindException
- ExceptionHandler
@ExceptionHandler(WebExchangeBindException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleBindException(WebExchangeBindException bindException) {
return bindingResult2String(bindException.getBindingResult());
}
- from表单提交
/**
* 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 formValidate(@Validated Mono user) {
return user
.map(u -> "Hello " + u.getName());
}
注意这里要标注produces = MediaType.APPLICATION_JSON_UTF8_VALUE,否则报406 Not Acceptable
- post json
/**
* 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 requestBodyValidate(@Validated @RequestBody Mono 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 manualValidate(Mono 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参数校验场景。
doc
- Webflux-Validation
- How to validate Mono when using Spring Reactive