第八章 综合案例 RESTRUL_CRUD

时间:2021-6-4 作者:qvyue

target

能够完成restful的增删改查
掌握静态资源不能加载的处理办法
掌握中文乱码的解决方案
掌握下拉框和单选框的回显操作
了解使用Spring表单标签重构页面

1. RESTRUL_CRUD_需求

使用 restful 实现员工的crud功能。

1.1 显示所有员工信息

① URL:emps
② 请求方式:GET
③ 显示效果

第八章 综合案例 RESTRUL_CRUD

1.2 添加操作-跳转至添加页面

① 显示添加⻚面:
② URL:emp
③ 请求方式:GET
④ 显示效果:

第八章 综合案例 RESTRUL_CRUD

1.3 添加操作-添加员工

① 添加员工信息
②URL:emp
③ 请求方式:POST
④ 显示效果:完成添加,重定向到emps请求

第八章 综合案例 RESTRUL_CRUD

1.4 删除操作

① URL:emp/{id}
② 请求方式:DELETE
③ 删除后效果:对应记录从数据表中删除

1.5 修改操作去往修改⻚面

① URL:emp/{id}
② 请求方式:GET
③ 显示效果:回显表单

1.6 修改操作修改员工

① URL:emp
② 请求方式:PUT
③ 显示效果:完成修改,重定向到emps请求

1.7 相关的类

① 实体类:Employee、Department
② Controller: EmployeeController
③ Dao:EmployeeDao、DepartmentDao

1.8 相关页面

① list.jsp
② input.jsp
③ edit.jsp

2. 搭建环境

新建动态 Web项目 SpringMVC_restful

2.1 导入jar

将以下jar复制到 lib 目录下:

commons-logging-1.2.jar
spring-aop-4.3.9.RELEASE.jar
spring-beans-4.3.9.RELEASE.jar
spring-context-4.3.9.RELEASE.jar
spring-core-4.3.9.RELEASE.jar
spring-expression-4.3.9.RELEASE.jar
spring-web-4.3.9.RELEASE.jar
spring-webmvc-4.3.9.RELEASE.jar

2.2 配置核心控制器:web.xml

Web.xml 中配置 HiddenHttpMethodFilter 过滤器和前端控制器

SpringMVC_Restfulindex.jspHiddenHttpMethodFilterorg.springframework.web.filter.HiddenHttpMethodFilterHiddenHttpMethodFilter/*springDispatcherServletorg.springframework.web.servlet.DispatcherServletcontextConfigLocationclasspath:springmvc.xml1springDispatcherServlet/

2.3 创建配置文件:springmvc.xml

在 src 下新建springmvc 配置文件,开启包扫描和视图解析

2.4 实体类

员工类:

package com.lee.entity;

public class Employee {

    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;
    private Department department;
    //getter、setter 略   
}

部门类:

package com.lee.entity;

public class Department {

    private Integer id;
    private String departmentName;

    //getter、setter 略   
}

2.5 Dao类

员工:

package com.lee.springmvc.dao;

@Repository
public class EmployeeDao {
  
  //模拟数据库数据
    private static Map employees = null;
    static {
        employees = new HashMap();
        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; //下次添加的id默认从1006开始
}

部门:

package com.lee.springmvc.dao;

@Repository
public class DepartmentDao {
  //模拟数据库数据
    private static Map departments = null;
    static {
        departments = new LinkedHashMap();
        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 getDepartments() {
        return departments.values();
    }

  //根据id获取部门信息
    public Department getDepartment(Integer id) {
        return departments.get(id);
    }
}

3. RESTRUL_CRUD_显示所有员工信息

1)增加页面链接:index.jsp






主页
显示员工列表


2)处理器

@Controller
public class EmpController {

    @Autowired
    EmployeeDao employeeDao;
    
    /**
     * 查询所有员工
     * @param map
     * @return
     */
    @RequestMapping("emps")
    public String getAll(Map map) {
        Collection emps = employeeDao.getAll();
        map.put("emps", emps);
        return "list";
    }
}

3)Dao层:

在EmployeeDao.java 中加入 getAll()方法来获取所有员工信息:

package com.lee.springmvc.dao;

@Repository
public class EmployeeDao {
  
    .......
    
    /**
     * 获取所有员工信息
     * @return
     */
    public Collection getAll() {
        return employees.values();
    }   
}

4)在views下编写list.jsp

需要用到jstl标签库进行遍历员工信息遍历,需要两个jar:

jstl-1.1.2.jar
standard-1.1.2.jar

在 WEB-INF/views 目录下新建list页面:


 




员工列表

    table,table tr th, table tr td {
      border:1px solid #a8aeb2;
      padding: 5px 10px;
    }
    table {
      min-height: 25px;
      line-height: 25px;
      text-align: center;
      border-collapse: collapse;
    } 

