首页 > 解决方案 > Optional 在返回值为 null 时不抛出异常

问题描述

我正在学习 Spring Boot,当服务在数据库上找不到项目时,我试图抛出异常,因此,我尝试了可选但当我测试它时,除了异常之外,我只得到一个空响应

    @GetMapping(value = "/compras", produces = "application/json")
public Optional<Compras> retrieveAllCompras(@RequestParam String id) {
    return Optional.of(compraRepository.findById(id)).orElseThrow(RuntimeException::new);

当在数据库中找不到该项目时,我希望出现异常

标签: javaspring-bootjava-8responseoptional

解决方案


Optional.of期望纯值。您也可以在文档中找到信息,

/**
 * Constructs an instance with the described value.
 *
 * @param value the non-{@code null} value to describe
 * @throws NullPointerException if value is {@code null}
 */
private Optional(T value) {
    this.value = Objects.requireNonNull(value);
}

例子,

jshell> Optional.of(100)
$2 ==> Optional[100]

jshell> Optional.of(null)
|  Exception java.lang.NullPointerException
|        at Objects.requireNonNull (Objects.java:221)
|        at Optional.<init> (Optional.java:107)
|        at Optional.of (Optional.java:120)
|        at (#1:1)

如果您的值可能null在运行时,您可以使用.ofNullable,

jshell> Optional.ofNullable(null)
$3 ==> Optional.empty

ALSO 函数式编程的思想是为所有输入返回一个值,而不是抛出Exception破坏函数组合的值。

jshell> Function<Integer, Optional<Integer>> f = x -> Optional.of(x + 1)
f ==> $Lambda$23/0x0000000801171c40@6996db8

jshell> Function<Integer, Optional<Integer>> g = x -> Optional.of(x * 2)
g ==> $Lambda$24/0x0000000801172840@7fbe847c

jshell> f.apply(5).flatMap(x -> g.apply(x))
$13 ==> Optional[12]

因此,在您的示例中,您可以将Optional.empty()其视为 item not found,但 Spring 也会考虑这一点,200这仍然比 throwing 更好500您可能希望发送404准确。

@GetMapping(
  value = "/compras", 
  produces = "application/json"
)
public Optional<Compras> retrieveAllCompras(@RequestParam String id) {
    return Optional.ofNullable(compraRepository.findById(id)); //will response as 200 even when no item found
}

您可以使用ResponseEntity<A>设置特定的http状态

传统的响应方式404定义特定的异常

import org.springframework.web.server.ResponseStatusException;
import org.springframework.http.HttpStatus;

@GetMapping(
  value = "/compras", 
  produces = "application/json"
)
public Compras retrieveAllCompras(@RequestParam String id) {
    return Optional.ofNullable(compraRepository.findById(id))
                   .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "item not found"))
}

推荐阅读