8、SpringMVC之RESTful案例
阅读本文前,需要先阅读SpringMVC之RESTful概述
8.1、前期工作
8.1.1、创建实体类Employee

package org.rain.pojo;
import java.io.Serializable;
/**
 * @author liaojy
 * @date 2023/10/19 - 21:31
 */
public class Employee implements Serializable {
    private Integer id;
    private String lastName;
    private String email;
    //1 male, 0 female
    private Integer gender;
    public Employee() {
    }
    public Employee(Integer id, String lastName, String email, Integer gender) {
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.gender = 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;
    }
    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", gender=" + gender +
                '}';
    }
}
8.1.2、创建EmployeeDao模拟操作数据

package org.rain.dao;
import org.rain.pojo.Employee;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
 * @author liaojy
 * @date 2023/10/19 - 21:36
 */
@Repository
public class EmployeeDao {
    // 通过map集合模拟数据库
    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));
    }
    // 新数据的id
    private static Integer initId = 1006;
    // 新增或修改
    public void save(Employee employee) {
        // 参数没有id表示要执行新增操作
        if (employee.getId() == null) {
            // 设置新增数据的id,并自增id值为下一次新增数据做准备
            employee.setId(initId++);
        }
        // 更新模拟数据库的数据
        employees.put(employee.getId(), employee);
    }
    // 查询所有
    public Collection<Employee> getAll(){
        return employees.values();
    }
    // 根据id查询
    public Employee get(Integer id){
        return employees.get(id);
    }
    // 根据id删除
    public void delete(Integer id){
        employees.remove(id);
    }
}
8.1.3、调整bean组件扫描

在原来的环境中,只扫描控制层组件,现在多了持久层组件,所以要调整扫描包的范围
    <!--在指定的包中,扫描bean组件-->
    <context:component-scan base-package="org.rain"></context:component-scan>
8.1.4、功能清单
| 功能 | URL 地址 | 请求方式 | 
|---|---|---|
| 访问首页 | / | GET | 
| 查询全部数据 | /employee | GET | 
| 跳转到添加数据页面 | /to/add | GET | 
| 执行保存 | /employee | POST | 
| 跳转到修改数据页面 | /to/update/2 | GET | 
| 执行修改 | /employee | PUT | 
| 删除 | /employee/2 | DELETE | 
8.2、查询列表功能
8.2.1、页面请求示例

<a th:href="@{/employee}">查询所有员工的信息</a>
8.2.2、控制器方法示例

    @GetMapping("/employee")
    public String getAllEmployee(Model model){
        // 获取所有员工的信息
        Collection<Employee> allEmployee = employeeDao.getAll();
        // 将所有员工的信息,共享到请求域
        model.addAttribute("allEmployee",allEmployee);
        // 跳转到列表页面
        return "employee_list";
    }
8.2.3、列表页面示例

注意:在idea中,某些thymeleaf语法可能会提示错误(红色波浪线),这是误报,可以不用管
<table border="10">
    <tr>
        <!--表头合并五列-->
        <th colspan="5">employee list</th>
    </tr>
    <tr>
        <th>id</th>
        <th>lastName</th>
        <th>email</th>
        <th>gender</th>
        <th>options</th>
    </tr>
    <!--在thymeleaf语法中,要循环一个标签,只需要在该标签中添加循环属性即可-->
    <tr th:each="employee : ${allEmployee}">
        <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="">update</a>
            <a href="">delete</a>
        </td>
    </tr>
</table>
8.2.4、测试效果


8.3、新增功能
8.3.1、页面请求示例

<th>options(<a th:href="@{/to/add}">add</a>)</th>
8.3.2、视图控制器示例

因为只需要实现页面跳转,没有处理业务的过程,所以可以使用视图控制器实现
<mvc:view-controller path="/to/add" view-name="employee_add"></mvc:view-controller>
8.3.3、新增页面示例

<form th:action="@{/employee}" method="post">
    <!--因为table标签中的子标签是固定的,所以要用form标签包含table标签-->
    <table border="10">
        <tr>
            <th colspan="2">employee add</th>
        </tr>
        <tr>
            <td>lastName</td>
            <td> <input type="text" name="lastName"> </td>
        </tr>
        <tr>
            <td>email</td>
            <td> <input type="text" name="email"> </td>
        </tr>
        <tr>
            <td>gender</td>
            <td>
                <input type="radio" name="gender" value="1">male
                <input type="radio" name="gender" value="0">female
            </td>
        </tr>
        <tr>
            <td colspan="2"> <input type="submit" value="add"> </td>
        </tr>
    </table>
