一、网关的概述
(1)什么是网关
二、网关路由
1.快速入门
(1)创建新模块
(2)引入网关依赖
<!--网关-->
<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>
<!--负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
(3)编写启动类
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
(4)配置路由规则
spring:
application:
name: gateway
cloud:
nacos:
server-addr: localhost:8848
gateway:
routes:
- id: item # 路由规则id,自定义,唯一
uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表
predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务
- Path=/items/**,/search/** # 这里是以请求路径作为判断规则
2.路由属性
网关路由对应的Java类型是RouteDefinition,其中常见的属性有:
- id:路由唯一标示
- uri:路由目标地址
- predicates:路由断言,判断请求是否符合当前路由。
- filters:路由过滤器,对请求或响应做特殊处理。
(1)路由断言
(2)路由过滤器
- 局部生效
- 全局生效
三、 网关及其数据传递
1. 网关请求处理流程
(1) 如何在网关转发之前做登录校验(自定义过滤器)
- 在过滤器(pre)中进行登录校验
(2)网关如何将用户信息传递给微服务
- 保存用户到请求头
(3)微服务之间怎么传递用户信息
2.自定义过滤器
网关过滤器有两种,分别是:
- GatewayFilter:路由过滤器,作用于任意指定的路由;默认不生效,要配置到路由后生效。
- GlobalFilter:全局过滤器,作用范围是所有路由;声明后自动生效
(1)自定义GlobalFilter(主要使用)
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 模拟登录校验逻辑
HttpHeaders headers = exchange.getRequest().getHeaders();
log.info("请求头:{}", headers);
// 放行
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
(2)自定义GatewayFilter
略
3.网关传递用户
(1)在自定义过滤器中,把获取到的用户写入请求头
(2)各个服务在进入controller时先将用户信息存入threadLocal
@Slf4j
public class UserInfoInterceptor implements HandlerInterceptor {
private static final ThreadLocal<Long> tl = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// controller 之前执行
// 1.获取登录用户信息
String userId = request.getHeader("user-info");
log.info("mvc拦截器获取用户信息:{}",userId);
if (StrUtil.isNotBlank(userId)){
// 2.判断是否获取用户,如果有,存入threadLocal
UserContext.setUser(Long.parseLong(userId));
}
// 3.放行
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// controller执行完后,清理用户
UserContext.removeUser();
}
}
@Configuration
@ConditionalOnClass(DispatcherServlet.class)
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserInfoInterceptor());
}
}
4.OpenFeign传递用户
(1)OpenFeign提供的拦截器(每次请求都会调用它)
@Component
public class UserInfoRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
template.header("user-info", String.valueOf(UserContext.getUser()));
}
}