如何在Spring-GraphQL项目中添加第二个GraphQL端点?
在Spring-GraphQL中配置多个GraphQL端点
完全可以实现!核心思路是手动注册多个GraphQlServlet实例,分别对应内部和公众端点,并通过访问控制规则隔离两者的权限范围。以下是具体实现步骤:
1. 禁用自动注册的默认端点
首先在配置文件中关闭Spring Boot自动生成的默认GraphQL端点,避免冲突:
# application.properties spring.graphql.servlet.enabled=false
2. 注册两个独立的GraphQL端点
创建配置类,手动注册两个Servlet实例,分别指定不同的访问路径:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.graphql.server.webmvc.GraphQlHttpHandler; import org.springframework.graphql.server.webmvc.GraphQlServlet; import org.springframework.boot.web.servlet.ServletRegistrationBean; @Configuration public class MultipleGraphQlEndpointsConfig { // 内部端点:供数据中心内部访问 @Bean public ServletRegistrationBean<GraphQlServlet> internalGraphQlServlet(GraphQlHttpHandler graphQlHttpHandler) { GraphQlServlet servlet = new GraphQlServlet(graphQlHttpHandler); ServletRegistrationBean<GraphQlServlet> registration = new ServletRegistrationBean<>(servlet, "/internal/graphql"); registration.setName("internalGraphQlServlet"); return registration; } // 公众端点:对外开放访问 @Bean public ServletRegistrationBean<GraphQlServlet> publicGraphQlServlet(GraphQlHttpHandler graphQlHttpHandler) { GraphQlServlet servlet = new GraphQlServlet(graphQlHttpHandler); ServletRegistrationBean<GraphQlServlet> registration = new ServletRegistrationBean<>(servlet, "/public/graphql"); registration.setName("publicGraphQlServlet"); return registration; } }
3. 配置访问控制(隔离内部/公众端点)
结合Spring Security,给内部端点添加IP白名单限制,只允许数据中心的IP段访问:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; import org.springframework.security.web.util.matcher.IpAddressMatcher; import org.springframework.web.servlet.handler.HandlerMappingIntrospector; @Configuration public class SecurityConfig { // 定义内部端点的IP匹配规则(替换为你的数据中心IP段) @Bean public MvcRequestMatcher internalEndpointMatcher(HandlerMappingIntrospector introspector) { MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, "/internal/graphql/**"); matcher.setIpAddressMatcher(new IpAddressMatcher("192.168.0.0/16")); return matcher; } // 配置权限规则 @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, MvcRequestMatcher internalEndpointMatcher) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers(internalEndpointMatcher).permitAll() // 允许内部IP访问 .requestMatchers("/public/graphql").permitAll() // 公众端点开放访问,可根据需求调整为角色限制 .anyRequest().authenticated() ); return http.build(); } }
4. 可选:为不同端点配置独立的GraphQL逻辑
如果需要内部和公众端点使用不同的schema、数据获取器,可以创建独立的GraphQlSource实例:
// 在MultipleGraphQlEndpointsConfig中添加以下Bean @Bean public GraphQlSource internalGraphQlSource() { return GraphQlSource.builder() .schemaResourceLoader(new DefaultResourceLoader()) .schemaLocations("classpath:internal-schema.graphqls") // 内部专属schema .runtimeWiring(runtimeWiring -> runtimeWiring .type("Query", typeWiring -> typeWiring .dataFetcher("internalData", internalDataFetcher()) ) ) .build(); } @Bean public GraphQlSource publicGraphQlSource() { return GraphQlSource.builder() .schemaResourceLoader(new DefaultResourceLoader()) .schemaLocations("classpath:public-schema.graphqls") // 公众专属schema .runtimeWiring(runtimeWiring -> runtimeWiring .type("Query", typeWiring -> typeWiring .dataFetcher("publicData", publicDataFetcher()) ) ) .build(); } // 为每个端点绑定独立的GraphQlHttpHandler @Bean public GraphQlHttpHandler internalGraphQlHttpHandler(GraphQlSource internalGraphQlSource) { return GraphQlHttpHandler.builder(internalGraphQlSource).build(); } @Bean public GraphQlHttpHandler publicGraphQlHttpHandler(GraphQlSource publicGraphQlSource) { return GraphQlHttpHandler.builder(publicGraphQlSource).build(); }
这种方式可以灵活满足你的需求:既可以让两个端点共用同一套GraphQL逻辑,也可以完全隔离各自的schema和数据处理流程,同时通过IP或权限控制确保内部端点的安全性。
内容的提问来源于stack exchange,提问作者Wilhelm
相关产品推荐
相关产品推荐

