why:参数类型不对。表单元素与模型数据绑定,是通过path与模型数据的属性相匹配。页面中的表单元素通常只是单个变量值,所以path需对应非对象的属性。
solution:将path的department改为department.id 因为department这个属性是对象
这个坑又踩了一下,而且我发现这个坑,还比较有意思,时不时还给我点花样 譬如Request method ‘GET’ not supported,然后这个问题整的我很郁闷。最终我发现自己很傻喝。
handler中@RequestMapping(value = “/emp/{id}”,method=RequestMethod.DELETE),注意这个{}只是占位符,便于处理方法调用该参数,界面请求url中是不含该符号的
jsp中通过表单提交post请求,然后通过HiddenHttpMethodFilter转换成delete请求。
p a g e C o n t e x t . r e q u e s t . c o n t e x t P a t h / c u r d / e m p / {pageContext.request.contextPath}/curd/emp/ pageContext.request.contextPath/curd/emp/{employee.id}
在JSP中用到EL表达式,形如${ } 注意一定得允许EL 即:<%@page isELIgnored=“false” %>
Spring表单标签
通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显
PS:spring的form表单只是确定页面的元素,具体显示取决于绑定属性的对应值
标签元素
form:input/、form:select/等用于绑定表单字段属性值;path:表单字段,对应 html 元素的 name 属性,支持级联属性
form:radiobutton 当表单bean对应的属性值与value值相等时,单选框被选中
form:radiobuttons 单选框组
- items:可以是List、String[]或Map PS:确定有多少个控件
- itemValue:指定radio的value值,可以是集合中bean的一个属性值 PS:判断选中哪个控件
- itemLabel:指定radio的label值 PS:就是选中后的对应显示
- delimiter:多个单选框控件可通过该指定分隔符 比如
等
回显时,path所绑定的值与某个itemValue一致时,显示对应的itemLabel
用法同form:radiobuttons的标签:form:checkboxs、form:select、form:option
form:errors:显示表单组件或数据校验所对应的错误
input.jsp
<form:form action="${pageContext.request.contextPath}/curd/emp" method="post" modelAttribute="employee">
<!--通过modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从request 域对象中读取 command 的表单bean,则会发生错误-->
<c:if test="${employee.id==null}"> <!--通过id去判断是添加还是修改 因为添加时回显用的是空参构造器生成的对象-->
lastName:<form:input path="lastName"/>
</c:if>
<c:if test="${employee.id!=null}"> <!--修改:PUT-->
<form:hidden path="id"/>
<!--因为 modelAttribute 对应的 bean 中没有 _method 这个属性,所以name="_method"不能写进form: -->
<input type="hidden" name="_method" value="PUT">
</c:if>
lastName:<form:input path="lastName"/>
email:<form:input path="email"/>
<%
Map<String, String> genders = new HashMap<>();
genders.put("1", "Male");
genders.put("0", "Female");
request.setAttribute("genders",genders);
%>
gender:<from:radiobuttons path="gender" items="${genders}"/>
<br>
<!--表单元素与模型数据绑定,是通过path与模型数据的属性相匹配,若该属性也为对象则需级联-->
deparment:<form:select path="department.id" items="${departments}" <!--employee的属性成员department-->
itemLabel="departmentName" itemValue="id"/>
<input type="submit" value="Submit"/>
</form:form>
EmployeeHandler
//--------------------显示全部----------------------------
@RequestMapping(value = "/emps")
public String listAll(Map<String,Object> map) {
System.out.println("listALL");
map.put("employees", employeeDao.getAll());
return "list";
}
//--------------------查:以便新增----------------------------
@RequestMapping(value = "/emp", method = RequestMethod.GET)
public String input(Map<String, Object> map) {
map.put("departments", departmentDao.getDepartments());
map.put("employee", new Employee()); //将该数据放入模型中,以便于form标签与其绑定
return "input";
}
//--------------------增:保存----------------------------
@RequestMapping(value = "/emp", method = RequestMethod.POST)
public String saveEmp(Employee employee) {
employeeDao.save(employee);
return "redirect:/curd/emps"; //注意一下响应的url是不是想要的
}
//--------------------删----------------------------
@RequestMapping(value = "/emp/{id}",method=RequestMethod.DELETE)
public String deleteEmp(@PathVariable("id") Integer id) {
System.out.println("delete:"+id);
employeeDao.delete(id);
return "redirect:/curd/emps";
}
//--------------------改----------------------------
//1.入参数据
@ModelAttribute //@ModelAttribute标记的方法, 会在每个目标方法执行之前都会执行一次。主要是为了入参时,表单没显示的属性保持不变。
public void getEmployee(@RequestParam(value = "id",required = false)Integer id,
Map<String,Object>map) {
map.put("employee", employeeDao.get(id));
}
//2.查:放入模型view以显示
@RequestMapping(value = "/emp/{id}",method = RequestMethod.GET)
public String input(@PathVariable("id")Integer id,Map<String,Object>map) {
map.put("employee", employeeDao.get(id));//这决定了回显的内容
map.put("departments", departmentDao.getDepartments()); //这只是决定页面可选择的数量
return "input";
}
//3.改:保存
@RequestMapping(value = "/emp",method=RequestMethod.PUT)
public String editEmp(Employee employee) {
//如果ModelAttribute、Session中没有则新建
System.out.println("edit save");
employeeDao.save(employee);
return "redirect:/curd/emps";
}
list.jsp对应的url:/curd/emps
<form:form id="deleteF" action="" method="post">
<input type="hidden" name="_method" value="DELETE"/>
</form:form>
<c:if test="${empty requestScope.employees}">
没有员工信息
</c:if>
<c:if test="${! empty requestScope.employees}">
<table border="1" cellpadding="10" cellspacing="0">
<tr>
<th>ID</th>
<th>LastName</th>
<th>Email</th>
<th>Gender</th>
<th>Department</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<c:forEach var="employee" items="${requestScope.employees}">
<tr>
<td>${
employee.id}</td>
<td>${
employee.lastName}</td>
<td>${
employee.email}</td>
<td>${
employee.gender ==0?"Female":"Male"}</td>
<td>${
employee.department.departmentName}</td>
<td><a href="${pageContext.request.contextPath}/curd/emp/${employee.id}">edit</a> </td>
<td><a class="delete"href="${pageContext.request.contextPath}/curd/emp/${employee.id}">delete</a></td>
</tr>
</c:forEach>
</table>
<a href="emp">add new</a>
</c:if>