1

请推荐使用Jetty HttpClient时解析 urlencoded 或 JSON 编码响应的最佳方法。

例如,我创建了以下实用程序类用于发送 ADM 消息BufferingResponseListener在其中使用UrlEncoded.decodeUtf8To(用于解析承载令牌响应)和JSON.parse(用于解析消息发送响应):

private final HttpClient mHttpClient;
private final String mTokenRequest;

private String mAccessToken;
private long mExpiresIn;

public Adm(HttpClient httpClient) {
    mHttpClient = httpClient;

    MultiMap<String> params = new MultiMap<>();
    params.add("grant_type", "client_credentials");
    params.add("scope", "messaging:push");
    params.add("client_id", "amzn1.application-oa2-client.XXXXX");
    params.add("client_secret", "XXXXX");
    mTokenRequest = UrlEncoded.encode(params, null, false);
}

private final BufferingResponseListener mMessageListener = new BufferingResponseListener() {
    @Override
    public void onComplete(Result result) {
        if (!result.isSucceeded()) {
            if (result.getResponse().getStatus() % 100 == 4) {
                String jsonStr = getContentAsString(StandardCharsets.UTF_8);
                Map<String, String> resp = (Map<String, String>) JSON.parse(jsonStr);
                String reason = resp.get("reason");
                if ("AccessTokenExpired".equals(reason)) {
                    postToken();
                } else if ("Unregistered".equals(reason)) {
                    // delete the invalid ADM registration id from the database
                }
            }
            return;
        }

        String jsonStr = getContentAsString(StandardCharsets.UTF_8);
        Map<String, String> resp = (Map<String, String>) JSON.parse(jsonStr);
        String oldRegistrationId = (String) result.getRequest().getAttributes().get("registrationID");
        String newRegistrationId = resp.get("registrationID");
        if (newRegistrationId != null && !newRegistrationId.equals(oldRegistrationId)) {
            // update the changed ADM registration id in the database
        }
    }
};

private final BufferingResponseListener mTokenListener = new BufferingResponseListener() {
    @Override
    public void onComplete(Result result) {
        if (result.isSucceeded()) {
            String urlencodedStr = getContentAsString(StandardCharsets.UTF_8);
            MultiMap<String> params = new MultiMap<>();
            UrlEncoded.decodeUtf8To(urlencodedStr, params);
            long now = System.currentTimeMillis() / 1000;
            mExpiresIn = now + Long.parseLong(params.getString("expires_in"));
            mAccessToken = params.getString("access_token");
        }
    }
};

public void postMessage(String registrationId, int uid, String jsonStr) {
    long now = System.currentTimeMillis() / 1000;
    if (mAccessToken == null || mAccessToken.length() < 32 || mExpiresIn < now) {
        postToken();
        return;
    }

    mHttpClient.POST(String.format("https://api.amazon.com/messaging/registrations/%1$s/messages", registrationId))
        .header(HttpHeader.ACCEPT, "application/json")
        .header(HttpHeader.CONTENT_TYPE, "application/json")
        .header(HttpHeader.AUTHORIZATION, "Bearer " + mAccessToken)
        .header("X-Amzn-Type-Version", "com.amazon.device.messaging.ADMMessage@1.0")
        .header("X-Amzn-Accept-Type", "com.amazon.device.messaging.ADMSendResult@1.0")
        .attribute("registrationID", registrationId)
        .content(new StringContentProvider(jsonStr))
        .send(mMessageListener);
}

private void postToken() {
    mHttpClient.POST("https://api.amazon.com/auth/O2/token")
        .header(HttpHeader.ACCEPT, "application/json")
        .header(HttpHeader.CONTENT_TYPE, "application/x-www-form-urlencoded")
        .content(new StringContentProvider(mTokenRequest))
        .send(mTokenListener);
}

上面的类工作正常,但是看到有带InputStream in参数的 Jetty 方法,比如

UrlEncoded.decodeTo​(java.io.InputStream in, MultiMap map, java.lang.String charset, int maxLength, int maxKeys)

JSON.parse​(java.io.InputStream in)

我想知道是否有更聪明的方法来获取和解析......也许比BufferingResponseListener?

换句话说,我的问题是:

如何使用上述解析方法的“流式”版本HttpClient

4

0 回答 0