RouterFunction中处理数据项校验如何实现


继续Spring Webflux,RouterFunction中处理数据项校验

RouterFunction中处理数据项校验如何实现


如何在Spring Webflux RouterFunction方式下实现数据项校验和异常处理呢?还有一些注意事项和补充的内容。

校验处理

定义一个校验工具类

@UtilityClass
public class CheckUtil {
    private final static String NO_NAME = "haha";//不允许传入haha作为name
    public void checkName(String name){
        if (NO_NAME.equals(name)){
            throw new RouterException("名称不允许");//抛出异常
        }
    }
}

自定义异常类

public class RouterException extends RuntimeException {

    public RouterException() {
    }
    public RouterException(String msg) {
        super(msg);
    }
    public RouterException(String message, Throwable cause) {
        super(message, cause);
    }
    public RouterException(Throwable cause) {
        super(cause);
    }
}

定义异常处理类

@Component
//由于webException 有多个异常处理的handler 如果要让我们的异常处理生效 需要把优先级调高
@Order(-1)
@Configuration
public class ExceptionHandler implements WebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
        ServerHttpResponse response = serverWebExchange.getResponse();
        //设置400响应头
        response.setStatusCode(HttpStatus.BAD_REQUEST);
        //设置返回类型
        response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
        //处理异常
        String errMsg = toStr(throwable);
        DataBuffer db = response.bufferFactory().wrap(errMsg.getBytes());
        return response.writeWith(Mono.just(db));
    }

    private String toStr(Throwable throwable) {
        //已知异常
        //这里当然是需要按照实际业务需要 定义异常对象来处理 这里只是拿OOM来充数的
        if(throwable instanceof RouterException){
            //已知异常可以简单处理
            return throwable.toString();
        }
        //未知异常 需要打印堆栈,方便定位
        else {
            throwable.printStackTrace();
            return throwable.toString();
        }
    }
}

业务代码改造

我们将新增用户的方法加入name校验

    /**
     * 新增用户
     * @param var1
     * @return
     */

    public Mono<ServerResponse> putUserHandle(ServerRequest var1){
        Mono<User> user = var1.bodyToMono(User.class);
        //对于校验
        return user.flatMap(u->{
            CheckUtil.checkName(u.getName());//校验用户名
            return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
                    //save方法不支持Mono对象,因此需要调用saveAll方法,该方法可以传入Publisher对象,而mono和flux都是Publisher对象
                    .body(this.userRepository.save(u), User.class);
            });
    }

当传入name=haha的数据时,会抛异常,并由异常处理类捕获进行处理。

注意

任何时候,我们不能直接将mono和flux中的对象获取之后直接处理,这样会导致对应的响应会变成阻塞模式,因此需要将对象交给SpringBoot去消费。

比如我们如果要去校验,我们需要这么去写:

/**
     * 新增用户
     * @param var1
     * @return
     */

    public Mono<ServerResponse> putUserHandle(ServerRequest var1){
        Mono<User> user = var1.bodyToMono(User.class);
        //对于校验
        return user.flatMap(u->{
            CheckUtil.checkName(u.getName());
            return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
                    //save方法不支持Mono对象,因此需要调用saveAll方法,该方法可以传入Publisher对象,而mono和flux都是Publisher对象
                    .body(this.userRepository.save(u), User.class);
            });
    }

扩展:

defaultIfEmpty

如果被观察者发射的数据为空,那么就发射defaultIfEmpty中给的那个值

public final Mono<T> defaultIfEmpty(T defaultV) {
    if (this instanceof ScalarCallable) {
        try {
            T v = this.block();
            if (v == null) {
                return just(defaultV);
            }
        } catch (Throwable var3) {
        }

        return this;
    } else {
        return onAssembly(new MonoDefaultIfEmpty(this, defaultV));
    }
}

switchIfEmpty

在被观察者不发送数据时可以发射更多的数据

public final Mono<T> switchIfEmpty(Mono<? extends T> alternate) {
    return onAssembly(new MonoSwitchIfEmpty(this, alternate));
}

可能出现的问题:

依赖包要注意,引入webflux的依赖包,不要再引入web的包,否则会冲突。导致routerfunction配置失效,访问url返回404。

由于之前我把servlet、SSE等都是在一个项目中,所以导致了这个问题。

这种情况在传统的Controller中是影响不大的,但是流式的响应是有问题的。


原文始发于微信公众号(云户):RouterFunction中处理数据项校验如何实现

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/25885.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!