一、实现背景:
在前后端分离的浪潮下,发现在实现springcloud gateway时,其默认返回的是字符串,这显示与返回的json结构格格不入。因此为了对gateway默认的反馈异常做了改造
二、整体思路:
通过gateway源码发现,其错误顶级接口为WebExceptionHandler,其实现如下:

其中DefaultErrorWebExceptionHandler为最底层的实现类,如果所有实现就重新来完成,这事一个不小的工程,如果自定义一个类,让其实现继承DefaultErrorWebExceptionHandler,然后重写里面的关键方法(getRoutingFunction、renderErrorResponse),这个不为一个好的选择
三、代码实现:
1. pom添加依赖
<!--spring-cloud-starter-gateway 网关依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2.编写代码
自定义异常类:
package com.charlie.cloudgataway.common.error;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: charlie
* @CreateTime: 2022/2/13
* Description: 自定义异常返回信息
*/
public class MyErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {
public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes,ResourceProperties resourceProperties,ErrorProperties errorProperties,ApplicationContext applicationContext) {
super(errorAttributes, resourceProperties, errorProperties, applicationContext);
}
/**
* 指定响应处理方法为Json处理的方法
* @param errorAttributes
* @return
*/
@Override
protected RouterFunctiongetRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(),this::renderErrorResponse);
}
/**
* 重写 renderErrorResponse,自定义响应数据
* @param request 请求参数
* @return
*/
@Override
protected MonorenderErrorResponse(ServerRequest request) {
Throwable throwable =super.getError(request);
Maperror =this.getErrorAttributes(request,this.getErrorAttributeOptions(request,MediaType.ALL));
return ServerResponse.status(this.getHttpStatus(error)).
contentType(MediaType.APPLICATION_JSON).
body(BodyInserters.fromValue(this.response(this.getHttpStatus(error),this.bulidMessage(request,thr owable))));
}
/**
* 根据Code获取对应的HttpStatus
* @param errorAttributes
* @return
*/
@Override
protected int getHttpStatus(Map errorAttributes) {
return (Integer)errorAttributes.get("status");
}
/**
* 构建异常信息
* @param request
* @param ex
* @return
*/
private String bulidMessage(ServerRequest request,Throwable ex) {
StringBuilder message =new StringBuilder("Failed to handle request [");
message.append(request.methodName());
message.append(" ");
message.append(request.uri());
message.append("]");
if(ex !=null) {
message.append(": ");
message.append(ex.getMessage());
}
return message.toString();
}
/**
* 构建返回的json数据格式
*
* @param status 状态码
* @param errorMessage 异常信息
* @return
*/
private Map<String,Object> response(int status,String errorMessage) {
Map<String,Object> map = new HashMap<>();
map.put("code",status);
map.put("message",errorMessage);
map.put("data",null);
return map;
}
}
自定义配置类:
package com.charlie.cloudgataway.config;
import com.charlie.cloudgataway.common.error.MyErrorWebExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;
import java.util.Collections;
import java.util.List;
/**
* @Author: charlie
* @CreateTime: 2022/2/13
* Description: Gateway异常配置类
*/
@Configuration
public class GatewayConfig {
private final ServerProperties serverProperties;
private final ApplicationContext applicationContext;
private final ResourceProperties resourceProperties;
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfig(ServerProperties serverProperties, ApplicationContext applicationContext, ResourceProperties resourceProperties,
ObjectProvider<List<ViewResolver>> viewResolverProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.serverProperties = serverProperties;
this.applicationContext = applicationContext;
this.resourceProperties = resourceProperties;
this.viewResolvers = viewResolverProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean("myErrorWebExceptionHandler")
@Order(Ordered.HIGHEST_PRECEDENCE)
public ErrorWebExceptionHandler myErrorWebExceptionHandler(ErrorAttributes errorAttributes) {
DefaultErrorWebExceptionHandler exceptionHandler = new MyErrorWebExceptionHandler(errorAttributes,
this.resourceProperties,this.serverProperties.getError(),this.applicationContext);
exceptionHandler.setViewResolvers(this.viewResolvers);
exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
return exceptionHandler;
}
}
四、效果对比:
1.重写前 异常访问返回结果

2.重写后 异常访问返回结果

以上的代码是通过本人运行,希望对看到的您有所帮助!对应异常返回的内容及格式,可以参考以上思考实现自定义