如何使用GraphQL

本篇內(nèi)容介紹了“如何使用GraphQL”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

創(chuàng)新互聯(lián)公司是專業(yè)的昌吉網(wǎng)站建設(shè)公司,昌吉接單;提供網(wǎng)站設(shè)計(jì)制作、做網(wǎng)站,網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行昌吉網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!

GraphQL 自帶一組默認(rèn)標(biāo)量類型

  • Int:有符號 32 位整數(shù)。

  • Float:有符號雙精度浮點(diǎn)值。

  • String:UTF‐8 字符序列。

  • Boolean:true 或者 false。

  • ID:ID 標(biāo)量類型表示一個(gè)唯一標(biāo)識符,通常用以重新獲取對象或者作為緩存中的鍵。ID 類型使用和 String 一樣的方式序列化;然而將其定義為 ID 意味著并不需要人類可讀型。

如何使用GraphQL 代碼見gitee倉庫example

GraphQL操作類型
  • query 查詢

  • mutation 突變(理解為修改即可)

  • subscription 腳本

dgs自定義scalar
  • 實(shí)現(xiàn)接口Coercing

  • 添加注解@DgsScalar 示例

@DgsScalar(name = "Date")
public class DateCoercing implements Coercing<date, string> {
    private static final String PATTERN = "yyyy-MM-dd HH:mm:ss";

    @Override
    public String serialize(Object o) throws CoercingSerializeException {
        if (o instanceof Date &amp;&amp; Objects.nonNull(o)) {
            Date date = (Date)o;
            SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
            return sdf.format(date);
        }
        return null;
    }

    @Override
    public Date parseValue(Object o) throws CoercingParseValueException {
        if (o instanceof Date &amp;&amp; Objects.nonNull(o)) {
            return (Date)o;
        } else {
            throw new CoercingParseValueException("type is not date ");
        }
    }

    @Override
    public Date parseLiteral(Object o) throws CoercingParseLiteralException {
        if (o instanceof String &amp;&amp; Objects.nonNull(o)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN);
            LocalDateTime localDateTime = LocalDateTime.parse(o.toString(), formatter);
            return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        }
        return null;
    }
}

.graphql配置
type Show {
    title: String
    releaseYear: Int
    now: Date
}
scalar Date

如何使用GraphQL

postman訪問 如何使用GraphQL

別名

當(dāng)兩個(gè)查詢名相同時(shí)會引發(fā)沖突,這時(shí)可以使用別名獲取不同的結(jié)果

{
  zhangsan: hello(name: "張三"),
  lisi: hello(name: "李四")
}
輸出:
{
    "data": {
        "zhangsan": "hello:張三!",
        "lisi": "hello:李四!"
    }
}
片段(fragment)

片段主要用于將多個(gè)相同的字段進(jìn)行封裝,我們在實(shí)際開發(fā)中會遇到返回結(jié)果中很多字段名名相同,使用==fragment==在.graphql文件中定義

{
  golang: shows (title: "golang"){
    ...showFields
  },
  java: shows (title: "java"){
    ...showFields
  }
 }
 
 # 定義片段
fragment showFields on Show {
  title
  releaseYear
  now
}
輸出
{
    "data": {
         "golang": [
      {
        "title": "golang",
        "releaseYear": 2009,
        "now": "2021-03-08 13:46:43"
      }
    ],
    "java": [
      {
        "title": "java",
        "releaseYear": 1995,
        "now": "2021-03-08 13:46:43"
      }
    ]
    }
}

上面的on后面的類型必須在.graphql文件中有定義

多個(gè).graphqls的使用

自定義address.graphqls

# 多個(gè).graphqls定義需要使用這種方式
extend type Query {
    listAddress(id: Int): Address
}

extend type Mutation {
    addAddress(input: AddressInput): Int
}

type Address {
    id: Int
    street: String
    city: String
    country: String
    customerId: Int
}

input AddressInput {
    street: String
    city: String
    country: String
    customerId: Int
}

自定義的其他的schema文件查詢需要使用type extend 具體類型方式

Mutation

mutation用于修改對象,dgs使用注意事項(xiàng)

  • @DgsData中的parentType="Mutation",field需要與schema中的保持一致

  • 對象類型在java中定義的同時(shí),需要在對應(yīng)的.graphqls文件中定義,類型是input

