Spring MVC 将 ArrayList 传递回控制器
Spring MVC passing ArrayList back to controller
我是 Spring 的新手。我显示一个用户列表。每行都有一个用于删除用户的复选框。
控制器:
@Controller
public class AdminController {
@Autowired
private UserDao userDao;
@RequestMapping(value = "/admin", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.addObject("users", userDao.findAll());
model.setViewName("admin");
return model;
}
@RequestMapping(value = "admin/remove", method = RequestMethod.POST)
public ModelAndView removeUser(@ModelAttribute(value = "users") ArrayList<User> users) {
ModelAndView model = new ModelAndView();
//UPDATE USERS HERE
model.setViewName("redirect:/admin");
return model;
}
JSP:
<form:form action="/admin/remove" method="POST" modelAttribute="users">
<table class="table table-striped">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email/login</th>
<th>Profession</th>
<th>Select<th>
</tr>
</thead>
<tbody>
<c:forEach var="user" items="${users}">
<tr>
<td>${user.firstName}</td>
<td>${user.lastName}</td>
<td>${user.login}</td>
<td>${user.profession}</td>
<td><input type="checkbox" value="${user.delete}"/></td>
</tr>
</c:forEach>
</tbody>
</table>
<input type="submit" value="Delete user(s)" class="btn-danger" />
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form:form>
列表呈现正确。如果我按下 "Delete user(s)" 按钮。 @modelAttribute 用户为空。
我也尝试将列表包装在一个新的 class 中,但我得到了相同的结果。
有什么想法吗?
这是因为您正在使用重定向:在您看来。查看 Flash 属性 :
- http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/support/RedirectAttributes.html
- http://viralpatel.net/blogs/spring-mvc-flash-attribute-example/
您应该能够获得更新后的列表:)
您的 ModelAttribute 为空,因为没有从您的 jsp 到您的模型属性的表单数据绑定。看一下 Spring 示例如何绑定集合“http://developer.ucsd.edu/develop/user-interface/building-a-form/form-binding-with-collections.html”。这将帮助您理解。
大多数 Spring 应用程序通常使用 form:input 和“path”参数来进行数据绑定。
您应该围绕 spring-mvc select 标记构建您的功能。不过,很少有更改是有序的,将列表推送到 POJO class 例如
public class FormBean {
private List<String> users;
public FormBean() {
}
public List<String> getUsers() {
return users;
}
public void setUsers(List<String> users) {
this.users = users;
}
}
将映射更改为
@RequestMapping(value = "admin/remove", method = RequestMethod.POST)
public ModelAndView removeUser(@ModelAttribute(value = "formBean") FormBean formBean) {
最后,将您的 c:forEach 替换为 springs select 标签,例如
<form:form action="/admin/remove" method="POST" modelAttribute="formBean">
...
<form:select path="users" items="${users}" multiple="true" />
...
</form>
感谢minion,我找到了答案
包装器:
public class UserListWrapper {
private ArrayList<User> users;
public ArrayList<User> getUsers() {
return users;
}
public void setUsers(ArrayList<User> users) {
this.users = users;
}
控制器:
@Controller
public class AdminController {
@Autowired
private UserDao userDao;
@RequestMapping(value = "/admin", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
UserListWrapper wrapper = new UserListWrapper();
wrapper.setUsers(new ArrayList<User>(userDao.findAll()));
model.addObject("userListWrapper",wrapper);
model.setViewName("admin");
return model;
}
@RequestMapping(value = "admin/remove", method = RequestMethod.POST)
public ModelAndView removeUser(@ModelAttribute(value = "userListWrapper") UserListWrapper userListWrapper) {
ModelAndView model = new ModelAndView();
userDao.removeFlaggedUsers(userListWrapper.getUsers());
model.setViewName("redirect:/admin");
return model;
}
}
查看:
<form:form action="/admin/remove" method="POST" modelAttribute="userListWrapper">
<table class="table table-striped">
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Email/login</th>
<th>Profession</th>
<th>Select<th>
</tr>
</thead>
<tbody>
<c:forEach varStatus="us" var="user" items="${userListWrapper.users}" >
<tr>
<td><form:input type="hidden" path="users[${us.index}].firstName"/>${user.firstName}</td>
<td><form:input type="hidden" path="users[${us.index}].lastName"/> ${user.lastName}</td>
<td><form:input type="hidden" path="users[${us.index}].login"/>${user.login}</td>
<td><form:input type="hidden" path="users[${us.index}].profession"/>${user.profession}</td>
<td><form:checkbox path="users[${us.index}].delete" value="${user.delete}"/></td>
<form:input type="hidden" path="users[${us.index}].id"/>
</tr>
</c:forEach>
</tbody>
</table>
<input type="submit" value="Delete user(s)" class="btn-danger" />
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form:form>
谢谢!
编辑:别忘了添加您没有显示的字段。
例如:
如果您不添加 id,您的删除将不起作用,因为返回的 User 对象中的 id 将为 NULL。
我是 Spring 的新手。我显示一个用户列表。每行都有一个用于删除用户的复选框。
控制器:
@Controller
public class AdminController {
@Autowired
private UserDao userDao;
@RequestMapping(value = "/admin", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.addObject("users", userDao.findAll());
model.setViewName("admin");
return model;
}
@RequestMapping(value = "admin/remove", method = RequestMethod.POST)
public ModelAndView removeUser(@ModelAttribute(value = "users") ArrayList<User> users) {
ModelAndView model = new ModelAndView();
//UPDATE USERS HERE
model.setViewName("redirect:/admin");
return model;
}
JSP:
<form:form action="/admin/remove" method="POST" modelAttribute="users">
<table class="table table-striped">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email/login</th>
<th>Profession</th>
<th>Select<th>
</tr>
</thead>
<tbody>
<c:forEach var="user" items="${users}">
<tr>
<td>${user.firstName}</td>
<td>${user.lastName}</td>
<td>${user.login}</td>
<td>${user.profession}</td>
<td><input type="checkbox" value="${user.delete}"/></td>
</tr>
</c:forEach>
</tbody>
</table>
<input type="submit" value="Delete user(s)" class="btn-danger" />
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form:form>
列表呈现正确。如果我按下 "Delete user(s)" 按钮。 @modelAttribute 用户为空。 我也尝试将列表包装在一个新的 class 中,但我得到了相同的结果。
有什么想法吗?
这是因为您正在使用重定向:在您看来。查看 Flash 属性 :
- http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/support/RedirectAttributes.html
- http://viralpatel.net/blogs/spring-mvc-flash-attribute-example/
您应该能够获得更新后的列表:)
您的 ModelAttribute 为空,因为没有从您的 jsp 到您的模型属性的表单数据绑定。看一下 Spring 示例如何绑定集合“http://developer.ucsd.edu/develop/user-interface/building-a-form/form-binding-with-collections.html”。这将帮助您理解。
大多数 Spring 应用程序通常使用 form:input 和“path”参数来进行数据绑定。
您应该围绕 spring-mvc select 标记构建您的功能。不过,很少有更改是有序的,将列表推送到 POJO class 例如
public class FormBean {
private List<String> users;
public FormBean() {
}
public List<String> getUsers() {
return users;
}
public void setUsers(List<String> users) {
this.users = users;
}
}
将映射更改为
@RequestMapping(value = "admin/remove", method = RequestMethod.POST)
public ModelAndView removeUser(@ModelAttribute(value = "formBean") FormBean formBean) {
最后,将您的 c:forEach 替换为 springs select 标签,例如
<form:form action="/admin/remove" method="POST" modelAttribute="formBean">
...
<form:select path="users" items="${users}" multiple="true" />
...
</form>
感谢minion,我找到了答案
包装器:
public class UserListWrapper {
private ArrayList<User> users;
public ArrayList<User> getUsers() {
return users;
}
public void setUsers(ArrayList<User> users) {
this.users = users;
}
控制器:
@Controller
public class AdminController {
@Autowired
private UserDao userDao;
@RequestMapping(value = "/admin", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
UserListWrapper wrapper = new UserListWrapper();
wrapper.setUsers(new ArrayList<User>(userDao.findAll()));
model.addObject("userListWrapper",wrapper);
model.setViewName("admin");
return model;
}
@RequestMapping(value = "admin/remove", method = RequestMethod.POST)
public ModelAndView removeUser(@ModelAttribute(value = "userListWrapper") UserListWrapper userListWrapper) {
ModelAndView model = new ModelAndView();
userDao.removeFlaggedUsers(userListWrapper.getUsers());
model.setViewName("redirect:/admin");
return model;
}
}
查看:
<form:form action="/admin/remove" method="POST" modelAttribute="userListWrapper">
<table class="table table-striped">
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Email/login</th>
<th>Profession</th>
<th>Select<th>
</tr>
</thead>
<tbody>
<c:forEach varStatus="us" var="user" items="${userListWrapper.users}" >
<tr>
<td><form:input type="hidden" path="users[${us.index}].firstName"/>${user.firstName}</td>
<td><form:input type="hidden" path="users[${us.index}].lastName"/> ${user.lastName}</td>
<td><form:input type="hidden" path="users[${us.index}].login"/>${user.login}</td>
<td><form:input type="hidden" path="users[${us.index}].profession"/>${user.profession}</td>
<td><form:checkbox path="users[${us.index}].delete" value="${user.delete}"/></td>
<form:input type="hidden" path="users[${us.index}].id"/>
</tr>
</c:forEach>
</tbody>
</table>
<input type="submit" value="Delete user(s)" class="btn-danger" />
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form:form>
谢谢!
编辑:别忘了添加您没有显示的字段。
例如:
如果您不添加 id,您的删除将不起作用,因为返回的 User 对象中的 id 将为 NULL。