java Sping Boot 将字段初始化为空

a64a0gku  于 2023-03-06  发布在  Java
关注(0)|答案(5)|浏览(210)

我有一个控制器,它可以根据id是否为null来查找一个或多个资源。

@GetMapping(value = "/teste")
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<?> find(Optional<ZonaIdDTO> id) {
    if (id.isPresent()) {
        return new ResponseEntity<>(
            this.zonaMapper.toZonaRetrievalDTO(this.zonaService.findById(id.get())),
            HttpStatus.OK
        );
    }

    return new ResponseEntity<>(
        this.zonaService
            .findAll()
            .stream()
            .map(this.zonaMapper::toZonaRetrievalDTO)
            .collect(Collectors.toSet()),
        HttpStatus.OK
    );
}

问题是条件id.isPresent()总是被赋值为false,即使我没有将id传递给控制器,在这种情况下,id对象字段被初始化为null,但是我希望对象本身是null,我该怎么办?
EDIT:非常清楚地说,我想知道为什么当我在没有任何参数的情况下发出请求时,参数id不是null,即使使用ZonaIdDTO代替Optional<ZonaIdDTO>也不起作用,而是将id的所有字段都设置为null
例如:

// `id` should be null here
GET localhost:8080/teste

// `id` shouldn't be null here
GET localhost:8080/teste?a=1&b=2&c=3
fdbelqdn

fdbelqdn1#

正如您在注解中所述,id应该是一个请求参数,并且应该是可选的(可以省略)。

public ResponseEntity<?> find(@RequestParam(required = false) Optional<ZonaIdDTO> id)

Spring需要注解@RequestParam来将id作为请求参数处理,并将其与其他类型的方法参数(路径变量)区分开来。
请检查:baeldung.com/spring-requestparam-vs-pathvariable
属性'required'是用来区分强制参数和可选参数的。请注意命名也很重要。如果请求参数是abc,那么方法参数也必须是abc(至少在默认情况下,可以使用属性'name'覆盖它)。

eqfvzcg8

eqfvzcg82#

java中的可选项不能为空。它必须总是非空的,如果没有数据,id.isPresent()将为假。
如果不需要对象id为空,则需要将函数签名保留为

public ResponseEntity<?> find(ZonaIdDTO id)
ldfqzlk8

ldfqzlk83#

只需将该参数作为可选参数发送即可。

public ResponseEntity<?> find(@RequestBody(required ="false") ZonaIdDTO id) {

if(id != null) {
...
} else {
...
}

}

是的,在控制器层实现逻辑是不好的做法,只需要编写一个服务类并在这个控制器中调用服务类方法。

ndasle7k

ndasle7k4#

这是一个不好的做法。你应该分离你的服务,并且在这一步你不应该有一个可选的。你可以使用可选的提取数据从你的数据库,因为你不确定是否有你所期望的,但与你的客户端,你应该尊重一些合同,只是返回一个异常4xx,如果客户端不尊重合同(Http 400坏请求)。
你的合同应该是
GET /示例:提取所有示例对象
获取/示例/{id}:提取ID由{id}定义的一个示例对象

@GetMapping(value = "/teste/{id}")
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<ZonaRetrievalDTO> getById(@PathVariable(name = "id") Integer id) {
        return new ResponseEntity<>(this.zonaMapper.toZonaRetrievalDTO(this.zonaService.findById(id)),
            HttpStatus.OK
        );
}
@GetMapping(value = "/teste")
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<Set<ZonaRetrievalDTO>> getAll() {
  return new ResponseEntity<>(
    this.zonaService
        .findAll()
        .stream()
        .map(this.zonaMapper::toZonaRetrievalDTO)
        .collect(Collectors.toSet()),
    HttpStatus.OK
  );
}
@PostMapping(value = "/teste")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<ZonaRetrievalDTO> getByCompositeKey(@RequestBody ZonaIdDTO zonaId) throws StructuralEntityException {
    return new ResponseEntity<>(this.zonaMapper.toZonaRetrievalDTO(this.zonaService.findByZonaId(zonaId)),
            HttpStatus.OK
        );
}

在你的开发中尽量避免〈?〉是可读的.你不应该为相同的web服务使用不同的对象

ars1skjm

ars1skjm5#

您的控制器存在设计问题,上面的答案为您提供了解决方法。您试图在应用程序中强制执行与REST架构工作方式不兼容的行为。
1.首先,您的参数应该只是一个DTO,以帮助您将对象解析为json
1.您可以删除方法上的@ResponseStatus(value = HttpStatus.OK),因为您已经返回了OK状态
1.缺省情况下,布尔值始终返回false
1.只需使用ZonaIdDTO作为参数

相关问题