</form>
8.3.4、控制器方法示例

注意:直接跳转到列表页面会显示不了数据,因为还没向请求域共享数据,所以需要先跳转到查询列表功能
此外,跳转要用重定向,而不是用请求转发;
如果用请求转发,因为源请求的请求方式是post,所以请求转发后的请求方式还会是post,这样就会一直重复调用insertEmployee方法,直至内存耗尽;
如果用重定向,因为重定向的请求方式肯定是get,所以会调用getAllEmployee方法,从而实现查询列表功能
    @PostMapping("/employee")
    public String insertEmployee(Employee employee){
        // 新增员工
        employeeDao.save(employee);
        // 重定向到查询列表功能
        return "redirect:/employee";
    }
8.3.5、测试效果




8.4、修改功能
8.4.1、页面请求示例

注意:因为员工id是变量,所以(在thymeleaf语法中)路径要使用单引号后再使用加号拼接变量
<a th:href="@{'/to/update/'+${employee.id}}">update</a>
8.4.2、控制器方法示例(回显数据)

    @GetMapping("/to/update/{id}")
    public String toUpdate(@PathVariable("id") Integer id, Model model){
        // 根据id查询员工信息
        Employee employee = employeeDao.get(id);
        // 将员工信息共享到请求域
        model.addAttribute("employee",employee);
        // 跳转到更新页面
        return "employee_update";
    }
8.4.3、更新页面示例

注意:请求方式和id用了隐藏域;
单选框的回显,用了th:field的属性,如果其值和value属性的值相等,则选中当前单选框
<form th:action="@{/employee}" method="post">
    <input type="hidden" name="_method" value="put">
    <input type="hidden" name="id" th:value="${employee.id}">
    <table border="10">
        <tr>
            <th colspan="2">employee update</th>
        </tr>
        <tr>
            <td>lastName</td>
            <td> <input type="text" name="lastName" th:value="${employee.lastName}"> </td>
        </tr>
        <tr>
            <td>email</td>
            <td> <input type="text" name="email" th:value="${employee.email}"> </td>
        </tr>
        <tr>
            <td>gender</td>
            <td>
                <input type="radio" name="gender" value="1" th:field="${employee.gender}">male
                <input type="radio" name="gender" value="0" th:field="${employee.gender}">female
            </td>
        </tr>
        <tr>
            <td colspan="2"> <input type="submit" value="update"> </td>
        </tr>
    </table>
</form>
8.4.4、控制器方法示例(执行修改)

    @PutMapping("/employee")
    public String updateEmployee(Employee employee){
        // 修改员工
        employeeDao.save(employee);
        // 重定向到查询列表功能
        return "redirect:/employee";
    }
8.4.5、测试效果




8.5、删除功能
8.5.1、页面请求示例

<a onclick="put()" th:href="@{'/employee/'+${employee.id}}">delete</a>
<form method="post">
    <input type="hidden" name="_method" value="delete">
</form>
<script type="text/javascript">
    function put() {
        // 获取form表单
        var form = document.getElementsByTagName("form")[0]
        // 将超链接的href属性值赋值给form表单的action属性
        // event.target表示当前触发事件的标签
        form.action = event.target.href;
        // 提交表单
        form.submit();
        // 阻止超链接的默认行为(跳转)
        event.preventDefault();
    }
</script>
8.5.2、控制器方法示例

    @DeleteMapping("/employee/{id}")
    public String deleteEmployee(@PathVariable("id") Integer id){
        // 删除员工
        employeeDao.delete(id);
        // 重定向到查询列表功能
        return "redirect:/employee";
    }
8.5.3、测试效果


8、SpringMVC之RESTful案例的更多相关文章
- 【SpringMVC】RESTFul简介以及案例实现
		RESTful 概念 REST:Representational State Transfer,表现层资源状态转移. 资源 资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成.每个资源 ... 
- HTTP Status 405 - Request method 'GET' not supported?(尚硅谷Restful案例练习关于Delete方法出现的错误)
		哈罗大家好,最近在如火如荼的学习java开发----Spring系列框架,当学习到SpringMVC,动手实践RESTFUL案例时,发现了以上报错405,get请求方法没有被支持. 首先第一步,我查看 ... 
