рдЧреНрд░рд╛рдлрдХреЙрд▓ рдХреЛ рдЕрдХреНрд╕рд░ REST рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╡реЗрдм APIs рдХреЛ рдбрд┐рдЬрд╛рдЗрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреНрд░рд╛рдВрддрд┐рдХрд╛рд░реА рддрд░реАрдХреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдЧрд░ рдЖрдк рдЗрди рддрдХрдиреАрдХреЛрдВ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ, рддреЛ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдЙрдирдХреЗ рдмреАрдЪ рдмрд╣реБрдд рдЕрдВрддрд░ рд╣реИрдВред рдЧреНрд░рд╛рдлрдХреЙрд▓ рдПрдХ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдирдпрд╛ рд╕рдорд╛рдзрд╛рди рд╣реИ, рдЬрд┐рд╕рдХреЗ рд╕реНрд░реЛрдд 2015 рдореЗрдВ рдлреЗрд╕рдмреБрдХ рд╕рдореБрджрд╛рдп рдХреЗ рд▓рд┐рдП рдЦреЛрд▓реЗ рдЧрдП рдереЗред рдЖрдЬ, REST рдЕрднреА рднреА рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рдкреНрд░рддрд┐рдорд╛рди рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдЗрдХреНрд░реЛрд╕рд┐рд╕реНрдЯрд░реНрд╕ рдХреЗ рдмреАрдЪ рдПрдкреАрдЖрдИ рдФрд░ рдЗрдВрдЯрд░рдСрдкрд░реЗрдмрд┐рд▓рд┐рдЯреА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдХреНрдпрд╛ рдЧреНрд░рд╛рдлрдХрд╛рдЗрд▓реНрдб рднрд╡рд┐рд╖реНрдп рдореЗрдВ REST рд╕реЗ рдЖрдЧреЗ рдирд┐рдХрд▓ рдкрд╛рдПрдЧреА? рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдФрд░ рдЬреАрдХреНрдпреВрдПрд▓ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдЧреНрд░рд╛рдлрдХреЙрдЗрди рдПрдкреАрдЖрдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреИрд╕реЗ рд╣реЛрддрд╛ рд╣реИред
рдЖрдЗрдП рдЕрдкрдиреЗ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рддреАрди рдорд╛рдЗрдХреНрд░реЛрд╕реЗрд░реЗрд╕ рд╣реИрдВ рдЬреЛ рд╕реНрдкреНрд░рд┐рдВрдЧ рдХреНрд▓рд╛рдЙрдб рдпреВрд░реЗрдХрд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдпреВрдЖрд░рдПрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ-рджреВрд╕рд░реЗ рдХреЗ рд╕рд╛рде рд╕рдВрд╡рд╛рдж рдХрд░рддреЗ рд╣реИрдВред

рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдореЗрдВ рдЧреНрд░рд╛рдлрдХреЙрд▓ рд╕рдкреЛрд░реНрдЯ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдирд╛
рд╣рдо рдЖрд╕рд╛рдиреА рд╕реЗ рд╢реБрд░реБрдЖрдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рдЧреНрд░рд╛рдлрдХреЙрд▓ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рд╕рдХреНрд╖рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЧреНрд░рд╛рдлрдХрд▓-рд╕реНрдкреНрд░рд┐рдВрдЧ-рдмреВрдЯ-рд╕реНрдЯрд╛рд░реНрдЯрд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдмрд╛рдж, рдЧреНрд░рд╛рдлрдХреНрдпреВрдПрд▓ рд╕рд░реНрд╡рд▓реЗрдЯ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ / рдЧреНрд░рд╛рдлрдХрд▓ рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧрд╛ред рд╣рдо application.yml рдлрд╝рд╛рдЗрд▓ рдореЗрдВ graphql.servlet.mapping рд╕рдВрдкрддреНрддрд┐ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдХреЗ рдЗрд╕ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкрде рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдЧреНрд░рд╛рдлрд╝рд┐рдХреНрд╡рд┐рдХ, рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░-рдЖрдзрд╛рд░рд┐рдд рдЖрдИрдбреАрдИ рднреА рд╢рд╛рдорд┐рд▓ рдХрд░рддреЗ рд╣реИрдВ, рдЧреНрд░рд╛рдлрдХрд╛рдЗрдХ рдкреНрд░рд╢реНрдиреЛрдВ рдФрд░ рдЧреНрд░рд╛рдлрдХреНрд▓рд╛рдЗрди рдЬрд╛рд╡рд╛ рдЯреВрд▓реНрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдХреНрд╡реЗрд░реАрдЬрд╝ рдФрд░ рдореНрдпреВрдЯреЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рдШрдЯрдХ рд╣реЛрддреЗ рд╣реИрдВред рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд╕рд╛рде рд╡рд░реНрдЧрдкрде рдХреА рд╕рднреА рдлрд╛рдЗрд▓реЗрдВ .graphqls рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕реНрдХреАрдорд╛ рдкрд░рд┐рднрд╛рд╖рд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
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')
рдЧреНрд░рд╛рдкрд╛рд╣рд┐рд▓реНрдХрд╛ рд╕реНрдХреАрдорд╛ рдХрд╛ рд╡рд┐рд╡рд░рдг
рдпреЛрдЬрдирд╛ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рд╡рд░рдг рдореЗрдВ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдШреЛрд╖рдгрд╛, рдЙрдирдХреЗ рдмреАрдЪ рд╕рдВрдмрдВрдз, рдФрд░ рдХрдИ рдСрдкрд░реЗрд╢рди рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬреЛ рдбреЗрдЯрд╛ рдмрдирд╛рдиреЗ, рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдпрд╛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдСрдмреНрдЬреЗрдХреНрдЯ рдФрд░ рдореНрдпреВрдЯреЗрд╢рди рдХреА рдЦреЛрдЬ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд╡реЗрд░реА рд╢рд╛рдорд┐рд▓ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдЖрдорддреМрд░ рдкрд░ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдХреЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рд╡рд░реНрдгрд┐рдд рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдбреЛрдореЗрди рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдЖрдк рдЗрдВрдЧрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдХреНрд╖реЗрддреНрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
!
рдЪрд░рд┐рддреНрд░ рдпрд╛ рдЕрдЧрд░ рдпрд╣ рдПрдХ рд╕рд░рдгреА рд╣реИ -
[тАж]
ред рд╡рд┐рд╡рд░рдг рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ рдпрд╛ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдВрджрд░реНрдн рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
type Employee { id: ID! organizationId: Int! departmentId: Int! name: String! age: Int! position: String! salary: Int! }
рд╕реНрдХреАрдорд╛ рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ рдкреНрд░рд╢реНрдиреЛрдВ рдФрд░ рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди рдХреА рдШреЛрд╖рдгрд╛рдПрдБ рд╣реИрдВред рдЕрдзрд┐рдХрд╛рдВрд╢ рдкреНрд░рд╢реНрди рд╕реНрдХреАрдорд╛ рдореЗрдВ [рдХрд░реНрдордЪрд╛рд░реА] рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕реВрдЪреА рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред EmployeeQueries рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдВрджрд░, рд╣рдо рд╕рднреА рдЦреЛрдЬ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЬрдмрдХрд┐ EmployeeMutations рдкреНрд░рдХрд╛рд░ рдореЗрдВ, рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ, рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдФрд░ рд╣рдЯрд╛рдиреЗ рдХреЗ рддрд░реАрдХреЗред рдпрджрд┐ рдЖрдк рдХрд┐рд╕реА рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рд╕рдВрдкреВрд░реНрдг рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЗрд╕реЗ рдЗрдирдкреБрдЯ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
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 }
рдХреНрд╡реЗрд░реА рдФрд░ рдореНрдпреВрдЯреЗрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛
рдЧреНрд░рд╛рдлрдХреНрд▓рд╛рдЗрди рдЬрд╛рд╡рд╛ рдЯреВрд▓реНрд╕ рдФрд░ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдЧреНрд░рд╛рдлрдХреЙрдЗрди рдХреЗ рдСрдЯреЛ-рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рд╣рдореЗрдВ рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдореЗрдВ рдкреНрд░рд╢реНрдиреЛрдВ рдФрд░ рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред EmployeesQuery рдмреАрди рдХреЛ рдЧреНрд░рд╛рдлрдХрд╛рдЗрдХреНрдпреВрд▓рд╛рдЗрдЬреЗрд╢рди рдЗрдВрд╕реЙрд▓рд╡рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕реНрдХреАрдорд╛ рдХреЗ рдЕрдВрджрд░ рдШреЛрд╖рд┐рдд рдХрд┐рдП рдЧрдП рдЧреНрд░рд╛рдлрд╝рдХреЙрд▓ рдкреНрд░рд╢реНрдиреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХреЗ рдЬрд╡рд╛рдм рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕рд╣реА рд╡рд┐рдзрд┐ рдХреЛ рдЦреЛрдЬрдиреЗ рдФрд░ рдХреЙрд▓ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛ред рдпрд╣рд╛рдВ рдкреНрд░рд╢реНрдиреЛрдВ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рд╡рд░реНрдЧ рд╣реИ:
@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); } }
рдпрджрд┐ рдЖрдк рдХреЙрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд░реНрдордЪрд╛рд░реА (рд▓рдВрдмреА рдЖрдИрдбреА) рд╡рд┐рдзрд┐, рддреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рд╢реНрди рд▓рд┐рдЦреЗрдВред рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЧреНрд░рд╛рдлрд┐рдХреНрд╡реЗрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдЬреЛ рдХрд┐ / рдЧреНрд░реЗрдлрд┐рдХ рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред

