GraphQL 是一種用於 API 的查詢語言,是由 Facebook 開源的一種用於提供數據查詢服務的抽象框架。在服務端 API 開發中,不少時候定義一個接口返回的數據相對固定,所以要得到更多信息或者只想獲得某部分信息時,基於 RESTful API 的接口就顯得不那麼靈活。而 GraphQL 對 API 中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘,也讓 API 更容易地隨着時間推移而演進,還能用於構建強大的開發者工具。 目前,LeetCode 和 GitHub 都藉助 GraphQL 來設計,提供了更大的靈活性,對於想借助 GitHub 來了解 GraphQL 可直接訪問 GraphQL API v4 ,或者參考 GraphQL 實戰:Github V4 API使用。而對於在 LeetCode 上使用 GraphQL 查詢,相對資料少一些,所以在這,我主要以 LeetCode 爲例,來作講解(實際上是由於本身業餘刷題時突發奇想,想寫一個爬蟲。java
若是直接搜索以 Java 語言爲載體的 GraphQL 的話,一大部分搜索結果都是介紹使用 graphql-java 來搭建查詢服務,而咱們的目的是利用 GraphQL 來獲取想要的數據,並不是本身搭建一個查詢服務,所以若是一開始就選錯了工具,就會致使後面的方向都是錯誤的。 以 LeetCode 第一題 1.Two Sum 爲例,獲取其後端發送過來的數據。利用 F12 功能調出以下界面,選 Network git
找到 graphql 文件(有好多 graphql 文件,能夠依次點擊查找本身想要的那個,這裏找到包含有題目信息的),從 preview 中咱們能夠看到 data 返回了題目相關的信息 那麼,如何構造 GraphQL Query 來獲取信息呢?從 Header 中的 Request Payload 中咱們能夠看到一個query
的字段,這是咱們要構造的 GraphQL Query 的一個重要信息。
咱們並不一開始就用代碼來獲取題目信息,而是先利用 Postman 來看看如何獲取題目信息。右鍵 Network 下的 graphql 文件—>Copy—>Copy as cURL(bash),以下圖所示:
以後,打開 Postman—>左上角Import—>Paste Raw Text粘貼,從 Body中能夠看到,構造好了的 GraphQL Query 與咱們在
Request Payload 中看到的
query
的字段相仿(由於有一點須要更改的細節)
固然,若是不想直接粘貼複製的 cURL,那麼咱們能夠本身在 Postman 中寫 Header 和 Body,須要注意的是這邊的
Content-Type
是
application/graphql
,Body 中的 GraphQL 構造,參照
Request Payload 中的
query
的字段來構造
獲取到的結果以下:
咱們在實際中,可能並不須要提供的全部信息,只想要某一部分,那麼只需更改
query
便可,這也是 GraphQL 的強大之處。好比咱們只想要題目的
content
信息,那麼其
query
則爲
query{question(titleSlug:"two-sum") {content}}
複製代碼
在上邊,已經利用 Postman 查詢到想要的數據了,而如今咱們要作的就是用代碼將上述操做展現出來。這邊,使用 OkHttp 來進行題目信息獲取。github
import okhttp3.*;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import java.io.IOException;
import java.util.Map;
import static java.lang.System.out;
public class Question {
public static void main(String... args) throws IOException {
String questionUrl = "https://leetcode.com/problems/two-sum/description/";
String graphqlUrl = "https://leetcode.com/graphql";
Connection.Response response = Jsoup.connect(questionUrl)
.method(Connection.Method.GET)
.execute();
Map<String,String>cookies = response.cookies();
for (Map.Entry<String,String>entry:cookies.entrySet()){
//out.println(entry.getKey() + ": " + entry.getValue());
}
String csrftoken = response.cookie("csrftoken");
String __cfduid = response.cookie("__cfduid");
OkHttpClient client = new OkHttpClient.Builder()
.followRedirects(false)
.followSslRedirects(false)
.build();
String postBody = "query{\n" +
" question(titleSlug:\"two-sum\") {\n" +
" content\n" +
" }\n" +
"}\n";
Request request = new Request.Builder()
.addHeader("Content-Type","application/graphql")
.addHeader("Referer",questionUrl)
.addHeader("Cookie","__cfduid=" + __cfduid + ";" + "csrftoken=" + csrftoken)
.addHeader("x-csrftoken",csrftoken)
.url(graphqlUrl)
.post(RequestBody.create(MediaType.parse("application/graphql; charset=utf-8"),postBody))
.build();
Response response1 = client.newCall(request).execute();
//out.println(response1.headers());
out.println(response1.body().string());
}
}
複製代碼
執行結果: 後端