IT虾米网

java之Servlet Gson().toJson 死循环

jackei 2023年12月18日 编程语言 113 0

我在 servlet 中遇到了一些问题,每次我更改下拉菜单中的选项时, 一个不同的值将传递给 servlet,然后它会导致无限循环。当我没有更改下拉列表中的选项(值没有变化)时,没有错误。

这是我的代码:

我的Javascript:

<script> 
 
function loadStaff(){ 
//dropdown 
var positionDropDown = document.getElementById("positionsDropdown"); 
//value of the drop down 
var positionID = positionDropDown.options[positionDropDown.selectedIndex].value; 
 
    $.getJSON('loadStaff?positionID=' + positionID, function(data) { 
            -- no populate code yet 
}); 
} 
</script> 

我的 AjaxServlet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
 
      String userPath = request.getServletPath(); 
 
    if (userPath.equals("/loadStaff")) { 
 
        String positionID = request.getParameter("positionID"); 
        Position position = positionFacade.find(Integer.parseInt(positionID)); 
        Collection staffCollection = position.getStaffCollection(); 
        List<Staff> staffList = new ArrayList(staffCollection); 
 
        String staffListJson = new Gson().toJson(staffList); 
        response.setContentType("application/json"); 
        response.setCharacterEncoding("UTF-8"); 
        response.getWriter().write(staffListJson); 
 
    } 
 
} 

调试时。错误出现在行:

String staffListJson = new Gson().toJson(staffList); 

输出错误:

> INFO:   WebModule[null] ServletContext.log(): The server side 
> component of the HTTP Monitor has detected a 
> java.lang.StackOverflowError. This happens when there is an infinite 
> loop in the web module. Correct the cause of the infinite loop before 
> running the web module again. 
>  
> INFO:   The server side component of the HTTP Monitor has detected a 
> java.lang.StackOverflowError. This happens when there is an infinite 
> loop in the web module. Correct the cause of the infinite loop before 
> running the web module again. WARNING:   
> StandardWrapperValve[AjaxServlet]: Servlet.service() for servlet 
> AjaxServlet threw exception java.lang.StackOverflowError 
 
> WARNING:   StandardWrapperValve[AjaxServlet]: Servlet.service() for 
> servlet AjaxServlet threw exception java.lang.StackOverflowError  at 
> sun.util.calendar.ZoneInfo.getOffsets(ZoneInfo.java:248)  at 
> java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2276) 
>   at 
> java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2248) 
>   at java.util.Calendar.setTimeInMillis(Calendar.java:1140)   at 
> java.util.Calendar.setTime(Calendar.java:1106)    at 
> java.text.SimpleDateFormat.format(SimpleDateFormat.java:955)  at 
> java.text.SimpleDateFormat.format(SimpleDateFormat.java:948)  at 
> java.text.DateFormat.format(DateFormat.java:336)  at 
> com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:90) 
>   at 
> com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:41) 
>   at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
>   at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892)  at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
>   at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
>   at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892)  at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
>   at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
>   at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
>   at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892) 

我还注意到这个跟踪只是堆栈跟踪的重复输出;

编辑: 员工类

