Spring-异常处理程序拦截来自另一个bean的响应

时间:2018-09-12 06:10:33

标签: java spring exception-handling

我有两个@RestController-(A和B)并注册了ResponseEntityExceptionHandler。应用异常处理程序后,是否可以(以及如何执行)从A调用并从B获得响应?

示例:

  1. 用户休息呼叫A
  2. AB呼叫getPerson
  3. B引发异常NotFound
  4. NotFound由异常处理程序处理,转换ResponseEntity并置于400状态
  5. B最终返回异常ResponseEntity
  6. AB获得400状态
  7. A可以得到400并对其进行处理

简单的@Autowired无法正常工作。

摘要:

A:

@RestController
@RequestMapping("/v1")
public class A {

    private final B b;

    @Autowired
    public A(B b) {
        this.b = b;
    }

    @PostMapping(
        value = "persons",
        consumes = "application/json",
        produces = "application/json")
    public ResponseEntity<List<StatusResponse<Person>>> addPersons(final List<Person> persons) {
        final List<StatusResponse<Person>> multiResponse = new ArrayList<>();
        for(final Person p: persons) {
            final ResponseEntity<Person> response = b.addPerson(person);
            multiResponse.add(new StatusResponse<>(
                response.getStatusCode(), response.getMessage(), response.getBody()
            ));
        }
        return ResponseEntity.status(HttpStatus.MULTI_STATUS).body(multiResponse);
    }

}

B:

@RestController
@RequestMapping("/v1")
public class B {

    @PostMapping(
        value = "person",
        consumes = "application/json",
        produces = "application/json")
    public ResponseEntity<Person> addPerson(final Person person) {
        accessService.checkAccess();
        return ResponseEntity.status(201).body(
            logicService.addPerson(person)
        );
    }

}

处理程序

@ControllerAdvice
public final class MyExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(MyException.class)
    protected ResponseEntity<Object> handleApiException(final MyException exception, final WebRequest webRequest) {
        //logic
        return afterLogic;
    }

}

1 个答案:

答案 0 :(得分:0)

不可能从异常处理程序中将控制权返回给控制器,该异常处理程序在处理了其方法后将被调用。您当前的流程如下call A.addPersons-> invoke B.addPerson- > B throws exception-> exception is propagate to A controller,并且在处理控制器方法(不是状态为400的ResponseEntity)后,将其另存为dispatchException以便在DispatcherServlet中进行进一步处理->使用MyExceptionHandler处理异常。从这个地方你不能回到控制器。

我不确定要在控制器中使用此异常来做什么,但是解决方案可能如下所示:

@RestController
@RequestMapping("/resources")
public class AController {

    private BService service;

    @Autowired
    public AController(BService service) {
        this.service = service;
    }

    @RequestMapping("/test")
    public ResponseEntity<String> test() {
        ResponseEntity<String> result = service.test();
        if (result.hasBody()) {
            //doSomething
        }

        return result; //or list like you did
    }
}

@Service
public class BService {

    public ResponseEntity<String> test() {
        try {
            return ResponseEntity.status(201).body(getResponse()); //this always throws exception. It's just for purpose of example
        } catch (CustomException ex) {
            return ResponseEntity.status(400).build();
        }

    }

    private String getResponse() {
        throw new CustomException("Not OK!");
    }
}