快速开始
引入依赖(必须排除springmvc的包)
<!--gateway--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
配置yaml
server:
port: 8888
spring:
application:
name: mall-gateway
cloud:
nacos:
discovery:
server-addr: 139.198.123.65:8848
gateway:
discovery:
locator:
#开启微服务名称来访问,默认为false,不建议用使用
enabled: true
#是否开启网关
enabled: true
路由断言工厂配置
路径匹配
spring:
cloud:
gateway:
#设置路由
routes:
#路由id,全局唯一
- id: order_router
#目标微服务的请求与端口与地址
#uri: http://localhost:8020
#lb 整合负载均衡过期ribbon,loadbalancer
uri: lb://mall-order
predicates:
- Path=/order/**
时间匹配
spring:
cloud:
gateway:
#设置路由
routes:
#路由id,全局唯一
- id: order_router
#目标微服务的请求与端口与地址
#uri: http://localhost:8020
#lb 整合负载均衡过期ribbon,loadbalancer
uri: lb://mall-order
predicates:
#匹配在指定日期时间之后发生的请求 入参是ZonedDateTime类型
- After=2022-04-01T08:18:29.833+08:00[Asia/Shanghai]
Cookie匹配
spring:
cloud:
gateway:
#设置路由
routes:
#路由id,全局唯一
- id: order_router
#目标微服务的请求与端口与地址
#uri: http://localhost:8020
#lb 整合负载均衡过期ribbon,loadbalancer
uri: lb://mall-order
predicates:
#cookie匹配
- Cookie=username,tong
Header匹配
spring:
cloud:
gateway:
#设置路由
routes:
#路由id,全局唯一
- id: order_router
#目标微服务的请求与端口与地址
#uri: http://localhost:8020
#lb 整合负载均衡过期ribbon,loadbalancer
uri: lb://mall-order
predicates:
#Header匹配 请求中带有X-Request-Id,其值与 \d+ 正则表达式正整数匹配
- Header=X-Request-Id,\d+
自定义路由断言工厂
@Component
@Slf4j
public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {
public CheckAuthRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
log.info("调用CheckAuthRoutePredicateFactory" + config.getName());
return serverWebExchange -> config.getName().equals("tong");
}
/**
* 需要定义一个内部类,该类用于封装application.yml中的配置
*/
public static class Config {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 快捷配置
* - CheckAuth: tong
* @return
*/
//@Override
//public List<String> shortcutFieldOrder() {
// return Collections.singletonList("name");
//}
}
spring:
cloud:
gateway:
#设置路由
routes:
#路由id,全局唯一
- id: order_router
#目标微服务的请求与端口与地址
#uri: http://localhost:8020
#lb 整合负载均衡过期ribbon,loadbalancer
uri: lb://mall-order
predicates:
#自定义断言工厂
- name: CheckAuth
args:
name: tong
#- CheckAuth: tong
过滤器工厂
添加请求参数与请求头
spring:
cloud:
gateway:
#设置路由
routes:
#路由id,全局唯一
- id: order_router
#配置过滤器工厂
filters:
#添加请求头
- AddRequestHeader=X-Request-color,red
#添加请求参数
- AddRequestParameter=color,blue
添加&去除路径
spring:
cloud:
gateway:
#设置路由
routes:
#路由id,全局唯一
- id: order_router
filters:
#添加前缀 对应的微服务需要配置context-path
- PrefixPath=/mall-order
#去掉一层前缀
- StripPrefix=1
重定向
spring:
cloud:
gateway:
#设置路由
routes:
#路由id,全局唯一
- id: order_router
filters:
#重定向到百度
- RedirectTo=302,https://www.baidu.com
自定义过滤器工厂
spring:
cloud:
gateway:
#设置路由
routes:
#路由id,全局唯一
- id: order_router
filters:
#配置自定义过滤器工厂
- CheckAuth=tong,shuaige
@Component
@Slf4j
public class CheckAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (exchange, chain) -> {
log.info("调用AbstractNameValueGatewayFilterFactory:" + config.getName() + config.getValue());
// TODO
return chain.filter(exchange);
};
}
}
自定义GlobalFilter
@Component
@Slf4j
public class CheckIpFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
HttpHeaders headers = exchange.getRequest().getHeaders();
//模拟IP的访问限制,即不在白名单中就不能调用的需求
if (getIp(headers).equals("127.0.0.1")) {
log.info("---非法访问---");
ServerHttpResponse response = exchange.getResponse();
byte[] bytes = new String("---非法访问---").getBytes();
response.setStatusCode(HttpStatus.NOT_ACCEPTABLE);
DataBuffer buffer = response.bufferFactory().wrap(bytes);
response.getHeaders().add("Context-Type", "application/json;charset=UTF-8");
return exchange.getResponse().writeWith(Mono.just(buffer));
}
return chain.filter(exchange);
}
private String getIp(HttpHeaders headers) {
return headers.getHost().getHostName();
}
@Override
public int getOrder() {
return 0;
}
}
@Component
@Slf4j
public class CheckAuthFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//校验请求头中的token
List<String> token = exchange.getRequest().getHeaders().get("token");
log.info("token:" + token);
if (token.isEmpty()) {
return null;
}
return chain.filter(exchange);
}
}
跨域
spring实现
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsWebFilter(source);
}
}
Gateway配置
spring:
cloud:
gateway:
#跨域
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods:
- GET
- POST
- DELETE
- PUT
- OPTION
网管限流(问题贼鸡儿多)
pom
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
yaml
spring:
cloud:
nacos:
discovery:
server-addr: 139.198.123.65:8848
sentinel:
transport:
dashboard: http://localhost:8080
注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例
@Configuration
public class SentinelConfig {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public SentinelConfig(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolvers;
this.serverCodecConfigurer = serverCodecConfigurer;
}
/**
* 限流异常处理器
* @return
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer);
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter(){
return new SentinelGatewayFilter();
}
}
GatewayRuleManager.loadRules(rules) 手动加载网关规则
@PostConstruct
public void doInit() {
//初始化自定义的api
initCustomizedApis();
//初始化网关限流规则
initGatewayRules();
//自定义限流异常处理器
initBlockRequestHandler();
}
private void initBlockRequestHandler() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
HashMap<String, String> result = new HashMap<>();
result.put("code", String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));
result.put("msg", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(result));
}
};
//设置自定义异常处理器
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
//resource:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称。
//count:限流阈值
//intervalSec:统计时间窗口,单位是秒,默认是 1 秒。
rules.add(new GatewayFlowRule("order_route")
.setCount(2)
.setIntervalSec(1)
);
// 加载网关规则
GatewayRuleManager.loadRules(rules);
}
private void initCustomizedApis() {
Set<ApiDefinition> definitions = new HashSet<>();
ApiDefinition api = new ApiDefinition("order_router")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem().setPattern("/order/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
definitions.add(api);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