- Spring+springmvc+Mybatis整合案例 annotation版(myeclipse)详细版
		Spring+springmvc+Mybatis整合案例 Version:annotation版 文档结构图: 从底层开始做起: 01.配置web.xml文件 <?xml version=&qu ... 
- Spring+springmvc+Mybatis整合案例   xml配置版(myeclipse)详细版
		Spring+springmvc+Mybatis整合案例 Version:xml版(myeclipse) 文档结构图: 从底层开始做起: 01.配置web.xml文件 <?xml version ... 
- SpringMVC实现RESTful服务
		SpringMVC实现RESTful服务 这里只说service,controller层的代码.Mapper层则直接继承Mapper<T>则可以,记住mybatis-config.xml一 ... 
- 基于springMVC的RESTful服务实现
		一,什么是RESTful RESTful(RESTful Web Services)一种架构风格,表述性状态转移,它不是一个软件,也不是一个标准,而是一种思想,不依赖于任何通信协议,但是开发时要成功映 ... 
- springmvc的RESTful风格
		springmvc对RESTful得支持RESTful架构,就是目前最流行得一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以挣得到越来越多网站的采用. RESTful(即Repres ... 
- 基于 springMVC 的 RESTful HTTP API 实践(服务端)
		理解 REST REST(Representational State Transfer),中文翻译叫"表述性状态转移".是 Roy Thomas Fielding 在他2000年 ... 
- SpringMVC:RESTful案例
		目录 相关准备 功能清单 具体功能:访问首页 ①配置view-controller ②创建页面 具体功能:查询所有员工数据 ①控制器方法 ②创建employee_list.html 具体功能:删除 ① ... 
- SpringMVC开发RESTful接口
		概念: 什么是REST? REST是Representational State Transfer的缩写.翻译为"表现层状态转化",restful是一种接口设计风格,它不是一个协议 ... 
随机推荐
- k8s——daemonset
			daemonset 为每一个匹配的node都部署一个守护进程 # daemonset node:type=logs daemonset 选择节点 - nadeSelector: 只调度到匹配指定的la ... 
- React事件处理 事件绑定 事件对象
			React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同: React 事件的命名采用小驼峰式,而不是纯小写. onClick onChange 使用 JSX 语法时你需要传入一个 ... 
- The sultion of P4959
			problem & blog 首先我们看到 \(x,y\) 有可能为负数,所以我们先把它旋转到第一象限. 然后我们发现如果 \(x_a \ge x_b\) 且 \(y_a \ge y_b\) ... 
- 如何使用 Loadgen 来简化 HTTP API 请求的集成测试
			引言 在编写 HTTP 服务的过程中,集成测试 [1] 是保证程序正确性的重要一环,如下图所示,其基本的流程就是不断向服务发起请求然后校验响应的状态和数据等: 为大量的 API 和用例编写测试是一件繁 ... 
- PowerShell 遇到 .ps1,因为在此系统上禁止运行脚本
			PowerShell 遇到 .ps1,因为在此系统上禁止运行脚本 解决方法: 以管理员身份打开PowerShell: 查看当前的执行策略: Get-ExecutionPolicy * `Restric ... 
- vuex中的数据在页面刷新后数据消失
			用sessionstorage 或者 localstorage 存储数据 存储: sessionStorage.setItem( '名', JSON.stringify(值) ) 使用: sessio ... 
- Redis的特点什么是?
			a.支持多种数据结构,如 string(字符串). list(双向链表).dict(hash表).set(集合).zset(排序set).hyperloglog(基数估算) b.支持持久化操作,可以进 ... 
- WebUI测试-获取html页面表格数据并存到Excel中
			from selenium.webdriver.support import expected_conditions as EC import pandas as pd table=WebDriver ... 
- openfly:基于nginx的4层代理管理平台
			简介 作者:京城郭少 基于nginx的4层代理管理平台 支持的功能: 被动健康检查 白名单 include导入文件 哈希 backup冗余互备 weight权重 注释 ...... 部署openfly ... 
- Vue 3 后端错误消息处理范例
			1. 错误消息格式 前后端消息传递时,我们可以通过 json 的 errors 字段传递错误信息,一个比较好的格式范例为: { errors: { global: ["网络错误"] ... 
