首页 > 解决方案 > Spring Boot 服务方法返回接口页面

问题描述

假设我有一个Stuff这样的界面:

public interface Stuff {
  Long getId();

  String getName();
}

我已经将此接口实现为StuffEntity

@Entity
public class StuffEntity implements Stuff {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  protected Long id;
  protected String name;

  // constructors, getters (implement interface methods), setters, ...
}

我有一个服务接口StuffService

public interface StuffService {
  Page<Stuff> getStuff(Pageable pageable);
}

实现为StuffServiceImpl

@Service
public class StuffServiceImpl implements StuffService {
  @Autowired
  private StuffEntityRepository repository;

  @Overrride
  public Page<Stuff> getStuff(Pageable pageable) {
    Page<StuffEntity> stuffEntityPage = repository.findAll(pageable);
    return new PageImpl<>(stuffEntityPage.getContent().stream()
      .map(Stuff.class::cast)
      .collect(
        Collectors.toList()), 
        stuffEntityPage.getPageable(), 
        stuffEntityPage.getTotalElements()
      );
}

我不喜欢在这里强制转换并创建 的新实例PageImpl,所以我尝试了这样的事情:

public interface StuffService {
  Page<? extends Stuff> getStuff(Pageable pageable);
}
@Service
public class StuffServiceImpl implements StuffService {
  @Autowired
  private StuffEntityRepository repository;

  @Overrride
  public Page<? extends Stuff> getStuff(Pageable pageable) {
    return repository.findAll(pageable);
}

正如我已经说过的,我不喜欢PageImpl在我的服务类中强制转换和创建新实例,但我喜欢这样我的代码看起来更干净。另一种方法不需要PageImpl在我的服务类中强制转换或创建新实例,但我不太担心服务的客户端,因为现在我返回通配符而不是接口。

您认为哪种方法更好?

标签: javaspringspring-boot

解决方案


最好不要使用通配符类型作为返回类型。

强烈建议不要使用通配符类型作为返回类型。因为类型推断规则相当复杂,所以该 API 的用户不太可能知道如何正确使用它。

让我们以返回“List<? extends Animal>”的方法为例。是否可以在此列表中添加一只狗、一只猫……我们根本不知道。编译器也没有,这就是为什么它不允许直接使用。通配符类型的使用应仅限于方法参数。

当方法返回通配符类型时,此规则会引发问题。

资源


推荐阅读