阅读本文前,需要先阅读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案例的更多相关文章

  1. 【SpringMVC】RESTFul简介以及案例实现

    RESTful 概念 REST:Representational State Transfer,表现层资源状态转移. 资源 资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成.每个资源 ...

  2. HTTP Status 405 - Request method 'GET' not supported?(尚硅谷Restful案例练习关于Delete方法出现的错误)

    哈罗大家好,最近在如火如荼的学习java开发----Spring系列框架,当学习到SpringMVC,动手实践RESTFUL案例时,发现了以上报错405,get请求方法没有被支持. 首先第一步,我查看 ...

  3. Spring+springmvc+Mybatis整合案例 annotation版(myeclipse)详细版

    Spring+springmvc+Mybatis整合案例 Version:annotation版 文档结构图: 从底层开始做起: 01.配置web.xml文件 <?xml version=&qu ...

  4. Spring+springmvc+Mybatis整合案例 xml配置版(myeclipse)详细版

    Spring+springmvc+Mybatis整合案例 Version:xml版(myeclipse) 文档结构图: 从底层开始做起: 01.配置web.xml文件 <?xml version ...

  5. SpringMVC实现RESTful服务

    SpringMVC实现RESTful服务 这里只说service,controller层的代码.Mapper层则直接继承Mapper<T>则可以,记住mybatis-config.xml一 ...

  6. 基于springMVC的RESTful服务实现

    一,什么是RESTful RESTful(RESTful Web Services)一种架构风格,表述性状态转移,它不是一个软件,也不是一个标准,而是一种思想,不依赖于任何通信协议,但是开发时要成功映 ...

  7. springmvc的RESTful风格

    springmvc对RESTful得支持RESTful架构,就是目前最流行得一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以挣得到越来越多网站的采用. RESTful(即Repres ...

  8. 基于 springMVC 的 RESTful HTTP API 实践(服务端)

    理解 REST REST(Representational State Transfer),中文翻译叫"表述性状态转移".是 Roy Thomas Fielding 在他2000年 ...

  9. SpringMVC:RESTful案例

    目录 相关准备 功能清单 具体功能:访问首页 ①配置view-controller ②创建页面 具体功能:查询所有员工数据 ①控制器方法 ②创建employee_list.html 具体功能:删除 ① ...

  10. SpringMVC开发RESTful接口

    概念: 什么是REST? REST是Representational State Transfer的缩写.翻译为"表现层状态转化",restful是一种接口设计风格,它不是一个协议 ...

随机推荐

  1. (数据科学学习手札161)高性能数据分析利器DuckDB在Python中的使用

    本文完整代码及附件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,就在几天前,经过六年多的 ...

  2. 工作中常用Less知识点实践总结

    我所理解的Less的一些好处 函数式编程css 自定义变量用于整体主题调整 嵌套语法简化开发复杂度 mixin的写法 .defaultBorder(@width: 10px, @style: soli ...

  3. 算法金 | LSTM 原作者带队,一个强大的算法模型杀回来了

    大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 时间拉回 2019 年,有「计算机界诺贝尔奖」之称图灵奖获得者公布,深度学习三巨头:Y ...

  4. EBLK日志收集方案

    ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案,是三个产品的首字母缩写,分别是ElasticSearch.Logstash 和 Kibana.该组合版本会统一发布. Elast ...

  5. 增补博客 第四篇 python 中文级联菜单

    from pypinyin import pinyin, Style # 定义菜单项和对应的子菜单 menu = { "文件": { "新建": {}, &qu ...

  6. spring boot jpa 进行通用多条件动态查询和更新 接口

    原因: jpa 没有类似于mybatis的那种 拼接sql的方式 想动态更新 需要使用 CriteriaUpdate的方式 去一直拼接,其实大多数场景只要传入一个非空实体类,去动态拼接sql 1.定义 ...

  7. spark读取写入jdbc.,Caused by: java.lang.NoSuchMethodException: org.apache.spark.sql.execution.datasources.jdbc.DriverWrapper.<init>()

    df.write .option("truncate", "true") .option("driver", mysqlDriver) .m ...

  8. Golang基于Mysql分布式锁实现集群主备

    背景 集群中如果需要主备,可以基于Redis.zk的分布式锁等实现,本文将介绍如何利用Mysql分布式锁进行实现. 原理 数据库中包含数据字段(此处为Master的主机名).版本号和上一次更新时间. ...

  9. 03-Python数据类型

    None类型 Python3中没有NULL,取而代之的是空类型None.空列表.空字典等. None是一个特殊的Python对象,表示无. None的类型是NoneType. 如果只想声明变量,而不想 ...

  10. 15分钟面试被5连CALL,你扛得住么?

    最近一个朋友跳槽找工作,跟V 哥说被15分钟内一个问题5连 CALL,还好是自己比较熟悉的技术点,面试官最后跟他说,面了几十个人,你是第一个回答比较满意的,我好奇都是什么问题,原来是关于锁的问题连环问 ...