前言

在使用 @FeignClient 调用服务时,您可以通过以下方式处理异常。


一、使用全局异常处理自定义返回码

使用该方式,服务端接口http状态码还是200
通用响应类

@Data
public class RestResponse<T> implements Serializable {

    /**
     * 操作返回信息
     */
    private String msg;

    /**
     * 操作返回信息代码
     */
    private Integer code;

    /**
     * 返回具体数据
     */
    private T data;

    public RestResponse<T> success(T data) {
        this.setData(data);
        this.setCode(200);
        this.setMsg("操作成功");
        return this;
    }

    public RestResponse<T> error(Integer code, String msg) {
        this.setCode(code);
        this.setMsg(msg);
        return this;
    }

    public RestResponse error() {
        return error(ResultEnum.UNKNOWN_ERR);
    }

    public RestResponse<T> error(String msg) {
        error();
        this.msg = msg;
        return this;
    }

    public RestResponse<T> error(ResultEnum rsEnum) {
        return error(rsEnum.getCode(), rsEnum.getMessage());
    }

    public RestResponse<T> success() {
        this.code = 200;
        this.msg = "操作成功";
        return this;
    }

    public RestResponse<T> success(ResultEnum resultEnum, T data) {
        this.setCode(resultEnum.getCode());
        this.setMsg(resultEnum.getMessage());
        this.setData(data);
        return this;
    }

    public RestResponse<T> success(Integer code, String message, T data) {
        this.setCode(code);
        this.setMsg(message);
        this.setData(data);
        return this;
    }
}

全局异常处理器

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public RestResponse ExceptionHandler(Exception e) {
        log.error(e.getMessage(), e);
        return new RestResponse().error(500, "接口调用失败");
    }

    // 可以捕获其他类型的异常
}

FeignClient 接口

@Service
@FeignClient(contextId = "TestService", value = "test")
public interface TestService {

    @PostMapping("/open")
    RestResponse<TestResult> test(@RequestBody TestForm form);
}

调用时通过自定义code来判断是否调用成功

RestResponse<TestResult> resp = service.test(form);
if (!"200".equals(resp.getCode())) {
    // 处理错误,抛异常或返回默认结果
    throw new BusinessException(resp.getMessage());
}
TestResult result = resp.getData();

二、使用http状态码

1. 使用 Feign 的 fallback(降级)机制

服务端异常返回非200状态码

@Slf4j
@RestController
@RequestMapping("/open")
public class OpenController {

	@Autowired
    private ITestService service;

	@PostMapping("/test")
	public Object test(TestForm form) {
		try {
            service.test(form);
            return ResponseEntity.ok("成功");
        } catch (Exception e) {
            log.error("失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
	}
}

FeignClient 接口

@Service
@FeignClient(contextId = "TestService", value = "test" fallback = MyFeignClientFallback.class)
public interface TestService {

    @PostMapping("/open")
    TestResult test(@RequestBody TestForm form);
}

MyFeignClientFallback自定义返回

@Component
public class MyFeignClientFallback implements MyFeignClient {
    @Override
    public DataResponse getData() {
        // 这里返回默认值或 null
        return null;
    }
}

2. 使用try catch进行异常捕获

服务端异常返回非200状态码

@Slf4j
@RestController
@RequestMapping("/open")
public class OpenController {

	@Autowired
    private ITestService service;

	@PostMapping("/test")
	public Object test(TestForm form) {
		try {
            service.test(form);
            return ResponseEntity.ok("成功");
        } catch (Exception e) {
            log.error("失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
	}
}

FeignClient 接口

@Service
@FeignClient(contextId = "TestService", value = "test")
public interface TestService {

    @PostMapping("/open")
    TestResult test(@RequestBody TestForm form);
}

客户端调用

try {
    TestResult res = testService.test();
    // 处理正常逻辑
} catch (Exception e) {
    // 处理异常情况,比如记录日志,返回默认值等
    log.error("Feign调用失败", e);
}

3. 使用自定义错误解码器(实现ErrorDecoder接口)

服务端异常返回非200状态码

@Slf4j
@RestController
@RequestMapping("/open")
public class OpenController {

	@Autowired
    private ITestService service;

	@PostMapping("/test")
	public Object test(TestForm form) {
		try {
            service.test(form);
            return ResponseEntity.ok("成功");
        } catch (Exception e) {
            log.error("失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
	}
}

自定义错误解码器

public class CustomErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        // 根据状态码返回不同的异常
        if (response.status() == 404) {
            return new NotFoundException("Resource not found");
        } else if (response.status() == 500) {
            return new InternalServerErrorException("Internal server error");
        }
        return new FeignException("Unknown error");
    }
}

在Feign客户端配置中注入自定义错误解码器

@Configuration
public class FeignConfig {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomErrorDecoder();
    }
}

FeignClient 接口引入自定义错误解码器

@Service
@FeignClient(contextId = "TestService", value = "test", configuration = FeignConfig.class)
public interface TestService {

    @PostMapping("/open")
    TestResult test(@RequestBody TestForm form);
}
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