因此,我在模型中设置了一个域对象(TestGenerationRequest),并通过JSP为该页面提供服务。然后,我有一个表单(Spring表单),用户可以在将模型提交回控制器之前在浏览器中与之交互。会收到域对象,并且会根据用户交互自动正确地填充其大多数字段。但是,每次收货时,一个字段都是空白。该字段称为“组”,是另一个域对象列表的列表。 “组”填充在浏览器中,并绑定到angularJS数组,该数组本身通过AJAX作为JSON从其他地方获取。发送回控制器的请求看起来不错,当使用Firefox的dev工具/网络检查时,请求的格式正确,但服务器端的组仍然为空。我究竟做错了什么?任何帮助表示赞赏!
TestGenerationRequest域对象:
public class TestGenerationRequest implements Serializable {
private final static long serialVersionUID = 934343334541L;
@JsonIgnore
public static final int FORMAT_PORTRAIT = 1;
@JsonIgnore
public static final int FORMAT_LANDSCAPE = 2;
@Min(1)
@Max(6)
private int testNum;
@NotNull(message = "{generatetest.error.selectedGrades.notnull}")
private List<String> selectedGrades;
@Min(1)
@Max(2)
private int orientation;
private boolean includeRepro;
private List<TeachingGroup> groups;
public TestGenerationRequest() {
super();
//this.selectedGrades = new ArrayList<String>();
this.groups = new ArrayList<TeachingGroup>();
this.orientation = TestGenerationRequest.FORMAT_PORTRAIT; //set default to portrait; this is reflected in the JSP view's default selection for user.
this.includeRepro = false; // set default, reflected in JSP view default
}
public int getTestNum() {
return testNum;
}
public void setTestNum(int testNum) {
this.testNum = testNum;
}
public int getOrientation() {
return orientation;
}
public void setOrientation(int orientation) {
this.orientation = orientation;
}
public boolean isIncludeRepro() {
return includeRepro;
}
public void setIncludeRepro(boolean includeRepro) {
this.includeRepro = includeRepro;
}
public List<String> getSelectedGrades() {
return selectedGrades;
}
public void setSelectedGrades(List<String> selectedGrades) {
this.selectedGrades = selectedGrades;
}
public List<TeachingGroup> getGroups() {
return groups;
}
public void setGroups(List<TeachingGroup> groups) {
this.groups = groups;
}
}
TeachingGroup域对象:
@Component
@XmlRootElement(name = "group")
@XmlAccessorType(XmlAccessType.FIELD)
public class TeachingGroup implements Serializable {
@JsonIgnore
private final static long serialVersionUID = 93459334534L;
private String name;
private int id;
private List<Student> students;
private int year;
@JsonIgnore
private int type;
@JsonIgnore
public static final int NORMAL_TEACHING_GROUP = 1;
@JsonIgnore
public static final int SKILLS_CLASS_GROUP = 1;
@JsonIgnore
private int schoolID;
@JsonIgnore
private int subject;
private List<Grade> availGrades;
private List<Integer> availTestNums;
@JsonIgnore
boolean studentsPopulated = false;
public TeachingGroup() {
super();
students = new ArrayList<Student>();
availGrades = new ArrayList<Grade>();
availTestNums = new ArrayList<Integer>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@XmlElement(name = "students")
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public void addStudent(Student s) {
if (!this.studentsPopulated || (!this.students.contains(s))) {
this.students.add(s);
this.studentsPopulated = true;
}
}
public int getYear() {
return year;
}
public void setYear(int y) {
year = y;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getSchoolID() {
return schoolID;
}
public void setSchoolID(int schoolID) {
this.schoolID = schoolID;
}
public int getSubject() {
return subject;
}
public void setSubject(int subject) {
this.subject = subject;
}
public List<Grade> getAvailGrades() {
return availGrades;
}
public void setAvailGrades(List<Grade> availGrades) {
this.availGrades = availGrades;
}
public List<Integer> getAvailTestNums() {
return availTestNums;
}
public void setAvailTestNums(List<Integer> availTestNums) {
this.availTestNums = availTestNums;
}
public boolean isStudentsPopulated() {
return studentsPopulated;
}
public void setStudentsPopulated(boolean studentsPopulated) {
this.studentsPopulated = studentsPopulated;
}
}
控制器,为初始请求提供服务并设置模型:
@RequestMapping("/generateTest")
public String generateTest(Model model) {
model.addAttribute("grades", subject.getGrades());
if (!model.containsAttribute("testGenRequest")) {
model.addAttribute("testGenRequest", new TestGenerationRequest());
}
return "generatetest";
}
控制器,收到最终形式:
@RequestMapping(value = "/generateTest/download.pdf", method = RequestMethod.POST)
public void generateTestDownload(@ModelAttribute("testGenRequest") @Valid TestGenerationRequest testGen, BindingResult result, Model model, HttpServletResponse response) {
if (result.hasErrors()) {
generateTest(model);
}
String[] suppressedFields = result.getSuppressedFields();
if (suppressedFields.length > 0) {
throw new RuntimeException("Attempting to bind disallowed fields: " + StringUtils.arrayToCommaDelimitedString(suppressedFields));
}
/*
testGen.getGroups() should return List<TeachingGroup> but the list is empty
*/
}
@InitBinder
public void initialiseBinder(WebDataBinder binder) {
if (binder.getTarget() != null) {
if (binder.getTarget().getClass().equals(TestGenerationRequest.class)) {
binder.setAllowedFields("testNum", "selectedGrades", "orientation", "includeRepro", "groups");
}
}
}
JSP;必须使用输入字段而不是form:hidden,否则angularJS也会忽略它,但尝试了许多排列形式,包括:hidden并将值设置为静态数据... rightValuesArray是先前通过AJAX服务的List的适当angularJS数组 generatetest.jsp:
<c:url var="actionURL" value="/generateTest/download.pdf"/>
<form:form method="POST" modelAttribute="testGenRequest" action="${actionURL}" class="form-horizontal" id="testForm">
<form:input path="groups" value="{{rightValuesArray}}" style="display: none;"/>
<snipped rest of form>
</form:form>
对Controller的最终请求,从Firefox的开发工具Network-> request-> Params中捕获,显示groups字段包含JSON:
_includeRepro on
_selectedGrades […]
0 on
1 on
2 on
3 on
4 on
5 on
6 on
7 on
8 on
groups [{"name":"classA","id":439,"students":[],"year":2,"availGrades":[],"availTestNums":[]},{"name":"classB","id":440,"students":[],"year":2,"availGrades":[],"availTestNums":[]}]
includeRepro true
orientation 1
selectedGrades […]
0 3
1 4
2 5
3 6
4 7
5 8
testNum 3
我正在使用
org.springframework.web.servlet.view.json.MappingJackson2JsonView
抱歉,这是一篇很长的帖子。今天,我花了很多时间试图使它起作用,并拔掉头发。如果人们发现错误,将不胜感激。谢谢
内容协商视图解析器。