GateWay是微服务开发中不可或缺的组件之一,为微服务架构的系统提供简单、有效且统一的API路由管理,配有多个服务的项目情况下,可以作为系统的统一入口,提高系统的整体性和统一性。下面根据SpringCloud Alibaba中项目的实际应用,详细说明网关的功能配置。
文章目录
一、版本与依赖
Springboot版本:2.6.6
SpringCloud版本:2021.0.1
SpringCloud Alibaba版本:2021.1
以下的配置都是按照这些版本来的,不同的版本配置会有一些差异
二、注册中心、配置中心的配置
在yml中配置注册中心、配置中心,我这边选用的是nacos,可以按照自己的项目需求选用注册、配置中心工具
spring:
application:
name: demo-gateway
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: 45e44563-14eb-4fe1-b5e2-5f7011d0bbb8
config:
server-addr: 127.0.0.1:8848
file-extension: yml
shared-configs:
- application-${
spring.profiles.active}.${
spring.cloud.nacos.config.file-extension}
refresh-enabled: true
namespace: 45e44563-14eb-4fe1-b5e2-5f7011d0bbb8
三、路由规则设置
1. 关键字说明
id:微服务的ID
uri:微服务对应的目标URL
predicates:断言,根据路径断言路由到对应微服务上
2. 配置示例
spring:
application:
name: demo-gateway
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: 45e44563-14eb-4fe1-b5e2-5f7011d0bbb8
config:
server-addr: 127.0.0.1:8848
file-extension: yml
shared-configs:
- application-${
spring.profiles.active}.${
spring.cloud.nacos.config.file-extension}
refresh-enabled: true
namespace: 45e44563-14eb-4fe1-b5e2-5f7011d0bbb8
gateway:
discovery:
locator:
enabled: true
# 路由规则
routes:
- id: demo-order
uri: lb://demo-order
predicates:
- Path=/order/**
- id: demo-member
uri: lb://demo-member
predicates:
- Path=/member/**
- id: demo-tool
uri: lb://demo-tool
predicates:
- Path=/tool/**
四、网关跨域解决
新增配置类如下:
/**
* 网关跨域配置
*/
@Configuration
public class GWCrosConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 允许cookies跨域
config.addAllowedOriginPattern("*");// 放行哪些原始域
config.addAllowedHeader("*");// #允许访问的头信息,*表示全部
config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
config.addAllowedMethod("OPTIONS");// 允许提交请求的方法类型,*表示全部允许
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
五、网关过滤器的设置
1. 网关过滤器实现
@Component
public class GatewayFilter implements GlobalFilter, Ordered {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 网关过滤器进行token拦截
*/
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//根据配置中心的文件判断是否需要token验证
if (!ConfigRefresh.tokenEnabled) {
return chain.filter(exchange);
}
//token非空验证
List<String> tokenLst = exchange.getRequest().getHeaders().get("token");
ServerHttpResponse response = exchange.getResponse();
if (tokenLst == null || tokenLst.size() == 0) {
try{
DataBuffer buffer = getResBuffer(response, 10001, "token为空,请携带token");
return response.writeWith(Mono.just(buffer));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//从集合中获取header携带的token
String token = tokenLst.get(0);
Long expire = redisTemplate.getExpire(token);
if (expire > 0) {
//token验证成功
return chain.filter(exchange);
}
//token验证失败
try{
DataBuffer buffer = getResBuffer(response,10002, "token验证失败");
return response.writeWith(Mono.just(buffer));
} catch (Exception e) {
return null;
}
}
public int getOrder() {
return 0;
}
/**
* 设置拦截之后返回的json
*/
private DataBuffer getResBuffer(ServerHttpResponse response, int code, String msg) throws Exception {
Map<String,Object> respData = new HashMap<String, Object>();
respData.put("code",code);
respData.put("msg",msg);
ObjectMapper objectMapper = new ObjectMapper();
byte[] bytes = objectMapper.writeValueAsBytes(respData);
DataBuffer buffer = response.bufferFactory().wrap(bytes);
response.setStatusCode(HttpStatus.OK);
response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
return buffer;
}
}
2. 拦截后返回标准json数据
六、不拦截指定路径设置(针对某个服务)
例如:对tool服务不做过滤拦截
1. 配置不拦截指定路径工厂
@Component
public class IgnoreGlobalFilterFactor extends AbstractGatewayFilterFactory {
public IgnoreGlobalFilterFactor() {
super(Config.class);
}
@Override
public GatewayFilter apply(Object config) {
return this::filter;
}
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
exchange.getAttributes().put(com.ebt.gateway.filter.GatewayFilter.ATTRIBUTE_IGNORE_GLOBAL_FILTER, true);
return chain.filter(exchange);
}
public static class Config {
}
@Override
public String name() {
return "IgnoreGlobalFilter";
}
}
2. yml中配置不拦截指定路径
3. 过滤器中配置
4. 设置顺序优先级,确保IgnoreGlobalFilterFactor先执行
七、无需认证地址的设置(针对某个url)
1. yml中配置无需认证地址
2. 配置组件读取地址信息
@Component
@ConfigurationProperties("spring.cloud.gateway")
public class NotAuthUrlProperties {
private LinkedHashSet<String> shouldSkipUrls;
public LinkedHashSet<String> getShouldSkipUrls() {
return shouldSkipUrls;
}
public void setShouldSkipUrls(LinkedHashSet<String> shouldSkipUrls) {
this.shouldSkipUrls = shouldSkipUrls;
}
}