八、RESTFul案例


1、准备工作

和传统 CRUD 一样,实现对员工信息的增删改查。

    搭建环境

    准备实体类

package com.atguigu.mvc.bean;

public class Employee {

   private Integer id;
   private String lastName;

   private String email;
   //1 male, 0 female
   private Integer gender;
   
   public Integer getId() {
      return id;
   }

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

   public String getLastName() {
      return lastName;
   }

   public void setLastName(String lastName) {
      this.lastName = lastName;
   }

   public String getEmail() {
      return email;
   }

   public void setEmail(String email) {
      this.email = email;
   }

   public Integer getGender() {
      return gender;
   }

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

   public Employee(Integer id, String lastName, String email, Integer gender) {
      super();
      this.id = id;
      this.lastName = lastName;
      this.email = email;
      this.gender = gender;
   }

   public Employee() {
   }
}

    准备dao模拟数据

package com.atguigu.mvc.dao;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.atguigu.mvc.bean.Employee;
import org.springframework.stereotype.Repository;


@Repository
public class EmployeeDao {

   private static Map<Integer, Employee> employees = null;
   
   static{
      employees = new HashMap<Integer, Employee>();

      employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1));
      employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1));
      employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0));
      employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0));
      employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1));
   }
   
   private static Integer initId = 1006;
   
   public void save(Employee employee){
      if(employee.getId() == null){
         employee.setId(initId++);
      }
      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);
   }
}

2、功能清单

功能URL 地址请求方式
访问首页√/GET
查询全部数据√/employeeGET
删除√/employee/2DELETE
跳转到添加数据页面√/toAddGET
执行保存√/employeePOST
跳转到更新数据页面√/employee/2GET
执行更新√/employeePUT

1、访问所有员工数据的页面实现

在首页里面写了一个查看员工信息的超链接,若想实现查看员工信息这个功能,我们该怎么办?

不能直接访问我们的员工列表页面,就需要用异步请求了,没有用AJAX,首先必须通过控制器的处理这个请求,查询出来数据,放在域对象中,在跳转到页面才能够看到数据。

要想去展示当前的员工信息,最好是用一个表格,html中最常用的两个标签,一个是表单,一个是表格, 表格用来展示数据,表单用来展示数据。

<th>是表头,能够自动加粗并居中。

<table border="1" cellspacing="0" cellpadding="0" style="text-align: center;">
    <tr>
        <!--合并列为5-->
        <th colspan="5">Employee Info</th>
    </tr>
    <tr>
        <th>id</th>
        <th>lastName</th>
        <th>email</th>
        <th>gender</th>
        <th>options</th>
    </tr>
    <!--each这里是代表我们要遍历的每一个数据,因为我们的数据是在请求域中去放的,所以我们要用${}去访问-->
    <tr th:each="employee : ${employeeList}">
    <!--不能直接在td里面${employee.id},因为我们当前在td标签里面去写的话,会被当成文本原样解析
    所以要想操作文本内容,应该用th:text
    -->
    <td th:text="${employee.id}"></td>
    <td th:text="${employee.lastName}"></td>
    <td th:text="${employee.email}"></td>
    <td th:text="${employee.gender}"></td>
    <td>
        <a href="@{/employee}+${employee.id}">delete</a>
        <a href="">update</a>
    </td>
    </tr>
</table>

1、${employee.id}这个值要想解析需要通过+拼接的形式,不能放在@{}里面,在@{}里面是解析成路径。

2、要想放在@{}里面,前面表示请求地址的/employee/要加上单引号' ',在里面用+号,此时${}里面会解析成数据

2、删除功能的实现

超链接只能发送get请求,要想发送delete请求,需要借助我们的过滤器,过滤器要求我们的表单必须有method=post,请求参数_method=delete。

此时是通过vue用超链接控制表单的提交,所以不用action手动提交表单。

<form method="post">
    <input type="hidden" name="_method" value="delete">
</form>

