SpringBoot Vert.x 四(阻塞Controller)

Vertx 呢 是一套异步框架 当然,理想是美好的,现实是骨感的。

很多实际应用场景中 都会涉及到 阻塞(耗时)操作

举个栗子:

@RequestMapping("findGirlFriend")
public ControllerHandler findGirlFriend() {
    return vertxRequest -> {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        vertxRequest.buildVertxRespone().respone(new ResponeWrapper(10001, null, "girl friend not found"));
    };
}

这时候 控制台应该输出了一些错误日志

QQ20200131-225559@2x

那对于这种阻塞(耗时)操作的接口,Vertx也有对应的处理

新增一个注解

/**
 * blocking handler
 *
 * @author pencilso
 * @date 2020/1/24 9:59 上午
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestBlockingHandler {
}

再次改造 VerticleMain 类 里的registerControllerMethod 方法 (这个类已经改造了好多次了 啊哈哈)

判断是否在方法上 或者 类上面 添加了 @RequestBlockingHandler 注解

/**
 * register controller method
 *
 * @param router              route
 * @param classRequestMapping controller requestMapping annotation
 * @param controllerClass     controller class
 * @param controller          controller instance
 */
private void registerControllerMethod(@NotNull Router router, @NotNull RequestMapping classRequestMapping, @NotNull Class<?> controllerClass, @NotNull Object controller) {
    //获取控制器里的方法
    Method[] controllerClassMethods = controllerClass.getMethods();
    Arrays.asList(controllerClassMethods).stream()
            .filter(method -> method.getAnnotation(RequestMapping.class) != null)
            .forEach(method -> {
                try {
                    RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class);
                    String superPath = classRequestMapping.value()[0];
                    String methodPath = methodRequestMapping.value()[0];
                    //if api path empty skip
                    if (StringUtils.isEmpty(superPath) || StringUtils.isEmpty(methodPath)) return;
                    String url = VerticleUtils.buildApiPath(superPath, methodPath);
                    //build route
                    Route route = VerticleUtils.buildRouterUrl(url, router, methodRequestMapping.method());
                    //run controller method get Handler object
                    Handler<RoutingContext> methodHandler = (Handler<RoutingContext>) method.invoke(controller);
                    //register controller mthod Handler object
                    RequestBlockingHandler requestBlockingHandler = Optional.ofNullable(method.getAnnotation(RequestBlockingHandler.class)).orElseGet(() -> controllerClass.getAnnotation(RequestBlockingHandler.class));
                    if (requestBlockingHandler != null) {
                        //register blocking handler
                        route.blockingHandler(methodHandler);
                    } else {
                        route.handler(methodHandler);
                    }
                    log.info("register controller -> [{}]  method -> [{}]  url -> [{}] ", controllerClass.getName(), method.getName(), url);
                } catch (Exception e) {
                    log.error("registerControllerMethod fail controller: [{}]  method: [{}]", controllerClass, method.getName());
                }
            });
}

现在给 findGirlFriend 方法 添加注解 @RequestBlockingHandler

@RequestBlockingHandler
@RequestMapping("findGirlFriend")
public ControllerHandler findGirlFriend() {
    return vertxRequest -> {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        vertxRequest.buildVertxRespone().respone(new ResponeWrapper(10001, null, "girl friend not found"));
    };
}

再次访问接口 控制台不再报错了 。

Github 源码