当前位置: 首页 > news >正文

39.RESTful案例

RESTful案例

准备环境

Employee.java

public class Employee {private Integer id;private String lastName;private String email;//1 male, 0 femaleprivate Integer gender;
}
//省略get、set和构造方法

EmployeeDao.java

package com.atguigu.SpringMVC.dao;import com.atguigu.SpringMVC.pojo.Employee;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;@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);}
}

将之前仅扫描"控制层组件",更改为扫描SpringMVC目录

功能清单

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

查询所有员工信息

EmployeeController.java

package com.atguigu.SpringMVC.controller;import com.atguigu.SpringMVC.dao.EmployeeDao;
import com.atguigu.SpringMVC.pojo.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;import java.util.Collection;@Controller
public class EmployeeController {@Autowiredprivate EmployeeDao employeeDao;@GetMapping("/employee")public String getAllEmployee(Model model){//获取所有员工信息Collection<Employee> allEmployee = employeeDao.getAll();//将所有的员工信息在请求域中共享model.addAttribute("allEmployees",allEmployee);//跳转到列表页面return "employee_list";}
}

employee_list.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" th:href="@{/static/css/index_work.css}">
</head>
<body><table><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><!--employee为在循环列中的别名,通过${allEmployees}将request域中的数据取出来,两者通过":"分隔--><tr th:each="employee:${allEmployees}"><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>delete</a><a>update</a></td></tr></table>
</body>
</html>

静态资源

static目录放入webapp目录下

当Tomcat的默认配置文件与WEB-INF目录下的web.xml存在配置冲突时,以当前工程的web.xml为准

静态资源的处理应该由默认的servlet进行处理,但是这里与配置的DispatcherServlet代替处理了请求,所以在配置默认的servlet的同时也要开启mvc注解驱动

运行效果

添加员工信息

添加流程:前端发送添加请求(GET)(th:href="@{/addEmployee}")–>后端转发到添加页面(view-name="employee_add")–>用户在表单填写信息后发送请求(POST)–>后端执行信息保存(employeeDao.save(employee))后回到显示页(return "redirect:/employee")

因为SpringMVC是通过请求处理再转发页面,而不是像JavaWeb一样通过地址直接转发到页面

发送添加请求

index.html

	<a th:href="@{/addEmployee}">添加员工信息</a>

为了方便,在employee_list.html中修改语句为:

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

转发到添加页面

对于发送添加请求只需要执行转发到添加页面即可,所以配置视图控制器即可

SpringMVC.xml

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

employee_add.html

<form th:action="@{/employee}" method="post"><table><tr><th colspan="2">add Employee</th></tr><tr><td>lastName</td><td><input type="text" name="lastName"></td></tr><tr><td>email</td><td><input type="email" 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>

保存信息后回到显示页

EmployeeController.java

