You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中为对象列表布尔字段绑定复选框报错排查

问题解决:Spring表单复选框绑定布尔字段报错

技术栈

  • java 8
  • spring Boot 2.2.11.RELEASE
  • spring 5.2.10.RELEASE
  • hibernate 5.4.22.FINAL
  • mysql-connector-java 8.0.22
  • eclipse oxygen
  • straight JSP, no Thymeleaf

问题描述

尝试在表单中渲染对象列表,其中对象包含boolean类型字段,需要与对应的复选框绑定。目前其他字段均正常工作,仅该布尔字段绑定复选框时出现问题。

实体类代码

public class PhoneNumberByAreaCodeSelected extends PhoneNumberByAreaCode implements java.io.Serializable {

    private static final long serialVersionUID = 3628007212507237450L;

    private boolean selected;

    //constructors
    public PhoneNumberByAreaCodeSelected() {}
    public PhoneNumberByAreaCodeSelected( String areaCode, String state, BigInteger total, boolean selected) {
        super(areaCode, state, total);
        this.selected = selected;
    }
    public PhoneNumberByAreaCodeSelected( PhoneNumberByAreaCode obj) {
        super.setAreaCode( obj.getAreaCode());
        super.setState( obj.getState());
        super.setTotal(obj.getTotal());
        this.selected = false;
    }
    
    //getters and setters
    public boolean isSelected() {
        return selected;
    }
    public boolean getSelected() {
        return selected;
    }
    public void setSelected(boolean selected) {
        this.selected = selected;
    }
}

表单后台Bean代码

public class PhoneNumberByAreaCodeSelectedList {

    private List<PhoneNumberByAreaCodeSelected> lisst;

    //constructors
    public PhoneNumberByAreaCodeSelectedList() { 
        this.lisst = new ArrayList<PhoneNumberByAreaCodeSelected>();
    }
    public PhoneNumberByAreaCodeSelectedList( List<PhoneNumberByAreaCodeSelected> lisst) {
        this.lisst = lisst;
    }
    
    //getters and setters
    public List<PhoneNumberByAreaCodeSelected> getLisst() {
        return lisst;
    }
    public void setLisst(List<PhoneNumberByAreaCodeSelected> lisst) {
        this.lisst = lisst;
    }
}

控制器代码

@RequestMapping(value="/list_phone_numbers_by_area_code", method = RequestMethod.GET)
@ModelAttribute("phoneNumberByAreaCodeSelectedList")
public ModelAndView showListPhoneNumbersForm( ) {
    
    List<PhoneNumberByAreaCode> lisst = service.groupPhoneNumbersByStateAndAreaCode();
    
    List<PhoneNumberByAreaCodeSelected> lisst_selected = new LinkedList<>();
    ListIterator<PhoneNumberByAreaCode> li = lisst.listIterator();
    while( li.hasNext()) {
        lisst_selected.add( new PhoneNumberByAreaCodeSelected( li.next()));
    }
    
    PhoneNumberByAreaCodeSelectedList obj = new PhoneNumberByAreaCodeSelectedList();
    obj.setLisst(lisst_selected);
        
    ModelAndView mv = new ModelAndView();
    mv.setViewName("list_phone_numbers_by_area_code");
    mv.addObject("cnt", obj.getLisst().size());
    mv.addObject("phoneNumberByAreaCodeSelectedList", obj);
    mv.addObject("timestamp", Utilities.getCurrentTimestamp());

    return mv;
}

@RequestMapping(value="/list_phone_numbers_by_area_code", method = RequestMethod.POST)
@ModelAttribute("phoneNumberByAreaCodeSelectedList")
public ModelAndView handleListPhoneNumbersForm( PhoneNumberByAreaCodeSelectedList obj, BindingResult result) {
    List<PhoneNumberByAreaCodeSelected> lisst = obj.getLisst();
    
    ModelAndView mv = new ModelAndView();
    mv.setViewName("create_campaign");        
    mv.addObject("cnt", lisst.size());
    mv.addObject("groups", lisst );
    mv.addObject("timestamp", Utilities.getCurrentTimestamp());
    
    return mv;
}

原正常显示的JSP代码