为这个超链接绑定了一个点击事件,通过vue处理这个点击事件,form表单是最后提交请求的方式,vue里面设置的阻止超链接的默认提交,而改为了vue里面设置的表单提交的方式。

 vue.js文件有两次添加不成功

此时就需要vue的js文件,刚在static配置完,打包的中会没有static文件(服务器中会没有),此时需要在LifeStyle中重新打包package,这时就会在服务器中部署。此时还是访问不了的,因为我们在实现SpringMVC的时候配置了一个前端控制器Dispatcher,请求路径的映射是一个斜线,表示所有请求,所以我们当前访问我们的静态资源是被我们的SpringMVC的前端控制器处理的,但是静态资源不能被SpringMVC处理,在web阶段讲过一个默认的servlet,叫defaultservlet,这个东西才是处理静态资源的servlet。

在springMVC.xml中配置开放静态资源的defaultservlet

    <!--开放对静态资源的访问-->
    <mvc:default-servlet-handler/>

静态资源在访问的时候先被SpringMVC(前端控制器)进行处理,如果在控制器中找不到相对应的请求映射,就会交给咱们默认的servlet进行处理。

<table id="dataTable" border="1" cellspacing="0" cellpadding="0" style="text-align: center;">
    <tr>
        <!--合并列为5-->
        <th colspan="5">Employee Info</th>
    </tr>
    <tr>
        <th>id</th>
        <th>lastName</th>
        <th>email</th>
        <th>gender</th>
        <th>options (<a th:href="@{/toAdd}">add</a> )</th>
    </tr>
    <!--each这里是代表我们要遍历的每一个数据,因为我们的数据是在请求域中去放的,所以我们要用${}去访问-->
    <tr th:each="employee : ${employeeList}">
    <!--不能直接在td里面${employee.id},因为我们当前在td标签里面去写的话,会被当成文本原样解析
    所以要想操作文本内容,应该用th:text
    -->
    <td th:text="${employee.id}"></td>
    <td th:text="${employee.lastName}"></td>
    <td th:text="${employee.email}"></td>
    <td th:text="${employee.gender}"></td>
    <td>
        <!--但是我们先不需要绑定数据,仅仅先要处理我们超链接的点击事件-->
        <a @click="deleteEmployee" th:href="@{'/employee/'+${employee.id}}">delete</a>
        <a href="">update</a>
    </td>
    </tr>
</table>

<form id="deleteForm" method="post">
    <input type="hidden" name="_method" value="delete">
</form>

<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript">
    <!--首先我们要先绑定vue当前的容器,容器需要包括我们要操作的元素,属性el,接下来我们要设置data来绑定数据-->
    var vue = new Vue({
        el:"#dataTable",
        //methods这个属性是来处理当前的事件的,在里面写函数的名称,再对应我们当前的函数,在里面首先获取我们
        //的form表单
        methods:{
            deleteEmployee:function (event){
            //用原生js获取form表单
                //根据id获取表单元素
                var deleteForm = document.getElementById("deleteForm");
                //form表单没有action,那么我们就要先给action赋值,
                // 它才能提交,因为如果没有action或者action没有值就会提交到当前页面,要把它提交到
                // 触发事件的超链接href那里,event表示当前触发的事件,下面的target指触发事件的元素,也就是
                // 这个超链接,在.href就能获得当前触发事件的超链接的href属性,thymeleaf先解析
                // 所以不用写th:href
                //将触发点击事件的超链接的href属性赋值给表单的action
                deleteForm.action = event.target.href;
                //提交表单
                deleteForm.submit();
                //注意标签的默认行为,超链接点击之后就算你绑定了有点击事件,它也会跳转页面,
                //像sumbit()按钮,就算你绑定了点击事件,它会先执行事件,再提交表单,所以要取消默认行为。
                //取消超链表的默认行为
                event.preventDefault();
            }
        }
    });
