当前位置: 首页 > article >正文

Spring Boot 与 GraphQL 2.0 集成:构建现代化 API

Spring Boot 与 GraphQL 2.0 集成构建现代化 API引言在现代 Web 开发中API 设计变得越来越重要。传统的 RESTful API 在面对复杂的数据查询需求时往往会面临过度获取或获取不足的问题。GraphQL 作为一种新型的 API 查询语言通过允许客户端精确指定所需的数据有效地解决了这些问题。本文将详细介绍如何在 Spring Boot 应用中集成 GraphQL 2.0构建现代化的 API 系统。一、GraphQL 2.0 简介1.1 核心概念GraphQL一种用于 API 的查询语言也是一个满足你数据查询的运行时。Schema定义 API 的类型系统包括查询类型、变更类型和订阅类型。Query用于获取数据的操作。Mutation用于修改数据的操作。Subscription用于订阅实时数据的操作。Resolver处理 GraphQL 查询的函数负责从数据源获取数据。1.2 主要特性精确获取数据客户端可以精确指定所需的数据字段避免过度获取。单一端点所有请求都通过单一端点处理简化 API 设计。类型系统通过强类型定义提供更好的开发体验和错误检查。实时数据通过订阅机制支持实时数据更新。自省能力可以查询 API 的类型定义便于工具和客户端生成。1.3 GraphQL 2.0 新特性增量交付支持部分响应提高大查询的性能。流式订阅改进的订阅机制支持更复杂的实时场景。类型扩展更灵活的类型系统支持接口和联合类型的扩展。指令增强更强大的指令系统支持自定义指令。二、Spring Boot 集成 GraphQL 2.02.1 添加依赖在pom.xml文件中添加 GraphQL 依赖dependency groupIdcom.graphql-java/groupId artifactIdgraphql-spring-boot-starter/artifactId version2023.1.0/version /dependency dependency groupIdcom.graphql-java/groupId artifactIdgraphiql-spring-boot-starter/artifactId version2023.1.0/version scoperuntime/scope /dependency dependency groupIdcom.graphql-java/groupId artifactIdgraphql-java-tools/artifactId version13.0.2/version /dependency2.2 定义 Schema创建 GraphQL schema 文件schema.graphqlstype Query { bookById(id: ID!): Book allBooks: [Book!]! } type Mutation { createBook(title: String!, author: String!, published: Int!): Book! updateBook(id: ID!, title: String, author: String, published: Int): Book! deleteBook(id: ID!): Boolean! } type Book { id: ID! title: String! author: String! published: Int! reviews: [Review!]! } type Review { id: ID! content: String! rating: Int! book: Book! }2.3 实现 Resolver创建 Book resolverimport com.coxautodev.graphql.tools.GraphQLQueryResolver; import org.springframework.stereotype.Component; import java.util.List; Component public class BookQueryResolver implements GraphQLQueryResolver { private final BookService bookService; public BookQueryResolver(BookService bookService) { this.bookService bookService; } public Book bookById(String id) { return bookService.findById(id); } public ListBook allBooks() { return bookService.findAll(); } }创建 Book mutation resolverimport com.coxautodev.graphql.tools.GraphQLMutationResolver; import org.springframework.stereotype.Component; Component public class BookMutationResolver implements GraphQLMutationResolver { private final BookService bookService; public BookMutationResolver(BookService bookService) { this.bookService bookService; } public Book createBook(String title, String author, int published) { return bookService.create(title, author, published); } public Book updateBook(String id, String title, String author, Integer published) { return bookService.update(id, title, author, published); } public boolean deleteBook(String id) { return bookService.delete(id); } }2.4 配置 GraphQL在application.yml文件中配置 GraphQLgraphql: servlet: mapping: /graphql enabled: true corsEnabled: true tools: schema-location-pattern: **/*.graphqls introspection-enabled: true2.5 测试 GraphQL启动应用后可以通过 GraphiQL 界面测试 GraphQL API访问http://localhost:8080/graphiql执行查询query { allBooks { id title author published reviews { id content rating } } }执行变更mutation { createBook(title: Spring Boot in Action, author: Craig Walls, published: 2022) { id title author published } }三、高级特性3.1 数据加载器使用数据加载器优化 N1 查询问题import com.graphql-java-kickstart.execution.context.DefaultGraphQLContext; import com.graphql-java-kickstart.execution.context.GraphQLContext; import com.graphql-java-kickstart.execution.context.GraphQLContextBuilder; import graphql.schema.DataFetchingEnvironment; import org.dataloader.DataLoader; import org.dataloader.DataLoaderRegistry; import org.springframework.stereotype.Component; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.stream.Collectors; Component public class CustomGraphQLContextBuilder implements GraphQLContextBuilder { private final ReviewService reviewService; private final Executor executor; public CustomGraphQLContextBuilder(ReviewService reviewService, Executor executor) { this.reviewService reviewService; this.executor executor; } Override public GraphQLContext build(DataFetchingEnvironment environment) { DataLoaderRegistry registry new DataLoaderRegistry(); // 创建书籍评论的数据加载器 DataLoaderString, ListReview reviewsDataLoader DataLoader.newDataLoader( bookIds - CompletableFuture.supplyAsync( () - reviewService.findByBookIds(bookIds), executor ) ); registry.register(reviews, reviewsDataLoader); return DefaultGraphQLContext.builder() .dataLoaderRegistry(registry) .build(); } }3.2 错误处理实现自定义错误处理import graphql.ExceptionWhileDataFetching; import graphql.GraphQLError; import graphql.servlet.GraphQLErrorHandler; import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Collectors; Component public class CustomGraphQLErrorHandler implements GraphQLErrorHandler { Override public ListGraphQLError processErrors(ListGraphQLError errors) { return errors.stream() .map(this::processError) .collect(Collectors.toList()); } private GraphQLError processError(GraphQLError error) { if (error instanceof ExceptionWhileDataFetching) { ExceptionWhileDataFetching exceptionError (ExceptionWhileDataFetching) error; if (exceptionError.getException() instanceof RuntimeException) { return new CustomGraphQLError(exceptionError.getException().getMessage()); } } return error; } private static class CustomGraphQLError implements GraphQLError { private final String message; CustomGraphQLError(String message) { this.message message; } Override public String getMessage() { return message; } Override public ListSourceLocation getLocations() { return null; } Override public ErrorClassification getErrorType() { return null; } } }3.3 认证与授权集成 Spring Security 实现认证与授权import com.graphql-java-kickstart.execution.context.DefaultGraphQLContext; import com.graphql-java-kickstart.execution.context.GraphQLContext; import com.graphql-java-kickstart.execution.context.GraphQLContextBuilder; import graphql.schema.DataFetchingEnvironment; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; Component public class SecurityGraphQLContextBuilder implements GraphQLContextBuilder { Override public GraphQLContext build(DataFetchingEnvironment environment) { return DefaultGraphQLContext.builder() .user(SecurityContextHolder.getContext().getAuthentication()) .build(); } }在 resolver 中使用import com.graphql-java-kickstart.execution.context.GraphQLContext; import graphql.schema.DataFetchingEnvironment; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; Component public class AdminMutationResolver implements GraphQLMutationResolver { PreAuthorize(hasRole(ADMIN)) public Book createBook(String title, String author, int published, DataFetchingEnvironment env) { GraphQLContext context env.getContext(); // 可以从 context 中获取当前用户信息 return bookService.create(title, author, published); } }3.4 订阅功能实现实时数据订阅type Subscription { bookAdded: Book! }创建订阅 resolverimport com.coxautodev.graphql.tools.GraphQLSubscriptionResolver; import org.reactivestreams.Publisher; import org.springframework.stereotype.Component; Component public class BookSubscriptionResolver implements GraphQLSubscriptionResolver { private final BookPublisher bookPublisher; public BookSubscriptionResolver(BookPublisher bookPublisher) { this.bookPublisher bookPublisher; } public PublisherBook bookAdded() { return bookPublisher.getPublisher(); } }创建发布者import org.reactivestreams.Publisher; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.FluxSink; import java.util.concurrent.ConcurrentLinkedQueue; Component public class BookPublisher { private final FluxBook bookFlux; private final FluxSinkBook bookSink; public BookPublisher() { ConcurrentLinkedQueueBook books new ConcurrentLinkedQueue(); this.bookFlux Flux.create(sink - { this.bookSink sink; }, FluxSink.OverflowStrategy.BUFFER); } public void publish(Book book) { bookSink.next(book); } public PublisherBook getPublisher() { return bookFlux; } }四、实践应用4.1 前后端分离架构在前后端分离架构中使用 GraphQL前端通过 GraphQL 查询获取所需数据后端提供统一的 GraphQL 端点减少网络传输量提高性能4.2 微服务架构在微服务架构中使用 GraphQL实现 API 网关聚合多个微服务的 GraphQL schema使用 Apollo Federation 或 GraphQL Mesh 实现服务间的 GraphQL 集成提供统一的 API 接口给客户端4.3 移动应用后端为移动应用提供 GraphQL API减少移动网络的数据传输支持离线操作和数据同步提供更灵活的 API 接口五、性能优化5.1 查询优化使用数据加载器解决 N1 查询问题批量查询减少数据库访问次数缓存策略缓存频繁访问的数据5.2 服务端优化Schema 优化合理设计类型和字段Resolver 优化减少 resolver 中的复杂逻辑分页处理实现高效的分页查询5.3 客户端优化查询合并将多个查询合并为一个查询缓存缓存客户端查询结果按需获取只获取必要的字段六、常见问题与解决方案问题原因解决方案N1 查询问题关联数据查询导致多次数据库访问使用数据加载器批量查询查询性能差复杂查询导致服务端负载高实现查询限制和超时机制错误处理困难GraphQL 错误格式复杂实现自定义错误处理缓存策略复杂难以确定缓存失效时机使用 Apollo Client 等客户端库管理缓存七、总结GraphQL 2.0 作为一种现代化的 API 查询语言为构建灵活、高效的 API 系统提供了新的思路。通过与 Spring Boot 的集成我们可以快速构建功能强大的 GraphQL API满足各种业务场景的需求。在实际应用中我们需要根据具体的业务场景和系统需求合理设计 GraphQL schema优化 resolver 实现以及采取相应的性能优化措施。同时我们还需要关注安全性、错误处理等方面的问题确保系统的稳定运行。通过本文的介绍相信大家已经对 Spring Boot 与 GraphQL 2.0 的集成有了更深入的了解。在实际项目中我们可以根据具体需求灵活运用 GraphQL 的各种特性构建更加现代化、高效的 API 系统。这其实可以更优雅一点你觉得呢欢迎在评论区留言讨论分享你的实践经验

相关文章:

Spring Boot 与 GraphQL 2.0 集成:构建现代化 API

Spring Boot 与 GraphQL 2.0 集成:构建现代化 API 引言 在现代 Web 开发中,API 设计变得越来越重要。传统的 RESTful API 在面对复杂的数据查询需求时,往往会面临过度获取或获取不足的问题。GraphQL 作为一种新型的 API 查询语言,…...

如何用OpenRocket实现专业火箭仿真?从设计到发射的全流程指南

如何用OpenRocket实现专业火箭仿真?从设计到发射的全流程指南 【免费下载链接】openrocket Model-rocketry aerodynamics and trajectory simulation software 项目地址: https://gitcode.com/GitHub_Trending/op/openrocket 在航空航天工程领域,…...

马年开始杂谈补

总感觉时间越过越快,是不是年纪大了。马年春节9天假期,历史上最长春节,一眨眼就过去了。今年刚开始就发生了很多事,不知福祸。首先是人工智能发展迅速,各种智能体开始出现。美以伊战争,油价狂飙。到了3月&a…...

Linux终极生态指南:5个实战技巧打造高效开源工作流

Linux终极生态指南:5个实战技巧打造高效开源工作流 【免费下载链接】awesome-linux :penguin: A list of awesome projects and resources that make Linux even more awesome. :penguin: 项目地址: https://gitcode.com/gh_mirrors/aw/awesome-linux Linux生…...

Linux文件系统驱动实战:exfat-nofuse跨平台存储解决方案全解析

Linux文件系统驱动实战:exfat-nofuse跨平台存储解决方案全解析 【免费下载链接】exfat-nofuse Android ARM Linux non-fuse read/write kernel driver for exFat and VFat Android file systems 项目地址: https://gitcode.com/gh_mirrors/ex/exfat-nofuse 开…...

3个超简单步骤:零门槛制作专业级AI视频

3个超简单步骤:零门槛制作专业级AI视频 【免费下载链接】Open-Sora Open-Sora:为所有人实现高效视频制作 项目地址: https://gitcode.com/GitHub_Trending/op/Open-Sora 在数字内容创作领域,AI视频生成技术正以前所未有的速度改变着创…...

AI生成内容检测新思路:除了红绿词表,我们还能用哪些方法识别ChatGPT写的文章?

AI生成内容检测技术全景:超越红绿词表的七种实战方法 当ChatGPT生成的论文摘要通过学术评审、AI撰写的新闻稿被主流媒体刊发时,内容真实性的边界正在变得模糊。某高校教授最近向我展示了一份学生作业——文笔流畅的哲学论述,最终被证实完全由…...

抖音直播回放下载工具:高效保存与智能管理解决方案

抖音直播回放下载工具:高效保存与智能管理解决方案 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 在数字内容爆炸的时代,精彩的直播内容稍纵即逝,如何永久保存这些宝贵的…...

如何用res-downloader解决多平台资源下载难题:从入门到精通

如何用res-downloader解决多平台资源下载难题:从入门到精通 【免费下载链接】res-downloader 资源下载器、网络资源嗅探,支持微信视频号下载、网页抖音无水印下载、网页快手无水印视频下载、酷狗音乐下载等网络资源拦截下载! 项目地址: https://gitcod…...

MATLAB数值解算实战:欧拉与龙格库塔算法对比(附完整代码)

MATLAB数值解算实战:欧拉与龙格库塔算法对比(附完整代码) 微分方程在工程建模中无处不在,从机械系统的振动分析到电路瞬态响应预测,都需要可靠的数值解法。MATLAB作为工程计算的标准工具,提供了多种微分方程…...

OpenClaw浏览器自动化:Qwen3-32B镜像实现竞品数据抓取与可视化

OpenClaw浏览器自动化:Qwen3-32B镜像实现竞品数据抓取与可视化 1. 为什么选择OpenClaw做竞品分析 去年在做产品迭代时,我每周都要手动收集竞品数据。从打开十几个网页、复制粘贴数据到Excel,再到生成对比图表,整个过程至少耗费3…...

springboot-vue基于web的同城医院陪诊服务预约系统设计与实现

目录技术选型与架构设计核心功能模块划分数据库设计要点关键接口示例安全与性能优化测试与部署项目里程碑计划项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作技术选型与架构设计 后端技术栈 使用Spring Boot 2.7.x框架搭建RE…...

通义千问1.5-1.8B-Chat-GPTQ-Int4在Keil开发环境中的嵌入式AI应用

通义千问1.5-1.8B-Chat-GPTQ-Int4在Keil开发环境中的嵌入式AI应用 在MCU上跑AI大模型?这听起来像是天方夜谭,但通义千问1.5-1.8B-Chat-GPTQ-Int4让这成为了现实。 1. 嵌入式AI的新可能 如果你正在开发智能家电、工业控制器或者物联网设备,可…...

Ollama部署Qwen2.5-VL-7B实战:图片识别与描述生成

Ollama部署Qwen2.5-VL-7B实战:图片识别与描述生成 1. 引言:认识Qwen2.5-VL多模态模型 Qwen2.5-VL是阿里云推出的开源多模态大模型系列的最新成员,作为Qwen2-VL的升级版本,它在视觉理解和语言交互方面实现了显著提升。本次我们将…...

GNSS/SINS组合导航实战:静基座精对准中的卡尔曼滤波参数调优技巧

GNSS/SINS组合导航实战:静基座精对准中的卡尔曼滤波参数调优技巧 在嵌入式导航系统开发中,静基座精对准是确保初始姿态精度的关键环节。许多工程师在调试卡尔曼滤波器时,常陷入参数试错的困境——Q矩阵该设多大?R矩阵如何匹配传感…...

MySQL基础运维:日志基础之慢查询日志与错误日志 | 作用、配置与查看方法全实战

本文承接MySQL运维系列内容,聚焦新手入门运维最刚需的两大核心日志:错误日志、慢查询日志。 很多新手学习MySQL时,都会遇到两个最头疼的问题:一是MySQL启动失败、运行报错,完全不知道去哪找原因;二是SQL执行…...

如何3分钟免费为Figma安装中文界面插件:设计师效率提升完整指南

如何3分钟免费为Figma安装中文界面插件:设计师效率提升完整指南 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 作为一名中文设计师,你是否曾在使用Figma时因为英…...

ComfyUI-Easy-Use:GPU资源优化与深度学习推理效能提升实践

ComfyUI-Easy-Use:GPU资源优化与深度学习推理效能提升实践 【免费下载链接】ComfyUI-Easy-Use In order to make it easier to use the ComfyUI, I have made some optimizations and integrations to some commonly used nodes. 项目地址: https://gitcode.com/g…...

3个步骤解决CAJ文献跨平台阅读难题:开源格式转换工具全解析

3个步骤解决CAJ文献跨平台阅读难题:开源格式转换工具全解析 【免费下载链接】caj2pdf Convert CAJ (China Academic Journals) files to PDF. 转换中国知网 CAJ 格式文献为 PDF。佛系转换,成功与否,皆是玄学。 项目地址: https://gitcode.c…...

Qwen3-ASR-1.7B与Python爬虫结合实战:音频数据采集与智能分析流水线

Qwen3-ASR-1.7B与Python爬虫结合实战:音频数据采集与智能分析流水线 1. 为什么需要这套音频分析流水线 最近在帮一家做社交媒体舆情监控的团队搭建分析系统时,他们提出了一个很实际的问题:视频平台里大量用户评论是以语音形式存在的&#x…...

iOS日志与事件深度解析工具:iLEAPP技术架构与实战指南

iOS日志与事件深度解析工具:iLEAPP技术架构与实战指南 【免费下载链接】iLEAPP iOS Logs, Events, And Plist Parser 项目地址: https://gitcode.com/gh_mirrors/il/iLEAPP 在移动设备取证和数据分析领域,iOS系统的复杂性一直是技术人员的挑战。面…...

3大创新方法构建AI训练数据集:老照片修复实战指南

3大创新方法构建AI训练数据集:老照片修复实战指南 【免费下载链接】Bringing-Old-Photos-Back-to-Life Bringing Old Photo Back to Life (CVPR 2020 oral) 项目地址: https://gitcode.com/gh_mirrors/br/Bringing-Old-Photos-Back-to-Life 老照片修复AI项目…...

Ostrakon-VL-8B网络编程实践:构建高可用模型服务的负载均衡架构

Ostrakon-VL-8B网络编程实践:构建高可用模型服务的负载均衡架构 最近在帮几个团队部署Ostrakon-VL-8B这类多模态大模型时,发现一个挺普遍的问题:单个实例跑得好好的,一旦流量上来或者服务时间长了,就容易出状况。要么…...

AudioSeal Pixel Studio效果展示:ASMR音频高频细节保留下的水印稳定性验证

AudioSeal Pixel Studio效果展示:ASMR音频高频细节保留下的水印稳定性验证 1. 专业级音频水印技术新标杆 AudioSeal Pixel Studio是基于Meta开源的AudioSeal算法构建的音频保护工具,它重新定义了数字水印技术的标准。这款工具能够在保持原始音频质量的…...

NSSM神器:一键将任意应用注册为Windows服务并实现日志自动分割

NSSM实战指南:将Windows应用转化为可靠系统服务的完整方案 在Windows服务器运维和开发过程中,我们经常需要确保关键应用程序能够持续稳定运行,即使系统重启或用户注销也不受影响。传统方式下,开发者通常需要编写复杂的服务包装代码…...

告别‘OSError‘:手把手教你为transformers库设置离线/代理模式,稳定加载预训练模型

构建稳定高效的Hugging Face模型加载环境:从原理到实践 当你在深夜赶项目进度时,突然遇到那个令人窒息的红色报错——"OSError: Couldnt connect to https://huggingface.co",这感觉就像在马拉松终点线前被绊倒。作为现代NLP开发的…...

AtlasOS终极解决:2502/2503错误代码效率提升方案

AtlasOS终极解决:2502/2503错误代码效率提升方案 【免费下载链接】Atlas 🚀 An open and lightweight modification to Windows, designed to optimize performance, privacy and security. 项目地址: https://gitcode.com/GitHub_Trending/atlas1/Atl…...

LVDS信号完整性救星:Xilinx OSERDESE2+IDELAY2配置避坑指南

LVDS信号完整性救星:Xilinx OSERDESE2IDELAY2配置避坑指南 当你在Gbps级LVDS接口设计中遇到信号抖动问题时,是否曾盯着眼图上的毛刺束手无策?作为Xilinx FPGA开发者,我们常陷入这样的困境:明明按照手册配置了OSERDESE2…...

中国象棋AlphaZero:零基础构建超越人类棋力的AI对战系统

中国象棋AlphaZero:零基础构建超越人类棋力的AI对战系统 【免费下载链接】ChineseChess-AlphaZero Implement AlphaZero/AlphaGo Zero methods on Chinese chess. 项目地址: https://gitcode.com/gh_mirrors/ch/ChineseChess-AlphaZero 中国象棋AlphaZero是一…...

FFXIV插件框架Dalamud深度解析:架构设计与技术实现

FFXIV插件框架Dalamud深度解析:架构设计与技术实现 【免费下载链接】Dalamud FFXIV plugin framework and API 项目地址: https://gitcode.com/GitHub_Trending/da/Dalamud Dalamud作为《最终幻想XIV》的插件开发框架,为开发者提供了强大的游戏数…...