自定义拦截feign错误

Posted 信行合一

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义拦截feign错误相关的知识,希望对你有一定的参考价值。

定义Feign错误处理的Decoder

package com.test.admin.util;

import com.test.admin.util.exception.AdminFeignException;
import feign.Response;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

@Slf4j
public class FeignErrorDecoder implements ErrorDecoder 
    @Override
    public AdminFeignException decode(String methodKey, Response response) 
        log.error("=== 调用FeignClient报错=====");
        log.error("=== FeignClient url:=====", response.request().url());
        log.error("=== FeignClient method:=====", methodKey);
        log.error("=== FeignClient error:=====", response.body());
        log.error("=== 调用FeignClient报错=====");
        if (StringUtils.isBlank(response.reason())) 
            return new AdminFeignException(response.status(), "服务端接口:" + methodKey + "报错!", response.body().toString());
        
        return new AdminFeignException(response.status(), response.reason(), "");
    


生成自定义Decoder实例


import com.test.admin.util.FeignErrorDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 打印feign log
* @Author ztd
*/
@Configuration
public class FeignClientConfig 

    @Bean
    public FeignErrorDecoder feignErrorDecoder() 
        return new FeignErrorDecoder();
    

这样后面出现了Feign相关的错误之后我们就可以通过拦截FeignErrorDecoder错误来明确处理Feign的错误了
举例如下:

@ExceptionHandler(value = Exception.class)
    @ResponseBody
    public AdminResponse defaultErrorHandler(HttpServletRequest req, Exception e, HttpServletResponse response) 
        log.error("====ExceptionHandler Exception 报错====", e);
        if(e instanceof RuntimeException) 
            if(StringUtils.isNotBlank(e.getMessage())) 
                if (e.getMessage().contains("com.netflix.client.ClientException")) 
                    String[] errorArr = e.getMessage().split(":");
                    return AdminResponse.fail("服务端服务不存在:" + errorArr[2]);
                 else if(e instanceof RetryableException) 
                    String[] errorArr = e.getMessage().split("executing");
                    return AdminResponse.fail("服务端服务链接超时:" + errorArr[1]);
                
            
            if (e instanceof UndeclaredThrowableException) 
                if (((UndeclaredThrowableException) e).getUndeclaredThrowable() instanceof AdminFeignException) 
                    AdminFeignException adminFeignException = (AdminFeignException) ((UndeclaredThrowableException) e).getUndeclaredThrowable();
                    AdminResponse fail = AdminResponse.fail(adminFeignException.getMessage());
                    fail.setExtendData(adminFeignException.getExtra());
                    return fail;
                
            
            return AdminResponse.fail(e.getMessage());
        
        if(e instanceof ClientException || e instanceof FeignException) 
            // 处理服务端 服务不存在的问题
            response.setStatus(HttpStatuCodes.CLIENT_NOT_EXISTS);
            return AdminResponse.fail("服务端服务不存在:" + e.getMessage());
         else if(e instanceof NullPointerException) 
            return AdminResponse.fail("NullPointerException: " + e.getMessage());
         else if(e instanceof JSONException) 
            return AdminResponse.fail("Json解析报错: " + e.getMessage());
        
        return AdminResponse.fail("接口内部错误:" + e.getMessage());
    
package com.test.admin.util.response;

import com.test.admin.util.StringUtil;
import com.test.platform.foundation.Response;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;

/**
 * 接口返回实体
 */
@Data
@Slf4j
public class AdminResponse 

   
    public static final int SUCCESS_STATUS = 0;

   
    public static final int FAIL_STATUS = 1;

    /**
     * 返回状态值
     */
    private int status;

    /**
     * 返回描述信息
     */
    private String message;

    /**
     * 返回数据
     */
    private Object Data;

    /**
     * 如果需要返回额外的信息,可以在这里填充
     */
    private Object extendData;

    public AdminResponse(int status) 
        this.status = status;
    

    public boolean isSuccess() 
        return this.status == SUCCESS_STATUS;
    

    public static final AdminResponse success() 
        return success(null);
    

    public static final AdminResponse success(Object data) 
        return success(data, null);
    

    public static final AdminResponse success(Object data, Object extend) 
        return success(data, extend, StringUtil.EMPTY);
    

    public static final AdminResponse success(Object data, Object extend, String msg) 
        AdminResponse response = new AdminResponse(SUCCESS_STATUS);
        response.setData(data);
        response.setExtendData(extend);
        response.setMessage(msg);
        return response;
    

    public static final AdminResponse fail(String message) 
        return fail(FAIL_STATUS, message);
    

    /**
     * 根据给定的 format + message 生成消息
     * @param format
     * @param message
     * @return
     */
    public static final AdminResponse fail(String format, String message) 
        message = String.format(format, message);
        return fail(FAIL_STATUS, message);
    

    public static final AdminResponse fail(String message, String logMsg, String exceptionMsg) 
        log.error(logMsg, exceptionMsg);
        return fail(FAIL_STATUS, message);
    

    public static final AdminResponse fail(int status, String message) 
        AdminResponse response = new AdminResponse(status);
        response.setMessage(message);
        return response;
    

    public static final AdminResponse fail(Object data) 
        AdminResponse response = fail(null);
        response.setData(data);
        return response;
    

    public static final AdminResponse convertResponse(Response response, String msg) 
        if (HttpStatus.OK.value() == response.getCode()) 
            return AdminResponse.success(response.getData());
        
        return AdminResponse.fail(msg);
    


以上是关于自定义拦截feign错误的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Alibaba - 14 OpenFeign自定义配置 + 调用优化 + 超时时间

Feign实现自定义错误处理

spring cloud 服务A调用服务B自定义token消失,记录

我爱java系列---微服务中feign拦截器的使用

Spring Cloud Alibaba全家桶——微服务调用组件Feign

SpringCloudAlibaba微服务组件Feign