GraphQL sering disajikan sebagai cara revolusioner untuk merancang API web dibandingkan dengan REST. Namun, jika Anda melihat lebih dekat pada teknologi ini, Anda akan melihat bahwa ada banyak perbedaan di antara mereka. GraphQL adalah solusi yang relatif baru, yang sumbernya dibuka untuk komunitas Facebook pada tahun 2015. Saat ini, REST masih merupakan paradigma paling populer yang digunakan untuk menyediakan API dan interoperabilitas antar layanan mikro. Apakah GraphQL dapat menyalip REST di masa depan? Mari kita lihat bagaimana interaksi microservice terjadi melalui GraphQL API menggunakan Spring Boot dan pustaka
GQL .
Mari kita mulai dengan contoh arsitektur sistem kita. Misalkan kita memiliki tiga layanan Microsoft yang berkomunikasi satu sama lain melalui URL yang diterima dari aplikasi Spring Cloud Eureka.

Mengaktifkan Dukungan GraphQL di Spring Boot
Kami dapat dengan mudah mengaktifkan dukungan untuk GraphQL di sisi server aplikasi Spring Boot menggunakan permulaan. Setelah menambahkan graphql-spring-boot-starter, servlet GraphQL akan secara otomatis tersedia di / graphql. Kita dapat mengganti jalur default ini dengan menentukan properti graphql.servlet.mapping dalam file application.yml. Kami juga menyertakan GraphiQL, IDE berbasis browser untuk menulis, memvalidasi, dan menguji permintaan GraphQL dan perpustakaan GraphQL Java Tools, yang berisi komponen yang berguna untuk membuat kueri dan mutasi. Berkat pustaka ini, semua file di classpath dengan ekstensi .graphqls akan digunakan untuk membuat definisi skema.
compile('com.graphql-java:graphql-spring-boot-starter:5.0.2') compile('com.graphql-java:graphiql-spring-boot-starter:5.0.2') compile('com.graphql-java:graphql-java-tools:5.2.3')
Deskripsi Skema GrpahQL
Setiap uraian skema berisi deklarasi jenis, hubungan di antara mereka, dan banyak operasi yang menyertakan kueri untuk mencari objek dan mutasi untuk membuat, memperbarui, atau menghapus data. Kami biasanya mulai dengan mendefinisikan tipe yang bertanggung jawab untuk domain dari objek yang dijelaskan. Anda dapat mengindikasikan apakah bidang tersebut harus diisi dengan
!
karakter atau jika array -
[β¦]
. Deskripsi harus berisi tipe yang dideklarasikan atau referensi ke tipe lain yang tersedia dalam spesifikasi.
type Employee { id: ID! organizationId: Int! departmentId: Int! name: String! age: Int! position: String! salary: Int! }
Bagian selanjutnya dari definisi skema berisi deklarasi kueri dan mutasi. Sebagian besar kueri mengembalikan daftar objek yang ditandai sebagai [Karyawan] dalam skema. Di dalam tipe EmployeeQueries, kami mendeklarasikan semua metode pencarian, sedangkan dalam tipe EmployeeMutations, metode untuk menambah, memperbarui, dan menghapus karyawan. Jika Anda melewatkan seluruh objek ke suatu metode, Anda harus mendeklarasikannya sebagai tipe input.
schema { query: EmployeeQueries mutation: EmployeeMutations } type EmployeeQueries { employees: [Employee] employee(id: ID!): Employee! employeesByOrganization(organizationId: Int!): [Employee] employeesByDepartment(departmentId: Int!): [Employee] } type EmployeeMutations { newEmployee(employee: EmployeeInput!): Employee deleteEmployee(id: ID!) : Boolean updateEmployee(id: ID!, employee: EmployeeInput!): Employee } input EmployeeInput { organizationId: Int departmentId: Int name: String age: Int position: String salary: Int }
Menerapkan Pertanyaan dan Mutasi
Berkat konfigurasi otomatis GraphQL Java Tools dan Spring Boot GraphQL, kami tidak perlu melakukan banyak upaya untuk mengimplementasikan kueri dan mutasi dalam aplikasi kami. Kacang EmployeesQuery harus mengimplementasikan antarmuka GraphQLQueryResolver. Berdasarkan ini, Spring akan dapat secara otomatis menemukan dan memanggil metode yang benar sebagai respons terhadap salah satu permintaan GraphQL yang telah dideklarasikan di dalam skema. Berikut adalah kelas yang berisi implementasi dari respons terhadap pertanyaan:
@Component public class EmployeeQueries implements GraphQLQueryResolver { private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeQueries.class); @Autowired EmployeeRepository repository; public List employees() { LOGGER.info("Employees find"); return repository.findAll(); } public List employeesByOrganization(Long organizationId) { LOGGER.info("Employees find: organizationId={}", organizationId); return repository.findByOrganization(organizationId); } public List employeesByDepartment(Long departmentId) { LOGGER.info("Employees find: departmentId={}", departmentId); return repository.findByDepartment(departmentId); } public Employee employee(Long id) { LOGGER.info("Employee find: id={}", id); return repository.findById(id); } }
Jika Anda ingin memanggil, misalnya, metode karyawan (Long id), tulis kueri berikut. Untuk mengujinya di aplikasi Anda, gunakan GraphiQL, yang tersedia di / graphiql.

