本文目录导读:

在Java中实现GraphQL主要有几种主流方案,我来详细介绍最常用的两种方法:
使用 GraphQL Java (官方库)
依赖配置 (Maven)
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>21.3</version>
</dependency>
完整案例:图书管理系统
// 1. 数据模型
@Data
@AllArgsConstructor
class Book {
private String id;
private String title;
private String author;
private int pages;
}
@Data
@AllArgsConstructor
class Author {
private String id;
private String name;
private int age;
}
// 2. 数据源 (模拟数据库)
class DataSource {
private static List<Book> books = Arrays.asList(
new Book("1", "Java编程思想", "Bruce Eckel", 880),
new Book("2", "Spring实战", "Craig Walls", 420),
new Book("3", "算法导论", "Thomas Cormen", 1312)
);
private static List<Author> authors = Arrays.asList(
new Author("1", "Bruce Eckel", 65),
new Author("2", "Craig Walls", 50)
);
public static Book getBookById(String id) {
return books.stream()
.filter(b -> b.getId().equals(id))
.findFirst()
.orElse(null);
}
}
// 3. GraphQL Schema 定义和查询执行
public class GraphQLServer {
public static void main(String[] args) throws Exception {
// 定义 Schema (可使用SDL字符串)
String schema = """
type Book {
id: ID!
title: String!
author: String!
pages: Int!
}
type Query {
bookById(id: ID!): Book
books: [Book]
}
""";
// 创建 Schema 对象
SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry typeRegistry = schemaParser.parse(schema);
// 创建 RuntimeWiring
RuntimeWiring wiring = RuntimeWiring.newRuntimeWiring()
.type("Query", builder -> builder
.dataFetcher("bookById", env -> {
String id = env.getArgument("id");
return DataSource.getBookById(id);
})
.dataFetcher("books", env -> DataSource.getBooks())
)
.build();
// 生成可执行的 Schema
SchemaGenerator generator = new SchemaGenerator();
GraphQLSchema graphQLSchema = generator.makeExecutableSchema(typeRegistry, wiring);
// 创建 GraphQL 执行引擎
GraphQL graphQL = GraphQL.newGraphQL(graphQLSchema).build();
// 执行查询
String query = """
query {
bookById(id: "1") {
title
author
pages
}
}
""";
ExecutionInput executionInput = ExecutionInput.newExecutionInput()
.query(query)
.build();
ExecutionResult result = graphQL.execute(executionInput);
System.out.println(result.getData().toString());
}
}
使用 Spring Boot + GraphQL (更常见)
依赖配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-graphql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Schema 定义 (resources/graphql/schema.graphqls)
type Book {
id: ID! String!
author: String!
pages: Int!
price: Float!
reviews: [Review]
}
type Review {
id: ID!
rating: Int!
comment: String
user: String!
}
type Query {
books(author: String, titleContains: String): [Book]
bookById(id: ID!): Book
reviews(bookId: ID!): [Review]
}
type Mutation {
addBook(title: String!, author: String!, pages: Int!, price: Float!): Book
addReview(bookId: ID!, rating: Int!, comment: String, user: String!): Review
}
模型类
// Book.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private String id;
private String title;
private String author;
private int pages;
private double price;
private List<Review> reviews;
}
// Review.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Review {
private String id;
private int rating;
private String comment;
private String user;
}
数据层
// BookRepository.java
@Repository
public class BookRepository {
private final Map<String, Book> books = new ConcurrentHashMap<>();
public BookRepository() {
// 初始化数据
Book book1 = new Book("1", "Java编程思想", "Bruce Eckel", 880, 79.0, new ArrayList<>());
Book book2 = new Book("2", "Spring实战", "Craig Walls", 420, 59.0, new ArrayList<>());
books.put("1", book1);
books.put("2", book2);
}
public List<Book> findAll() {
return new ArrayList<>(books.values());
}
public Book findById(String id) {
return books.get(id);
}
public Book save(Book book) {
String id = String.valueOf(books.size() + 1);
book.setId(id);
books.put(id, book);
return book;
}
public List<Book> findByAuthor(String author) {
return books.values().stream()
.filter(b -> b.getAuthor().equalsIgnoreCase(author))
.collect(Collectors.toList());
}
}
// ReviewRepository.java
@Repository
public class ReviewRepository {
private final Map<String, List<Review>> reviews = new ConcurrentHashMap<>();
public ReviewRepository() {
// 初始化评论数据
reviews.put("1", Arrays.asList(
new Review("1", 5, "经典著作", "张三"),
new Review("2", 4, "内容深入", "李四")
));
}
public List<Review> findByBookId(String bookId) {
return reviews.getOrDefault(bookId, new ArrayList<>());
}
public Review save(String bookId, Review review) {
String id = UUID.randomUUID().toString();
review.setId(id);
reviews.computeIfAbsent(bookId, k -> new ArrayList<>()).add(review);
return review;
}
}
GraphQL 控制器
// BookController.java
@Controller
public class BookController {
@Autowired
private BookRepository bookRepository;
@Autowired
private ReviewRepository reviewRepository;
@QueryMapping
public List<Book> books(@Argument String author, @Argument String titleContains) {
if (author != null) {
return bookRepository.findByAuthor(author);
}
if (titleContains != null) {
return bookRepository.findAll().stream()
.filter(b -> b.getTitle().toLowerCase().contains(titleContains.toLowerCase()))
.collect(Collectors.toList());
}
return bookRepository.findAll();
}
@QueryMapping
public Book bookById(@Argument String id) {
return bookRepository.findById(id);
}
@QueryMapping
public List<Review> reviews(@Argument String bookId) {
return reviewRepository.findByBookId(bookId);
}
@MutationMapping
public Book addBook(@Argument String title, @Argument String author,
@Argument int pages, @Argument double price) {
Book book = new Book(null, title, author, pages, price, new ArrayList<>());
return bookRepository.save(book);
}
@MutationMapping
public Review addReview(@Argument String bookId, @Argument int rating,
@Argument String comment, @Argument String user) {
Review review = new Review(null, rating, comment, user);
return reviewRepository.save(bookId, review);
}
// 为Book类型添加reviews的关联查询
@SchemaMapping(typeName = "Book", field = "reviews")
public List<Review> getReviews(Book book) {
return reviewRepository.findByBookId(book.getId());
}
}
应用配置 (application.yml)
spring:
graphql:
graphiql:
enabled: true # 开启GraphiQL测试界面
schema:
locations: classpath:graphql/
测试查询示例
访问 http://localhost:8080/graphiql 打开GraphiQL界面,可以执行以下查询:
# 查询所有书籍
query {
books {
id author
pages
price
}
}
# 带参数的查询
query {
bookById(id: "1") { author
reviews {
rating
comment
user
}
}
}
# 新增书籍
mutation {
addBook(title: "Python编程", author: "Guido", pages: 500, price: 69.0) {
id }
}
# 新增评论
mutation {
addReview(bookId: "1", rating: 5, comment: "非常好的一本书", user: "王五") {
id
rating
}
}
主要优势
- 精确的数据获取:客户端只需要请求需要的数据
- 单一端点:所有接口都通过
/graphql端点访问 - 强类型系统:Schema定义明确了数据类型和关系
- 版本控制友好:通过Schema演进,不需要版本号
最佳实践
- N+1查询问题:使用DataLoader解决
- 安全性:实现深度限制、查询复杂度分析
- 缓存策略:合理使用HTTP缓存和持久化缓存
- 错误处理:统一的错误格式和异常处理
这个案例展示了Java实现GraphQL的基本方式,可以根据实际需求进行扩展和优化。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播