zl程序教程

您现在的位置是:首页 >  后端

当前栏目

SpringMVC入门第三部分

SpringMVC入门 部分 第三
2023-09-14 09:13:36 时间

利用SpringMVC做一个CRUD符合Rest风格的网站案例

Web环境搭建

1.导入相关坐标

  <!--导入spring的坐标-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <!--导入aspectj的坐标-->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.4</version>
    </dependency>
    <!--引入Spring测试坐标-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <!--junit坐标-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
    </dependency>
    <!--mysql驱动的坐标-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.32</version>
    </dependency>
    <!--c3p0数据库连接池的坐标-->
    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.1.2</version>
    </dependency>
    <!--druid数据库连接池坐标-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.10</version>
    </dependency>
    <!--spring jdbc的坐标-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <!--spring tx的坐标,处理事务的-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>

    <!--SpringWeb模块相关的坐标-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>

    <!--servlet的坐标-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>

    <!--jstl的依赖-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
<!--standard的依赖-->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>

2.web.xml进行配置

Tips: 字符编码的Filter配置要在支持REST风格的filter配置之前

<!--配置springmcv的前段控制器-->
  <servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--SpringMvc.xml是前段控制器需要使用-->
    <!--sevlet的初始化参数-->
    <!--contextConfigLocation:指定SpringMVC配置文件的位置-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:SpringMVC.xml</param-value>
    </init-param>
    <!--默认第一次访问时创建对象,这里填入1,表示服务器启动时创建镀锡-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <!--
    /和/*都是拦截所有请求,但是/*的范围更大,还会拦截到*.jsp这些请求
    一旦拦截jsp页面就不会显示了
    /会拦截所有请求,但是不会拦截*.jsp,能保证jsp访问正常
    -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--配置一个字符编码的Filter-->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--初始化参数-->
    <!--encoding:指定解决POST请求的乱码-->
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <!--forceEncoding:顺手解决响应乱码
    response.setCharacterEncoding(this.encoding)-->
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!--支持REST风格的filter-->
  <!--配置filter-->
  <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>

3.SpringMVC.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="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.xsd
 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven />
    <!--context的组件扫描,需要引入context命名空间-->
    <!--只需要扫描cotroller包下的内容-->
    <context:component-scan base-package="com"/>


    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
        <!--指定创建jstlView-->
        <!--  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>-->
    </bean>

</beans>

数据库环境搭建

在这里插入图片描述

1.propertise配置文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/tx
jdbc.username=root
jdbc.password=xxxxxxx

2.在Spring容器中引入pro配置文件,配置数据源,配置JDBCTemplate对象

SpringMVC.xml

    <!--加载jdbc.properties-->
    <!--引入context命名空间-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--数据源对象-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--jdbc模板对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

Dao层

EmployeeDao类:

@Repository
public class EmployeeDao {
@Autowired //按照类型注入
    JdbcTemplate jdbcTemplate;

    //保存员工信息到数据库
    public void save( Employee employee)
    {
        String  sql="insert employee values(?,?,?,?,?)";
          jdbcTemplate.update(sql,employee.getId(),employee.getName(),employee.getDepartment(),
                  employee.getEamil(),employee.getGender());
    }

    //查询并返回对应员工信息
    public Employee exist(Employee employee)
    {
        String  sql="select * from employee where name=? and id= ?";
try{
    Employee employee1 = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Employee>(Employee.class), employee.getName(), employee.getId());
      return employee1;
}
catch (Exception e)
{
return null;
}
    }

   //删除某个员工的信息
    public void delete(Employee employee)
    {
        String sql="delete from employee where id=?";
        jdbcTemplate.update(sql,employee.getId());
    }

    //返回所有员工的信息
    public List<Employee> getAllEmployees()
    {
        String sql="select* from employee";
        List<Employee> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Employee>(Employee.class));
    return list;
    }
}


POJO—自定义对象层

employee类:

@Component
public class Employee {
private Integer id;
private  String name;
private  String department;
private  String eamil;
private  Integer gender;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getEamil() {
        return eamil;
    }

    public void setEamil(String eamil) {
        this.eamil = eamil;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", department='" + department + '\'' +
                ", eamil='" + eamil + '\'' +
                ", gender=" + gender +
                '}';
    }
}


展示所有员工的界面设计思路

访问index.jsp---->直接发送/emps请求----->控制器查询所有员工-------->放在请求域中-------->转发到list页面进行展示

index.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%--访问页面就直接展示员工列表页面--%>
<jsp:forward page="/emps"></jsp:forward>

EmployeeController类:

@Controller
public class EmployeeController {

   @Autowired
    EmployeeDao employeeDao;
    @RequestMapping("/emps")
    public String getEmps(Model model)
    {
        List<Employee> all = employeeDao.getAllEmployees();
        for(Employee employee:all)
            System.out.println(employee);
        System.out.println("当前方法调用一次");
        model.addAttribute("employees",all);
        return "list";
    }
}

list.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>员工展示页面</title>
</head>
<body>
<%--cellpadding标签属性:设定单元边沿与单元内容之间的间距--%>
<%--cellspacing 标签属性:设定单元格之间的间距--%>
<table border="1px" cellpadding="5px" cellspacing="0" bgcolor="grey">
    <%--
private Integer id;
private  String name;
private  String department;
private  String eamil;
private  String gender;--%>
    <tr>
        <th>员工ID</th>
        <th>员工姓名</th>
        <th>员工部门</th>
        <th>员工邮箱</th>
        <th>员工性别</th>
        <td>修改</td>
        <td>删除</td>
    </tr>
    <c:forEach items="${employees}" var="emp">
        <tr>
           <%-- 取出容器中的值--%>
            <td>${emp.id}</td>
            <td>${emp.name}</td>
            <td>${emp.department}</td>
            <td>${emp.eamil}</td>
            <td>${emp.gender==0?"女":"男"}</td>
            <td>修改</td>
            <td>删除</td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

在这里插入图片描述


添加员工

在这里插入图片描述
EmployeeController类新增方法:

    /*从数据库中查询出所有部门信息*/
    @RequestMapping("/toAddPage")
    public String toAddPage(Model model)
    {
        List<Employee> all = employeeDao.getAllEmployees();
        List<String> departName = new LinkedList<String>();
        for(Employee employee:all)
        {
            departName.add(employee.getDepartment());
        }
        model.addAttribute("departments",departName);
        return "addPage";
    }

