Talk about webflux parameter verification

  springboot

Order

This paper mainly studies how to verify the parameters of webflux.

Using 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;
    //...
}    

Handle exceptions with onErrorResume

  • Form form submission
    /**
     * 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())));
    }
  • 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<String> requestBodyValidate(@Validated @RequestBody Mono<User> user) {

        return user
                .map(u -> "Hello " + u.getName())
                .onErrorResume(WebExchangeBindException.class, e -> Mono.just(bindingResult2String(e.getBindingResult())));
    }

Note that the catch here lives in WebExchangeBindException.

Handling WebExchangeBindException by ExceptionHandler

  • ExceptionHandler
    @ExceptionHandler(WebExchangeBindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public String handleBindException(WebExchangeBindException bindException) {
        return bindingResult2String(bindException.getBindingResult());
    }
  • From form submission
    /**
     * 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());
    }

Note that products = mediatype.application _ JSON _ utf8 _ value should be marked here, otherwise 406 Not Acceptable is reported.

  • 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<String> requestBodyValidate(@Validated @RequestBody Mono<User> user) {

        return user
                .map(u -> "Hello " + u.getName());
    }

Note that onErrorResume is not used here to handle WebExchangeBindException, but is instead handed over to ExceptionHandler for processing.

Manual check

Although javax.validation is convenient, the specific business scenario is very complex. It is not a simple single field verification. Some require correlation verification. At this time, javax.validation is powerless. This time it may be necessary to manually write the verification.

    /**
     * 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");
            }
        });
    }

Summary

By using javax.validation automatic verification and Mono.error manual verification, it can basically handle most webflux parameter verification scenarios.

doc