复选框Spring MVC表单绑定错误

时间:2013-08-03 11:07:12

标签: spring spring-mvc

我有一个学生班,与学科班级有一对多关联:

public class Student implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = -779930820340758193L;
    private int studentId;
    private String studentName;
    private List<Subject> subjectList;


    public Student(int studentId, String studentName, List<Subject> subjectList) {
        super();
        this.studentId = studentId;
        this.studentName = studentName;
        this.subjectList = subjectList;
    }
    public Student() {
    }
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getStudentName() {
        return studentName;
    }
    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }
    public List<Subject> getSubjectList() {
        return subjectList;
    }
    public void setSubjectList(List<Subject> subjectList) {
        this.subjectList = subjectList;
    }
    @Override
    public String toString() {
        return "Student [studentId=" + studentId + ", studentName="
                + studentName + ", subjectList=" + subjectList + "]";
    }


}

主题:

public class Subject implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 7135393884889475409L;
    private int subjectId;
    private String subjectName;

    public Subject(int subjectId, String subjectName) {
        super();
        this.subjectId = subjectId;
        this.subjectName = subjectName;
    }
    public int getSubjectId() {
        return subjectId;
    }
    public void setSubjectId(int subjectId) {
        this.subjectId = subjectId;
    }
    public String getSubjectName() {
        return subjectName;
    }
    public void setSubjectName(String subjectName) {
        this.subjectName = subjectName;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + subjectId;
        result = prime * result
                + ((subjectName == null) ? 0 : subjectName.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Subject other = (Subject) obj;
        if (subjectId != other.subjectId)
            return false;
        if (subjectName == null) {
            if (other.subjectName != null)
                return false;
        } else if (!subjectName.equals(other.subjectName))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "Subject [subjectId=" + subjectId + ", subjectName="
                + subjectName + "]";
    }

}

我的控制器返回所有科目的列表以及学生注册的科目,以便在视图中默认选中它们。

控制器:

public class HelloController{

   @RequestMapping(value = "", method = RequestMethod.GET)
   public String printHello(ModelMap model) {
      model.addAttribute("message", "Hello Spring MVC Framework!");

      List<Subject> allList = new ArrayList<Subject>();
      allList.add(new Subject(1,"English"));
      allList.add(new Subject(2,"Maths"));
      allList.add(new Subject(3,"Science"));
      allList.add(new Subject(4,"Social"));
      allList.add(new Subject(5,"Tamil")); 

      List<Subject> enrolledList = new ArrayList<Subject>();
      enrolledList.add(new Subject(1,"English")); 
      enrolledList.add(new Subject(3,"Science"));

      Student student = new Student(1,"SRI",enrolledList);
      model.addAttribute("student", student);
      model.addAttribute("availableList", allList);
      return "home";
   }

   @RequestMapping(value = "save" , method = RequestMethod.POST)
   public String saveStudent(@ModelAttribute Student student , ModelMap model){
       System.out.println(">>>>>>>>>>>>"+student);
       model.addAttribute("finalStudent", student); 
       return "success";
   }

针对home.jsp

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Hello World</title>
</head>
<body>
    <h2>${student.studentName}</h2>
    <form:form method="POST" action="save" modelAttribute="student">
        <form:checkboxes title="Subjects taken" path="subjectList"
            items="${availableList}" itemLabel="subjectName" element="div" />
        <input type = "submit" value = "Save"/>
    </form:form>
</body>
</html>

但是,在此表单的sumbit上,我收到以下错误:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'student' on field 'subjectList': rejected value [Subject [subjectId=1, subjectName=English],Subject [subjectId=3, subjectName=Science]]; codes [typeMismatch.student.subjectList,typeMismatch.subjectList,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.subjectList,subjectList]; arguments []; default message [subjectList]]; default message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.List' for property 'subjectList'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.sri.test.Subject] for property 'subjectList[0]': no matching editors or conversion strategy found]
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:656)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
有人能帮帮我吗?提前谢谢......

2 个答案:

答案 0 :(得分:0)

您需要实现StringToSubjectConverter类将提交的字符串转换为Subject对象:

public class StringToSubjectConverter implements Converter<String, Subject> {
  @Override
  public Subject convert(String s) {
    return ...; // your code to convert from `String` to `Subject`
  }
}

使用Spring Conversion Service注册此转换器:

  <mvc:annotation-driven conversion-service="conversionService" />

  <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
      <set>
        <bean class="package.StringToSubjectConverter" />
      </set>
    </property>
  </bean>

答案 1 :(得分:0)

我已经解决了你的问题。在这里,您尝试将Subject对象的String数组绑定到Subject对象List,这是不可能将“String [] subject”转换为List,这里是使用checkboxe得到的值

"Subject [subjectId=1,subjectName=English]"

由于toString方法被覆盖,选择主题后会出现这种输出格式。

现在,Spring在内部尝试将此String或String [] {以及多项选择}转换为您的List。即使使用convert()方法,也无法转换。

因此,您必须在save方法中创建逻辑,首先从String []中提取这些值,然后在从提取的值创建Subject后将其设置为Subject列表。

然后你需要将它设置为List方法的setter。

这是下面的代码,修改了两种方法

1)你的主题类的toString

@Override
public String toString() {
    return "subjectId=" + subjectId + ",subjectName="+ subjectName;
} 

2)HelloController的保存方法

@RequestMapping(value = "save.do", method = RequestMethod.POST)
public String saveStudent(@ModelAttribute Student student,
        BindingResult result, HttpServletRequest request, ModelMap model) {
    System.out.println(">>>>>>>>>>>>" + student);
    int i = 0;

    List<Subject> lSubjects=new ArrayList<Subject>();
    String[] subjectsInString = request.getParameterValues("subjectList");
    String[] eachSubject=null;
    Subject subject=null;
    int subjectId=0;
    String subjectName=null;

    if (result.hasErrors()) {

        List<FieldError> fieldErrors = result.getFieldErrors();
        while (i < fieldErrors.size()) {
            System.out.println("Error: " + fieldErrors.get(i));
            i++;
        }

        for (String subjectInString : subjectsInString) {
            System.out.println(subjectInString);
            eachSubject=subjectInString.split(",");
            for(String value:eachSubject){
                if(value.contains("subjectId"))
                subjectId=Integer.parseInt(value.substring(value.lastIndexOf('=')+1,value.length()));

                if(value.contains("subjectName"))
                subjectName=value.substring(value.lastIndexOf('=')+1,value.length());

                /**/
            }

            subject=new Subject(subjectId, subjectName);
            lSubjects.add(subject);
            //eachSubject
        }
        student.setSubjectList(lSubjects);
        System.out.println("Subject List[ "+student.getSubjectList()+" ]");

    } else {
        model.addAttribute("finalStudent", student);
    }
    return "success";

}

我希望这会对你有帮助,如果你还面临问题,请告诉我。