我正在编写Spring应用程序,我想将其分为几层,以将域与框架完全分开。
因此,我的域方法返回了vavr的Either<Error, T>
,而我的控制器对所有这些方法都使用了简单的解析器。
<T> ResponseEntity resolve(Either<Error, T> either) {
return either
.map(this::successResponse)
.getOrElseGet(this::failureResponse);
}
private ResponseEntity<Object> successResponse(Object obj) {
return new ResponseEntity<>(mapper.toDto(obj), HttpStatus.OK);
}
问题是,我不想从控制器返回域实体,所以我编写了通用映射器,该映射器将使用单个方法将每个域对象转换为其dto。
public <T, Y> Y toDto(T domainObject) {
if(domainObject instanceof Reservation) {
return (Y) reservationMapper.toDto((Reservation)domainObject);
}
return null;
}
Reservation
和ReservationMapper
在这里是一个域的具体实现,当然可以用更好的解决方案代替if
,但事实并非如此。情况是,它不起作用。它抛出
java.lang.ClassCastException:类
com.johndoe.reservationsystem.adapter.dto.ReservationDto不能为
强制转换为类org.springframework.util.MultiValueMap
我发现一种解决方法是创建一个空的抽象类
Dto
,使我所有的dto类都对此进行扩展,并仅在Dto
方法中返回Y
而不是toDto
。关键是,我不是很喜欢它,我想找到更好的解决方案。可能不是必需的,但这是
ReservationMapper
的实现class ReservationMapper {
ReservationDto toDto(Reservation reservation) {
return ReservationDto.builder()
.id(reservation.getId())
.ownerId(reservation.getOwnerId())
.reservedObjectId(reservation.getReservedObjectId())
.title(reservation.getTitle())
.description(reservation.getDescription())
.startDate(reservation.getStartDate())
.endDate(reservation.getEndDate())
.build();
}
}
最佳答案
您的方法签名
public <T, Y> Y toDto(T domainObject)
引起了这个问题,因为在您调用的上下文中
return new ResponseEntity<>(mapper.toDto(obj), HttpStatus.OK)
解释为好像可以返回
MultiValueMap<String, String>
以符合构造函数public ResponseEntity(MultiValueMap<String, String> headers, HttpStatus status)
参见javadoc:
ResponseEntity(MultiValueMap<String, String>, HttpStatus)
通过修改您的
toDto
方法以使其明确表示绝对不会返回MultiValueMap
,您可以解决此问题。例如,仅指定:public Object toDto(Object domainObject)
对于转换方法可能会做到这一点。或者,您可以约束您的通用参数,以便明确表明它无法基于其调用当前所在的类型推断上下文返回任意类型的实例。
关于java - 返回泛型类型时发生ClassCastException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57082424/