@Entity 
public class Staff implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id") 
    private Integer id; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "last_name") 
    private String lastName; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "first_name") 
    private String firstName; 
    @Size(max = 45) 
    @Column(name = "middle_name") 
    private String middleName; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 6) 
    @Column(name = "gender") 
    private String gender; 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "date_of_birth") 
    @Temporal(TemporalType.DATE) 
    private Date dateOfBirth; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "nationality") 
    private String nationality; 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "date_hired") 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date dateHired; 
    @Size(max = 20) 
    @Column(name = "status") 
    private String status; 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "staff") 
    private Collection<StaffApointments> staffApointmentsCollection; 
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "staff") 
    private StaffContact staffContact; 
    @JoinColumn(name = "account_id", referencedColumnName = "id") 
    @ManyToOne(optional = false) 
    private Account accountId; 
    @JoinColumn(name = "position_id", referencedColumnName = "id") 
    @ManyToOne(optional = false) 
    private Position positionId; 
 
    public Staff() { 
    } 
 
    public Staff(Integer id) { 
        this.id = id; 
    } 
 
    public Staff(Integer id, String lastName, String firstName, String gender, Date dateOfBirth, String nationality, Date dateHired) { 
        this.id = id; 
        this.lastName = lastName; 
        this.firstName = firstName; 
        this.gender = gender; 
        this.dateOfBirth = dateOfBirth; 
        this.nationality = nationality; 
        this.dateHired = dateHired; 
    } 
 
    public Integer getId() { 
        return id; 
    } 
 
    public void setId(Integer id) { 
        this.id = id; 
    } 
 
    public String getLastName() { 
        return lastName; 
    } 
 
    public void setLastName(String lastName) { 
        this.lastName = lastName; 
    } 
 
    public String getFirstName() { 
        return firstName; 
    } 
 
    public void setFirstName(String firstName) { 
        this.firstName = firstName; 
    } 
 
    public String getMiddleName() { 
        return middleName; 
    } 
 
    public void setMiddleName(String middleName) { 
        this.middleName = middleName; 
    } 
 
    public String getGender() { 
        return gender; 
    } 
 
    public void setGender(String gender) { 
        this.gender = gender; 
    } 
 
    public Date getDateOfBirth() { 
        return dateOfBirth; 
    } 
 
    public void setDateOfBirth(Date dateOfBirth) { 
        this.dateOfBirth = dateOfBirth; 
    } 
 
    public String getNationality() { 
        return nationality; 
    } 
 
    public void setNationality(String nationality) { 
        this.nationality = nationality; 
    } 
 
    public Date getDateHired() { 
        return dateHired; 
    } 
 
    public void setDateHired(Date dateHired) { 
        this.dateHired = dateHired; 
    } 
 
    public String getStatus() { 
        return status; 
    } 
 
    public void setStatus(String status) { 
        this.status = status; 
    } 
 
    @XmlTransient 
    public Collection<StaffApointments> getStaffApointmentsCollection() { 
        return staffApointmentsCollection; 
    } 
 
    public void setStaffApointmentsCollection(Collection<StaffApointments> staffApointmentsCollection) { 
        this.staffApointmentsCollection = staffApointmentsCollection; 
    } 
 
    public StaffContact getStaffContact() { 
        return staffContact; 
    } 
 
    public void setStaffContact(StaffContact staffContact) { 
        this.staffContact = staffContact; 
    } 
 
    public Account getAccountId() { 
        return accountId; 
    } 
 
    public void setAccountId(Account accountId) { 
        this.accountId = accountId; 
    } 
 
    public Position getPositionId() { 
        return positionId; 
    } 
 
    public void setPositionId(Position positionId) { 
        this.positionId = positionId; 
    } 
 
    @Override 
    public int hashCode() { 
        int hash = 0; 
        hash += (id != null ? id.hashCode() : 0); 
        return hash; 
    } 
 
    @Override 
    public boolean equals(Object object) { 
        // TODO: Warning - this method won't work in the case the id fields are not set 
        if (!(object instanceof Staff)) { 
            return false; 
        } 
        Staff other = (Staff) object; 
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { 
            return false; 
        } 
        return true; 
    } 
 
    @Override 
    public String toString() { 
        return "entity.Staff[ id=" + id + " ]"; 
    } 
 
} 

这也是 Position 类:

@Entity 
public class Position implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id") 
    private Integer id; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "name") 
    private String name; 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "positionId") 
    private Collection<Staff> staffCollection; 
 
    public Position() { 
    } 
 
    public Position(Integer id) { 
        this.id = id; 
    } 
 
    public Position(Integer id, String name) { 
        this.id = id; 
        this.name = name; 
    } 
 
    public Integer getId() { 
        return id; 
    } 
 
    public void setId(Integer id) { 
        this.id = id; 
    } 
 
    public String getName() { 
        return name; 
    } 
 
    public void setName(String name) { 
        this.name = name; 
    } 
 
    @XmlTransient 
    public Collection<Staff> getStaffCollection() { 
        return staffCollection; 
    } 
 
    public void setStaffCollection(Collection<Staff> staffCollection) { 
        this.staffCollection = staffCollection; 
    } 
 
    @Override 
    public int hashCode() { 
        int hash = 0; 
        hash += (id != null ? id.hashCode() : 0); 
        return hash; 
    } 
 
    @Override 
    public boolean equals(Object object) { 
        // TODO: Warning - this method won't work in the case the id fields are not set 
        if (!(object instanceof Position)) { 
            return false; 
        } 
        Position other = (Position) object; 
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { 
            return false; 
        } 
        return true; 
    } 
 
    @Override 
    public String toString() { 
        return "entity.Position[ id=" + id + " ]"; 
    } 
 
} 

编辑 2:

除了 staffCollection 之外,我在 staff 类的属性中添加了 @expose。但我仍然有 1 个问题。每次选择下拉列表中的第一个值(值= 1)时,它仍然会出现无限循环错误。谁能帮帮我?

编辑 3:

修复了!我添加了 final GsonBuilder builder = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation();作为一个整体。现在可以了

请您参考如下方法:

问题是每个Staff对象包含一个包含 Collection 的 Position 对象的 Staff对象,每个对象包含一个 CollectionStaff再次对象等。GSON 将永远继续走这棵树,因为它永远不会停止。

要解决它,您可以查看 this 的答案。问题。


评论关闭
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!