【问题标题】:Spring - Intercept response from another bean by exception handlerSpring - 通过异常处理程序拦截来自另一个 bean 的响应
【发布时间】:2018-09-12 06:10:33
【问题描述】:

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

例子:

  1. 用户休息电话A
  2. AgetPerson 通话B
  3. B 抛出异常 NotFound
  4. NotFound 由异常处理程序处理,转换 ResponseEntity 并放入 400 状态
  5. B终于返回异常ResponseEntity
  6. AB 获得 400 状态
  7. A 可以得到这个 400 并用它做点什么

简单的@Autowired 不起作用。

片段:

答:

@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);
    }

}

乙:

@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;
    }

}

【问题讨论】:

  • 你能放一些代码sn-p吗?
  • 或多或少会像我更新了一样。
  • 可能会在哪一行抛出MyException?是 logicService.addPerson(person) 吗?
  • MyException 可以是 accessService 的 accessException,也可以是逻辑服务的 notfoundexception/badrequestexception 等。
  • ByeBye 可能是您缺少“@Component 或 @Service”注释。请检查 accessService 或逻辑服务上的注释。

标签: java spring exception-handling


【解决方案1】:

无法从处理其方法后调用的异常处理程序将控制权返回给控制器。您当前的流程如下所示 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!");
    }
}

【讨论】:

  • 不幸的是,异常处理有很多结果,在控制器中简单的映射会产生很多代码重复。好吧,看来这是不可能的了。
  • 你想对 A 控制器中的这个异常做什么?只需将状态为 400 的 StatusResponse 添加到 multiResponse?
  • 或多或少 - 是的,但我需要一个来自异常和消息的特定状态响应。
  • 问题是异常映射器根据类型将许多不同的异常映射到 MyException。我不想在控制器 A 中创建大型多堆缓存。
  • 异常映射器是什么意思?
【解决方案2】:

forward 类似于重定向,但完全发生在服务器端; Servlet 容器将相同的请求转发到目标 URL; URL 不会在浏览器中更改。 在春天你可以这样做,你可以传递属性:

@Controller
@RequestMapping("/")
public class YourController {

    @GetMapping("/forward")
    public ModelAndView redirectWithUsingForwardPrefix(ModelMap model) {
        model.addAttribute("attribute", "forward");
        return new ModelAndView("forward:/redirectedUrl", model);
    }
}

【讨论】:

    猜你喜欢
    • 2018-07-24
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 2018-10-31
    • 2016-05-24
    相关资源
    最近更新 更多