使用网关异常处理类来返回给前端错误信息的json数据,可处理的类别如全局过滤器、局部过滤器中校验失败的信息。如token信息的校验,没有token时的错误信息的返回,供前端进行相应处理!
步骤:皆在网关模块操作
- 创建自定义的异常类
//自定义异常.传入对应异常信息即可
public class IllegalTokenException extends RuntimeException {
public IllegalTokenException(String message) {
super(message);
}
}
- 创建网关异常处理器
场景:在网关过滤器中,token信息未通过校验的时候
@Configuration
public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler {
//日志对象
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionConfiguration.class);
@Override //参数1: request response ex:出现异常时异常对象
public Mono handle(ServerWebExchange exchange, Throwable ex) {
//存放响应到response的数据
Map result = new HashMap<>(1);
//1.获取响应对象
ServerHttpResponse response = exchange.getResponse();
//2.response是否结束 用于多个异常处理时候
if (response.isCommitted()) {
return Mono.error(ex);
}
//2.设置响应头类型
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
//3.设置响应状态吗
if (ex instanceof IllegalTokenException) {
response.setStatusCode(HttpStatus.FORBIDDEN);
} else {
response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
}
//4.设置响应内容
return response
.writeWith(Mono.fromSupplier(() -> {
DataBufferFactory bufferFactory = response.bufferFactory();
log.error("msg:",ex);
result.put("msg", ex.getMessage());
ObjectMapper objectMapper = new ObjectMapper();
try {
//设置响应到response的数据
return bufferFactory.wrap(objectMapper.writevalueAsBytes(result));
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}));
}
}
- 在局部、全局过滤器中对相关不合法或异常情况进行手动抛出即可
@Component public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory{ private final static Logger log = LoggerFactory.getLogger(MyParamGatewayFilterFactory.class); public MyParamGatewayFilterFactory() { super(Config.class); } @Override public List shortcutFieldOrder() { //指定把yaml配置的过滤器的值赋值给配置类的param属性。 - MyParam=name即param=name //如果Config中定义了多个属性时候传入即可。例如声明了config中有name和age 配置文件中为- MyParam=name,age //return Arrays.asList("param","age"); return Arrays.asList("param"); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { log.info("进入过滤器"); // http://localhost:9090/admins/demos?name=yh 相当于config.param ==> name //获取请求参数中param对应的参数名 的参数值 ServerHttpRequest request = exchange.getRequest(); if (request.getQueryParams().containsKey(config.param)){//此处循环遍历是因为可以为一个参数名称指定多个值。如name=yh&name=zq //一般一个属性只给传一个值 //String value=request.getQueryParams().get(config.param).get(0); request.getQueryParams().get(config.param).forEach((v) -> { log.info("获得请求的参数::"+config.param+"="+ v); //做相应的业务处理 }); } else { throw new IllegalTokenException("no params name!"); } return chain.filter(exchange);//执行请求 }; } public static class Config{ //对应配置在application.yml配置文件中的过滤器参数名 private String param; public String getParam() { return param; } public void setParam(String param) { this.param = param; } } }
- 配置局部过滤器
在网关配置文件的filters下添加即可
server:
port: 9090
spring:
# application:
# name: API-GATEWAY
cloud:
# nacos:
# server-addr: 8.142.68.138:8848
gateway:
routes: #配置路由规则
# admins
- id: admins_router
# 配置路由到的地址ip:port
uri: lb://API-ADMINS
# 配置路径的映射
predicates:
- Path=/admins/**
filters:
# 去除断言前的路径.1代表去除一级
- StripPrefix=1
#局部过滤器名字的前部分
- MyParam=name
- 使用网关访问配置了局部过滤器的请求,没有name参数会报错
这样可以很好的向前端返回数据而不是404
完结撒花