input AddressInput {
    street: String
    city: String
    country: String
    customerId: Int
}
  • graphiql查詢頁面中的對象要放在變量中定義

查詢輸入框的示例
添加以對象格式傳參
mutation AddAddress($addAddress: AddressInput) {
  	addAddress(input: $addAddress)
}
修改的請求參數(shù)直接以參數(shù)形式傳遞
mutation UpdateAddress {
  updateAddress(id: 1, street: "鳳陽街道", city: "廣州") {
    id
    street
    city
    customerId
  }
}
query variables中的變量值
{
  "addAddress": {
  	"street": "江海街道", "city": "廣州", "country": "中國", "customerId": 1
	}
}

如何使用GraphQL 變更中的多個(gè)字段(Multiple fields in mutations) 一個(gè)變更也能包含多個(gè)字段,一如查詢。查詢和變更之間名稱之外的一個(gè)重要區(qū)別是:

  • 非變量定義方式

mutation AddAddress1 {
  addAddress(input: {    
    street: "昌崗街道",
    city: "廣州",
    country: "中國",
    customerId: 1
  
  })   
}
![](https://gitee.com/sharehappy/figurebed/raw/master/md/img/2021/04/20210421183524.png)

查詢字段時(shí),是并行執(zhí)行,而變更字段時(shí),是線性執(zhí)行,一個(gè)接著一個(gè)。

操作名稱

上面我們主要是查詢,省略了query關(guān)鍵字和查詢名稱,生產(chǎn)中加上這些可以減少代碼歧義

query Abc {
  hello(name: "zhangsan")
}

mutation AddAddress($addAddress: AddressInput) {
  	addAddress(input: $addAddress)
}

mutation UpdateAddress {
  updateAddress(id: 1, street: "鳳陽街道", city: "廣州") {
    id
    street
    city
    customerId
  }
}
  1. 操作類型可以是 query、mutation 或 subscription,描述你打算做什么類型的操作。操作類型是必需的,除非你使用查詢簡寫語法,在這種情況下,你無法為操作提供名稱或變量定義。

  2. 操作名稱是你的操作的有意義和明確的名稱。它僅在有多個(gè)操作的文檔中是必需的,但我們鼓勵(lì)使用它,因?yàn)樗鼘τ谡{(diào)試和服務(wù)器端日志記錄非常有用。 當(dāng)在你的網(wǎng)絡(luò)或是 GraphQL 服務(wù)器的日志中出現(xiàn)問題時(shí),通過名稱來從你的代碼庫中找到一個(gè)查詢比嘗試去破譯內(nèi)容更加容易。 就把它想成你喜歡的程序語言中的函數(shù)名

變量(Variables)

前面都是基于多個(gè)參數(shù)查詢,為了擴(kuò)展減少修改代碼,我們通常將多個(gè)參數(shù)封裝成對象。GraphQL 擁有一級方法將動(dòng)態(tài)值提取到查詢之外,然后作為分離的字典傳進(jìn)去。這些動(dòng)態(tài)值即稱為變量

使用變量之前,我們得做三件事:

  • 使用 $variableName 替代查詢中的靜態(tài)值。

  • 聲明 $variableName 為查詢接受的變量之一。

  • 將 variableName: value 通過傳輸專用(通常是 JSON)的分離的變量字典中。

示例:

添加地址的變量
mutation AddAddress($addAddress: AddressInput) {
  	addAddress(input: $addAddress)
}
輸入框中的實(shí)際變量值
{
  "addAddress": {
  	"street": "江海街道", "city": "廣州", "country": "中國", "customerId": 1
	}
}
變量定義(Variable definitions)

變量定義看上去像是上述查詢中的 ($addAddress: AddressInput)。其工作方式跟類型語言中函數(shù)的參數(shù)定義一樣。它以列出所有變量,<font color="red">變量前綴必須為 $</font>,后跟其類型,本例中為 AddressInput。

所有聲明的變量都必須是標(biāo)量、枚舉型或者輸入對象類型。所以如果想要傳遞一個(gè)復(fù)雜對象到一個(gè)字段上,你必須知道服務(wù)器上其匹配的類型。可以從Schema頁面了解更多關(guān)于輸入對象類型的信息。

變量定義可以是可選的或者必要的。上例中,AddressInput 后并沒有 <font color="red">!</font>,因此其是可選的。但是如果你傳遞變量的字段要求非空參數(shù),那變量一定是必要的。

默認(rèn)變量(Default variables)

可以通過在查詢中的類型定義后面附帶默認(rèn)值的方式,將默認(rèn)值賦給變量。

query HeroNameAndFriends($episode: Episode = "JEDI") {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}

當(dāng)所有變量都有默認(rèn)值的時(shí)候,你可以不傳變量直接調(diào)用查詢。如果任何變量作為變量字典的部分傳遞了,它將覆蓋其默認(rèn)值。

指令(Directives)

指令可以用來動(dòng)態(tài)控制是否顯示某個(gè)字段,有些場景下我們可能需要使用對象的A屬性,一些場景不需要A屬性,可以使用指令控制

query movies($withDirector: Boolean!) {
  movies {
    title
    director @skip(if: $withDirector)
    actor @include (if: $withDirector) {
    	name
    } 
    actor {      
      home
    }
    
  }
}
變量
{
  "withDirector": false
}

變量值為true 如何使用GraphQL 變量值為false 如何使用GraphQL 對于字段操作可以使用@skip,如果對對象中的某些屬性操作可以使用@include

我們用了 GraphQL 中一種稱作指令的新特性。一個(gè)指令可以附著在字段或者片段包含的字段上,然后以任何服務(wù)端期待的方式來改變查詢的執(zhí)行。GraphQL 的核心規(guī)范包含兩個(gè)指令,其必須被任何規(guī)范兼容的 GraphQL 服務(wù)器實(shí)現(xiàn)所支持:

  • @include(if: Boolean) 僅在參數(shù)為 true 時(shí),包含此字段。

  • @skip(if: Boolean) 如果參數(shù)為 true,跳過此字段。 指令在你不得不通過字符串操作來增減查詢的字段時(shí)解救你。服務(wù)端實(shí)現(xiàn)也可以定義新的指令來添加新的特性。

內(nèi)聯(lián)片段(inline fragment)

如果你查詢的字段返回的是接口或者聯(lián)合類型,那么你可能需要使用內(nèi)聯(lián)片段來取出下層具體類型的數(shù)據(jù):

/**
 * 根據(jù)枚舉類型不同獲取不同類型的結(jié)果,graphql中使用的是內(nèi)聯(lián)片段
 * @param filter
 * @return
 */
@DgsData(parentType = "Query", field = "movieFilter")
public List<movie> movieFilter(@InputArgument("filter")MovieType filter) {
    return initMovie(filter);
}
private List<movie> initMovie(MovieType movieType) {
    List<movie> movies = new ArrayList&lt;&gt;();
    Actor actor1 = new Actor();
    actor1.setHome("廣州");
    actor1.setName("張三");
    Actor actor2 = new Actor();
    actor2.setHome("上海");
    actor2.setName("李四");
    if (movieType.equals(MovieType.Action) || movieType.equals(MovieType.All)) {
        movies.add(new ActionMovie("Crouching Tiger", null, 0, actor1));
        movies.add(new ActionMovie("Black hawk down", null, 10, actor1));
    }
    if (movieType.equals(MovieType.Scary) || movieType.equals(MovieType.All)) {
        movies.add(new ScaryMovie("American Horror Story", null, true, 10, actor2));
        movies.add(new ScaryMovie("Love Death + Robots", null, false, 4, actor2));
    }
    return movies;
}

schema

# 定義枚舉
enum MovieType {
    Scary
    Action
    All
}

type Query {
    movieFilter(filter: MovieType): [Movie]
}

graphiql查詢

如何使用GraphQL

元字段(Meta fields)

某些情況下,你并不知道你將從 GraphQL 服務(wù)獲得什么類型,這時(shí)候你就需要一些方法在客戶端來決定如何處理這些數(shù)據(jù)。GraphQL 允許你在查詢的任何位置請求 __typename,一個(gè)元字段,以獲得那個(gè)位置的對象類型名稱 如何使用GraphQL


schema和類型

枚舉

枚舉類型是一種特殊的標(biāo)量,它限制在一個(gè)特殊的可選值集合內(nèi)。

  • 驗(yàn)證這個(gè)類型的任何參數(shù)是可選值的的某一個(gè)

  • 與類型系統(tǒng)溝通,一個(gè)字段總是一個(gè)有限值集合的其中一個(gè)值。

enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}
接口(Interfaces)

