mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-20 02:08:15 +08:00
异常全局处理
This commit is contained in:
parent
08c88e9e27
commit
783a3f9946
@ -1,10 +1,12 @@
|
||||
package com.ruoyi.gateway.config;
|
||||
|
||||
import com.ruoyi.gateway.config.handler.GlobalErrorWebExceptionHandler;
|
||||
import com.ruoyi.gateway.config.provider.RedisRouteDefinitionRepository;
|
||||
import com.ruoyi.gateway.filter.CustomerGlobalFilter;
|
||||
import com.ruoyi.gateway.ratelimit.CustomerRedisRateLimiter;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
|
||||
@ -53,4 +55,9 @@ public class GatewayConfig
|
||||
{
|
||||
return new CustomerGlobalFilter(customerRedisRateLimiter);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ErrorWebExceptionHandler errorWebExceptionHandler() {
|
||||
return new GlobalErrorWebExceptionHandler();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
package com.ruoyi.gateway.config.handler;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 网关异常通用处理器,只作用在webflux 环境下 , 优先级低于 {@link ResponseStatusExceptionHandler} 执行
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-10-18
|
||||
*/
|
||||
@Slf4j
|
||||
@Order(-1)
|
||||
public class GlobalErrorWebExceptionHandler implements ErrorWebExceptionHandler {
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex)
|
||||
{
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
|
||||
if (response.isCommitted()) {
|
||||
return Mono.error(ex);
|
||||
}
|
||||
|
||||
// header set
|
||||
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
if (ex instanceof ResponseStatusException) {
|
||||
final ResponseStatusException statusException = (ResponseStatusException) ex;
|
||||
response.setStatusCode(statusException.getStatus());
|
||||
}
|
||||
Optional<Integer> code = Optional.ofNullable(response.getRawStatusCode());
|
||||
final String message = getMessage(ex);
|
||||
|
||||
return response.writeWith(Mono.fromSupplier(() -> {
|
||||
DataBufferFactory bufferFactory = response.bufferFactory();
|
||||
return bufferFactory.wrap(JSONUtil.toJsonStr(result(code, message))
|
||||
.getBytes(StandardCharsets.UTF_8));
|
||||
}));
|
||||
}
|
||||
|
||||
private String getMessage(Throwable ex)
|
||||
{
|
||||
if(ex instanceof ResponseStatusException) {
|
||||
String reason = ((ResponseStatusException) ex).getReason();
|
||||
log.info(reason);
|
||||
return reason;
|
||||
}
|
||||
String message = ex.getMessage();
|
||||
log.error(message, ex);
|
||||
return message;
|
||||
}
|
||||
|
||||
private Map<String, Object> result(Optional<Integer> code, String message) {
|
||||
final HashMap<String, Object> result = MapUtil.newHashMap(3);
|
||||
result.put("code", code.orElse(HttpStatus.INTERNAL_SERVER_ERROR.value()));
|
||||
result.put("message", message);
|
||||
result.put("data", null);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.ruoyi.gateway.constant;
|
||||
|
||||
/**
|
||||
* 错误消息常量
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-10-18
|
||||
*/
|
||||
public interface ErrorMessageConstant {
|
||||
String AK_REQUIRE = "没有找到授权码";
|
||||
String CONTENT_TYPE_NOT_SUPPORTED = "请求ContentType不支持";
|
||||
String METHOD_NOT_SUPPORTED = "请求Method不支持";
|
||||
String RATE_LIMIT = "调用次数过多";
|
||||
String RULE_EXPIRED = "规则已过期";
|
||||
String RULE_NOT_EXIST = "规则不存在";
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package com.ruoyi.gateway.exception;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||
|
||||
/**
|
||||
* 网关异常-AK必要
|
||||
@ -8,7 +8,10 @@ import lombok.NoArgsConstructor;
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-10-04
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class AkRequireException extends GatewayException {
|
||||
|
||||
public AkRequireException()
|
||||
{
|
||||
super(ErrorMessageConstant.AK_REQUIRE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.ruoyi.gateway.exception;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||
|
||||
/**
|
||||
* 网关异常-请求方法不支持
|
||||
@ -8,7 +8,10 @@ import lombok.NoArgsConstructor;
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-10-04
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class ContentTypeNotSupportedException extends GatewayException {
|
||||
|
||||
public ContentTypeNotSupportedException()
|
||||
{
|
||||
super(ErrorMessageConstant.CONTENT_TYPE_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.ruoyi.gateway.exception;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
/**
|
||||
* 网关异常
|
||||
@ -8,7 +9,30 @@ import lombok.NoArgsConstructor;
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-10-04
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class GatewayException extends RuntimeException {
|
||||
public class GatewayException extends ResponseStatusException {
|
||||
|
||||
public GatewayException(String reason)
|
||||
{
|
||||
super(HttpStatus.INTERNAL_SERVER_ERROR, reason);
|
||||
}
|
||||
|
||||
public GatewayException(HttpStatus status)
|
||||
{
|
||||
super(status);
|
||||
}
|
||||
|
||||
public GatewayException(HttpStatus status, String reason)
|
||||
{
|
||||
super(status, reason);
|
||||
}
|
||||
|
||||
public GatewayException(HttpStatus status, String reason, Throwable cause)
|
||||
{
|
||||
super(status, reason, cause);
|
||||
}
|
||||
|
||||
public GatewayException(int rawStatusCode, String reason, Throwable cause)
|
||||
{
|
||||
super(rawStatusCode, reason, cause);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.ruoyi.gateway.exception;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||
|
||||
/**
|
||||
* 网关异常-请求方法不支持
|
||||
@ -8,7 +8,10 @@ import lombok.NoArgsConstructor;
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-10-04
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class MethodNotSupportedException extends GatewayException {
|
||||
|
||||
public MethodNotSupportedException()
|
||||
{
|
||||
super(ErrorMessageConstant.METHOD_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
package com.ruoyi.gateway.exception;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* 网关异常-限流异常
|
||||
@ -11,18 +9,10 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-10-04
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class RateLimitException extends GatewayException {
|
||||
|
||||
private TimeUnit timeUnit;
|
||||
private int replenishRate;
|
||||
private int tokensLeft;
|
||||
private String message;
|
||||
public RateLimitException(int replenishRate, int tokensLeft, TimeUnit timeUnit) {
|
||||
this.replenishRate = replenishRate;
|
||||
this.tokensLeft = tokensLeft;
|
||||
this.timeUnit = timeUnit;
|
||||
String unit = StrUtil.upperFirst(timeUnit.name().toLowerCase());
|
||||
message = String.format("服务限流: 上限[%d/%s], 实际[%d/%s]", replenishRate, unit, tokensLeft, unit);
|
||||
public RateLimitException()
|
||||
{
|
||||
super(HttpStatus.TOO_MANY_REQUESTS, ErrorMessageConstant.RATE_LIMIT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.ruoyi.gateway.exception;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||
|
||||
/**
|
||||
* 网关异常-规则已过期
|
||||
@ -8,7 +8,10 @@ import lombok.NoArgsConstructor;
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-10-04
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class RuleExpiredException extends GatewayException {
|
||||
|
||||
public RuleExpiredException()
|
||||
{
|
||||
super(ErrorMessageConstant.RULE_EXPIRED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.ruoyi.gateway.exception;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||
|
||||
/**
|
||||
* 网关异常-规则不存在
|
||||
@ -8,7 +8,10 @@ import lombok.NoArgsConstructor;
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-10-04
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class RuleNotExistException extends GatewayException {
|
||||
|
||||
public RuleNotExistException()
|
||||
{
|
||||
super(ErrorMessageConstant.RULE_NOT_EXIST);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@ import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
@ -34,7 +33,6 @@ import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setResponseStatus;
|
||||
import static org.springframework.util.CollectionUtils.unmodifiableMultiValueMap;
|
||||
|
||||
/**
|
||||
@ -310,9 +308,7 @@ public class CustomerGlobalFilter implements GlobalFilter, Ordered {
|
||||
}
|
||||
return rateLimiter(exchange, rule, route, index + 1, rateLimiterAfterSupplier);
|
||||
}
|
||||
setResponseStatus(exchange, HttpStatus.TOO_MANY_REQUESTS);
|
||||
exchange.getResponse().setComplete();
|
||||
return Mono.error(new RateLimitException(limit.intValue(), 1, timeUnit));
|
||||
return Mono.error(RateLimitException::new);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user