addPage.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>员工添加页面</title>
</head>
<body>
<h1 style="color: greenyellow">添加员工</h1>
<form action="">
    员工id:<input name="id" placeholder="请输入员工id"><br/>
    姓名: <input name="name" placeholder="请输入姓名"><br/>
    邮箱: <input name="eamil" placeholder="请输入员工邮箱"><br/>
    性别: &nbsp;&nbsp;&nbsp;<input type="radio" name="gender" value="1">
    &nbsp;&nbsp;<input type="radio" name="gender" value="0"><br/>
    请选择员工所在部门:
    <select name="department">
       <c:forEach items="${departments}" var="dept">
           <option value="${dept}">${dept}</option>
       </c:forEach>
    </select>
    <input type="submit" value="提交">
</form>
</body>
</html>

在这里插入图片描述


Spring表单标签技术

在这里插入图片描述

需要在最上面导入Spring提供的标签库

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

好处

通过SpringMVC的表单标签可以实现将模型数据中的属性和HTML表单元素相绑定
以实现表单数据更便捷编辑和表单值的回显

spring标签库,替换上面的html写的form表单

<form:form>
    <%--
      path就是原来html----input标签里面的name项,即提交得到的key
      path的作用:
      1.当做原生的name项
      2.自动回显隐含模型中某个对象对应的这个属性的值
    --%>
    员工id:<form:input path="id"/><br/>
    姓名:<form:input path="name"/><br/>
    邮箱:<form:input path="eamil"/><br/>
    性别:<br/>
    男:<form:radiobutton path="gender" value="1"/>
    女:<form:radiobutton path="gender" value="0"/>
    请选择员工所在的部门:
    <%--items:指定要遍历的集合,自动遍历
    如果遍历出来的是一个自定义对象
    itemLabel="属性名": 指定遍历出来的这个对象的哪个属性是作为optiob标签体的值--->在页面显示要选择的选项里面显示的内容
    itemValue="属性名":指定刚才遍历出来的这个对象的哪个属性是作为要提交的value值--%>
    <form:select path="department" items="${departments}"/>
        <br/>
    <%--原生的html标签和spring标签混合使用--%>
<input type="submit" value="提交">
</form:form>