Kacang yang bertanggung jawab untuk mengimplementasikan metode mutasi perlu mengimplementasikan antarmuka GraphQLMutationResolver. Terlepas dari nama EmployeeInput, kami terus menggunakan objek domain Karyawan yang sama yang dikembalikan oleh permintaan.
@Component public class EmployeeMutations implements GraphQLMutationResolver { private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeQueries.class); @Autowired EmployeeRepository repository; public Employee newEmployee(Employee employee) { LOGGER.info("Employee add: employee={}", employee); return repository.add(employee); } public boolean deleteEmployee(Long id) { LOGGER.info("Employee delete: id={}", id); return repository.delete(id); } public Employee updateEmployee(Long id, Employee employee) { LOGGER.info("Employee update: id={}, employee={}", id, employee); return repository.update(id, employee); } }
Dan di sini kita menggunakan GraphiQL untuk menguji mutasi. Berikut adalah perintah yang menambahkan karyawan baru dan menerima respons dengan id dan nama karyawan.
Mengenai hal ini, saya menghentikan sebentar terjemahan artikel ini dan menulis "penyimpangan liris" saya, tetapi sebenarnya mengganti deskripsi bagian layanan-mikro melalui Klien Apollo, untuk berinteraksi melalui perpustakaan GQL dan Unirest - perpustakaan untuk mengeksekusi permintaan HTTP.
Klien GraphQL di Groovy.
Untuk membuat permintaan GraphQL di microservice servis-departemen, saya akan menggunakan
pembuat Query :
String queryString = DSL.buildQuery { query('employeesByDepartment', [departmentId: departmentId]) { returns { id name position salary } } }
Konstruksi pada DSL GQL ini menciptakan kueri bentuk:
{ employeesByDepartment (departmentId: 1) { id name position salary } }
Dan, lebih lanjut, saya akan melakukan permintaan HTTP di alamat yang diteruskan ke metode.
Kami akan mencari tahu bagaimana alamat permintaan dibentuk lebih lanjut.
(Unirest.post(serverUrl) .body(JsonOutput.toJson([query: queryString])) .asJson() .body.jsonObject['data']['employeesByDepartment'] as List) .collect { JsonUtils.jsonToData(it.toString(), Employee.class) }
Setelah menerima respons, kami mengubahnya dari JSONObject ke tampilan daftar Karyawan.
Klien GrpahQL untuk layanan karyawan mikro
Pertimbangkan penerapan karyawan layanan mikro. Dalam contoh ini, saya menggunakan klien Eureka secara langsung. eurekaClient membuat semua instance layanan yang berjalan terdaftar sebagai layanan karyawan. Kemudian ia secara acak memilih beberapa instance dari yang terdaftar (2). Selanjutnya, ia mengambil nomor port-nya dan membentuk alamat permintaan (3) dan meneruskannya ke objek EmployeeGQL yang merupakan klien GraphQL di Groovy dan yang dijelaskan pada paragraf sebelumnya.
@Component public class EmployeeClient { private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeClient.class); private static final String SERVICE_NAME = "EMPLOYEE-SERVICE"; private static final String SERVER_URL = "http://localhost:%d/graphql"; Random r = new Random(); @Autowired private EurekaClient discoveryClient;
Selanjutnya, saya βmeneruskanβ kata itu kepada penulis lagi, atau lebih tepatnya saya melanjutkan terjemahan artikelnya.Akhirnya, EmployeeClient disuntikkan ke dalam kelas yang menanggapi permintaan DepartmentQueries dan digunakan di dalam departemenByOrganizationWithEmployees permintaan.
public List<Department> departmentsByOrganizationWithEmployees(Long organizationId) { LOGGER.info("Departments find: organizationId={}", organizationId); List<Department> departments = repository.findByOrganization(organizationId); for (int i = 0; i < departments.size(); i++) { departments.get(i).setEmployees(employeeClient.findByDepartment(departments.get(i).getId())); } return departments; }
Sebelum membuat permintaan yang diperlukan, kita harus melihat diagram yang dibuat untuk layanan departemen. Setiap objek Departemen dapat berisi daftar karyawan yang ditugaskan, dan kami juga mendefinisikan jenis Karyawan yang dirujuk oleh jenis Departemen.
schema { query: DepartmentQueries mutation: DepartmentMutations } type DepartmentQueries { departments: [Department] department(id: ID!): Department! departmentsByOrganization(organizationId: Int!): [Department] departmentsByOrganizationWithEmployees(organizationId: Int!): [Department] } type DepartmentMutations { newDepartment(department: DepartmentInput!): Department deleteDepartment(id: ID!) : Boolean updateDepartment(id: ID!, department: DepartmentInput!): Department } input DepartmentInput { organizationId: Int! name: String! } type Department { id: ID! organizationId: Int! name: String! employees: [Employee] } type Employee { id: ID! name: String! position: String! salary: Int! }
Sekarang kita dapat memanggil kueri pengujian kami dengan daftar bidang yang diperlukan menggunakan GraphiQL. Aplikasi departemen-layanan tersedia secara default pada port 8091, yaitu, kita dapat melihatnya di
http: // localhost: 8091 / graphiqlKesimpulan
Mungkin GraphQL dapat menjadi alternatif yang menarik untuk API REST standar. Namun, kita tidak boleh menganggapnya sebagai pengganti REST. Ada beberapa kasus di mana GraphQL mungkin menjadi pilihan terbaik, tetapi di mana REST adalah pilihan terbaik. Jika klien Anda tidak perlu memiliki semua bidang dikembalikan oleh sisi server, dan terlebih lagi Anda memiliki banyak klien dengan persyaratan berbeda untuk satu titik masuk, maka GraphQL adalah pilihan yang baik. Jika Anda melihat apa yang ada di komunitas microservice, Anda dapat melihat bahwa sekarang tidak ada solusi berbasis Java yang memungkinkan Anda untuk menggunakan GraphQL bersama-sama dengan penemuan layanan, penyeimbang, atau gateway API di luar kotak. Pada artikel ini, saya menunjukkan contoh menggunakan GQL dan Unirest untuk membuat klien GraphQL dengan Spring Cloud Eureka untuk komunikasi layanan mikro. Contoh kode untuk penulis artikel dalam bahasa Inggris di GitHub
github.com/piomin/sample-graphql-microservices.git .
Contoh saya ketika dengan perpustakaan GQL :
github.com/lynx-r/sample-graphql-microservices