рдореНрдпреВрдЯреЗрд╢рди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╝рд┐рдореНрдореЗрджрд╛рд░ рдмреАрди рдХреЛ рдЧреНрд░рд╛рдлрд╝рдХреНрдпреВрд▓рдореБрдЯреЗрд╢рдиResolver рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред EmployeeInput рдирд╛рдо рдХреЗ рдмрд╛рд╡рдЬреВрдж, рд╣рдо рдЙрд╕реА рдХрд░реНрдордЪрд╛рд░реА рдбреЛрдореЗрди рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВ рдЬреЛ рдЕрдиреБрд░реЛрдз рджреНрд╡рд╛рд░рд╛ рд╡рд╛рдкрд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
@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); } }
рдФрд░ рдпрд╣рд╛рдБ рд╣рдо рдореНрдпреВрдЯреЗрд╢рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреНрд░рд╛рдлрд┐рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рдПрдХ рдХрдорд╛рдВрдб рд╣реИ рдЬреЛ рдПрдХ рдирдпрд╛ рдХрд░реНрдордЪрд╛рд░реА рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдФрд░ рдХрд░реНрдордЪрд╛рд░реА рдХреА рдЖрдИрдбреА рдФрд░ рдирд╛рдо рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред
рдЗрд╕ рдкрд░, рдореИрдВ рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдЕрдиреБрд╡рд╛рдж рдХреЛ рд░реЛрдХ рджреЗрддрд╛ рд╣реВрдВ рдФрд░ рдЕрдкрдирд╛ "рдЧреАрддрд╛рддреНрдордХ рд╡рд┐рд╖рдпрд╛рдВрддрд░" рд▓рд┐рдЦрддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдкреЛрд▓реЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕ рднрд╛рдЧ рдХреЗ рд╡рд░реНрдгрди рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ, рддрд╛рдХрд┐ рдЬреАрдПрд╕рдПрд▓ рдФрд░ рдпреВрдиреАрд╕реНрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП - HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреБрд╕реНрддрдХрд╛рд▓рдпред
Groovy рдкрд░ GraphQL рдЧреНрд░рд╛рд╣рдХред
рд╡рд┐рднрд╛рдЧ-рд╕реЗрд╡рд╛рд░рдд рдорд╛рдЗрдХреНрд░реЛрд╕рд┐рд╕реНрдЯ рд╕реЗрд╡рд╛ рдореЗрдВ рдЧреНрд░рд╛рдлрдХреЙрд▓ рдХреНрд╡реЗрд╢реНрдЪрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ
рдХреНрд╡реЗрд░реА рдмрд┐рд▓реНрдбрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛:
String queryString = DSL.buildQuery { query('employeesByDepartment', [departmentId: departmentId]) { returns { id name position salary } } }
DSL GQL рдкрд░ рдпрд╣ рдирд┐рд░реНрдорд╛рдг рдкреНрд░рдкрддреНрд░ рдХреА рдПрдХ рдХреНрд╡реЗрд░реА рдмрдирд╛рддрд╛ рд╣реИ:
{ employeesByDepartment (departmentId: 1) { id name position salary } }
рдФрд░, рдЖрдЧреЗ, рдореИрдВ рд╡рд┐рдзрд┐ рд╕реЗ рдкрд╛рд░рд┐рдд рдкрддреЗ рдкрд░ рдПрдХ HTTP рдЕрдиреБрд░реЛрдз рдХрд░реВрдВрдЧрд╛ред
рд╣рдо рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдПрдВрдЧреЗ рдХрд┐ рдЕрдиреБрд░реЛрдз рдХрд╛ рдкрддрд╛ рдЖрдЧреЗ рдХреИрд╕реЗ рдмрдирддрд╛ рд╣реИред
(Unirest.post(serverUrl) .body(JsonOutput.toJson([query: queryString])) .asJson() .body.jsonObject['data']['employeesByDepartment'] as List) .collect { JsonUtils.jsonToData(it.toString(), Employee.class) }
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЗрд╕реЗ JSONObject рд╕реЗ рдХрд░реНрдордЪрд╛рд░реА рд╕реВрдЪреА рджреГрд╢реНрдп рдореЗрдВ рдмрджрд▓ рджреЗрддреЗ рд╣реИрдВред
рдХрд░реНрдордЪрд╛рд░реА microservice рдХреЗ рд▓рд┐рдП GrpahQL рдЧреНрд░рд╛рд╣рдХ
Microservice рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдореИрдВрдиреЗ рд╕реАрдзреЗ рдпреВрд░реЗрдХрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред eurekaClient рдХреЛ рдХрд░реНрдордЪрд╛рд░реА-рд╕реЗрд╡рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рд╕рднреА рд░рдирд┐рдВрдЧ рд╕рд░реНрд╡рд┐рд╕ рдЗрдВрд╕реНрдЯреЗрдВрд╕реЗрд╕ рдорд┐рд▓рддреЗ рд╣реИрдВред рдлрд┐рд░ рд╡рд╣ рдмреЗрддрд░рддреАрдм рдврдВрдЧ рд╕реЗ рдкрдВрдЬреАрдХреГрдд рд▓реЛрдЧреЛрдВ (2) рд╕реЗ рдХреБрдЫ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж, рдпрд╣ рдЕрдкрдирд╛ рдкреЛрд░реНрдЯ рдирдВрдмрд░ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдЕрдиреБрд░реЛрдз рдкрддрд╛ (3) рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ EmployeeGQL рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдкрд╛рд╕ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдЧреНрд░реВрд╡реА рдкрд░ рдЧреНрд░рд╛рдлрдХреНрдпреВрдПрд▓ рдХреНрд▓рд╛рдЗрдВрдЯ рд╣реИ рдФрд░ рдЬрд┐рд╕реЗ рдкрд┐рдЫрд▓реЗ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
@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;
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рд▓реЗрдЦрдХ рдХреЛ рдлрд┐рд░ рд╕реЗ "рдкрд╛рд╕" рдХрд░рддрд╛ рд╣реВрдВ, рдпрд╛ рдлрд┐рд░ рдореИрдВ рдЙрд╕рдХреЗ рд▓реЗрдЦ рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдЬрд╛рд░реА рд░рдЦрддрд╛ рд╣реВрдВредрдЕрдВрдд рдореЗрдВ, EmployeeClient рдХреЛ рдПрдХ рд╡рд░реНрдЧ рдореЗрдВ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рд╡рд┐рднрд╛рдЧ рдХреЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рднрд╛рдЧреЛрдВ рдХреЗ рдЕрдВрджрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
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; }
рдЖрд╡рд╢реНрдпрдХ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рд╡рд┐рднрд╛рдЧ-рд╕реЗрд╡рд╛ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдП рдЧрдП рдЖрд░реЗрдЦ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рдиреА рдЪрд╛рд╣рд┐рдПред рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рднрд╛рдЧ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдЕрд╕рд╛рдЗрди рдХрд┐рдП рдЧрдП рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реЛ рд╕рдХрддреА рд╣реИ, рдФрд░ рд╣рдордиреЗ рд╡рд┐рднрд╛рдЧ рдкреНрд░рдХрд╛рд░ рджреНрд╡рд╛рд░рд╛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░реНрдордЪрд╛рд░реА рдкреНрд░рдХрд╛рд░ рдХреЛ рднреА рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИред
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! }
рдЕрдм рд╣рдо рдЕрдкрдиреА рдкрд░реАрдХреНрд╖рд╛ рдХреА рдХреНрд╡реЗрд░реА рдХреЛ рдЧреНрд░рд╛рдлреАрдХреНрдпреВрдПрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрд╡рд╢реНрдпрдХ рдлрд╝реАрд▓реНрдб рдХреА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВред рд╡рд┐рднрд╛рдЧ-рд╕реЗрд╡рд╛ рдЖрд╡реЗрджрди рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдкреЛрд░реНрдЯ 8091 рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ,
рдЕрд░реНрдерд╛рддреН , рд╣рдо рдЗрд╕реЗ
http: // localhost: 8091 / graphiql рдкрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ
рдирд┐рд╖реНрдХрд░реНрд╖
рд╢рд╛рдпрдж рд░реЗрдЦрд╛рдХрди рдорд╛рдирдХ REST API рдХрд╛ рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рд╡рд┐рдХрд▓реНрдк рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╣рдореЗрдВ рдЗрд╕реЗ REST рдХреЗ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рд╕рдордЭрдирд╛ рдЪрд╛рд╣рд┐рдПред рдРрд╕реЗ рдХрдИ рдорд╛рдорд▓реЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдЧреНрд░рд╛рдлрдХреЙрд▓ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡реЗ рдЬрд╣рд╛рдВ REST рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИред рдпрджрд┐ рдЖрдкрдХреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рд╕реЗ рд╕рднреА рдлрд╝реАрд▓реНрдбреНрд╕ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рд╡рд╛рд▓реЗ рдХрдИ рдХреНрд▓рд╛рдЗрдВрдЯ рд╣реИрдВ, рддреЛ рдЧреНрд░рд╛рдлрдХреЙрд▓ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИред рдпрджрд┐ рдЖрдк рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕ рд╕рдореБрджрд╛рдп рдореЗрдВ рдХреНрдпрд╛ рд╣реИ, рддреЛ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЕрдм рдХреЛрдИ рдЬрд╛рд╡рд╛-рдЖрдзрд╛рд░рд┐рдд рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рд╕рд░реНрд╡рд┐рд╕ рдбрд┐рд╕реНрдХрд╡рд░реА, рдмреИрд▓реЗрдВрд╕рд░ рдпрд╛ рдмреЙрдХреНрд╕ рдХреЗ рдмрд╛рд╣рд░ рдЧреЗрдЯрд╡реЗ рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдорд┐рд▓рдХрд░ рдЧреНрд░рд╛рдлрдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВрдиреЗ рдорд╛рдЗрдХреНрд░реЛрдХреНрд░реЗрдЧрд░ рд╕рдВрдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рд╕реНрдкреНрд░рд┐рдВрдЧ рдХреНрд▓рд╛рдЙрдб рдпреВрд░реЗрдХрд╛ рдХреЗ рд╕рд╛рде рдПрдХ рдЧреНрд░рд╛рдлрдХреНрдпреВрдПрд▓ рдХреНрд▓рд╛рдЗрдВрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреАрдХреНрдпреВрдПрд▓ рдФрд░ рдпреВрдиреЗрд╕реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛рдпрд╛ред GitHub
github.com/piomin/sample-graphql-microservices.git рдкрд░ рдЕрдВрдЧреНрд░реЗрдЬреА рдореЗрдВ рдПрдХ рд▓реЗрдЦ рдХреЗ рд▓реЗрдЦрдХ рдХреЗ рд▓рд┐рдП рдирдореВрдирд╛ рдХреЛрдбред
GQL рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╕рд╛рде рдореЗрд░рд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг :
github.com/lynx-r/sample-graphql-microservices