我使用 Retrofit2 将一些数据发布到 Spring Boot REST 服务,服务器中发生了很多异常。当我的数据库中有关系时就会发生这种情况。
我在 Spring Boot 应用程序上有一个 REST 服务,该应用程序在 Heroku 服务上运行,我正在使用 Android 应用程序执行登录和注册任务,我在 Android 中使用 Retrofit2 将数据 POST 到 REST 服务,一切一直运行良好,直到由于其他原因我在数据库中的用户之间创建了一个关系,这个关系是一个“follow”,也就是说,在 follow
表中创建一个关系,其中我有 关注的用户的 ID
和关注的用户的 ID
。当我在数据库中创建此关系并尝试使用我创建的方法登录时,我在 REST 服务中遇到了一堆错误,我不知道为什么会发生这种情况。
因此,在 Android 中,我调用了 Retrofit2 客户端以及创建服务的方法,该方法使用 HTTP 方法将 UserService.class
作为参数传递。我还将 User
类的用户作为参数传递,其中包含我想要 POST 的信息,然后调用 enqueue 方法。
RetrofitClient.createService(UserService.class).login(user).enqueue(new CallBack<User>(){
@Override
public void onResponse(Call<User> call, Response<User> response) {
//Some logic here
}
});
在我的 UserService.java
中,我有 POST 用户对象信息的方法。
public interface UserService {
@POST("login")
public Call<User> login(@Body User user);
}
现在在后端,我有一个 REST Controller ,其中有将用于 Retrofit2 的登录端点。
@PostMapping(path = "login", consumes = "application/json", produces = "application/json")
@CrossOrigin(origins = "*", methods= {RequestMethod.GET,RequestMethod.POST})
public Object login(@RequestBody String json) {
//Some logic here
}
正如我所说,当用户与数据库之间没有关系时,此端点运行良好,但是当用户关注另一个用户时,即当后续表中出现新行时,可以说:
如下表:
id_follow id_user_follower id_user_following
1 1 2
在上面的示例中,用户 1 关注用户 2,当我尝试登录时,即使用 UserService
类中的登录方法,它会抛出一堆错误。
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
这重复了 300 多行错误。
这里的问题是,在一堆错误之间,服务器返回 200 HTTP 响应,我在 Spring Boot 中管理了异常,并且捕获了该异常,当捕获时,我将错误代码发送到我的 Android Retrofit2 客户端,但是无法登录。
预期结果:
将 POST 从 Retrofit2 发送到 Spring Boot 后,响应必须是 HTTP 200 响应,但服务器中不得发生异常。
实际结果:
服务器有一个 200 HTTP 响应,但服务器中有很多异常,它们向 Android 应用程序返回错误代码,并且登录不起作用。
这是我想要从 Spring Boot 中的 RestController 以 JSON 形式返回的实体。
@Entity
@Table(name = "users")
public class User extends AuditModel{
private static final long serialVersionUID = 1700575815607801150L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idUser;
private String name;
private String lastName;
@Column(name = "nick_name", unique = true)
private String nickName;
private String avatarResource;
@Column(unique=true)
private String email;
private String password;
private String birthDate;
private String gender;
private String postalCode;
private int active;
public Long getIdUser() {
return idUser;
}
public void setIdUser(Long idUser) {
this.idUser = idUser;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getAvatarResource() {
return avatarResource;
}
public void setAvatarResource(String avatarResource) {
this.avatarResource = avatarResource;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public Long getId() {
return idUser;
}
public void setId(Long idUser) {
this.idUser = idUser;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
/* Relations */
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Comment> comments;
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<UserMemory> userMemories;
public List<UserMemory> getUserMemories() {
return userMemories;
}
public void setUserMemories(List<UserMemory> userMemories) {
this.userMemories = userMemories;
}
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Vote> votes;
public List<Vote> getVotes() {
return votes;
}
public void setVotes(List<Vote> votes) {
this.votes = votes;
}
@OneToMany(mappedBy = "userFollower", fetch = FetchType.LAZY)
private List<Follow> usersFollowers;
public List<Follow> getUsersFollowers() {
return usersFollowers;
}
public void setUsersFollowers(List<Follow> usersFollowers) {
this.usersFollowers = usersFollowers;
}
@OneToMany(mappedBy = "userFollowing", fetch = FetchType.LAZY)
private List<Follow> usersFollowing;
public List<Follow> getUsersFollowing() {
return usersFollowing;
}
public void setUsersFollowing(List<Follow> usersFollowing) {
this.usersFollowing = usersFollowing;
}
}
最佳答案
通过使用fetchtype.LAZY
,某些值在序列化过程中将不存在。这将使 ObjectMapper
尝试获取这些内容,而这一切最终都会陷入某种无限循环。
永远不建议序列化 @Entity
带注释的类,因为数据库表可能会更改,进而会更改调用客户端的 API。
最好的方法是在序列化之前将数据传输到特定的 ResponseDTO
,以便 API 和数据库表可以在不破坏任何内容的情况下进行更改。
关于java - Spring Boot 服务器在使用 Retrofit2 进行 POST 时出错,仅当数据库中存在关系时才会发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57243912/