注意:SpringMVC认为,表单数据中的每一项最终都是要回显的

path指定的是一个属性,这个属性是从隐含模型(请求域)中取出的某个对象中的属性

path指定的每一个属性,请求域中必须有一个对象,拥有这个属性

这个对象就是请求域中的command的值,没有就报错,错误如下:

在这里插入图片描述


在隐含模型中放入command对象

EmployeeController类:

    /*从数据库中查询出所有部门信息*/
    @RequestMapping("/toAddPage")
    public String toAddPage(Model model)
    {
        List<Employee> all = employeeDao.getAllEmployees();
        List<String> departName = new LinkedList<String>();
        for(Employee employee:all)
        {
            departName.add(employee.getDepartment());
        }
        model.addAttribute("departments",departName);
        /*在隐含模型中放入一个command对象*/
        model.addAttribute("command",new Employee());
        return "addPage";
    }

addPages.jsp:

<form:form>
    <%--
      path就是原来html----input标签里面的name项,即提交得到的key
      path的作用:
      1.当做原生的name项
      2.自动回显隐含模型中某个对象对应的这个属性的值
    --%>
    员工id:<form:input path="id"/><br/>
    姓名:<form:input path="name"/><br/>
    邮箱:<form:input path="eamil"/><br/>
    性别:<br/>
    男:<form:radiobutton path="gender" value="1"/>
    女:<form:radiobutton path="gender" value="0"/>
    请选择员工所在的部门:
    <%--items:指定要遍历的集合,自动遍历
    如果遍历出来的是一个自定义对象
    itemLabel="属性名": 指定遍历出来的这个对象的哪个属性是作为optiob标签体的值--->在页面显示要选择的选项里面显示的内容
    itemValue="属性名":指定刚才遍历出来的这个对象的哪个属性是作为要提交的value值--%>
    <form:select path="department" items="${departments}"/>
        <br/>
    <%--原生的html标签和spring标签混合使用--%>
<input type="submit" value="提交">
</form:form>

在这里插入图片描述


以前我们表单标签会从请求域中获取一个command对象,把这个对象中每一个属性对应的显示在页面上

可以告诉SpringMVC不要去取command的值了,我放了一个modelAttribute指定的值,取对象用的key就使用我modelAttribute指定的

演示:

EmployeeController类:

    /*从数据库中查询出所有部门信息*/
    @RequestMapping("/toAddPage")
    public String toAddPage(Model model)
    {
        List<Employee> all = employeeDao.getAllEmployees();
        List<String> departName = new LinkedList<String>();
        for(Employee employee:all)
        {
            departName.add(employee.getDepartment());
        }
        model.addAttribute("departments",departName);
        /*在隐含模型中放入一个employee对象*/
        model.addAttribute("employee",new Employee(null,"超级大忽悠","空军部","@307667",1));
        return "addPage";
    }

addPage.jsp

<form:form modelAttribute="employee">
    <%--
      path就是原来html----input标签里面的name项,即提交得到的key
      path的作用:
      1.当做原生的name项
      2.自动回显隐含模型中某个对象对应的这个属性的值
    --%>
    员工id:<form:input path="id"/><br/>
    姓名:<form:input path="name"/><br/>
    邮箱:<form:input path="eamil"/><br/>
    性别:<br/>
    男:<form:radiobutton path="gender" value="1"/>
    女:<form:radiobutton path="gender" value="0"/>
    请选择员工所在的部门:
    <%--items:指定要遍历的集合,自动遍历
    如果遍历出来的是一个自定义对象
    itemLabel="属性名": 指定遍历出来的这个对象的哪个属性是作为optiob标签体的值--->在页面显示要选择的选项里面显示的内容
    itemValue="属性名":指定刚才遍历出来的这个对象的哪个属性是作为要提交的value值--%>
    <form:select path="department" items="${departments}"/>
    <br/>
    <%--原生的html标签和spring标签混合使用--%>
<input type="submit" value="提交">
</form:form>

在这里插入图片描述


点击提交按钮,对数据进行保存

以后jsp页面什么form表单的action提交路径,a标签的herf属性都写绝对路径,因此需要先获取项目根路径

//将当前项目的根路径存储再pageContext域中
<%pageContext.setAttribute("ctp",request.getContextPath());%>
<form:form modelAttribute="employee" action="${ctp}/emp" method="post">

