侧边栏壁纸
博主头像
浅醉谷博主等级

行动起来,活在当下

  • 累计撰写 6 篇文章
  • 累计创建 10 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

FeignClient调用异常处理+Hystrix

浅醉
2024-06-15 / 0 评论 / 0 点赞 / 42 阅读 / 8408 字 / 正在检测是否收录...

1 整合hystrix实现异常回调

hystrix是于熔断、降级等的组件,在springboot中可以很容易的FeignClient进行整合从而实现异常回调和处理。

依赖引入:

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.7.RELEASE</version>
        </dependency>

开启hystrix组件功能:在启动类上添加该注解,用于开启Hystrix的功能

@EnableHystrix  // 该注解上已经添加有 @EnableCircuitBreaker

开启Feign和hystrix的整合:在application.properties中添加(整合Feign和Hystrix的关键,否则可能导致异常回调功能不生效)

#开启feignClient和hystrix的整合,@EnableCircuitBreaker 注解是单独开启服务熔断降级,而没有和feignClient整合
#所以添加@EnableCircuitBreaker并不能是FeignClient的fallBack生效
feign.hystrix.enabled=true

1.1 FallBack回调类实现

FeignClient代码和配置:使用fallBack属性,定义fallback实现类

import com.alibaba.fastjson.JSONObject;
import com.htb.thirdclient.fallback.BaiDuCollectClientFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

@FeignClient(value = "baiDuCollectClient", url = "http://data.zz.baidu.com", fallback = BaiDuCollectClientFallback.class)  
public interface BaiDuCollectClient {

    @PostMapping("/urls?site={site}&token={token}")
    JSONObject send(@PathVariable("site")String site, @PathVariable("token")String token, String url);
}

BaiDuCollectClientFallback 代码实现:(这种方式无法在回调中获取到异常信息)

import com.alibaba.fastjson.JSONObject;
import com.htb.thirdclient.BaiDuCollectClient;
import org.springframework.stereotype.Component;

/**
 * FeignClient+Hystrix整合异常回调实现类示例
 * 缺点:这种方式无法获取到异常信息
 */
@Component
public class BaiDuCollectClientFallback implements BaiDuCollectClient {
    @Override
    public JSONObject send(String site, String token, String url) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("msg", "调用异常了");
        return jsonObject;
    }
}

1.2 FallBackFactory回调工厂类实现

FeignClient代码和配置:使用fallbackFactory 参数,实现FallbackFactory接口

import com.alibaba.fastjson.JSONObject;
import com.htb.thirdclient.fallback.BaiDuCollectClientFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

@FeignClient(value = "baiDuCollectClient", url = "http://data.zz.baidu.com", fallbackFactory = BaiDuCollectClientFallbackFactory.class) 
public interface BaiDuCollectClient {

    @PostMapping("/urls?site={site}&token={token}")
    JSONObject send(@PathVariable("site")String site, @PathVariable("token")String token, String url);
}

BaiDuCollectClientFallbackFactory代码实现:(这种方式可以获取到具体的异常信息)

import com.alibaba.fastjson.JSONObject;
import com.htb.thirdclient.BaiDuCollectClient;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

/**
 * FeignClient+Hystrix整合异常回调工厂示例
 * 优点:这种方式可以获取到具体的异常信息
 */
@Component
public class BaiDuCollectClientFallbackFactory implements FallbackFactory<BaiDuCollectClient> {
    @Override
    public BaiDuCollectClient create(Throwable throwable) {
        return new BaiDuCollectClient() {
            @Override
            public JSONObject send(String site, String token, String url) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("site", site);
                jsonObject.put("url", url);
                jsonObject.put("error", throwable.getMessage());
                return jsonObject;
            }
        };
    }
}

2 自定义异常处理配置

FeignClient代码和配置:

import com.alibaba.fastjson.JSONObject;
import com.htb.thirdclient.baidu.BaiDuFeignConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

@FeignClient(value = "baiDuCollectClient", url = "http://data.zz.baidu.com", configuration = BaiDuFeignConfig.class)
public interface BaiDuCollectClient {

    @PostMapping("/urls?site={site}&token={token}")
    JSONObject send(@PathVariable("site")String site, @PathVariable("token")String token, String url);
}

BaiDuFeignConfig实现:

import feign.codec.ErrorDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class BaiDuFeignConfig {
 
    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomErrorDecoder();
    }
}

自定义异常处理:CustomErrorDecoder

package com.htb.thirdclient.baidu;

import feign.Response;
import feign.codec.ErrorDecoder;
import feign.Util;
import java.io.IOException;
import org.springframework.http.HttpStatus;
 
public class CustomErrorDecoder implements ErrorDecoder {
 
    @Override
    public Exception decode(String methodKey, Response response) {
        String body = "";
        try {
            if (response.body() != null) {
                body = Util.toString(response.body().asReader());
            }
        } catch (IOException e) {
            // 处理读取响应体时的异常
            e.printStackTrace();
        }

        HttpStatus status = HttpStatus.valueOf(response.status());
        switch (status) {
            case BAD_REQUEST:
                return new BadRequestException("Bad request error: " + body);
            case NOT_FOUND:
                return new NotFoundException("Resource not found: " + body);
            case INTERNAL_SERVER_ERROR:
                return new InternalServerErrorException("Internal server error: " + body);
            default:
                return new GeneralFeignException("General error: " + body, response.status());
        }
    }
 
    // 自定义异常类
    public static class BadRequestException extends RuntimeException {
        public BadRequestException(String message) {
            super(message);
        }
    }
 
    public static class NotFoundException extends RuntimeException {
        public NotFoundException(String message) {
            super(message);
        }
    }
 
    public static class InternalServerErrorException extends RuntimeException {
        public InternalServerErrorException(String message) {
            super(message);
        }
    }
 
    public static class GeneralFeignException extends RuntimeException {
        private final int status;
 
        public GeneralFeignException(String message, int status) {
            super(message);
            this.status = status;
        }
 
        public int getStatus() {
            return status;
        }
    }
}

0

评论区