跟許多類型系統(tǒng)一樣,GraphQL 支持接口。一個(gè)接口是一個(gè)抽象類型,它包含某些字段,而對象類型必須包含這些字段,才能算實(shí)現(xiàn)了這個(gè)接口。

interface Movie {
    title: String
    director: String
    actor: Actor
}

type ScaryMovie implements Movie {
    title: String
    director: String
    gory: Boolean
    scareFactor: Int
    actor: Actor
}

type ActionMovie implements Movie {
    title: String
    director: String
    nrOfExplosions: Int
    actor: Actor
}
聯(lián)合類型(union)

聯(lián)合類型和接口十分相似,但是它并不指定類型之間的任何共同字段。

union MovieResult = ScaryMovie | ActionMovie

在我們的schema中,任何返回一個(gè) MovieResult 類型的地方,都可能得到一個(gè) ScaryMovie、ActionMovie p。注意,聯(lián)合類型的成員需要是具體對象類型;你不能使用接口或者其他聯(lián)合類型來創(chuàng)造一個(gè)聯(lián)合類型。

這時(shí)候,如果你需要查詢一個(gè)返回 SearchResult 聯(lián)合類型的字段,那么你得使用條件片段才能查詢?nèi)我庾侄巍?/p>

schema
# union 聯(lián)合類型
movieFilter(filter: MovieType): [MovieResult]