处理表单提交请求的方法

    //只接收Post请求
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    public String addEmp(Employee employee)//这里会自动赋值
    {
        System.out.println("要添加的员工信息:"+employee);
        employeeDao.save(employee);
        //返回列表页面,直接重定向到查询所有员工的请求
     return  "redirect:/emps";
    }

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


修改员工

注意:被@ModelAttribute注解的方法会在所有的controller方法执行之前执行,即每一个controller方法执行之前,都会执行该方法

被@ModelAttribute注解的方法和目标controller方法用的都是一套的resolve方法,因此目标方法里面能写什么,获取什么,注解方法里面也能写和获取对应的内容

在这里插入图片描述

在EmployeeDao类中新增一个按照id查找对应员工的方法:

    //按照员工的id查找对应的员工
    public Employee getEmpById(Integer id)
    {
        String  sql="select * from employee where id= ?";
        try{
            Employee employee1 = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Employee>(Employee.class),id);
            return employee1;
        }
        catch (Exception e)
        {
            return null;
        }
    }

EmployeeController类:按照id查询对应的员工

    @RequestMapping("/emp/{id}")
    public String getEmp(@PathVariable("id")Integer id,Model model)
    {
       //1.按照对应id去数据库中查出对应的员工信息
        Employee emp = employeeDao.getEmpById(id);
        //2.放在隐含模型中
        model.addAttribute("EditEmp",emp);
        //3.全部的部门信息放到隐含模型中,是为了可以在下拉框中修改部门信息
        List<Employee> all = employeeDao.getAllEmployees();
        List<String> departName = new LinkedList<String>();
        for(Employee employee:all)
        {
            departName.add(employee.getDepartment());
        }
        model.addAttribute("departments",departName);
        return "edit";
    }

UpdateEmp方法:修改员工的方法,只有put请求才会接收

modelAttributes方法:取出数据库中的对应对象,在该对象的基础上进行修改,而不是新建一个对象

    /*虽然上面也有/emp/{id}的请求路径方式,但是没有限制请求方式,而下面我们限制了请求方式
    优先精确匹配*/
    /*修改员工的方法,只有put请求才会接收*/
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.PUT)
    //在从数据库取出来的对象数据的基础上进行修改
    public String UpdateEmp(@ModelAttribute("employee") Employee employee)
    {
        System.out.println("要修改的员工:"+employee);
        //调用数据库中修改对象数据的方法,员工的id是不变的
           employeeDao.UpdateEmp(employee);
        return "redirect:/emps";
    }

 @ModelAttribute
 /*从请求参数中拿到id*/
    public void modelAttributes(@RequestParam(value = "id",required = false)Integer id,Model model)
    {
        if(id!=null)
        {
            Employee emp = employeeDao.getEmpById(id);
            model.addAttribute("employee",emp);
        }
        System.out.println("提前运行的方法调用了");
    }

edit.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>员工修改页面</title>
</head>
<h1 style="color: hotpink">员工信息修改</h1>
<% pageContext.setAttribute("ctp",request.getContextPath());%>
<body>
<%--modelAttribute:这个表单的所有内容显示绑定的是请求域中EditEmp的值--%>
<form:form action="${ctp}/emp/${EditEmp.id}"
           modelAttribute="EditEmp"
method="post">
    <%--put---->对应Rest风格的更新请求,这里hiiden是为了不在页面上显示处理,隐藏数据--%>
    <input type="hidden" name="_method" value="put">
    <%--员工id不能修改,可以采用隐藏数据的模式,但是不安全--%>
    <input type="hidden" name="id" value="${EditEmp.id}">
    姓名:<form:input path="name"/><br/>
    邮箱:<form:input path="eamil"/><br/>
    性别:<br/>
    男:<form:radiobutton path="gender" value="1"/>
    女:<form:radiobutton path="gender" value="0"/>
    请选择员工所在的部门:
    <form:select path="department" items="${departments}"/>
    <br/>
    <input type="submit" value="修改">
</form:form>
</body>
</html>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里逻辑有一个小bug,部门的种类应该单独创建一个类,而不是按照扫描当前数据库所有员工获取所有的部门种类,这里懒的改了


删除功能实现

