将 Spring hateos ResourceAssembler 迁移到 RepresentationModelAssembler
Migrate Spring hateos ResourceAssembler to RepresentationModelAssembler
据此postResourceAssembler
改为RepresentationModelAssembler
我有这个使用 Spring HATEOAS 1.0 的代码:
import org.springframework.hateoas.ResourceAssembler;
public class BaseAssembler<T extends BaseTransaction, D extends BaseResource>
implements ResourceAssembler<T, D> {
...
}
迁移到 implementation 'org.springframework.boot:spring-boot-starter-hateoas:2.6.4'
之后
我改成了:
public class BaseAssembler<T extends BaseTransaction, D extends BaseResource>
implements RepresentationModelAssembler<T, D> {
.........
}
但是我得到错误:
Type parameter 'D' is not within its bound; should extend 'org.springframework.hateoas.RepresentationModel<?>'
你知道我该如何解决这个问题吗?
编译器报告类型参数 D
不在您定义的范围内:
public class BaseAssembler<T extends BaseTransaction, D extends BaseResource>
implements RepresentationModelAssembler<T, D> {
.........
}
换句话说,就是不能用D extends BaseResource
实现RepresentationModelAssembler<T, D>
(注意这里的类型参数D
),因为那个类型应该扩展'org.springframework.hateoas.RepresentationModel<?>'.
RepresentationModelAssembler
gives you the ability to convert between domain types, your entities, to RepresentationModel
s,一个基于 class 的构想,旨在丰富您的 DTO 以收集链接。
定义如下:
public interface RepresentationModelAssembler<T, D extends RepresentationModel<?>>
再次注意类型参数的定义D
.
在您的代码中,您需要使用如下内容:
public class BaseAssembler<T extends BaseTransaction, D extends RepresentationModel<?>>
implements RepresentationModelAssembler<T, D> {
.........
}
请考虑阅读一些 this or this other 文章,它们提供了各种各样的示例和用例来展示如何实现所需的行为。
例如,给定以下实体,摘自其中一篇被引用的文章:
@Entity
public class Director {
@Id
@GeneratedValue
@Getter
private Long id;
@Getter
private String firstname;
@Getter
private String lastname;
@Getter
private int year;
@OneToMany(mappedBy = "director")
private Set<Movie> movies;
}
以及以下 DTO:
@Builder
@Getter
@EqualsAndHashCode(callSuper = false)
@Relation(itemRelation = "director", collectionRelation = "directors")
public class DirectorRepresentation extends RepresentationModel<DirectorRepresentation> {
private final String id;
private final String firstname;
private final String lastname;
private final int year;
}
您的 RepresentationModelAssembler
看起来像:
@Component
public class DirectorRepresentationAssembler implements RepresentationModelAssembler<Director, DirectorRepresentation> {
@Override
public DirectorRepresentation toModel(Director entity) {
DirectorRepresentation directorRepresentation = DirectorRepresentation.builder()
.id(entity.getId())
.firstname(entity.getFirstname())
.lastname(entity.getLastname())
.year(entity.getYear())
.build();
directorRepresentation.add(linkTo(methodOn(DirectorController.class).getDirectorById(directorRepresentation.getId())).withSelfRel());
directorRepresentation.add(linkTo(methodOn(DirectorController.class).getDirectorMovies(directorRepresentation.getId())).withRel("directorMovies"));
return directorRepresentation;
}
@Override
public CollectionModel<DirectorRepresentation> toCollectionModel(Iterable<? extends Director> entities) {
CollectionModel<DirectorRepresentation> directorRepresentations = RepresentationModelAssembler.super.toCollectionModel(entities);
directorRepresentations.add(linkTo(methodOn(DirectorController.class).getAllDirectors()).withSelfRel());
return directorRepresentations;
}
}
就您的接口和对象模型而言:
@Entity
public class Director extends BaseTransaction{
@Id
@GeneratedValue
@Getter
private Long id;
@Getter
private String firstname;
@Getter
private String lastname;
@Getter
private int year;
@OneToMany(mappedBy = "director")
private Set<Movie> movies;
}
public class DirectorRepresentationAssembler
extends BaseAssembler<Director, DirectorRepresentation>
implements RepresentationModelAssembler<Director, DirectorRepresentation> {
//... the above code
}
DirectorRepresentation
同上。
可能有帮助的Spring HATEOAS reference guide itself provides some guidance as well about the changes performed in Spring HATEOAS 1.0 and about how to migrate from the previous version. It even includes a script
无论如何,如上所述,在您的用例中,您只需要修改 BaseAssembler
接口以根据类型 D extends RepresentationModel<?>
进行定义;然后尝试以某种方式将 BaseResource
关联到 RepresentationModel
或摆脱 BaseResource
并改用 RepresentationModel
。
例如,您可以尝试按如下方式定义 BaseResource
:
public class BaseResource extends RepresentationModel<BaseResource>{
// your implementation
}
那么,绑定就对了:
public class BaseAssembler<T extends BaseTransaction, D extends BaseResource>
implements RepresentationModelAssembler<T, D> {
// your implementation
}
通过这些更改,DirectorRepresentation
将扩展 BaseResource
:
public class DirectorRepresentation extends BaseResource {
}
您可以像这样扩展 BaseAssembler
:
public class DirectorRepresentationAssembler
extends BaseAssembler<Director, DirectorRepresentation>
implements RepresentationModelAssembler<Director, DirectorRepresentation> {
// your implementation
}
在我看来,您在存储库中发布的代码大部分都很好。我认为唯一的问题是 this line of code,正如我之前提到的,我认为您需要在定义 BaseResource
class 时提供类型参数。例如:
package com.hateos.test.entity.web.rest.resource;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.joda.time.DateTime;
import org.springframework.hateoas.RepresentationModel;
import java.util.UUID;
public class BaseResource extends RepresentationModel<BaseResource> {
@JsonProperty
@ApiModelProperty(position = 1, required = true)
public UUID id;
@JsonProperty
public DateTime creationTime;
@JsonProperty
public DateTime lastUpdatedTime;
}
请注意 extends
关键字后包含的代码片段 RepresentationModel<BaseResource>
。
我不确定它是否会工作,但至少有了这个更改,每个编译都很好,而且似乎工作正常。
据此postResourceAssembler
改为RepresentationModelAssembler
我有这个使用 Spring HATEOAS 1.0 的代码:
import org.springframework.hateoas.ResourceAssembler;
public class BaseAssembler<T extends BaseTransaction, D extends BaseResource>
implements ResourceAssembler<T, D> {
...
}
迁移到 implementation 'org.springframework.boot:spring-boot-starter-hateoas:2.6.4'
之后
我改成了:
public class BaseAssembler<T extends BaseTransaction, D extends BaseResource>
implements RepresentationModelAssembler<T, D> {
.........
}
但是我得到错误:
Type parameter 'D' is not within its bound; should extend 'org.springframework.hateoas.RepresentationModel<?>'
你知道我该如何解决这个问题吗?
编译器报告类型参数 D
不在您定义的范围内:
public class BaseAssembler<T extends BaseTransaction, D extends BaseResource>
implements RepresentationModelAssembler<T, D> {
.........
}
换句话说,就是不能用D extends BaseResource
实现RepresentationModelAssembler<T, D>
(注意这里的类型参数D
),因为那个类型应该扩展'org.springframework.hateoas.RepresentationModel<?>'.
RepresentationModelAssembler
gives you the ability to convert between domain types, your entities, to RepresentationModel
s,一个基于 class 的构想,旨在丰富您的 DTO 以收集链接。
定义如下:
public interface RepresentationModelAssembler<T, D extends RepresentationModel<?>>
再次注意类型参数的定义D
.
在您的代码中,您需要使用如下内容:
public class BaseAssembler<T extends BaseTransaction, D extends RepresentationModel<?>>
implements RepresentationModelAssembler<T, D> {
.........
}
请考虑阅读一些 this or this other 文章,它们提供了各种各样的示例和用例来展示如何实现所需的行为。
例如,给定以下实体,摘自其中一篇被引用的文章:
@Entity
public class Director {
@Id
@GeneratedValue
@Getter
private Long id;
@Getter
private String firstname;
@Getter
private String lastname;
@Getter
private int year;
@OneToMany(mappedBy = "director")
private Set<Movie> movies;
}
以及以下 DTO:
@Builder
@Getter
@EqualsAndHashCode(callSuper = false)
@Relation(itemRelation = "director", collectionRelation = "directors")
public class DirectorRepresentation extends RepresentationModel<DirectorRepresentation> {
private final String id;
private final String firstname;
private final String lastname;
private final int year;
}
您的 RepresentationModelAssembler
看起来像:
@Component
public class DirectorRepresentationAssembler implements RepresentationModelAssembler<Director, DirectorRepresentation> {
@Override
public DirectorRepresentation toModel(Director entity) {
DirectorRepresentation directorRepresentation = DirectorRepresentation.builder()
.id(entity.getId())
.firstname(entity.getFirstname())
.lastname(entity.getLastname())
.year(entity.getYear())
.build();
directorRepresentation.add(linkTo(methodOn(DirectorController.class).getDirectorById(directorRepresentation.getId())).withSelfRel());
directorRepresentation.add(linkTo(methodOn(DirectorController.class).getDirectorMovies(directorRepresentation.getId())).withRel("directorMovies"));
return directorRepresentation;
}
@Override
public CollectionModel<DirectorRepresentation> toCollectionModel(Iterable<? extends Director> entities) {
CollectionModel<DirectorRepresentation> directorRepresentations = RepresentationModelAssembler.super.toCollectionModel(entities);
directorRepresentations.add(linkTo(methodOn(DirectorController.class).getAllDirectors()).withSelfRel());
return directorRepresentations;
}
}
就您的接口和对象模型而言:
@Entity
public class Director extends BaseTransaction{
@Id
@GeneratedValue
@Getter
private Long id;
@Getter
private String firstname;
@Getter
private String lastname;
@Getter
private int year;
@OneToMany(mappedBy = "director")
private Set<Movie> movies;
}
public class DirectorRepresentationAssembler
extends BaseAssembler<Director, DirectorRepresentation>
implements RepresentationModelAssembler<Director, DirectorRepresentation> {
//... the above code
}
DirectorRepresentation
同上。
可能有帮助的Spring HATEOAS reference guide itself provides some guidance as well about the changes performed in Spring HATEOAS 1.0 and about how to migrate from the previous version. It even includes a script
无论如何,如上所述,在您的用例中,您只需要修改 BaseAssembler
接口以根据类型 D extends RepresentationModel<?>
进行定义;然后尝试以某种方式将 BaseResource
关联到 RepresentationModel
或摆脱 BaseResource
并改用 RepresentationModel
。
例如,您可以尝试按如下方式定义 BaseResource
:
public class BaseResource extends RepresentationModel<BaseResource>{
// your implementation
}
那么,绑定就对了:
public class BaseAssembler<T extends BaseTransaction, D extends BaseResource>
implements RepresentationModelAssembler<T, D> {
// your implementation
}
通过这些更改,DirectorRepresentation
将扩展 BaseResource
:
public class DirectorRepresentation extends BaseResource {
}
您可以像这样扩展 BaseAssembler
:
public class DirectorRepresentationAssembler
extends BaseAssembler<Director, DirectorRepresentation>
implements RepresentationModelAssembler<Director, DirectorRepresentation> {
// your implementation
}
在我看来,您在存储库中发布的代码大部分都很好。我认为唯一的问题是 this line of code,正如我之前提到的,我认为您需要在定义 BaseResource
class 时提供类型参数。例如:
package com.hateos.test.entity.web.rest.resource;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.joda.time.DateTime;
import org.springframework.hateoas.RepresentationModel;
import java.util.UUID;
public class BaseResource extends RepresentationModel<BaseResource> {
@JsonProperty
@ApiModelProperty(position = 1, required = true)
public UUID id;
@JsonProperty
public DateTime creationTime;
@JsonProperty
public DateTime lastUpdatedTime;
}
请注意 extends
关键字后包含的代码片段 RepresentationModel<BaseResource>
。
我不确定它是否会工作,但至少有了这个更改,每个编译都很好,而且似乎工作正常。