SpringBoot多模块项目中GraphQL接口无法暴露求助
问题场景
我有一个多模块Gradle项目,graphql-service模块包含GraphQL相关代码,可运行的ServiceMain类位于service-main模块(该模块的RestController可正常工作),但GraphQLController无法对外暴露。尝试过将application.properties移至可运行模块、移动GraphQLController,甚至将所有GraphQL相关文件移至service-main模块,均未解决问题。确认依赖和Gradle配置正常,单独运行GraphQL代码可正常工作,但在多模块场景下无法运行。
文件架构
-root |_graphql-service | |_main | |_java | | |_com.example.graphql | | |_Author | | |_Book | | |_GraphQLController | |_resources | |_graphql | | |_schema.graphqls | | | |_application.properties | |_service-main |_main |_java |_com.example.service.main |_ServiceMain |_RestController
核心代码片段
schema.graphqls
type Query { bookById(id: ID): Book } type Book { id: ID name: String pageCount: Int author: Author } type Author { id: ID firstName: String lastName: String }
ServiceMain.java
@SpringBootApplication public class ServiceMain { public static void main(String[] args) { SpringApplication.run(ServiceMain.class, args); } }
GraphQLController.java
@Controller public class GraphQLController { private static final Logger LOG = LoggerFactory.getLogger(GraphQLController.class); @QueryMapping public Book bookById(@Argument String id){ LOG.info("Invoking bookById"); return Book.getById(id); } @SchemaMapping public Author author(Book book){ LOG.info("Invoking author"); return Author.getById(book.getAuthorId()); } }
Book.java
public class Book { private String id; private String name; private int pageCount; private String authorId; private static final Logger LOG = LoggerFactory.getLogger(Book.class); public Book(String id, String name, int pageCount, String authorId){ LOG.info("Initializing Book Object"); this.id = id; this.name = name; this.pageCount = pageCount; this.authorId = authorId; } private static List<Book> books = Arrays.asList( new Book("0", "name-0", 345, "0"), new Book("1", "name-1", 543, "1"), new Book("2", "name-2", 123, "2"), new Book("3", "name-3", 678, "3") ); public static Book getById(String id){ LOG.info("Filtering Books By ID"); return books.stream().filter( book -> book.getId().equals(id) ).findFirst().orElse(null); } public String getId(){ LOG.info("Getting Book ID"); return id; } public String getAuthorId(){ LOG.info("Getting Author ID"); return authorId; } }
Author.java
public class Author { private String id; private String firstName; private String lastName; private static final Logger LOG = LoggerFactory.getLogger(Author.class); public Author(String id, String firstName, String lastName){ LOG.info("Initializing Author Object"); this.id = id; this.firstName = firstName; this.lastName = lastName; } private static List<Author> authors = Arrays.asList( new Author("0", "name-0", "last-name-0"), new Author("1", "name-1", "last-name-1"), new Author("2", "name-2", "last-name-2"), new Author("4", "name-3", "last-name-3") ); public static Author getById(String id){ LOG.info("Getting Author By ID"); return authors.stream().filter( author -> author.getId().equals(id) ).findFirst().orElse(null); } public String getId(){ LOG.info("Getting Author ID"); return id; } }
application.properties
spring.graphql.graphiql.enabled=true spring.graphql.graphiql.path=/graphiql
问题排查与解决方法
1. 修复Spring Boot组件扫描范围
@SpringBootApplication默认只扫描当前类所在包及其子包,ServiceMain在com.example.service.main,而GraphQLController在com.example.graphql,不在默认扫描范围内,导致Controller未被注册。
修改ServiceMain.java,添加扫描包配置:
@SpringBootApplication(scanBasePackages = "com.example") public class ServiceMain { public static void main(String[] args) { SpringApplication.run(ServiceMain.class, args); } }
或者精准指定两个模块的包:
@SpringBootApplication(scanBasePackages = {"com.example.service.main", "com.example.graphql"})
2. 确保模块依赖正确配置
确认service-main模块的build.gradle中已正确依赖graphql-service:
dependencies { implementation project(':graphql-service') // 其他Spring Boot、GraphQL依赖... }
同时确保graphql-service模块的资源文件(schema.graphqls)能被正确打包并被service-main加载,Gradle默认会打包src/main/resources下的文件,无需额外配置,若有自定义资源规则需检查是否包含graphql目录。
3. 统一依赖版本避免冲突
多模块项目中易出现依赖版本不一致问题,在根项目build.gradle中通过dependencyManagement统一管理版本:
dependencyManagement { imports { mavenBom "org.springframework.boot:spring-boot-dependencies:3.2.0" // 替换为你的Spring Boot版本 } }
确保两个模块使用相同版本的Spring Boot和Spring GraphQL依赖。
4. 验证GraphQL组件注册状态
添加日志配置,查看启动时的组件扫描和GraphQL加载情况,在application.properties中添加:
logging.level.org.springframework.graphql=DEBUG logging.level.org.springframework.context.annotation=DEBUG
启动后检查日志,确认是否出现:
- 扫描到
GraphQLController的日志 Registered GraphQL query mapping for 'bookById'的注册日志- 成功加载
schema.graphqls的日志
5. 检查注解与映射匹配
确认@QueryMapping的方法名与schema中的查询名称完全一致(大小写敏感),当前代码中bookById匹配正常,无需修改。若存在拼写错误会导致映射失败。
内容的提问来源于stack exchange,提问作者Ayman Subbagh