在这里插入图片描述
list.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>员工展示页面</title>
</head>
<% pageContext.setAttribute("ctp",request.getContextPath());%>
<body>
<%--cellpadding标签属性:设定单元边沿与单元内容之间的间距--%>
<%--cellspacing 标签属性:设定单元格之间的间距--%>
<table border="1px" cellpadding="5px" cellspacing="0" bgcolor="grey">
    <tr>
        <th>员工ID</th>
        <th>员工姓名</th>
        <th>员工部门</th>
        <th>员工邮箱</th>
        <th>员工性别</th>
        <td>修改</td>
        <td>删除</td>
    </tr>
    <c:forEach items="${employees}" var="emp">
        <tr>
           <%-- 取出容器中的值--%>
            <td>${emp.id}</td>
            <td>${emp.name}</td>
            <td>${emp.department}</td>
            <td>${emp.eamil}</td>
            <td>${emp.gender==0?"女":"男"}</td>
            <td><a href="${ctp}/emp/${emp.id}">修改</a></td>
            <td>
                <form action="${ctp}/emp/${emp.id}" method="post">
<input type="hidden" name="_method" value="delete"/>
                    <input type="submit" value="删除"/>
                </form>
            </td>
        </tr>
    </c:forEach>
</table>

<a href="toAddPage" >添加员工</a>
</body>
</html>

deleteEmp方法:负责删除员工

    //删除方法
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.DELETE)
    public String deleteEmp(@PathVariable("id") Integer id)
    {
        employeeDao.delete(id);
        return "redirect:/emps";
    }

在这里插入图片描述


最终完整源码呈现

目录结构

