Spring Gateway 异常统一拦截返回JSON数据

教程分享 > WEB技术 > JavaScript (3475) 2024-08-07 11:21:12

简介

Spring Cloud Gateway中的全局异常处理不能直接用@ControllerAdvice来处理,通过跟踪异常信息的抛出,找到对应的源码,自定义一些处理逻辑来符合业务的需求。

网关都是给接口做代理转发的,后端对应的都是REST API,返回数据格式都是JSON。如果不做处理,当发生异常时,Gateway默认给出的错误信息是页面,不方便前端进行异常处理。

需要对异常信息进行处理,返回JSON格式的数据给客户端。下面先看实现的代码,后面再跟大家讲下需要注意的地方。

Spring Gateway全局处理

1.添加错误处理类

import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

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.error.ErrorAttributeOptions;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;

/**
 * 自定义异常处理
 *
 * <p>异常时用JSON代替HTML异常信息<p>
 *
 * @author leftso
 *
 */
public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {

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

    /**
     * 获取异常属性
     */
    @Override
    protected Map<String, Object> getErrorAttributes(ServerRequest request,ErrorAttributeOptions options) {
        int code = 888;
        Throwable error = super.getError(request);
        return response(code, this.buildMessage(request, error));
    }

    /**
     * 指定响应处理方法为JSON处理的方法
     * @param errorAttributes
     */
    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    /**
     * 根据code获取对应的HttpStatus
     * @param errorAttributes
     * @return
     */
    @Override
    protected int getHttpStatus(Map<String, Object> errorAttributes) {
        //注意这里必须返回HTTP代码200否则无法显示错误信息
        return 200;
    }

    /**
     * 构建异常信息
     * @param request
     * @param ex
     * @return
     */
    private String buildMessage(ServerRequest request, Throwable ex) {
        StringBuffer message = new StringBuffer("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
     */
    public static Map<String, Object> response(int status, String errorMessage) {
        Result<Object> fail = Result.fail(status, errorMessage);
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(fail));
        return jsonObject;
    }

}
注意事项
  • getHttpStatus(Map<String, Object> errorAttributes)  这个方法的返回值必须是200,其他错误代码会导致后面的json数据不输出,因为走了其他状态码的处理器,为了统一,这里就200,错误信息通过返回对象进行传递。

 

  • response(int status, String errorMessage)方法中的Result为自定义的API通用返回类,可以根据自己情况处理,这里主要就是返回一个map,到时候输出JSON内容就是这个map的值

2.配置启用全局异常处理器
 


import java.util.Collections;
import java.util.List;

import com.glj.gateway.handler.JsonExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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 javax.annotation.Resource;

/**
 * 覆盖默认的异常处理
 *
 * @author leftso
 *
 */
@Configuration
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class ErrorHandlerConfiguration {

    private final ServerProperties serverProperties;

    private final ApplicationContext applicationContext;

    private final ResourceProperties resourceProperties;

    private final List<ViewResolver> viewResolvers;

//    private final ServerCodecConfigurer serverCodecConfigurer;

    @Resource
    ServerCodecConfigurer serverCodecConfigurer;

    public ErrorHandlerConfiguration(ServerProperties serverProperties,
                                     ResourceProperties resourceProperties,
                                     ObjectProvider<List<ViewResolver>> viewResolversProvider,
//                                     ServerCodecConfigurer serverCodecConfigurer,
                                     ApplicationContext applicationContext) {
        this.serverProperties = serverProperties;
        this.applicationContext = applicationContext;
        this.resourceProperties = resourceProperties;
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
//        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Resource
    ErrorAttributes errorAttributes;

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public ErrorWebExceptionHandler errorWebExceptionHandler() {
        JsonExceptionHandler exceptionHandler = new JsonExceptionHandler(
                errorAttributes,
                this.resourceProperties,
                this.serverProperties.getError(),
                this.applicationContext);
        exceptionHandler.setViewResolvers(this.viewResolvers);
        exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
        exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
        return exceptionHandler;
    }
}

搞定收工。。
https://www.leftso.com/article/914.html

相关文章
简介Spring Cloud Gateway中的全局异常处理不能直接用@ControllerAdvice来处理,通过跟踪异常信息的抛出,找到对应的源码,自定义一些处理逻辑来符合业务的需求
学习创建和配置使用JSP 模板文件渲染视图层的Spring Boot jsp 视图解析器
Java编程之Spring Boot中使用jsp视图模板
spring boot 开发技巧,在开发web项目中跳过thyemeleaf模板/js/css等缓存避免每次修改资源文件都需要重启服务器
Spring Boot 2.0 @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") 注解格式化日期失效原因及解决。
一、项目环境Spring Boot 2.1.2.RELEASEshiro-spring 1.4二、去掉URL jsessionid在shiro配置中,配置关闭url中显示sessionId ...
偶然遇到一个spring boot 的接口错误,Content type 'application/json;charset=UTF-8' not supported经过排查发现是参数里面的对象...
在国内项目中,阿里的fastjson包因其使用简单功能强大很多人喜欢在项目中使用,我也是其中一员
handlerexceptionresolver 返回json
前言有时候,我们需要对js的原生对象进行扩展,达到全局使用更方便的效果
jsp中EL表达式获取值中含逆转字符的处理当我们在jsp页面使用EL表达式对input设置value的时候&lt;input type='text' value='$
引言AES代表高级加密系统,它是一种对称加密算法
使用Jackson写巨大的JSON文件
       学习使用Gson JsonReader类,这是一个基于拉的流式JSON解析器,它有助于将JSON作为标记流来读取​GSON1. JsonReader是什么JsonReader是流式...
Java EE 8 JSON Pointer讲解,Java EE 8包含JSON处理API的更新,并为最新的JSON标准提供最新的IEFT标准。