转载

java – 混合Spring MVC Spring数据休息导致奇怪的MVC响应

我有两个JPA实体,一个具有SDR导出的存储库,另一个具有Spring MVC控制器和一个未导出的存储库.

MVC暴露实体引用了SDR管理实体.参见下面的代码参考.

从UserController检索用户时,问题出现. SDR管理实体不会序列化,似乎Spring可能正在尝试在响应中使用HATEOAS参考.

以下是完全填充用户的GET如下所示:

{
  "username": "foo@gmail.com",
  "enabled": true,
  "roles": [
    {
      "role": "ROLE_USER",
      "content": [],
      "links": [] // why the content and links?
    }
    // no places?
  ]
}

如何使用嵌入式SDR管理实体清楚地从Controller中返回User实体?

Spring MVC管理

实体

@Entity
@Table(name = "users")
public class User implements Serializable {

    // UID

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonIgnore
    private Long id;

    @Column(unique = true)
    @NotNull
    private String username;

    @Column(name = "password_hash")
    @JsonIgnore
    @NotNull
    private String passwordHash;

    @NotNull
    private Boolean enabled;

    // No Repository
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
    @NotEmpty
    private Set<UserRole> roles = new HashSet<>();

    // The SDR Managed Entity
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "user_place", 
        joinColumns = { @JoinColumn(name = "users_id") }, 
        inverseJoinColumns = { @JoinColumn(name = "place_id")})
    private Set<Place> places = new HashSet<>();

    // getters and setters
}

回购

@RepositoryRestResource(exported = false)
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
    // Query Methods
}

调节器

@RestController
public class UserController {

    // backed by UserRepository
    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @RequestMapping(path = "/users/{username}", method = RequestMethod.GET)
    public User getUser(@PathVariable String username) {
        return userService.getByUsername(username);
    }

    @RequestMapping(path = "/users", method = RequestMethod.POST)
    public User createUser(@Valid @RequestBody UserCreateView user) {
        return userService.create(user);
    }

    // Other MVC Methods
}

SDR管理

实体

@Entity
public class Place implements Serializable {

    // UID

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @NotBlank
    private String name;

    @Column(unique = true)
    private String handle;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "address_id")
    private Address address;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "contact_info_id")
    private ContactInfo contactInfo;

    // getters and setters
}

回购

public interface PlaceRepository extends PagingAndSortingRepository<Place, Long> {
    // Query Methods
}

简而言之:Spring Data REST和Spring HATEOAS劫持ObjectMapper,并希望将资源之间的关系用作链接,而不是嵌入资源.

拿一个与另一个实体有一一对应关系的实体:

@Entity
public class Person {
    private String firstName;
    private String lastName;
    @OneToOne private Address address;
}

SDR / HATEOAS将返回地址作为链接:

{
    "firstName": "Joe",
    "lastName": "Smith",
    "_links": {
        "self": { "href": "http://localhost:8080/persons/123123123" },
        "address": { "href": "http://localhost:8080/addresses/9127391273" }
    }
}

默认格式可以根据您在类路径上的具体情况而有所不同.我相信这是我的例子中的HAL,这是你包括SDR和HATEOAS的默认值.根据所述配置可能不同但相似.

当地址由SDR管理时,Spring将会执行此操作.如果它不是由SDR管理的,那么它将包含响应中的整个地址对象.我怀疑单独解释你所看到的行为.

角色

您没有包含关于UserRole的信息,但是根据您的代码,它似乎可能不在用户管理之外,因此没有注册一个Spring数据存储库.如果是这种情况,那就是为什么它被嵌入 – 没有其他的“链接”的存储库.

角色下的内容和链接看起来像Spring试图将其序列化为一个页面.一般情况下,内容将会有一系列的资源,链接将会有诸如“self”的链接或其他资源的链接.我不知道是什么原因造成的.

地点

Place拥有自己的Spring Data存储库,因此它将被视为一个被管理实体,并且被链接而不是嵌入.我怀疑你正在寻找的是一个投影.结帐春天 documentation on projections .它看起来像这样:

@Projection(name = "embedPlaces", types = { User.class })
interface EmbedPlaces {
    String getUsername();
    boolean isEnabled();
    Set<Place> getPlaces();
}

这应该是序列化用户名,启用和角色,并省略一切.我没有亲自使用预测,所以我不能保证它的工作效率,但这是文档中的解决方案.

编辑:当我们在此时,请注意,这也适用于创建或更新资源. Spring将资源作为URL.因此,如果我正在创建一个新人,我的身体可能看起来像个人/地址示例:

{
    "firstName": "New",
    "lastName": "Person",
    "address": "http://localhost:8080/addresses/1290312039123"
}

很容易忘记这些东西,因为广泛,广泛,广泛,广泛,绝大多数的“REST”API不是REST,SDR / HATEOAS采取REST的观点(例如,应该是REST).

http://stackoverflow.com/questions/37232377/mixing-spring-mvc-spring-data-rest-results-in-odd-mvc-responses

原文  https://codeday.me/bug/20181015/296603.html
正文到此结束
Loading...