在这里插入图片描述

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <!--配置springmcv的前段控制器-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--SpringMvc.xml是前段控制器需要使用-->
        <!--sevlet的初始化参数-->
        <!--contextConfigLocation:指定SpringMVC配置文件的位置-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:SpringMVC.xml</param-value>
        </init-param>
        <!--默认第一次访问时创建对象,这里填入1,表示服务器启动时创建镀锡-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <!--
        /和/*都是拦截所有请求,但是/*的范围更大,还会拦截到*.jsp这些请求
        一旦拦截jsp页面就不会显示了
        /会拦截所有请求,但是不会拦截*.jsp,能保证jsp访问正常
        -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--配置一个字符编码的Filter-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--初始化参数-->
        <!--encoding:指定解决POST请求的乱码-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!--forceEncoding:顺手解决响应乱码
        response.setCharacterEncoding(this.encoding)-->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--支持REST风格的filter-->
    <!--配置filter-->
    <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-app>
        

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%--访问页面就直接展示员工列表页面--%>
<jsp:forward page="/emps"></jsp:forward>

addPages.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>员工添加页面</title>
</head>
<body>

<%pageContext.setAttribute("ctp",request.getContextPath());%>
<form:form modelAttribute="employee" action="${ctp}/emp" method="post">
    <%--
      path就是原来html----input标签里面的name项,即提交得到的key
      path的作用:
      1.当做原生的name项
      2.自动回显隐含模型中某个对象对应的这个属性的值
    --%>
    员工id:<form:input path="id"/><br/>
    姓名:<form:input path="name"/><br/>
    邮箱:<form:input path="eamil"/><br/>
    性别:<br/>
    男:<form:radiobutton path="gender" value="1"/>
    女:<form:radiobutton path="gender" value="0"/>
    请选择员工所在的部门:
    <%--items:指定要遍历的集合,自动遍历
    如果遍历出来的是一个自定义对象
    itemLabel="属性名": 指定遍历出来的这个对象的哪个属性是作为optiob标签体的值--->在页面显示要选择的选项里面显示的内容
    itemValue="属性名":指定刚才遍历出来的这个对象的哪个属性是作为要提交的value值--%>
    <form:select path="department" items="${departments}"/>
    <br/>
    <input type="submit" value="提交">
</form:form>
<%--原生的html标签和spring标签混合使用--%>


<%--<h1 style="color: greenyellow">添加员工</h1>
<form action="">
    员工id:<input name="id" placeholder="请输入员工id"><br/>
    姓名: <input name="name" placeholder="请输入姓名"><br/>
    邮箱: <input name="eamil" placeholder="请输入员工邮箱"><br/>
    性别: &nbsp;&nbsp;&nbsp;<input type="radio" name="gender" value="1">
    &nbsp;&nbsp;<input type="radio" name="gender" value="0"><br/>
    请选择员工所在部门:
    <select name="department">
       <c:forEach items="${departments}" var="dept">
           <option value="${dept}">${dept}</option>
       </c:forEach>
    </select>
    <input type="submit" value="提交">
</form>--%>
</body>
</html>

add.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>员工修改页面</title>
</head>
<h1 style="color: hotpink">员工信息修改</h1>
<% pageContext.setAttribute("ctp",request.getContextPath());%>
<body>
<%--modelAttribute:这个表单的所有内容显示绑定的是请求域中EditEmp的值--%>
<form:form action="${ctp}/emp/${EditEmp.id}"
           modelAttribute="EditEmp"
method="post">
    <%--put---->对应Rest风格的更新请求,这里hiiden是为了不在页面上显示处理,隐藏数据--%>
    <input type="hidden" name="_method" value="put">
    <%--员工id不能修改,可以采用隐藏数据的模式,但是不安全--%>
    <input type="hidden" name="id" value="${EditEmp.id}">
    姓名:<form:input path="name"/><br/>
    邮箱:<form:input path="eamil"/><br/>
    性别:<br/>
    男:<form:radiobutton path="gender" value="1"/>
    女:<form:radiobutton path="gender" value="0"/>
    请选择员工所在的部门:
    <form:select path="department" items="${departments}"/>
    <br/>
    <input type="submit" value="修改">
</form:form>
</body>
</html>

list.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>员工展示页面</title>
</head>
<% pageContext.setAttribute("ctp",request.getContextPath());%>
<body>
<%--cellpadding标签属性:设定单元边沿与单元内容之间的间距--%>
<%--cellspacing 标签属性:设定单元格之间的间距--%>
<table border="1px" cellpadding="5px" cellspacing="0" bgcolor="grey">
    <tr>
        <th>员工ID</th>
        <th>员工姓名</th>
        <th>员工部门</th>
        <th>员工邮箱</th>
        <th>员工性别</th>
        <td>修改</td>
        <td>删除</td>
    </tr>
    <c:forEach items="${employees}" var="emp">
        <tr>
           <%-- 取出容器中的值--%>
            <td>${emp.id}</td>
            <td>${emp.name}</td>
            <td>${emp.department}</td>
            <td>${emp.eamil}</td>
            <td>${emp.gender==0?"女":"男"}</td>
            <td><a href="${ctp}/emp/${emp.id}">修改</a></td>
            <td>
                <form action="${ctp}/emp/${emp.id}" method="post">
<input type="hidden" name="_method" value="delete"/>
                    <input type="submit" value="删除"/>
                </form>
            </td>
        </tr>
    </c:forEach>
</table>

<a href="toAddPage" >添加员工</a>
</body>
</html>

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/tx
jdbc.username=root
jdbc.password=xxxxx

SpringMVC.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="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.xsd
 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven />
    <!--context的组件扫描,需要引入context命名空间-->
    <!--只需要扫描cotroller包下的内容-->
    <context:component-scan base-package="com"/>

    <!--加载jdbc.properties-->
    <!--引入context命名空间-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--数据源对象-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--jdbc模板对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>



    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
        <!--指定创建jstlView-->
        <!--  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>-->
    </bean>

</beans>

EmployeeController

package com.Controller;

import com.Dao.EmployeeDao;
import com.POJO.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.LinkedList;
import java.util.List;

@Controller
public class EmployeeController {
   @Autowired
    EmployeeDao employeeDao;
    /*从数据库中查询出所有员工信息*/
    @RequestMapping("/emps")
    public String getEmps(Model model)
    {
        List<Employee> all = employeeDao.getAllEmployees();
        model.addAttribute("employees",all);
        System.out.println("得到所有的员工");
        return "list";
    }
    /*从数据库中查询出所有部门信息*/
    @RequestMapping("/toAddPage")
    public String toAddPage(Model model)
    {
        List<Employee> all = employeeDao.getAllEmployees();
        List<String> departName = new LinkedList<String>();
        for(Employee employee:all)
        {
            departName.add(employee.getDepartment());
        }
        model.addAttribute("departments",departName);
        /*在隐含模型中放入一个employee对象*/
        model.addAttribute("employee",new Employee(null,"超级大忽悠","空军部","@307667",1));
        return "addPage";
    }
    //只接收Post请求
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    public String addEmp(Employee employee)//这里会自动赋值
    {
        System.out.println("要添加的员工信息:"+employee);
        employeeDao.save(employee);
        //返回列表页面,直接重定向到查询所有员工的请求
     return  "redirect:/emps";
    }

    @RequestMapping("/emp/{id}")
    public String getEmp(@PathVariable("id")Integer id,Model model)
    {
       //1.按照对应id去数据库中查出对应的员工信息
        Employee emp = employeeDao.getEmpById(id);
        //2.放在隐含模型中
        model.addAttribute("EditEmp",emp);
        //3.全部的部门信息放到隐含模型中
        List<Employee> all = employeeDao.getAllEmployees();
        List<String> departName = new LinkedList<String>();
        for(Employee employee:all)
        {
            departName.add(employee.getDepartment());
        }
        model.addAttribute("departments",departName);
        return "edit";
    }

    /*虽然上面也有/emp/{id}的请求路径方式,但是没有限制请求方式,而下面我们限制了请求方式
    优先精确匹配*/
    /*修改员工的方法,只有put请求才会接收*/
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.PUT)
    //在从数据库取出来的对象数据的基础上进行修改
    public String UpdateEmp(@ModelAttribute("employee") Employee employee)
    {
        System.out.println("要修改的员工:"+employee);
        //调用数据库中修改对象数据的方法,员工的id是不变的
           employeeDao.UpdateEmp(employee);
        return "redirect:/emps";
    }

 @ModelAttribute
 /*从请求参数中拿到id*/
    public void modelAttributes(@RequestParam(value = "id",required = false)Integer id,Model model)
    {
        if(id!=null)
        {
            Employee emp = employeeDao.getEmpById(id);
            model.addAttribute("employee",emp);
        }
        System.out.println("提前运行的方法调用了");
    }

    //删除方法
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.DELETE)
    public String deleteEmp(@PathVariable("id") Integer id)
    {
        employeeDao.delete(id);
        return "redirect:/emps";
    }
}

