SpringCloud-GateWay工具类

网关常用工具类

过滤器

自定义过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Log4j2
public class UserTokenFilter extends AbstractGatewayFilterFactory {

/**
* 不需要登录的接口
*/
private static final String NO_LOGIN_PATH = "/api/v1/user/user/info/outer";

@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
// 获取请求路径
String path = request.getURI().getPath();
// 如果请求的是这些路径,直接放行
if (path.contains(NO_LOGIN_PATH)) {
return chain.filter(exchange);
}
HttpHeaders headers = request.getHeaders();
// 获取客户端唯一token
String token = headers.getFirst("Authorization");
if (StrUtil.isBlank(token)) {
return FilterErrorUtil.error(exchange, ResponseCode.TOKEN_EXPIRED);
}
try {
String bearer = "Bearer ";
if (!token.contains(bearer)) {
return FilterErrorUtil.error(exchange, ResponseCode.TOKEN_EXPIRED);
}
token = token.replace(bearer, "");
// 判断token是否失效
if (!TokenUtil.checkToken(token)) {
return FilterErrorUtil.error(exchange, ResponseCode.TOKEN_EXPIRED);
}
// 解密token,获取信息,存入请求头
Map map = JSONObject.parseObject(TokenUtil.getUserInfo(token), Map.class);
request.mutate().header(HttpRequestHeaderName.USER_ID, map.get("id").toString());
request.mutate().header(HttpRequestHeaderName.OPEN_ID, map.get("openid").toString());
} catch (Exception e) {
e.printStackTrace();
return FilterErrorUtil.error(exchange, ResponseCode.TOKEN_EXPIRED);
}
return chain.filter(exchange);
};
}

FilterErrorUtil

1
2
3
4
5
6
7
8
9
10
11
public static Mono<Void> error(ServerWebExchange exchange, ResponseCode info) {
ServerHttpRequest request = exchange.getRequest();
log.warn("错误请求,请求路径 {}", request.getURI().getPath());
StrBuilder msg = new StrBuilder();
msg.append("{\"code\":").append(info.getCode()).append(",\"message\":\"").append(info.getMessage()).append("\"}");
byte[] bytes = msg.toString().getBytes(StandardCharsets.UTF_8);
ServerHttpResponse response = exchange.getResponse();
DataBuffer data = response.bufferFactory().wrap(bytes);
response.getHeaders().add("Content-Type", "application/json;charset=utf-8");
return response.writeWith(Flux.just(data));
}

配置类

1
2
3
4
@Bean
public UserTokenFilter userTokenFilter() {
return new UserTokenFilter();
}

微服务拦截

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: user-6004 #socket微服务
uri: lb://user-6004
predicates:
- Path=/api/v1/user/**
filters:
# 自定义过滤器
- UserTokenFilter

统一异常处理

CustomErrorWebFluxAutoConfiguration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass(WebFluxConfigurer.class)
@AutoConfigureBefore(WebFluxAutoConfiguration.class)
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class CustomErrorWebFluxAutoConfiguration {

private final ServerProperties serverProperties;

private final ApplicationContext applicationContext;

private final ResourceProperties resourceProperties;

private final List<ViewResolver> viewResolvers;

private final ServerCodecConfigurer serverCodecConfigurer;

public CustomErrorWebFluxAutoConfiguration(ServerProperties serverProperties,
ResourceProperties resourceProperties,
ObjectProvider<ViewResolver> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer,
ApplicationContext applicationContext) {
this.serverProperties = serverProperties;
this.applicationContext = applicationContext;
this.resourceProperties = resourceProperties;
this.viewResolvers = viewResolversProvider.orderedStream()
.collect(Collectors.toList());
this.serverCodecConfigurer = serverCodecConfigurer;
}

@Bean
@ConditionalOnMissingBean(value = ErrorWebExceptionHandler.class, search = SearchStrategy.CURRENT)
@Order(-1)
public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
JsonErrorWebExceptionHandler exceptionHandler = new JsonErrorWebExceptionHandler(
errorAttributes,
resourceProperties,
this.serverProperties.getError(),
applicationContext);
exceptionHandler.setViewResolvers(this.viewResolvers);
exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
return exceptionHandler;
}

@Bean
@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
public DefaultErrorAttributes errorAttributes() {
return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException());
}
}

JsonErrorWebExceptionHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class JsonErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {

public JsonErrorWebExceptionHandler(ErrorAttributes errorAttributes,
ResourceProperties resourceProperties,
ErrorProperties errorProperties,
ApplicationContext applicationContext) {
super(errorAttributes, resourceProperties, errorProperties, applicationContext);
}

@Override
protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
Throwable error = super.getError(request);
Map<String, Object> errorAttributes = new HashMap<>(8);
errorAttributes.put("message", error.getMessage());
errorAttributes.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
errorAttributes.put("method", request.methodName());
errorAttributes.put("path", request.path());
return errorAttributes;
}

@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}

@Override
protected int getHttpStatus(Map<String, Object> errorAttributes) {
// 这里其实可以根据errorAttributes里面的属性定制HTTP响应码
return HttpStatus.OK.value();
}
}

相关文章

SpringCloud

服务注册与发现

服务调用

SpringCloud-OpenFeign问题

SpringQuartz动态定时任务

DockerCompose常用软件配置

Redis集群搭建

redis分布式锁

服务链路追踪

K8S