</script>
    @RequestMapping(value = "/employee/{id}",method = RequestMethod.DELETE)
    //要想获得路径中占位符所表示的数据,应该再形参位置设置形参,通过@PathVariable("id"),将占位符表示的值
    //与形参中进行绑定
    public String deleteEmployee(@PathVariable("id") Integer id){
        employeeDao.delete(id);
        //我们应该跳转到列表页面,不能直接跳列表页面,因为列表页面是由上面的这个控制器来完成的
        //所以应该用转发或者重定向来return上面控制器那个请求,
        //但是要用重定向,让浏览器发送一个新的请求,来显示上面控制器方法的那个地址
        return "redirect:/employee";
    }

以上是删除功能的操作。

3、增加员工操作

1、在员工列表页面中添加超链接,跳转到一个添加员工的页面

        <th>options (<a th:href="@{/toAdd}">add</a>)</th>

2、因为只需要页面视图的跳转,所以可以在SpringMVC中配置标签

    <mvc:view-controller path="/toAdd" view-name="employee_add"></mvc:view-controller>

3、在创建增加员工的页面,在里面写一个表单就可以了,因为添加就是用post方式提交,必须是用

th:action,不然解析不了里面的地址

<form th:action="@{/employee}" method="post">
  lastName: <input type="text" name="lastName"><br>
  email: <input type="text" name="email"><br>
  gender: <input type="radio" name="gender" value="1">male
  <input type="radio" name="gender" value="0">female<br/>
  <input type="submit" value="add"><br>
</form>

 4、在写控制器方法获取表单中的属性数据

    @RequestMapping(value = "/employee",method = RequestMethod.POST)
    public String addEmployee(Employee employee){
        employeeDao.save(employee);
        return "redirect:/employee";
    }

4、根据员工id修改员工信息(修改功能)

修改功能与删除功能差不多,但是修改功能不能像删除功能一样点击直接实现删除功能,点击之后也要有相对应的页面,相对应的表单。

<a th:href="@{'/employee/' + ${employee.id}}">update</a>

在employee_list.html表单中添加上面超链接,根据传入的id值跳转到相对应的控制器方法,有控制器方法里面的@PathVariable("id") Integer id 参数获取id的值,利用Model model参数向我们的request域对象中进行共享,根据id通过employeeDao.get(id)方法获取用户对象,这个对象就是要我们要修改的用户信息,此时就用addAttribute方法放入employee的键值对,再跳转到employee_update对应的修改页面。

    @RequestMapping(value = "/employee/{id}",method = RequestMethod.GET)
    public String getEmployeeById(@PathVariable("id") Integer id,Model model){
        Employee employee = employeeDao.get(id);
        model.addAttribute("employee",employee);
        return "employee_update";
    }
此时就在employee_update进行回显(把th:value="${employee.id}"解析的数值写到表单里)
<form th:action="@{/employee}" method="post">
    <input type="hidden" name="_method" value="put">
    <input type="hidden" name="id" th:value="${employee.id}">
  lastName: <input type="text" name="lastName" th:value="${employee.lastName}"><br>
  email: <input type="text" name="email" th:value="${employee.email}"><br>
  gender: <input type="radio" name="gender" value="1" th:field="${employee.gender}">male
  <input type="radio" name="gender" value="0" th:field="${employee.gender}">female<br/>
  <input type="submit" value="update"><br>
</form>
单选框回显,需要th:field="${employee.id}",就会拿着field的值与value进行比较,如果一致就会自动添加checked = "checked",最后id也要回显,但是对用户没用,所以用隐藏域。

此时表单会提交到方法为put的/employee的请求

此时再写一个控制器方法保存修改完后的employee数据,这个方法是向Map<Integer, Employee>

的对象employees中put(id,employee);再重定向到到显示所有数据的/employee中,因为重定向默认是get,所以说可以重名

    @RequestMapping(value="/employee",method = RequestMethod.PUT)
    public String updateEmployee(Employee employee){
        //这个方法会判断id是否会重复,无重复会加1,有重复那么添加的数据会覆盖原来的数据
        employeeDao.save(employee);
        return "redirect:/employee";
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值