省略了Service层,为了教学方便
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
commons-logging-1.1.3.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 配置扫描的包:com.atguigu.springmvc.crud -->
<context:component-scan base-package="com.atguigu.springmvc"/>
<!-- 配置视图解析器:默认采用转发 -->
<bean id="internalResourceViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
/WEB-INF/views/list.jsp
index.jsp
@Repository
public class EmployeeDao {
private static Map<Integer, Employee> employees = null;
@Autowired
private DepartmentDao departmentDao;
static{
employees = new HashMap<Integer, Employee>();
employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1, new Department(101, "D-AA")));
employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1, new Department(102, "D-BB")));
employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0, new Department(103, "D-CC")));
employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0, new Department(104, "D-DD")));
employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1, new Department(105, "D-EE")));
}
private static Integer initId = 1006;
public void save(Employee employee){
if(employee.getId() == null){
employee.setId(initId++);
}
employee.setDepartment(departmentDao.getDepartment(
employee.getDepartment().getId()));
employees.put(employee.getId(), employee);
}
public Collection<Employee> getAll(){
return employees.values();
}
public Employee get(Integer id){
return employees.get(id);
}
public void delete(Integer id){
employees.remove(id);
}
}
@Repository
public class DepartmentDao {
private static Map<Integer, Department> departments = null;
static{
departments = new LinkedHashMap<Integer, Department>();
departments.put(101, new Department(101, "D-AA"));
departments.put(102, new Department(102, "D-BB"));
departments.put(103, new Department(103, "D-CC"));
departments.put(104, new Department(104, "D-DD"));
departments.put(105, new Department(105, "D-EE"));
}
public Collection<Department> getDepartments(){
return departments.values();
}
public Department getDepartment(Integer id){
return departments.get(id);
}
}
<a href="empList">To Employee List</a>
@Controller
public class EmployeeHandler {
@Autowired
private EmployeeDao employeeDao ;
@RequestMapping("/empList")
public String empList(Map<String,Object> map){
map.put("empList", employeeDao.getAll()); //默认存放到request域中
return "list";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:if test="${empty requestScope.empList }">
对不起,没有找到任何员工!
</c:if>
<c:if test="${!empty requestScope.empList }">
<table border="1" cellpadding="10" cellspacing="0">
<tr>
<td>EmpId</td>
<td>LastName</td>
<td>Gender</td>
<td>Email</td>
<td>DepartmentName</td>
<td>Edit</td>
<td>Delete</td>
</tr>
<c:forEach items="${requestScope.empList }" var="emp">
<tr>
<td>${emp.id }</td>
<td>${emp.lastName }</td>
<td>${emp.gender==0?"Female":"Male" }</td>
<td>${emp.email }</td>
<td>${emp.department.departmentName }</td>
<td><a href="">Edit</a></td>
<td><a href="">Delete</a></td>
</tr>
</c:forEach>
</table>
</c:if>
</body>
</html>
<a href="empInput">Add Employee</a>
@RequestMapping(value="/empInput",method= RequestMethod.GET)
public String empInput(Map<String,Object> map){
map.put("deptList", departmentDao.getDepartments());
//解决错误:java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
Employee employee = new Employee();
//map.put("command", employee);
map.put("employee", employee);
return "add";
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!--
1.为什么使用SpringMVC的form标签
① 快速开发
② 表单回显
2.可以通过modelAttribute指定绑定的模型属性,
若没有指定该属性,则默认从request域中查找command的表单的bean
如果该属性也不存在,那么,则会发生错误。
-->
<form:form action="empAdd" method="POST" modelAttribute="employee">
LastName : <form:input path="lastName"/><br><br>
Email : <form:input path="email"/><br><br>
<%
Map<String,String> map = new HashMap<String,String>();
map.put("1", "Male");
map.put("0","Female");
request.setAttribute("genders", map);
%>
Gender : <br><form:radiobuttons path="gender" items="${genders }" delimiter="<br>"/><br><br>
DeptName :
<form:select path="department.id"
items="${deptList }"
itemLabel="departmentName"
itemValue="id"></form:select><br><br>
<input type="submit" value="Submit"><br><br>
</form:form>
</body>
</html>
HTTP Status 500 -
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/views/add.jsp at line 18
15: ② 表单回显
16: -->
17: <form:form action="empAdd" method="POST">
18: LastName : <form:input path="lastName"/>
19: Email : <form:input path="email"/>
20: <%
21: Map<String,String> map = new HashMap<String,String>();
Stacktrace:
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:505)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:410)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:266)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1225)
org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1012)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:822)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!--
1.为什么使用SpringMVC的form标签
① 快速开发
② 表单回显
2.可以通过modelAttribute指定绑定的模型属性,
若没有指定该属性,则默认从request域中查找command的表单的bean
如果该属性也不存在,那么,则会发生错误。
-->
<form:form action="empAdd" method="POST" modelAttribute="employee">
LastName : <form:input path="lastName" /><br><br>
Email : <form:input path="email" /><br><br>
<%
Map<String,String> map = new HashMap<String,String>();
map.put("1", "Male");
map.put("0","Female");
request.setAttribute("genders", map);
%>
Gender : <br><form:radiobuttons path="gender" items="${genders }" delimiter="<br>"/><br><br>
DeptName :
<form:select path="department.id"
items="${deptList }"
itemLabel="departmentName"
itemValue="id"></form:select><br><br>
<input type="submit" value="Submit"><br><br>
</form:form>
</body>
</html>
@Controller
public class EmployeeHandler {
@RequestMapping(value="/empAdd",method=RequestMethod.POST)
public String empAdd(Employee employee){
employeeDao.save(employee);
return "redirect:/empList";
}
}
<td><a href="/empDelete/${emp.id }">Delete</a></td>
@RequestMapping(value="/empDelete/{id}" ,method=RequestMethod.DELETE)
public String empDelete(@PathVariable("id") Integer id){
employeeDao.delete(id);
return "redirect:/empList";
}
发起请求,无法执行,因为delete请求必须通过post请求转换为delete请求,借助:HiddenHttpMethodFilter过滤器
/scripts/jquery-1.9.1.min.js
警告: No mapping found for HTTP request with URI [/SpringMVC_03_RESTFul_CRUD/scripts/jquery-1.9.1.min.js] in DispatcherServlet with name 'springDispatcherServlet'
3. 解决办法,SpringMVC 处理静态资源
① 为什么会有这样的问题:
优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀,若将 DispatcherServlet 请求映射配置为 /, 则 Spring MVC 将捕获 WEB 容器的所有请求, 包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理, 因找不到对应处理器将导致错误。
② 解决: 在 SpringMVC 的配置文件中配置 mvc:default-servlet-handler/
4. 配置后,原来的请求又不好使了
需要配置<mvc:annotation-driven />
<mvc:default-servlet-handler/>
作用<!--
<mvc:default-servlet-handler/> 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,
它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,
就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由 DispatcherServlet 继续处理
一般 WEB 应用服务器默认的 Servlet 的名称都是 default。
若所使用的 WEB 服务器的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定
参考:CATALINA_HOME/config/web.xml
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
该标签属性default-servlet-name默认值是"default",可以省略。
<mvc:default-servlet-handler/>
-->
<mvc:default-servlet-handler default-servlet-name="default"/>
<td><a class="delete" href="empDelete/${emp.id }">Delete</a></td>
<form action="" method="post">
<input type="hidden" name="_method" value="DELETE"/>
</form>
<script type="text/javascript" src="scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
$(function(){
$(".delete").click(function(){
var href = $(this).attr("href");
$("form").attr("action",href).submit();
return false ;
});
});
</script>
<td><a href="empEdit/${emp.id }">Edit</a></td>
//修改员工 - 表单回显
@RequestMapping(value="/empEdit/{id}",method=RequestMethod.GET)
public String empEdit(@PathVariable("id") Integer id, Map<String,Object> map){
map.put("employee", employeeDao.get(id));
map.put("deptList",departmentDao.getDepartments());
return "edit";
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!--
1.为什么使用SpringMVC的form标签
① 快速开发
② 表单回显
2.可以通过modelAttribute指定绑定的模型属性,
若没有指定该属性,则默认从request域中查找command的表单的bean
如果该属性也不存在,那么,则会发生错误。
修改功能需要增加绝对路径,相对路径会报错,路径不对
-->
<form:form action="${pageContext.request.contextPath }/empUpdate"
method="POST" modelAttribute="employee">
<%--
LastName : <form:input path="lastName" /><br><br>
--%>
<form:hidden path="id"/>
<input type="hidden" name="_method" value="PUT">
<%-- 这里不要使用form:hidden标签,否则会报错。
<form:hidden path="_method" value="PUT"/>
Spring的隐含标签,没有value属性,同时,path指定的值,在模型对象中也没有这个属性(_method),所以回显时会报错。
org.springframework.beans.NotReadablePropertyException:
Invalid property '_method' of bean class [com.atguigu.springmvc.crud.entities.Employee]:
Bean property '_method' is not readable or has an invalid getter method:
Does the return type of the getter match the parameter type of the setter?
--%>
Email : <form:input path="email" /><br><br>
<%
Map<String,String> map = new HashMap<String,String>();
map.put("1", "Male");
map.put("0","Female");
request.setAttribute("genders", map);
%>
Gender : <br><form:radiobuttons path="gender" items="${genders }" delimiter="<br>"/><br><br>
DeptName :
<form:select path="department.id"
items="${deptList }"
itemLabel="departmentName"
itemValue="id"></form:select><br><br>
<input type="submit" value="Submit"><br><br>
</form:form>
</body>
</html>
@RequestMapping(value="/empUpdate",method=RequestMethod.PUT)
public String empUpdate(Employee employee){
employeeDao.save(employee);
return "redirect:/empList";
}