Spring Cloud Gateway 网关


<!--网关--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--nacos discovery--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
server:
port: 8080
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: 192.168.87.133:8848
gateway:
routes:
- id: item-service
uri: lb://item-service
predicates:
- Path=/items/**,/search/**
- id: cart
uri: lb://cart-service
predicates:
- Path=/carts/**
- id: user
uri: lb://user-service
predicates:
- Path=/users/**,/addresses/**
- id: trade
uri: lb://trade-service
predicates:
- Path=/orders/**
- id: pay
uri: lb://pay-service
predicates:
- Path=/pay-orders/**
default-filters:
- AddRequestHeader=truth, blue
路由断言

路由过滤

登录实现


自定义过滤器

nettyRouting优先级默认是最小的, 因此指定一个较大的数即可
package com.hmall.gateway.filters;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class MyGlobalFilter implements GlobalFilter , Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// TODO 模拟登录检验
ServerHttpRequest request = exchange.getRequest();
HttpHeaders headers = request.getHeaders();
System.out.println(headers);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
实现
网关
- 这里没有进行传递用户
package com.hmall.gateway.filters;
import cn.hutool.core.text.AntPathMatcher;
import com.hmall.common.exception.UnauthorizedException;
import com.hmall.gateway.config.AuthProperties;
import com.hmall.gateway.utils.JwtTool;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.List;
@RequiredArgsConstructor
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
private final AuthProperties authProperties;
private final JwtTool jwtTool;
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取request对象
ServerHttpRequest request = exchange.getRequest();
// 2. 判断是否需要做登录拦截
List<String> excludePaths = authProperties.getExcludePaths();
RequestPath path = request.getPath();
if(isExclude(path.toString(),excludePaths)){
// 放行
return chain.filter(exchange);
}
// 3. 获取token
String token = null;
List<String> tokens = request.getHeaders().get("authorization");
if(tokens!=null&&!tokens.isEmpty()){
token = tokens.get(0);
}
Long userId = null;
// 4. 校验解析token, 获取用户信息
try {
userId = jwtTool.parseToken(token);
} catch (UnauthorizedException e) {
// 401 表示未登录
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
Mono<Void> voidMono = exchange.getResponse().setComplete();
return voidMono;
}
// 5. 保存用户信息到请求头
System.out.println("userId = "+userId);
return chain.filter(exchange);
}
private boolean isExclude(String path, List<String> excludePaths) {
for (String excludePatten : excludePaths) {
if(antPathMatcher.match(excludePatten, path)){
return true;
}
}
return false;
}
@Override
public int getOrder() {
return 0;
}
}
网关到微服务
- 因为微服务都引用了
common包, 因此将拦截器放到common中
public class UserInfoInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1. 获取登录信息
String userInfo = request.getHeader("user-info");
// 2. 判断是否获取了用户
if(StrUtil.isNotBlank(userInfo)){
// 3. 存入 threadLocal UserContext.setUser(Long.valueOf(userInfo));
}
// 4. 放行
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 清理用户
UserContext.removeUser();
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserInfoInterceptor());
}
}
-
因为
common包不会被微服务包扫描, 因此@Configuration不会生效, 因此 -
网关引入 配置类后报错, 因为网关不是
springBoot, 因此设置自定配置类的生效条件
微服务到微服务
- 是由
openFeign发起的



- 使
feign配置类生效