查詢
query Movie($filter: MovieType!) {
  movieFilter(filter: $filter) {
    __typename
    ... on ScaryMovie {
      scareFactor
      title
      director
      actor {
        name
        home
      }
    }
    ... on ActionMovie {
      nrOfExplosions
      title
      director
      actor {
        name
        home
      }
    }
  }
}

聯(lián)合類型可以理解為根據(jù)不同的參數(shù)返回不同類型數(shù)據(jù)的組合,與接口稍有不同,可以對比schema和查詢結(jié)果

graph-java中的Instrumentation

實(shí)現(xiàn)instrumentation接口或者繼承SimpleInstrumentation可以進(jìn)行日志、權(quán)限處理,類似spring中的aop

@Configuration
public class GraphQLConfig {

    @Bean
    @Primary
    public Instrumentation instrumentation() {
        Instrumentation instrumentation = new ChainedInstrumentation(new TracingInstrumentation(), new CustomInstrumentation());
        return instrumentation;
    }

}

加@Primary是由于DgsAutoConfiguration.kt中有對應(yīng)的bean注入了 如何使用GraphQL

分頁

graphql中的分頁只能知道是否還有下一頁數(shù)據(jù),不能獲取總量和當(dāng)前頁,這種結(jié)果可以結(jié)合dataLoader緩存根據(jù)條件查詢滾動(dòng)翻頁 schema.graphqls

### 分頁相關(guān)
type AddressConnection {
    edges: [AddressEdge]
    pageInfo: PageInfo
}

type AddressEdge {
    cursor: String
    node: Address
}

type PageInfo {
    hasPreviousPage: Boolean!
    hasNextPage: Boolean!
}
    /**
     * 分頁查詢
     * @param environment
     * @param customerId 查詢條件
     * @param first 后面的的多少條結(jié)果
     * @param after 每條數(shù)據(jù)都有游標(biāo),當(dāng)前游標(biāo)后的幾條數(shù)據(jù) 與first配合使用,null則從第一條開始
     * @param last 前面多少條數(shù)據(jù)
     * @param before  當(dāng)前游標(biāo)前的幾條數(shù)據(jù) 與last配合使用,null則從最后一條開始
     * @return
     */
    @DgsData(parentType = "Query", field = "pageAddress")
    public Connection<address> pageAddress(DataFetchingEnvironment environment, @InputArgument("customerId")Integer customerId, @InputArgument("first")Integer first,
                                           @InputArgument("after")String after, @InputArgument("last")Integer last, @InputArgument("before")String before) {
        List<address> addressList = addressMapper.selectList(Wrappers.<address>lambdaQuery().eq(Address::getCustomerId, customerId));
        return new SimpleListConnection(addressList).get(environment);
    }

如何使用GraphQL

如何使用GraphQL

“如何使用GraphQL”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

新聞標(biāo)題:如何使用GraphQL
當(dāng)前路徑:http://muchs.cn/article42/iehiec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、做網(wǎng)站、手機(jī)網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈App開發(fā)、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名