Spring Feign客户端调用应保留在try块中时进入异常块

时间:2018-10-19 08:20:38

标签: spring spring-boot exception-handling spring-cloud-feign feign

需要有关Spring Feign客户端的一些小帮助。这就是这种情况,

我有2个Spring Boot服务。假设服务A和服务B。我已经使用Feign客户端配置了服务A,通过该客户端我可以调用服务B方法。

这是我的服务A的代码,

我的FeignCleint配置界面,

@FeignClient(name = "FeignClient", url = "http://localhost:8081/ServiceB/hello")
public interface FeignApi {

    @RequestMapping(method = RequestMethod.GET)
    ResponseEntity<?> hello();
}

我的rest控制器使用上面的伪装配置来调用Service B方法,

@RestController
public class ApiController {

    @Autowired
    private FeignApi feignApi;

    @RequestMapping(value = "/callServiceB")
    public ResponseEntity<?> companyInfo() {
        ResponseEntity<?> response = new ResponseEntity("OK Response", HttpStatus.OK);
        try {
            response = feignApi.hello();

            // Code for some other things related to application.

            return response;
        } catch (Exception ex) {
            System.out.println("Service A Exception block reached.");
            return new ResponseEntity(ex.getMessage(), HttpStatus.BAD_REQUEST);
        }
    }
}

以下是我对服务B的控制权

@RestController
public class MyController {

    @GetMapping("/hello")
    public String hello() throws Exception {

        if (true) {
            throw new Exception("Service B Exception...");
        }
        return "Hello World";
    }
}

还有我的Controller建议来处理我手动抛出的异常,

@ControllerAdvice
public class MyControllerAdvice {

    @ExceptionHandler
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity<?> handleException(Exception exception, Model model) {
        return new ResponseEntity<>("Caused due to : " + exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

现在我的流程如下 如您所见,我正在使用伪客户端从服务A调用服务B。我的服务B正在手动抛出一个异常,该异常是我使用控制器建议捕获的,并将异常详细信息作为ResponseEntity发送给调用服务A。以便服务A可以处理这些详细信息并基于此继续前进。

问题是,当我使用

拨打服务A的电话时
  

http://localhost:8080/feign/callServiceB

服务B按预期失败。现在,我期望的是服务A应该以ResponseEntity的形式返回响应。但是真正发生的是,流程进入了异常块,而不是停留在try块中。我可以看到这行打印出来,

"Service A Exception block reached."

这是我不明白的。如果我已经使用控制器建议管理了服务B异常,并以ResponseEntity的形式将响应发送回了服务A,那么服务A的流程如何进入catch块。我希望它仅在我想根据数据进行进一步处理时才保留在try块中。

任何想法,我该如何解决?还是即使我正在使用控制器建议来管理异常时,它的行为如何?在这种情况下,预期的行为应该是什么?

请咨询。

2 个答案:

答案 0 :(得分:0)

默认情况下,Feign会针对任何错误情况抛出FeignException。 利用后备机制处理故障。

<form class="post-form" method="post" enctype="multipart/form-data">
        {%csrf_token%}
        {{form.as_p}}
        <button type="submit" class="save btn btn-default">Submit</button>
        </form>

确保您添加以下属性以在最新版本的hystrix命令中包装方法

@FeignClient(name = "FeignClient", url = "http://localhost:8081/ServiceB/hello", fallback= FeignApiFallback.class)
public interface FeignApi {

    @RequestMapping(method = RequestMethod.GET)
    ResponseEntity<?> hello();
}

@Component
class FeignApiFallback implements FeignApi {

    @Override
    public ResponseEntity<?> hello() {
        //do more logic here
        return ResponseEntity.ok().build();
    }

}

答案 1 :(得分:0)

除200以外的任何状态,假冒客户端都将其视为异常,并且您在控制器建议中设置HttpStatus.INTERNAL_SERVER_ERROR。

您可以使用自定义的ErrorDecoder

推荐https://github.com/OpenFeign/feign/wiki/Custom-error-handling