SpringMVC

    科技2022-08-14  113

    RESTRUL_CRUD_需求 显示所有员工信息 URI:emps请求方式:GET显示效果

    添加员工信息 显示添加页面:URI:emp请求方式:GET显示效果

    添加员工信息:URI:emp请求方式:POST显示效果:完成添加,重定向到 list 页面。

    删除操作 URL:emp/{id}请求方式:DELETE删除后效果:对应记录从数据表中删除 修改操作:lastName 不可修改!显示修改页面 URI:emp/{id}请求方式:GET显示效果:回显表单。 修改员工信息 URI:emp 请求方式:PUT显示效果:完成修改,重定向到 list 页面。

    相关的类

    省略了Service层,为了教学方便

    实体类:Employee、DepartmentHandler:EmployeeHandlerDao:EmployeeDao、DepartmentDao

    相关的页面 list.jspinput.jspedit.jsp RESTRUL_CRUD_显示所有员工信息 搭建开发环境 拷贝jar包

    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

    创建配置文件:springmvc.xml  增加context,mvc,beans名称空间。

    <?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>

    配置核心控制器:web.xml

    <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>

    将 POST 请求转换为 PUT 或 DELETE 请求

    <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

    增加实体类

    增加DAO类

    package com.atguigu.springmvc.crud.dao;

    import java.util.Collection;

    import java.util.HashMap;

    import java.util.Map;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.stereotype.Repository;

    import com.atguigu.springmvc.crud.entities.Department;

    import com.atguigu.springmvc.crud.entities.Employee;

    @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);

    }

    }

    package com.atguigu.springmvc.crud.dao;

    import java.util.Collection;

    import java.util.HashMap;

    import java.util.Map;

    import org.springframework.stereotype.Repository;

    import com.atguigu.springmvc.crud.entities.Department;

    @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>

    增加处理器

    package com.atguigu.springmvc.crud.handlers;

    import java.util.Map;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.stereotype.Controller;

    import org.springframework.web.bind.annotation.RequestMapping;

    import com.atguigu.springmvc.crud.dao.EmployeeDao;

    @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";

    }

    SpringMVC中没遍历的标签,需要使用jstl标签进行集合遍历增加jstl标签库jar包

    <%@ 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>

    RESTRUL_CRUD_添加操作&表单标签 在list.jsp上增加连接

    <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)

    使用 Spring的表单标签

    通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显form 标签 一般情况下,通过 GET 请求获取表单页面,而通过 POST 请求提交表单页面因此获取表单页面和提交表单页面的 URL 是相同的只要满足该最佳条件的契约<form:form> 标签就无需通过 action 属性指定表单提交的 URL可以通过 modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从 request 域对象中读取 command 的表单 bean,如果该属性值也不存在,则会发生错误。SpringMVC 提供了多个表单组件标签,如 <form:input/>、<form:select/> 等,用以绑定表单字段的属性值,它们的共有属性如下: path表单字段,对应 html 元素的 name 属性,支持级联属性htmlEscape:是否对表单值的 HTML 特殊字符进行转换,默认值为 truecssClass:表单组件对应的 CSS 样式类名cssErrorClass:表单组件的数据存在错误时,采取的 CSS 样式form:input、form:password、form:hidden、form:textarea:对应 HTML 表单的 text、password、hidden、textarea 标签form:radiobutton:单选框组件标签,当表单 bean 对应的属性值和 value 值相等时,单选框被选中form:radiobuttons:单选框组标签,用于构造多个单选框 items:可以是一个 List、String[] 或 MapitemValue:指定 radio 的 value 值。可以是集合中 bean 的一个属性值itemLabel:指定 radio 的 label 值delimiter:多个单选框可以通过 delimiter 指定分隔符form:checkbox:复选框组件。用于构造单个复选框form:checkboxs:用于构造多个复选框。使用方式同 form:radiobuttons 标签form:select:用于构造下拉框组件。使用方式同 form:radiobuttons 标签form:option:下拉框选项组件标签。使用方式同 form:radiobuttons 标签form:errors:显示表单组件或数据校验所对应的错误 <form:errors path= “*” /> :显示表单所有的错误<form:errors path= “user*” /> :显示所有以 user 为前缀的属性对应的错误<form:errors path= username /> :显示特定表单对象属性的错误 添加员工实验代码 表单

    <%@ 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";

    }

    }

    RESTRUL_CRUD_删除操作&处理静态资源

    删除实验代码 页面链接

    <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";

    }

    HiddenHttpMethodFilter过滤器

    发起请求,无法执行,因为delete请求必须通过post请求转换为delete请求,借助:HiddenHttpMethodFilter过滤器 需要使用jQuery来转换请求方式 加入jQuery库文件

    /scripts/jquery-1.9.1.min.js

    jQuery库文件不起作用

    警告: No mapping found for HTTP request with URI [/SpringMVC_03_RESTFul_CRUD/scripts/jquery-1.9.1.min.js] in DispatcherServlet with name 'springDispatcherServlet'

    解决办法,SpringMVC 处理静态资源

    SpringMVC 处理静态资源:

    为什么会有这样的问题:

    优雅的 REST 风格的资源URL 不希望带 .html .do 等后缀

    若将 DispatcherServlet 请求映射配置为 /,

    Spring MVC 将捕获 WEB 容器的所有请求, 包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理,

    因找不到对应处理器将导致错误。

    解决: 在 SpringMVC 的配置文件中配置 <mvc:default-servlet-handler/>配置后,原来的请求又不好使了

    需要配置<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"/>

    通过jQuery转换为DELETE请求

    <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>

    删除操作流程图解

    RESTRUL_CRUD_修改操作

    根据id查询员工对象,表单回显 页面链接

    <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";

    }

    @ModelAttribute

    public void getEmployee( @RequestParam(value="id",required=false) Integer id,Map<String,Object> map){

      if(id!=null){

         map.put("employee", employeeDao.get(id));

      }

    }

     

     

     

     

     

    Processed: 0.011, SQL: 8