从Play 2.4迁移到Play 2.5时,WS验证方法出现问题

时间:2016-06-15 02:24:20

标签: web-services playframework request java-8 response

我有一个我需要重构的方法,因为在Play 2.5中不推荐使用F.Promise。它实际上很可读。它发送请求并通过自定义安全令牌进行身份验证,如果响应为200,则返回true。

public boolean verify(final String xSassToken){

    WSRequest request = WS.url(mdVerifyXSassTokenURL)
            .setHeader("X-SASS", xSassToken)
            .setMethod("GET");

    final F.Promise<WSResponse> responsePromise = request.execute();

    try {
        final WSResponse response = responsePromise.get(10000);
        int status = response.getStatus();
        if(status == 200 ) { //ok
            return true;
        }
    } catch (Exception e) {
        return false;
    }

    return false;
}

我要做的第一件事是改变这一行:

final F.Promise<WSResponse> responsePromise = request.execute();

对此:

final CompletionStage<WSResponse> responsePromise = request.execute();

但是,CompletionStage(T)没有等效的get()方法,因此我不确定获得WSResponse的最快捷,最简单的方法,我可以验证其状态。

1 个答案:

答案 0 :(得分:1)

是的,它没有。至少不是直接的。

你在做什么&#34;错误&#34;在PlayFramework的上下文中。 get是一个阻止调用,您应该尽可能避免阻塞。这就是WS提供非阻止API和handle asynchronous results方法的原因。因此,首先,您应该将verify代码重写为异步:

public CompletionStage<Boolean> verify(final String xSassToken) {
    return WS.url(mdVerifyXSassTokenURL)
             .setHeader("X-SASS", xSassToken)
             .setMethod("GET")
             .execute()
             .thenApply(response -> response.getStatus() == Http.Status.OK);
}

注意我是如何使用thenApply返回一个新的java.util.concurrent.CompletionStage而不是一个普通的布尔值。这意味着调用verify的代码也可以这样做。根据实例,控制器上的操作可以执行以下操作:

public class MyController extends Controller {

    public CompletionStage<Result> action() {
        return verify("whatever").thenApply(success -> {
            if (success) return ok("successful request");
            else return badRequest("xSassToken was not valid");
        });
    }

    public CompletionStage<Boolean> verify(final String xSassToken) { ... }
}

通过这种方式,您的应用程序将能够处理更大的工作量而不会挂起。

编辑:

由于您必须保持兼容性,因此我将采用这种方式来改进设计并在迁移时保持代码兼容:

/**
 * @param xSassToken the token to be validated
 * @return if the token is valid or not
 * 
 * @deprecated Will be removed. Use {@link #verifyToken(String)} instead since it is non blocking.
 */
@Deprecated
public boolean verify(final String xSassToken) {
    try {
        return verifyToken(xSassToken).toCompletableFuture().get(10, TimeUnit.SECONDS);
    } catch (Exception e) {
        return false;
    }
}

public CompletionStage<Boolean> verifyToken(final String xSassToken) {
    return WS.url(mdVerifyXSassTokenURL)
            .setHeader("X-SASS", xSassToken)
            .setMethod("GET")
            .execute()
            .thenApply(response -> response.getStatus() == Http.Status.OK);
}

基本上,弃用旧的verify方法并建议用户迁移到新方法。