ID LASTNAME EMAIL GENDER DEPARTMENT
${emp.id } ${emp.lastName } ${emp.email } ${emp.gender ==1?"男":"女"} ${emp.department.departmentName }

开发经验

如果加载css样式或者js等会出现静态资源无法被访问的情况:

这是由于springmvc的dispatcherServlet把静态资源也当成请求进行处理了,可以使用以下两个标签,把静态资源交给Tomcat的servlet去处理,就能解决这个问题:

4. RESTRUL_CRUD_添加操作

1)在list.jsp上增加连接


  ....
ID LASTNAME EMAIL GENDER DEPARTMENT ADD

2)在EmpController中增加处理方法

此处理器是跳转到增加页面的处理器,并不是具体的增加方法

/**
     * 跳转到添加页面,并查出所有部门信息
     * @param map
     * @return
     */
@RequestMapping(value = "emp",method = RequestMethod.GET)
public String toAdd(Map map) {
  //查询所有部门
  Collection departments = departmentDao.getDepartments();
  map.put("departments", departments);
  return "add";
}

这个控制器不仅仅跳转到增加页面,而且获取了部门信息。

3)add.jsp页面







添加页面

        
lastName
email
gender 男 女
department SELECT DEPARTMENT ${dept.departmentName }

4)在EmpController处理器中新增员工

/**
     * 添加员工
     * @param emp
     * @return
     */
@RequestMapping(value = "emp" ,method = RequestMethod.POST)
public String addEmp(Employee emp) {
  employeeDao.addEmp(emp);
  return "redirect:/emps";
}

注意:

这里需要使用重定向,重定向到获取所有员工的控制器。

开发中,增删改后都要进行重定向,请求转发会造成表单重复提交问题。

5)在EmployeeDao中编写员工添加方法:

package com.lee.springmvc.dao;

@Repository
public class EmployeeDao {
  
  ...
    
    @Autowired
    DepartmentDao departmentDao;

    /**
     * 添加员工
     * @param emp
     */
    public void addEmp(Employee emp) {
        // System.out.println(emp); 
        // 由于前台传来的emp中只有部门id,没有部门名称。所以根据部门id查出部门信息
        Department department = departmentDao.getDepartment(emp.getDepartment().getId());
        emp.setId(initId);  //为emp设置id
        emp.setDepartment(department);  // 为emp设置部门信息
        employees.put(initId, emp); // 将emp加入到员工中
        initId++;
    }   
}

开发经验

再添加信息时,添加中文会出现乱码情况。

解决方案:在web.xml中添加字符编码过滤器,这个过滤器一定要添加到其他过滤器之前。

encodingFilterorg.springframework.web.filter.CharacterEncodingFilterencodingUTF-8encodingFilter/*

5. RESTRUL_CRUD_更新操作

1)添加更新链接:

在list.jsp中添加更新按钮:


${emp.id }
    ${emp.lastName }
    ${emp.email }
    ${emp.gender ==1?"男":"女"}
    ${emp.department.departmentName }
    UPDATE
  

2)在EmpController控制器中编写跳转到更新员工的页面的方法:

/**
     * 跳转到更新员工的页面
     * @param id
     * @param map
     * @return
     */
@RequestMapping(value = "emp/{id}",method = RequestMethod.GET)
public String toUpdate(@PathVariable("id") Integer id,Map map) {
  Employee emp = employeeDao.getEmpById(id);//根据员工id查员工信息
  Collection departments = departmentDao.getDepartments();
  map.put("emp", emp);
  map.put("departments", departments);
  return "update";
}

3)在EmployeeDao 中编写根据员工id查询员工信息:

public Employee getEmpById(Integer id) {
  Employee employee = employees.get(id);
  return employee;
}

4)在 WEB-INF下新建update.jsp

注意:

如果更新页面报错405,就在表单action写绝对路径







更新信息

    
lastName
email
gender 男 女
department ${dept.departmentName }

5)在EmpController控制器中编写 更新员工的方法:

/**
     * 更新员工信息
     * @param emp
     * @return
     */
@RequestMapping(value = "emp" ,method = RequestMethod.PUT)
public String updateEmp(Employee emp) {
  employeeDao.updateEmp(emp);
  return "redirect:/emps";
}

6)在EmployeeDao下编写更新员工的方法:

public void updateEmp(Employee emp) {
  // 由于前台传来的emp中只有部门id,没有部门名称。所以根据部门id查出部门信息
  Department department = departmentDao.getDepartment(emp.getDepartment().getId());
  emp.setDepartment(department);    // 为emp设置部门信息
  employees.replace(emp.getId(), emp);
}   

开发经验

如何设置下拉框回显:


  ${dept.departmentName }

如何设置单选框回显


  男
  女

或者:


  checked="checked" />男
checked="checked" />女

更新的action需要绝对路径

update.jsp中的form表单的action必须是绝对路径,否则会出现路径请求异常。

el表达式获取绝对路径:


6. RESTURL_CRUD_删除操作

6.1 方法一

1)在list.jsp中添加删除按钮,由于删除需要使用delete方式的请求,所以用form表单传值:


  
    


2)在EmpController中编写根据id删除员工的方法:

/**
     * 根据id删除员工
     * @param id
     * @return
     */
@RequestMapping(value = "emp/{id}",method = RequestMethod.DELETE)
public String deleteEmpById(@PathVariable("id") Integer id) {
  employeeDao.deleteEmp(id);
  return "redirect:/emps";
}

3)在 EmployeeDao中编写删除代码:

/**
     * 根据id删除员工
     * @param id
     */
public void deleteEmp(Integer id) {
  employees.remove(id);
}   

6.2 方法二

请求路径:

Delete

控制器:

/**
     * 根据id删除员工
     * @param id
     * @return
     */
@RequestMapping(value = "emp/{id}" ,method = RequestMethod.DELETE)
public String delEmp(@PathVariable("id") Integer id) {
  employeeDao.delete(id);
  return "redirect:/emps";
}

发起请求,无法执行,因为 delete 请求必须借助HiddenHttpMethodFilter 过滤器把 post 请求转换为 delete 请求,

需要使用 jQuery 来转换请求方式



    $(function() {
        $(".delete").click(function(){
            var href = this.href;
            if(confirm("确认删除")){
                $("form").attr("action",href).submit();
                return false;//使函数终止执行
            }           
        });
    });

  

开发经验:

如果报如下错误:

第八章 综合案例 RESTRUL_CRUD

检查第一步: jQuery的路径应该是绝对路径,否则资源找不到。

检查第二步:springmvc有没有处理静态资源(重要)。

6.3 删除操作执行图解

第八章 综合案例 RESTRUL_CRUD

7. 扩展:作用

首先打开Tomcat的web.xml文件:可以看到如下的servlet

defaultorg.apache.catalina.servlets.DefaultServletdebug0listingsfalse1default/

这是Tomcat配置的servlet,名字是default,拦截所有请求。

他是专门处理静态资源请求的servlet。springmvc中会配置一个dispatcherServlet去处理所有的请求,但是不包含静态资源,所以静态资源会失效。因此需要在springmvc配置文件中加上:,就可以去处理dispatcherServlet处理不了的静态资源了。但是加上后,又只能访问静态资源,原来的请求又失效了,因此需要配合 一起使用。

8. 扩展:Spring的表单标签

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

使用spring的表单标签需要引入标签库:


8.1 使用spring标签重构添加

  • 修改EmpController控制器中的跳转方法:
/**
     * 跳转到添加页面
     * @return
     */
@RequestMapping(value = "emp",method = RequestMethod.GET )
public String toAdd(Map map) {
  Collection departments = departmentDao.getDepartments();
  Map genders = new HashMap();
  genders.put("0", "男");
  genders.put("1", "女");
  map.put("departments", departments);
  map.put("genders", genders);
  /**
         * 如果不加下面这行代码,会报错
         */
  map.put("command", new Employee());
  return "add";
}
  • 修改add.jsp:

 
 




添加员工信息

        LastName:
email:
Gender:
Department:

重新加载项目,一切OK。

注意:

如果EmpController控制器中的 toAdd() 方法没有map.put("command", new Employee());代码,会如下报错:

第八章 综合案例 RESTRUL_CRUD

报错原因:

由于spring的from表单自带回显功能,form会去控制器中寻找默认为command的属性,command中包含表单的所有信息,command就是”模型属性”,form会解析command中的信息显示在表格中。

此外,也可以在表单中使用modelAttribute指定:

控制器相应的改为:

map.put("employee", new Employee());

8.2 使用Spring标签重构修改

可以把添加和修改写到一个页面,将add.jsp改名为:add_update_form.jsp:


 
 




添加/修改员工信息


        LastName:
email:
Gender:
Department:

EmpController控制器中修改”跳转到更新”和”跳转到添加页面”的方法:

/*跳转到添加页面 */
@RequestMapping(value = "emp",method = RequestMethod.GET)
public String toAdd(Map map) {
  Collection departments = departmentDao.getDepartments();
  Map genders = new HashMap();
  genders.put("0", "男");
  genders.put("1", "女");
  map.put("genders", genders);
  map.put("departments", departments);
  map.put("employee", new Employee());
  return "add_update_form";
}

/*跳转到更新页面*/
@RequestMapping(value = "emp/{id}",method = RequestMethod.GET)
public String toUpdate(@PathVariable("id") Integer id,Map map) {
  Employee emp = employeeDao.getEmpById(id);//根据员工id查员工信息
  Collection departments = departmentDao.getDepartments();
  Map genders = new HashMap();
  genders.put("0", "男");
  genders.put("1", "女");
  map.put("genders", genders);
  map.put("employee", emp); 
  map.put("departments", departments);
  return "add_update_form";
}
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。