<body>
  ${cnt} elements in lisst on server side
  <br>
  <form:form modelAttribute="phoneNumberByAreaCodeSelectedList" method="post">
  <div class="container">
      <table>
        <thead>
          <tr>
            <th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
            <th>areaCode</th>
            <th>state</th>
            <th>total</th>
          </tr>
        </thead>
        <tbody>
          <c:forEach items="${phoneNumberByAreaCodeSelectedList.lisst}" var="item" varStatus="loop">
            <tr>
              <td>${item.areaCode}</td>
              <td>${item.state}</td>
              <td>${item.total}</td>
            </tr>
          </c:forEach>
        </tbody>
      </table>
      <br>
      <input type="reset"  value="Reset" />
      <input type="submit" value="Cancel" />
      <input type="submit" value="Submit"/>
    </div>
  </form:form>
  <br>
  <nav class="navbar navbar-default navbar-fixed-bottom">
    <div class="container-fluid">
      <div align="center">generated ${timestamp}</div>
    </div>
  </nav> 
</body>

添加复选框后报错的JSP代码

<body>
  ${cnt} elements in lisst on server side
  <br>
  <form:form modelAttribute="phoneNumberByAreaCodeSelectedList" method="post">
  <div class="container">
      <table>
        <thead>
          <tr>
            <th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
            <th>areaCode</th>
            <th>state</th>
            <th>total</th>
          </tr>
        </thead>
        <tbody>
          <c:forEach items="${phoneNumberByAreaCodeSelectedList.lisst}" var="item" varStatus="loop">
            <tr>
              <td><form:checkbox path="items[${loop.index}].selected" name="selected" value="${item.selected}"/></td>   <!-- added -->
              <td>${item.areaCode}</td>
              <td>${item.state}</td>
              <td>${item.total}</td>
            </tr>
          </c:forEach>
        </tbody>
      </table>
      <br>
      <input type="reset"  value="Reset" />
      <input type="submit" value="Cancel" />
      <input type="submit" value="Submit"/>
    </div>
  </form:form>
  <br>
  <nav class="navbar navbar-default navbar-fixed-bottom">
    <div class="container-fluid">
      <div align="center">generated ${timestamp}</div>
    </div>
  </nav> 
</body>

报错信息

Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'items[0]' of bean class [com.faxcount.application.model.PhoneNumberByAreaCodeSelectedList]: Bean property 'items[0]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

解决办法

报错原因很明确:你在form:checkbox的path属性中使用了items[${loop.index}].selected,但你的表单BeanPhoneNumberByAreaCodeSelectedList中存储列表的字段是lisst,而非items,Spring无法找到对应的getItems()方法,因此抛出属性不可读异常。

修改JSP中的复选框代码,将path改为lisst[${loop.index}].selected,并且不需要手动指定name和value属性,Spring表单标签会自动处理这些属性并完成绑定:

<td><form:checkbox path="lisst[${loop.index}].selected"/></td>

修改后的完整JSP代码如下:

<body>
  ${cnt} elements in lisst on server side
  <br>
  <form:form modelAttribute="phoneNumberByAreaCodeSelectedList" method="post">
  <div class="container">
      <table>
        <thead>
          <tr>
            <th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
            <th>areaCode</th>
            <th>state</th>
            <th>total</th>
          </tr>
        </thead>
        <tbody>
          <c:forEach items="${phoneNumberByAreaCodeSelectedList.lisst}" var="item" varStatus="loop">
            <tr>
              <td><form:checkbox path="lisst[${loop.index}].selected"/></td>
              <td>${item.areaCode}</td>
              <td>${item.state}</td>
              <td>${item.total}</td>
            </tr>
          </c:forEach>
        </tbody>
      </table>
      <br>
      <input type="reset"  value="Reset" />
      <input type="submit" value="Cancel" />
      <input type="submit" value="Submit"/>
    </div>
  </form:form>
  <br>
  <nav class="navbar navbar-default navbar-fixed-bottom">
    <div class="container-fluid">
      <div align="center">generated ${timestamp}</div>
    </div>
  </nav> 
</body>

这样修改后,Spring就能正确识别列表字段,完成复选框与selected布尔字段的绑定,提交表单后也能正确获取选中状态。

内容的提问来源于stack exchange,提问作者code_warrior

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 01:44:58