EmployeeDao

package com.Dao;

import com.POJO.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;
@Repository
public class EmployeeDao {
@Autowired //按照类型注入
    JdbcTemplate jdbcTemplate;

    //保存员工信息到数据库
    public void save( Employee employee)
    {
        String  sql="insert employee values(?,?,?,?,?)";
          jdbcTemplate.update(sql,employee.getId(),employee.getName(),employee.getDepartment(),
                  employee.getEamil(),employee.getGender());
    }

    //查询并返回对应员工信息
    public Employee exist(Employee employee)
    {
        String  sql="select * from employee where name=? and id= ?";
try{
    Employee employee1 = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Employee>(Employee.class), employee.getName(), employee.getId());
      return employee1;
}
catch (Exception e)
{
return null;
}
    }

   //删除某个员工的信息
    public void delete(Integer id)
    {
        String sql="delete from employee where id=?";
        jdbcTemplate.update(sql,id);
    }

    //返回所有员工的信息
    public List<Employee> getAllEmployees()
    {
        String sql="select* from employee";
        List<Employee> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Employee>(Employee.class));
    return list;
    }

    //按照员工的id查找对应的员工
    public Employee getEmpById(Integer id)
    {
        String  sql="select * from employee where id= ?";
        try{
            Employee employee1 = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Employee>(Employee.class),id);
            return employee1;
        }
        catch (Exception e)
        {
            return null;
        }
    }

    //修改员工的信息
    public void UpdateEmp(Employee employee)
    {
        //对员工进行进行修改
        String sql="update  employee set name=? ,department=? ,eamil=? ,gender=? where id=?";
        jdbcTemplate.update(sql,employee.getName(),employee.getDepartment(),employee.getEamil(),employee.getGender()
        ,employee.getId());
    }
}

Employee

package com.POJO;

import org.springframework.stereotype.Component;

@Component
public class Employee {
private Integer id;
private  String name;
private  String department;
private  String eamil;
private  Integer gender;

    public Employee(Integer id, String name, String department, String eamil, Integer gender) {
        this.id = id;
        this.name = name;
        this.department = department;
        this.eamil = eamil;
        this.gender = gender;
    }

    public Employee() {

    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getEamil() {
        return eamil;
    }

    public void setEamil(String eamil) {
        this.eamil = eamil;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", department='" + department + '\'' +
                ", eamil='" + eamil + '\'' +
                ", gender=" + gender +
                '}';
    }
}