考虑到这一点,我决定尝试我在问题中提到的完成块解决方案。我所有的服务方法现在都有一个结果转换器作为它们的最终参数,它接受模型对象的流并将其转换为视图层需要/请求的任何结果类型。我很高兴地报告它的作用就像一个魅力,并且有一些很好的副作用。
这是我的服务基类:
public class ReadOnlyServiceImpl<MODEL extends AbstractSyncableEntity, DAO extends AbstractSyncableDAO<MODEL>> implements ReadOnlyService<MODEL> {
@Autowired
protected DAO entityDAO;
protected <S> S resultsTransformer(Supplier<Stream<MODEL>> resultsSupplier, Function<Stream<MODEL>, S> resultsTransform) {
try (Stream<MODEL> results = resultsSupplier.get()) {
return resultsTransform.apply(results);
}
}
@Override
@Transactional(readOnly = true)
public <S> S getAll(Function<Stream<MODEL>, S> resultsTransform) {
return resultsTransformer(entityDAO::findAll, resultsTransform);
}
}
这里的resultsTransformer 方法温和地提醒子类不要忘记try-with-resources 模式。
这是一个调用服务基类的示例控制器:
public abstract class AbstractReadOnlyController<MODEL extends AbstractSyncableEntity,
DTO extends AbstractSyncableDTOV2,
SERVICE extends ReadOnlyService<MODEL>>
{
@Autowired
protected SERVICE entityService;
protected Function<MODEL, DTO> modelToDTO;
protected AbstractReadOnlyController(Function<MODEL, DTO> modelToDTO) {
this.modelToDTO = modelToDTO;
}
protected List<DTO> modelStreamToDTOList(Stream<MODEL> s) {
return s.map(modelToDTO).collect(Collectors.toList());
}
// Read All
protected List<DTO> getAll(Optional<String> lastUpdate)
{
if (!lastUpdate.isPresent()) {
return entityService.getAll(this::modelStreamToDTOList);
} else {
Date since = new TimeUtility(lastUpdate.get()).getTime();
return entityService.getAllUpdatedSince(since, this::modelStreamToDTOList);
}
}
}
我认为让控制器通过 Java 8 lambda 来决定服务的返回类型是对泛型的一种非常巧妙的使用。虽然看到 Controller 直接返回 Service 调用的结果对我来说很奇怪,但我很欣赏这段代码的紧凑性和表现力。
我想说,这对于尝试大规模切换到 Java 8 Streams 来说是一个积极的因素。希望这对以后有类似问题的人有所帮助。