    //添加员工信息@PostMapping("/employee")//自动匹配提交的表单信息将匹配成功的变量调用set方法保存到employee中public String addEmployee(Employee employee){employeeDao.save(employee);//重定向到显示员工信息的方法中-->这里不能使用转发,因为转发则依旧会将POST请求转发出去,导致又调用了自身,进入了死循环,所以需要通过重定向的方式发送GET请求进入"显示页"方法中return "redirect:/employee";}

注意:EmployeeDao中的数据是用static关键字定义的,在没有保存数据的前提下重定向后数据没有丢失

运行效果

修改员工信息

更新流程:前端发送修改请求(GET)(th:href="@{'/employee/'+${employee.id}})–>后端获取员工信息后(employeeDao.get(id))在前端更新页面中显示(return "employee_update")—>用户在表单更新信息后发送请求(PUT)–>后端执行数据保存(employeeDao.save(employee))后回到显示页(return "redirect:/employee")

发送修改请求

employee_list.html修改语句为:

    <!--如果采用"/employee/${employee.id}"的写法后面的$运算符也会被当成地址--><a th:href="@{'/employee/'+${employee.id}}">update</a>

定义请求方法体

EmployeeController.java

    //转发更新请求定位到更新页面@GetMapping("/employee/{id}")public String toUpdateEmployee(@PathVariable("id") Integer id,Model model){//根据id查询员工信息Employee employee = employeeDao.get(id);//将员工信息共享到请求域中model.addAttribute("employee",employee);//跳转到employee_update.htmlreturn "employee_update";}//更新员工信息@PutMapping("/employee")public String updateEmployee(Employee employee){//修改员工信息employeeDao.save(employee);//重定向到显示员工信息的方法中return "redirect:/employee";}

定义更新页面内容

employee_update.html

<form th:action="@{/employee}" method="post"><input name="_method" value="put" type="hidden"><input name="id" th:value="${employee.id}" type="hidden"><table><tr><th colspan="2">update Employee</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="email" name="email" th:value="${employee.email}"></td></tr><tr><td>gender</td><td><!--如果"gender"的value值和${employee.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</td></tr><tr><td colspan="2"><input type="submit" value="update"></td></tr></table>
</form>

运行结果

删除员工信息

删除流程:前端通过VUE实现点击超链接时提交绑定的表单–>前端通过表单发送删除请求(DELETE)–>后端执行数据删除后回到显示页(return "redirect:/employee")

发送删除请求

employee_list.html为:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" th:href="@{/static/css/index_work.css}">
</head>
<body>
<div id="app"><table><tr><!--合并五列内容为一列显示--><th colspan="5">employee list</th></tr><tr><th>id</th><th>lastName</th><th>email</th><th>gender</th><th>options(<a th:href="@{/addEmployee}">add</a>)</th></tr><!--employee为在循环列中的别名,通过${allEmployees}将request域中的数据取出来,两者通过":"分隔--><tr th:each="employee:${allEmployees}"><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><!--通过绑定表单事件实现点击时调用表单进行提交实现发送delete请求(VUE实现)--><a @click="deleteEmployee()" th:href="@{'/employee/'+${employee.id}}">delete</a><!--如果采用"/employee/${employee.id}"的写法后面的$运算符也会被当成地址--><a th:href="@{'/employee/'+${employee.id}}">update</a></td></tr></table>
</div><form method="post"><input type="hidden" name="_method" value="delete"></form><!--引入VUE--><script type="text/javascript" th:src="@{/static/js/vue.js}"></script><!--实现点击超链接时提交对应的表单--><script type="text/javascript">var vue = new Vue({el:"#app",methods:{deleteEmployee(){//获取form表单var form = document.getElementsByTagName("form")[0];//将超链接的href属性给form表单的action属性form.action = event.target.href; //event.target表示当前触发事件的标签//将表单提交form.submit();//阻止超链接的默认跳转行为event.preventDefault();}}});</script>
</body>
</html>

定义方法体行为

EmployeeController.java

    //删除员工信息@DeleteMapping("/employee/{id}")public String deleteEmployee(@PathVariable("id") Integer id){//根据id删除员工信息employeeDao.delete(id);//重定向到显示员工信息的方法中return "redirect:/employee";}

运行结果:成功实现删除操作

相关文章:

39.RESTful案例

RESTful案例 准备环境 Employee.java public class Employee {private Integer id;private String lastName;private String email;//1 male, 0 femaleprivate Integer gender; } //省略get、set和构造方法EmployeeDao.java package com.atguigu.SpringMVC.dao;import com.…...

Power Pivot 实现数据建模

一、简介 Excel中的透视表适合小规模数据&#xff1b;如果想在稍微大一些的数据中进行高性能透视表分析&#xff0c;就要使用Power Pivot&#xff1b;再大一些数据&#xff0c;可能就需要大数据分析服务来进行分析。 Power Pivot&#xff0c;可以让没有技术背景的企业业务人员…...

Ansible自动化运维之playbooks剧本

文章目录 一.playbooks介绍1.playbooks简述2.playbooks剧本格式3.playbooks组成部分4.运行playbooks及检测文件配置 二.模块实战实例1.playbooks模块实战实例2.vars模块实战实例3.指定远程主机sudo切换用户4.when模块实战实例5.with_items迭代模块实战实例6.Templates 模块实战…...

Docker - Docker安装MySql并启动

因为项目需要连接数据库&#xff0c;但是远程服务器上的mysql我不知道账户和密码&#xff0c;这个时候便是docker发挥作用的关键时刻了&#xff01; 目录 docker安装安装gcc卸载老docker&#xff08;如有&#xff09;安装软件包设置镜像仓库更新yum软件包索引安装docker启动doc…...

SQL Server 2019导入txt数据

1、选择导入数据 2、选择Flat file Source 选择文件&#xff0c;如果第一行不是列名&#xff0c;就不勾选。 3、下一步 可以看看数据是否是对的 4、下一步 选择SQL server Native Client 11&#xff0c;数据库选择导入进的库 输入连接数据库的名字和要导入的数据库 下一…...

科研 | Zotero导入无PDF的参考文献、书籍

最近在用Zotero在Word中插入参考文献的时候发现&#xff0c;有些没在网上找到对应的PDF版本&#xff0c;但也不是必须要PDF版本的参考文献或者参考书籍&#xff0c;如何才能不影响正常的文献排版 主要是先在网上找到对应文献&#xff0c;书籍&#xff0c;网页等的ISBN&#xf…...

【Docker】docker入门之dockerfile编写

文章目录 前言一、docker是什么&#xff1f;docker介绍docker指令 二、docker有什么用&#xff1f;三、docker怎么用&#xff1f;FROMMAINTAINERRUNENVWORKDIRCOPY、ADDUSEREXPOSE实例 四、docker注意事项docker容器中使用某些宿主机设备时需要额外的权限docker容器中文件内容中…...

javaee之黑马乐优商城1

问题1&#xff1a;整体的项目架构与技术选型 技术选型 开发环境 域名测试 如何把项目起来&#xff0c;以及每一个目录结构大概是什么样子 通过webpack去启动了有个项目&#xff0c;这里还是热部署&#xff0c;文件改动&#xff0c;内容就会改动 Dev这个命令会生成一个本地循环…...

滴滴前端一面面经(已挂)

面试过程 前段时间面试了滴滴的前端实习岗位&#xff0c;大厂的面试机会很难得&#xff0c;复习了很多前端知识。 拿到面试机会&#xff0c;是在地铁上投递了boss&#xff0c;当时hr看了我的简历就和我约了第二天的面试。电脑也没带&#xff0c;晚上就用手机复习了前端的一些…...

靠谱的适合上班族做的副业,这几种一定要试试!

作为上班族&#xff0c;我们的时间常常被工作和日常生活所占据&#xff0c;很少有机会去追求自己的兴趣和创造额外的收入来源。然而&#xff0c;副业是一种理想的选择&#xff0c;可以帮助我们实现多样化的发展&#xff0c;并在经济上取得一定的突破。正如书中所言&#xff1a;…...

VSCode连接服务器

Pycharm连接服务器参考我的另一篇文章Pycharm远程连接服务器_pycharm进入服务器虚拟环境终端_Jumbo星的博客-CSDN博客 本质上Pycharm和VSCode都只是IDE&#xff0c;没有什么好坏之分。但是因为Pycharm连接服务器&#xff08;准确来说是部署&#xff09;需要买professional。而…...

Python爬虫网络安全:优劣势和适用范围分析

各位Python程序猿大佬们&#xff01;在当今数字化时代&#xff0c;网络安全是至关重要的。保护你的网络通信安全对于个人和组织来说都是非常重要的任务。在本文中&#xff0c;我将与你一起探讨Python网络安全编程中的代理、虚拟专用网络和TLS这三个关键概念&#xff0c;分析它们…...

swift APP缓存

这里的APP缓存是指Cache文件夹里的内容&#xff0c;iOS系统从iOS 10开始就支持系统自动清理功能了。 建议重要的内容不要放到 Cache文件夹中。 一、获取缓存 /// 获取缓存大小public static func getCacheSize() -> String {let folderPath NSSearchPathForDirectoriesIn…...

Linux中的dpkg指令(dpkg -l | grep XXX等)

dpkg是Debian包管理系统中的一个工具&#xff0c;用于在Linux系统中安装、升级、删除和管理软件包。它是Debian、Ubuntu以及基于它们的发行版中的包管理器。 dpkg 有很多用法&#xff0c;常用之举例:dpkg -l | grep apt 显示系统中安装的与apt相关&#xff08;命名&#xff09…...

import type {} from ‘module‘ 具体解释

import type { AxiosInstance, AxiosRequestConfig } from axiosimport type { RequestConfig, RequestInterceptors } from ./typesimport type {} from module 是 TypeScript 中的一种导入语法&#xff0c;用于导入类型声明而不导入具体的值&#xff0c;它告诉 TypeScript 编…...

十年JAVA搬砖路——数据结构线性结构

线性结构 线性表是一种数据结构&#xff0c;用于存储一组有序的数据元素。它的特点是数据元素之间存在一对一的关系&#xff0c;每个元素只有一个前驱和一个后继&#xff08;除了第一个元素和最后一个元素&#xff09;。线性表可以用数组或链表来实现。 数据是指事物的符号表…...

Mybatis为什么需要预编译等一系列问题

1 SQL 预编译 SQL 预编译是一种提高数据库访问效率的技术&#xff0c;它通过将 SQL 语句预编译并存储在数据库中&#xff0c;减少每次执行时需要进行解析和编译的开销&#xff0c;从而提高数据库访问的效率。 在预编译阶段&#xff0c;SQL 语句会被解析并转换为可执行的二进制…...

【JVM基础】JVM入门基础

目录 JVM的位置三种 JVMJVM体系结构类加载器双亲委派机制概念例子作用 沙箱安全机制组成沙箱的基本组件 NativeJNI&#xff1a;Java Native Interface&#xff08;本地方法接口&#xff09;Native Method Stack&#xff08;本地方法栈&#xff09; PC寄存器&#xff08;Program…...

【SpringBoot】详细介绍Spring Boot中@Component

在Spring Boot中&#xff0c;Component是一个通用的注解&#xff0c;用于标识一个类是Spring框架中的组件。Component注解是Spring的核心注解之一&#xff0c;它提供了自动扫描和实例化bean的功能。 具体来说&#xff0c;Component注解的作用是将一个普通的Java类转化为Spring…...

Redis执行lua脚本-Time函数-获取当前时间

演变过程&#xff1a; TIME 命令返回当前服务器的时间&#xff0c;包含两个条目 Unix 时间戳和这一秒已经过去的微秒数。 eval " local res redis.call(time); return res; " 0 eval " local current_time redis.call(TIME) local unix_timestamp tonumb…...

VS Code光标主题buen-cursor:提升开发者编码体验的视觉优化方案

1. 项目概述&#xff1a;一个为开发者定制的光标主题 如果你和我一样&#xff0c;每天有超过8小时的时间都泡在代码编辑器里&#xff0c;那么你一定对那个闪烁的光标再熟悉不过了。它可能是你思考的起点&#xff0c;也可能是你调试时目光的焦点。但你是否想过&#xff0c;这个…...

LoRA模型合并实战指南:多技能融合与vLLM部署

1. 项目概述&#xff1a;LoRA模型合并的“瑞士军刀”最近在折腾大语言模型微调的朋友&#xff0c;估计对LoRA&#xff08;Low-Rank Adaptation&#xff09;这个词都不陌生。它就像给预训练好的大模型“打补丁”&#xff0c;用极小的参数量&#xff08;通常只有原模型的0.1%到1%…...

用Git和Markdown构建个人知识库:Wandercode项目实践指南

1. 项目概述&#xff1a;从“漫游代码”到个人知识管理系统的蜕变最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“Wandercode”&#xff0c;直译过来就是“漫游代码”。乍一看这个标题&#xff0c;可能会让人联想到某种代码生成器或者自动化脚本工具。但当我深入探究其仓…...

基于MCP协议构建个人AI工作流:模块化套件配置与隐私优先实践

1. 项目概述&#xff1a;一个为个人工作流注入AI智能的MCP套件 最近在折腾AI Agent和自动化工作流的朋友&#xff0c;应该都绕不开一个词&#xff1a; MCP 。全称是Model Context Protocol&#xff0c;你可以把它理解成AI模型&#xff08;比如Claude、ChatGPT&#xff09;和外…...

嵌入式开发革命:LuatOS云编译实战指南与效率提升

1. 项目概述&#xff1a;为什么我们需要云编译&#xff1f;作为一名在嵌入式领域摸爬滚打了十多年的老鸟&#xff0c;我太懂那种“买板一时爽&#xff0c;环境火葬场”的痛了。尤其是这几年&#xff0c;合宙、乐鑫、兆易这些厂商的产品线越来越丰富&#xff0c;Air780E、ESP32-…...

AI如何学习科学品味:从多模态特征到科研评估系统构建

1. 项目概述&#xff1a;当AI开始学习“科学品味” 最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“AI-Can-Learn-Scientific-Taste”。光看名字&#xff0c;你可能觉得这又是一个关于AI模型训练或者科学计算的常规项目。但点进去仔细琢磨&#xff0c;你会发现它的野心远…...

显存又爆了?移动云弹性KV缓存:让你告别“显存焦虑”

上下文越长&#xff0c;显存越吃紧对话轮次越多&#xff0c;延迟越明显并发量一高&#xff0c;服务就卡顿……随着AI大模型向超长上下文、高并发、多轮交互深度演进&#xff0c;AI推理所需缓存的内容呈指数级增长。显存容量的需求爆炸与显存采购的高昂成本&#xff0c;使得超长…...

Odrive 0.5.5 固件启动流程详解:从USB初始化到电机线程就绪,新手避坑指南

ODrive 0.5.5 固件启动全流程拆解&#xff1a;从硬件初始化到电机控制线程就绪 当一块崭新的ODrive开发板首次通电时&#xff0c;固件究竟在后台执行了哪些精密操作&#xff1f;本文将深入RTOS内核&#xff0c;以时间轴方式还原从rtos_main入口到双轴电机线程就绪的完整启动过程…...

基于CircuitPython的电机动态性能测试系统:从原理到实践

1. 项目概述与核心价值搞电机驱动&#xff0c;最怕的就是“凭感觉”。你手上有个直流有刷电机&#xff0c;数据手册上写着空载转速12000转&#xff0c;堵转扭矩50mNm&#xff0c;但实际装到你的机器人关节或者小车上&#xff0c;带上传动机构&#xff0c;性能到底怎么样&#x…...

ElevenLabs泰米尔语音部署踩坑实录:DNS解析超时、UTF-8 BOM导致静音、方言ID混淆——97%开发者忽略的3个关键参数

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ElevenLabs泰米尔语音部署踩坑实录&#xff1a;DNS解析超时、UTF-8 BOM导致静音、方言ID混淆——97%开发者忽略的3个关键参数 DNS解析超时&#xff1a;被忽略的区域路由策略 ElevenLabs 的 API 在印度…...