资讯动态

Gateway - 入门教程

发布时间:2026/10/24 1:39:39 来源:尧图企业网站定制
一、基本概念1.网关基本概念客户端和服务端中间的一堵墙可以起到的作用有请求转发、负载均衡、权限控制等等个人理解网关解决从客户端如8080端口进入服务端时调用哪个微服务的问题请求转发功能Feign解决各微服务之间的相互调用问题API网关介绍API 网关出现的原因是微服务架构的出现不同的微服务一般会有不同的网络地址而外部客户端可能需要调用多个服务的接口才能完成一个业务需求如果让客户端直接与各个微服务通信会有以下的问题客户端会多次请求不同的微服务增加了客户端的复杂性。存在跨域请求在一定场景下处理相对复杂。认证复杂每个服务都需要独立认证。难以重构随着项目的迭代可能需要重新划分微服务。例如可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信那么重构将会很难实施。某些微服务可能使用了防火墙 / 浏览器不友好的协议直接访问会有一定的困难。以上这些问题可以借助 API 网关解决。API 网关是介于客户端和服务器端之间的中间层所有的外部请求都会先经过 API 网关这一层。也就是说API 的实现方面更多的考虑业务逻辑而安全、性能、监控可以交由 API 网关来做这样既提高业务灵活性又不缺安全性。2.什么是Gateway网关Spring Cloud Gateway核心概念网关提供API全托管服务丰富的API管理功能辅助企业管理大规模的API以降低管理成本和安全风险包括协议适配、协议转发、安全策略、防刷、流量、监控日志等功能。一般来说网关对外暴露的URL或者接口信息我们统称为路由信息。如果研发过网关中间件或者使用过Zuul的人会知道网关的核心是Filter以及Filter ChainFilter责任链。Sprig Cloud Gateway也具有路由和Filter的概念。Spring Cloud Gateway中几个重要的概念路由路由是网关最基础的部分路由信息有一个ID、一个目的URL、一组断言和一组Filter组成。如果断言路由为真则说明请求的URL和配置匹配断言匹配的规则。Java8中的断言函数。Spring Cloud Gateway中的断言函数输入类型是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自于httprequest中的任何信息比如请求头和参数等。过滤器一个标准的Spring webFilter。Spring cloud gateway中的filter分为两种类型的Filter分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理3.网关实现流程客户端发送请求先到网关将网关服务和其它要访问的服务在注册中心进行注册通过网关访问到注册的其它服务GateWay Handler Mapping访问之后做映射路径匹配GateWay Web Handler处理匹配Filter过滤器实现权限管理、跨域等二、项目整合1.引入依赖在api_gateway中引入依赖!--nacos注册中心--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency!--Gateway网关依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency!--gson--dependencygroupIdcom.google.code.gson/groupIdartifactIdgson/artifactId/dependency!--服务调用--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependency2.编写配置文件properties写法# nacos中注册的服务名spring.application.nameservice-gateway# nacos服务地址spring.cloud.nacos.discovery.server-addr127.0.0.1:8848#使用服务发现路由服务调用spring.cloud.gateway.discovery.locator.enabledtrue#服务路由名小写#spring.cloud.gateway.discovery.locator.lower-case-service-idtrue#设置路由id下标从[0]开始#理论随便写建议写服务的名字spring.cloud.gateway.routes[0].idservice-acl#设置路由的url#格式lb://nacos中注册的服务名spring.cloud.gateway.routes[0].urilb://service-acl#设置路由断言匹配规则,代理servicerId为auth-service的/auth/路径#格式Pathspring.cloud.gateway.routes[0].predicatesPath/*/acl/** spring.cloud.gateway.routes[1].idservice-edu spring.cloud.gateway.routes[1].urilb://service-edu spring.cloud.gateway.routes[1].predicatesPath/eduservice/**yml写法server: port:8222spring: application: cloud: gateway: discovery: locator: enabled:trueroutes: - id: service-acl uri: lb://service-acl predicates: -Path/*/acl/**# 路径匹配- id: service-edu uri: lb://service-edu predicates: -Path/eduservice/**# 路径匹配nacos: discovery: server-addr:127.0.0.1:88483.启动类importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cloud.client.discovery.EnableDiscoveryClient;SpringBootApplication EnableDiscoveryClient public class ApiGatewayApplication{public static void main(String[]args){SpringApplication.run(ApiGatewayApplication.class, args);}}4.测试启动nacos启动Gateway启动需要调用的服务打开naocs地址http://localhost:8848/nacos默认账号密码都为nacos点开服务列表检查Gateway等服务是否注册到nacos先通过原服务端口号访问然后通过网关端口号访问三、工具类1.跨域配置importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.cors.CorsConfiguration;importorg.springframework.web.cors.reactive.CorsWebFilter;importorg.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;importorg.springframework.web.util.pattern.PathPatternParser;ConfigurationpublicclassCorsConfig{BeanpublicCorsWebFiltercorsFilter(){CorsConfigurationconfignewCorsConfiguration();config.addAllowedMethod(*);config.addAllowedOrigin(*);config.addAllowedHeader(*);UrlBasedCorsConfigurationSourcesourcenewUrlBasedCorsConfigurationSource(newPathPatternParser());source.registerCorsConfiguration(/**,config);returnnewCorsWebFilter(source);}}2.全局Filter统一处理会员登录与外部不允许访问的服务importcom.google.gson.JsonObject;importorg.springframework.cloud.gateway.filter.GatewayFilterChain;importorg.springframework.cloud.gateway.filter.GlobalFilter;importorg.springframework.core.Ordered;importorg.springframework.core.io.buffer.DataBuffer;importorg.springframework.http.server.reactive.ServerHttpRequest;importorg.springframework.http.server.reactive.ServerHttpResponse;importorg.springframework.stereotype.Component;importorg.springframework.util.AntPathMatcher;importorg.springframework.web.server.ServerWebExchange;importreactor.core.publisher.Mono;importjava.nio.charset.StandardCharsets;importjava.util.List;ComponentpublicclassAuthGlobalFilterimplementsGlobalFilter,Ordered{privateAntPathMatcherantPathMatchernewAntPathMatcher();OverridepublicMonoVoidfilter(ServerWebExchangeexchange,GatewayFilterChainchain){ServerHttpRequestrequestexchange.getRequest();Stringpathrequest.getURI().getPath();//api接口校验用户必须登录if(antPathMatcher.match(/api/**/auth/**,path)){ListStringtokenListrequest.getHeaders().get(token);if(nulltokenList){ServerHttpResponseresponseexchange.getResponse();returnout(response);}else{// Boolean isCheck JwtUtils.checkToken(tokenList.get(0));// if(!isCheck) {ServerHttpResponseresponseexchange.getResponse();returnout(response);// }}}//内部服务接口不允许外部访问if(antPathMatcher.match(/**/inner/**,path)){ServerHttpResponseresponseexchange.getResponse();returnout(response);}returnchain.filter(exchange);}OverridepublicintgetOrder(){return0;}privateMonoVoidout(ServerHttpResponseresponse){JsonObjectmessagenewJsonObject();message.addProperty(success,false);message.addProperty(code,28004);message.addProperty(data,鉴权失败);byte[]bitsmessage.toString().getBytes(StandardCharsets.UTF_8);DataBufferbufferresponse.bufferFactory().wrap(bits);//response.setStatusCode(HttpStatus.UNAUTHORIZED);//指定编码否则在浏览器中会中文乱码response.getHeaders().add(Content-Type,application/json;charsetUTF-8);returnresponse.writeWith(Mono.just(buffer));}}3.异常处理importorg.springframework.beans.factory.ObjectProvider;importorg.springframework.boot.autoconfigure.web.ResourceProperties;importorg.springframework.boot.autoconfigure.web.ServerProperties;importorg.springframework.boot.context.properties.EnableConfigurationProperties;importorg.springframework.boot.web.reactive.error.ErrorAttributes;importorg.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.Ordered;importorg.springframework.core.annotation.Order;importorg.springframework.http.codec.ServerCodecConfigurer;importorg.springframework.web.reactive.result.view.ViewResolver;importjava.util.Collections;importjava.util.List;ConfigurationEnableConfigurationProperties({ServerProperties.class,ResourceProperties.class})publicclassErrorHandlerConfig{privatefinalServerPropertiesserverProperties;privatefinalApplicationContextapplicationContext;privatefinalResourcePropertiesresourceProperties;privatefinalListViewResolverviewResolvers;privatefinalServerCodecConfigurerserverCodecConfigurer;publicErrorHandlerConfig(ServerPropertiesserverProperties,ResourcePropertiesresourceProperties,ObjectProviderListViewResolverviewResolversProvider,ServerCodecConfigurerserverCodecConfigurer,ApplicationContextapplicationContext){this.serverPropertiesserverProperties;this.applicationContextapplicationContext;this.resourcePropertiesresourceProperties;this.viewResolversviewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurerserverCodecConfigurer;}BeanOrder(Ordered.HIGHEST_PRECEDENCE)publicErrorWebExceptionHandlererrorWebExceptionHandler(ErrorAttributeserrorAttributes){JsonExceptionHandlerexceptionHandlernewJsonExceptionHandler(errorAttributes,this.resourceProperties,this.serverProperties.getError(),this.applicationContext);exceptionHandler.setViewResolvers(this.viewResolvers);exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());returnexceptionHandler;}}4.返回packagecom.athly.gateway.handler;importorg.springframework.boot.autoconfigure.web.ErrorProperties;importorg.springframework.boot.autoconfigure.web.ResourceProperties;importorg.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;importorg.springframework.boot.web.reactive.error.ErrorAttributes;importorg.springframework.context.ApplicationContext;importorg.springframework.web.reactive.function.server.*;importjava.util.HashMap;importjava.util.Map;/** * 自定义异常处理 * p异常时用JSON代替HTML异常信息p */publicclassJsonExceptionHandlerextendsDefaultErrorWebExceptionHandler{publicJsonExceptionHandler(ErrorAttributeserrorAttributes,ResourcePropertiesresourceProperties,ErrorPropertieserrorProperties,ApplicationContextapplicationContext){super(errorAttributes,resourceProperties,errorProperties,applicationContext);}/** * 获取异常属性 */OverrideprotectedMapString,ObjectgetErrorAttributes(ServerRequestrequest,booleanincludeStackTrace){MapString,ObjectmapnewHashMap();map.put(success,false);map.put(code,20005);map.put(message,网关失败);map.put(data,null);returnmap;}/** * 指定响应处理方法为JSON处理的方法 * param errorAttributes */OverrideprotectedRouterFunctionServerResponsegetRoutingFunction(ErrorAttributeserrorAttributes){returnRouterFunctions.route(RequestPredicates.all(),this::renderErrorResponse);}/** * 根据code获取对应的HttpStatus * param errorAttributes */OverrideprotectedintgetHttpStatus(MapString,ObjecterrorAttributes){return200;}}

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