Java 当返回值为null时,Optional不会引发异常

Java 当返回值为null时,Optional不会引发异常,java,spring-boot,java-8,response,optional,Java,Spring Boot,Java 8,Response,Optional,我正在学习SpringBoot,当服务在数据库中找不到项目时,我试图抛出一个异常,因此,我尝试使用optional,但当我测试它时,除了异常之外,我只得到一个空响应 @GetMapping(value = "/compras", produces = "application/json") public Optional<Compras> retrieveAllCompras(@RequestParam String id) { return Optional.of(

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

    @GetMapping(value = "/compras", produces = "application/json")
public Optional<Compras> retrieveAllCompras(@RequestParam String id) {
    return Optional.of(compraRepository.findById(id)).orElseThrow(RuntimeException::new);
@GetMapping(value=“/compras”,products=“application/json”)
公共可选retrieveAllCompras(@RequestParam字符串id){
返回可选的.of(comparepository.findById(id)).OrelsThrow(RuntimeException::new);

当在数据库中找不到该项时,我预计会出现异常

可选。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)
同时 函数式编程的思想是为所有输入返回一个值,而不是抛出破坏函数组合的异常

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]
你可以用

响应
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"))
}

控制器返回
可选
。这意味着不会调用
#get
方法。如果
可选
值,控制器将返回null


更改为:
public Compras retrieve allcompras…
,您将获得异常

请考虑此处的类型,如果您想返回可选,您将执行一个
。orElse
,您必须再次包装它。这将是一种方法:

    @GetMapping(value = "/compras", produces = "application/json")
public Optional<Compras> retrieveAllCompras(@RequestParam String id) {
    return Optional.of(compraRepository.findById(id)).orElseThrow(RuntimeException::new);
 @GetMapping(value = "/compras", produces = "application/json")
public Optional<Compras> retrieveAllCompras(@RequestParam String id) {
    return Optional.ofNullable(compraRepository.findById(id)).
                     map(Optional::of).
                     orElseThrow(() -> new RuntimeException("Not found"));
@GetMapping(value=“/compras”,products=“application/json”)
公共可选retrieveAllCompras(@RequestParam字符串id){
返回可选的.ofNullable(comparepository.findById(id))。
映射(可选::of)。
OrelsThrow(()->新运行时异常(“未找到”);
我会解释:

  • Optional.ofNullable()
    将返回一个
    Optional
    ,其值为
    Optional(“一些压缩机”)
    或值为
    Optional.Empty
  • map(Optional::of)
    将再次包装可选项,因此您将拥有
    Optional[Optional]
    或(这里的技巧)Optional.Empty,因为map不包装可选项。Empty(这是他与我们在一起的原因)
  • 最后,
    orelsetrow(()->new RuntimeException(“Not found”)
    将解包可选的,在本例中是从
    optional[optional]
    解包到
    optional
    ,或者,如果是
    optional.Empty
    它将抛出异常

  • 根据对象名称和调用的方法(
    comparepository.findById(id)
    )判断,您的服务实际上是一个存储库。如果它是一个Spring数据存储库,那么您应该将
    的创建留给Spring数据:。因此

    compraRepository.findById(id).orElseThrow(NotFoundException::new)
    

    很好,我应该添加optional.empty,如果是的话,通过告诉item not found right?返回新的响应,非常感谢!是的,您可以将http响应代码设置为
    404
    。Spring默认情况下,如果一切顺利,可以让您发回
    200
    ,如果抛出一般异常,则可以让您发回
    500
    。但是您知道
    500
    表示服务器错误。在您的示例中,如果项目未找到理想的
    404
    @Santiagomolanoperdomo,我添加了一个示例,该示例将在
    可选时发送
    404
    。空的
    非常感谢!我不知道ResponeStatusException,我是通过创建一个新类来实现的,非常感谢!这确实是ex的定义有力的回答!加一!
    
    compraRepository.findById(id).orElseThrow(NotFoundException::new)