核心概念:
- <dependencies>
- <!-- spring-cloud gateway,底层基于netty -->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-gateway</artifactId>
- </dependency>
- <!-- 端点监控 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
- <!-- nacos注册中⼼ -->
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-nacosdiscovery</artifactId>
- </dependency>
- </dependencies>
配置文件(动态路由)例子:
- server:
- #gateway的端⼝
- port: 8888
- spring:
- application:
- name: cloud-gateway
- cloud:
- nacos:
- discovery:
- server-addr: 127.0.0.1:8848
- gateway:
- routes:
- - id: service-user
- uri: lb://service-user
- predicates:
- - Path=/user/**
谓词工厂:

- spring:
- cloud:
- gateway:
- routes:
- - id: wfx-jifen
- uri: lb://wfx-goods
- predicates:
- - Path=/goods/detail/100
- - After=2022-11-28T15:26:40.626+08:00[Asia/Shanghai]
- - Cookie=name,jack
- - Header=token
- - Host=**.baidu.com,**.taobao.com
- - Query=name,tom
- - RemoteAddr=192.168.56.10,192.168.56.11
过滤器:
分成了全局和局部过滤器。局部只针对某一路由,全局针对所有路由。
使用内置过滤器:
- spring:
- cloud:
- gateway:
- routes:
- - id: add_request_header_route
- uri: https://example.org
- filters:
- - AddRequestHeader=Foo, Bar
一般内置过滤器无法满足需求,所以经常使用自定义过滤器。自定义全局过滤器(请求是否带token的例子):
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cloud.gateway.filter.GatewayFilterChain;
- import org.springframework.cloud.gateway.filter.GlobalFilter;
- import org.springframework.core.Ordered;
- import org.springframework.core.io.buffer.DataBuffer;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.http.server.reactive.ServerHttpRequest;
- import org.springframework.http.server.reactive.ServerHttpResponse;
- import org.springframework.stereotype.Component;
- import org.springframework.util.StringUtils;
- import org.springframework.web.server.ServerWebExchange;
- import reactor.core.publisher.Mono;
- import java.nio.charset.StandardCharsets;
- import com.google.gson.JsonObject;
-
- @Component
- public class AuthFilter implements GlobalFilter, Ordered {
-
- @Autowired
- private RedisTemplate
redisTemplate; -
- //针对所有的路由进⾏过滤
- @Override
- public Mono
filter(ServerWebExchange exchange, - GatewayFilterChain chain) {
- //过滤器的前处理
- ServerHttpRequest request = exchange.getRequest();
- ServerHttpResponse response = exchange.getResponse();
-
- //获取当前的请求连接
- String path = request.getURI().getPath();
- if(!(path.contains("api/ucenter/login")||path.contains("api/ucenter/register")||path.contains("admin/acl/user/**"))){
- String token = request.getHeaders().getFirst("token");
- if(StringUtils.isEmpty(token)){
- JsonObject message = new JsonObject();
- message.addProperty("success", false);
- message.addProperty("code", 28004);
- message.addProperty("data", "没有登录");
- return response(response,message);
- }else{
- String tokenRedis = redisTemplate.opsForValue().get("token");
- if(!tokenRedis.equals(token)){
- JsonObject message = new JsonObject();
- message.addProperty("success", false);
- message.addProperty("code", 28004);
- message.addProperty("data", "令牌无效");
- return response(response,message);
- }else{
- return chain.filter(exchange); //放⾏
- }
- }
- }
- return chain.filter(exchange);
- }
- private Mono
response(ServerHttpResponse response,Object message){ - response.getHeaders().add("Content-Type",
- "application/json;charset=UTF-8");
- byte[] bits = message.toString().getBytes(StandardCharsets.UTF_8);
- DataBuffer dataBuffer =
- response.bufferFactory().wrap(bits);
- return response.writeWith(Mono.just(dataBuffer));//响应json数据
- }
-
- @Override
- public int getOrder() {
- return 0;
- }
- }
自定义异常处理:
服务网关调用服务时返回的错误信息对开发人员并不是很友好,所以可以自定义异常处理:
- import org.springframework.boot.autoconfigure.web.ErrorProperties;
- import org.springframework.boot.autoconfigure.web.ResourceProperties;
- import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
- import org.springframework.boot.web.reactive.error.ErrorAttributes;
- import org.springframework.context.ApplicationContext;
- import org.springframework.http.HttpStatus;
- import org.springframework.web.reactive.function.server.*;
- import java.util.HashMap;
- import java.util.Map;
-
- //自定义异常处理
- public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {
- public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
- ErrorProperties errorProperties, ApplicationContext applicationContext) {
- super(errorAttributes, resourceProperties, errorProperties, applicationContext);
- }
- /**
- * 获取异常属性
- */
- @Override
- protected Map
getErrorAttributes(ServerRequest request, boolean includeStackTrace) { - Map
map = new HashMap<>(); - map.put("success", false);
- map.put("code", 20005);
- map.put("message", "网关失败");
- map.put("data", null);
- return map;
- }
- /**
- * 指定响应处理方法为JSON处理的方法
- * @param errorAttributes
- */
- @Override
- protected RouterFunction
getRoutingFunction(ErrorAttributes errorAttributes) { - return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
- }
- /**
- * 根据code获取对应的HttpStatus
- * @param errorAttributes
- */
- @Override
- protected int getHttpStatus(Map
errorAttributes) { - return HttpStatus.OK.value();
- }
- }
- import org.springframework.beans.factory.ObjectProvider;
- import org.springframework.boot.autoconfigure.web.ResourceProperties;
- import org.springframework.boot.autoconfigure.web.ServerProperties;
- import org.springframework.boot.context.properties.EnableConfigurationProperties;
- import org.springframework.boot.web.reactive.error.ErrorAttributes;
- import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.Ordered;
- import org.springframework.core.annotation.Order;
- import org.springframework.http.codec.ServerCodecConfigurer;
- import org.springframework.web.reactive.result.view.ViewResolver;
- import java.util.Collections;
- import java.util.List;
-
- //覆盖默认的异常处理
- @Configuration
- @EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
- public class ErrorHandlerConfig {
- private final ServerProperties serverProperties;
- private final ApplicationContext applicationContext;
- private final ResourceProperties resourceProperties;
- private final List
viewResolvers; - private final ServerCodecConfigurer serverCodecConfigurer;
- public ErrorHandlerConfig(ServerProperties serverProperties,
- ResourceProperties resourceProperties,
- ObjectProvider
> viewResolversProvider,
- ServerCodecConfigurer serverCodecConfigurer,
- ApplicationContext applicationContext) {
- this.serverProperties = serverProperties;
- this.applicationContext = applicationContext;
- this.resourceProperties = resourceProperties;
- this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
- this.serverCodecConfigurer = serverCodecConfigurer;
- }
- @Bean
- @Order(Ordered.HIGHEST_PRECEDENCE)
- public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
- JsonExceptionHandler exceptionHandler = new JsonExceptionHandler(
- errorAttributes,
- this.resourceProperties,
- this.serverProperties.getError(),
- this.applicationContext);
- exceptionHandler.setViewResolvers(this.viewResolvers);
- exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
- exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
- return exceptionHandler;
- }
- }
跨域:
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.cors.CorsConfiguration;
- import org.springframework.web.cors.reactive.CorsWebFilter;
- import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
- import org.springframework.web.util.pattern.PathPatternParser;
-
- @Configuration
- public class CorsConfig {
- //处理跨域
- @Bean
- public CorsWebFilter corsFilter() {
- CorsConfiguration config = new CorsConfiguration();
- config.addAllowedMethod("*");
- config.addAllowedOrigin("*");
- config.addAllowedHeader("*");
- UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
- source.registerCorsConfiguration("/**", config);
- return new CorsWebFilter(source);
- }
- }