[spring] Spring MVC - CRUD 操作

news2024/11/20 12:32:45

[spring] Spring MVC - CRUD 操作

基础实现源自于这两篇笔记:

  • [spring] Spring Boot REST API - 项目实现
  • [spring] Spring Boot REST API - CRUD 操作

除了 Rest API 部分改成了 Controller 之外,其他没什么变化,还是使用 service --> DAO --> DB 这个实现方式,因此关于 CRUD 的部分——即 hibernate 实现的部分,这里不会过多涉及

也因此,这部分的代码实现应该还是挺快的,毕竟主要还是 HTML 模板+controller 实现

获取 employee

除了新增 HTML 模板之外,主要还是把 @RestController 换成 @Controller,其他大方向没什么变化,实现如下:

@Controller
@RequestMapping("/employees")
public class EmployeeController {
    private EmployeeService employeeService;

    @Autowired
    public EmployeeController (EmployeeService employeeService) {
        this.employeeService = employeeService;
    }

    @GetMapping("/list")
    public String listEmployees (Model model) {
        // get employee from db
        List<Employee> employeeList = employeeService.findAll();

        // add employees to model
        model.addAttribute("employees", employeeList);

        return "list-employees";
    }
}

这里先丢一个非常简单的 UI,保证逻辑对,数据可以正常显示即可:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Employee Directory</title>
  </head>
  <body>
    <span th:text="${employees}" />

    <script src="http://localhost:35729/livereload.js"></script>
  </body>
</html>

结果如下:

在这里插入图片描述

数据可以正常显示

从 8080 端口重定向

现在直接访问 localhost:8080 会显示 white label 的问题

考虑到正常情况下都是会直接访问 80/8080 端口,这里做一个小小的优化。首先在 resources/static 下面创建一个 index.html 文件,代码如下

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <meta http-equiv="refresh" content="0; URL='employees/list'" />
  </head>
  <body>
    <script src="http://localhost:35729/livereload.js"></script>
  </body>
</html>

这个操作就是在访问 8080 端口时,直接重定向到 localhost/employees/list,实现效果如下:

在这里插入图片描述

更新的 bootstrap 代码如下:

<tbody>
  <tr th:each="employee: ${employees}">
    <td th:text="${employee.firstName}"></td>
    <td th:text="${employee.lastName}"></td>
    <td th:text="${employee.email}"></td>
  </tr>
</tbody>

这里的 bootstrap 是直接引用 cdn 的

添加 employee

这里会出现一个新的知识点,controller 部分实现如下:

    @GetMapping("/showFormForAdd")
    public String addEmployee (Model model) {
        Employee employee = new Employee();

        model.addAttribute("employee", employee);
        return "employees/employee-form";
    }

    @PostMapping("/save")
    public String saveEmployee(@ModelAttribute("employee") Employee employee) {
        employeeService.save(employee);

        // use a redirect to prevent duplicate submission
        return "redirect:/employees/list";
    }

⚠️:这里的 redirect:/employees/list,这里主要告知 spring mvc,一个新的 GET 请求会被建立,这样可以有效避免重复提交数据

HTML 模板的实现如下,首先是添加一个按钮,重定向到新的 employee-form 页面:

<a th:href="@{/employees/showFormForAdd}" class="btn btn-primary btn-sm mb-3">
  Add Employee
</a>

随后再是新建一个表单,用来保存用户信息:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Save Employee</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
      crossorigin="anonymous"
    />
  </head>
  <body>
    <div class="container">
      <h3>Employee Directory</h3>
      <hr />

      <p class="h4 mb-4">Save Employee</p>

      <form
        action="#"
        th:action="@{/employees/save}"
        autocomplete="off"
        th:object="${employee}"
        method="post"
      >
        <label for="firstName">First Name: </label>
        <input
          type="text"
          th:field="*{firstName}"
          id="firstName"
          class="form-control mb-4 w-25"
          placeholder="First Name"
        />

        <label for="lastName">Last Name: </label>
        <input
          type="text"
          th:field="*{lastName}"
          id="lastName"
          class="form-control mb-4 w-25"
          placeholder="Last Name"
        />

        <label for="email">Email: </label>
        <input
          type="email"
          th:field="*{email}"
          id="email"
          class="form-control mb-4 w-25"
          placeholder="Email"
        />

        <button type="submit" class="btn btn-info col-2">Save</button>
      </form>

      <br />

      <a th:href="@{/employees/list}">Back to Employee List</a>
    </div>

    <script src="http://localhost:35729/livereload.js"></script>
  </body>
</html>

最终实现效果如下:

在这里插入图片描述

更新 employee

这里基本可以复用添加 employee 部分的代码,主要也是因为 hibernate 在实现 save 的功能时,如果当前的 DAO 在数据库已经存在的话,就会实现更新,反之实现新增

因此这里只需要做一点的更新即可,首先是 controller 部分的更新:

    @GetMapping("/showFormForUpdate")
    public String showFormForUpdate(@RequestParam("employeeId") int id, Model model) {
        // get employee from the service
        Employee employee = employeeService.findById(id);

        // set employee in the model to populate the form
        model.addAttribute("employee", employee);

        // send data over to form
        return "employees/employee-form";
    }

随后时添加新的 update 按钮,这部分添加到循环输出 employee 信息里的最后一行:

<td>
  <a
    th:href="@{/employees/showFormForUpdate(employeeId=${employee.id})}"
    class="btn btn-info btn-sm"
  >
    Update
  </a>
</td>

最后是新增一个隐藏的 id,这样可以让 HTML 模板中的对象和 controller 中实现正确的 mapping,毕竟 id 对于更新来说事必要的,如果没有这个隐藏的 id 选项,那么 findById 无法找到正确的对象,所有的更新操作都有可能成为新增操作:

<form
  action="#"
  th:action="@{/employees/save}"
  autocomplete="off"
  th:object="${employee}"
  method="post"
>
  <!-- add hidden form field to handle the update -->
  <input type="hidden" th:field="*{id}" />
</form>

最终效果如下:

在这里插入图片描述

数据库中的信息:

在这里插入图片描述

删除 employee

这部分也非常的简单,首先在添加 update 按钮的旁边新增一个 delete:

<a
  th:href="@{/employees/delete(employeeId=${employee.id})}"
  class="btn btn-danger btn-sm"
  onclick="if (!(confirm('Are you sure you want to delete this employee?'))) return false"
>
  Delete
</a>

controller 的更新如下:

    @GetMapping("/delete")
    public String delete(@RequestParam("employeeId") int id) {
        employeeService.deleteById(id);

        return "redirect:/employees/list";
    }

最终结果:

在这里插入图片描述

在这里插入图片描述

这样 spring mvc 的 crud 操作就都实现完成了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1855269.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6/23 第四周 python操作excel

excel对于python来说就是一个二维数组&#xff0c;只是多了一个多sheet的index的索引&#xff0c;在确定索引之后&#xff0c;不管是读取还是写入&#xff0c;都是类似于二维数组。对于数据的处理&#xff0c;读取和写入就够了&#xff0c;如果要应用图表&#xff0c;个人觉得还…

nest.js关键笔记

Nest.js 介绍核心功能设计模式&#xff1a;IOC 控制反转 DI 依赖注入前置知识&#xff1a;装饰器前置知识装饰器-实现一个GET请求 Nestjs脚手架Nestjs cli 常用命令 RESTful 风格设计Nestjs 控制器控制器中常见的参数装饰器 Session 实例Nestjs 提供者**工厂模式**异步模式 Nes…

Linux 7种 进程间通信方式

传统进程间通信 通过文件实现进程间通信 必须人为保证先后顺序 A--->硬盘---> B&#xff08;B不知道A什么时候把内容传到硬盘中&#xff09; 1.无名管道 2.有名管道 3.信号 IPC进程间通信 4.消息队列 5.共享内存 6.信号灯集 7.socket通信 一、无名管道&a…

《书生·浦语大模型实战营》第5课 学习笔记:LMDeploy 量化部署 LLM 实践

文章大纲 0.背景知识与简介计算机组成原理&#xff1a;变量的存储参数量与推理的关系 1.LMDeploy环境部署1.1 创建开发机1.2 创建conda环境InternStudio开发机创建conda环境&#xff08;推荐&#xff09;本地环境创建conda环境 1.3 安装LMDeploy 2.LMDeploy模型对话(chat)2.1 H…

Golang | Leetcode Golang题解之第187题重复的DNA序列

题目&#xff1a; 题解&#xff1a; const L 10 var bin map[byte]int{A: 0, C: 1, G: 2, T: 3}func findRepeatedDnaSequences(s string) (ans []string) {n : len(s)if n < L {return}x : 0for _, ch : range s[:L-1] {x x<<2 | bin[byte(ch)]}cnt : map[int]in…

Python | Leetcode Python题解之第187题重复的DNA序列

题目&#xff1a; 题解&#xff1a; L 10 bin {A: 0, C: 1, G: 2, T: 3}class Solution:def findRepeatedDnaSequences(self, s: str) -> List[str]:n len(s)if n < L:return []ans []x 0for ch in s[:L - 1]:x (x << 2) | bin[ch]cnt defaultdict(int)for…

期货交易纪律2024年6月22号

文章目录 期货交易系统构建第一步、选品第二步、开仓纪律第三步、持仓 2024年6月22号&#xff0c;开始写期货交易的第三篇日记。 交易记录&#xff1a;市场继续震荡&#xff0c;这两天无交易&#xff0c;继续梳理一些期货交易选品&#xff0c;周末详细的了解了一下豆粕&#xf…

axure制作菜单下拉、隐藏、点击选中效果

在高保真原型中&#xff0c;制作导航栏菜单时&#xff0c;需要达到点击下拉按钮&#xff0c;子菜单自动弹出&#xff0c;点击其中一个子菜单项可栏目变为选中状态且跳转到对应的子页面。制作材料可以从antdesign中去下载&#xff0c;以下述网络配置菜单为例。在箭头处添加互动效…

Pytest和Unitest框架对比

在学到自动化的时候,很多同学都遇到了Pytest和Unitest框架,有的人是两个都学,但是学的不精只是知道分别怎么用.不了解两个区别是什么.有的是犹豫到底要学习那个框架.其实要做好自动化测试,是有必要了解不同框架之间的差异化的. Pytest 特点: Pytest采用了更简洁、更灵活的语法…

C语言 | Leetcode C语言题解之第187题重复的DNA序列

题目&#xff1a; 题解&#xff1a; #define MAXSIZE 769/* 选取一个质数即可 */ typedef struct Node {char string[101];int index;struct Node *next; //保存链表表头 } List;typedef struct {List *hashHead[MAXSIZE];//定义哈希数组的大小 } MyHashMap;List * …

【建设方案】大数据湖一体化建设方案(ppt原件)

1、背景&#xff1a;大数据湖的发展背景与建设理念 2、体系&#xff1a;大数据湖体系规划与建设思路 3、生态圈&#xff1a;探索新兴业务入湖建设模式 4、共享&#xff1a;大数据湖统一访问共享规划 5、运营&#xff1a;大数据湖一体化运营管理建设 &#xff08;本方案及更多方…

交通大数据分析与挖掘实训【对提供的CSV格式数据使用pandas库分析-Matplotlib库绘图】

背景&#xff1a; 《交通大数据分析与挖掘》实训 指 导 书 编著 二○二四年五月 一、实训目的 1、掌握python开发环境&#xff08;如Anaconda&#xff09;及Numpy等常见第三方库的使用&#xff1b; 2、熟悉Anaconda在线编程平台&#xff0c;学会基本的python程序编写…

CMake笔记之CMAKE_INSTALL_PREFIX详解以及ROS中可执行文件为什么会在devel_lib中

CMake笔记之CMAKE_INSTALL_PREFIX详解以及ROS中可执行文件为什么会在devel_lib中 code review! 文章目录 CMake笔记之CMAKE_INSTALL_PREFIX详解以及ROS中可执行文件为什么会在devel_lib中1.CMAKE_INSTALL_PREFIX详解变量作用设置 CMAKE_INSTALL_PREFIX示例影响范围常见用法特别…

OpenHarmony 应用开发FullSDK获取与替换

DevEco Studio是OpenHarmony应用集成开发环境。public-SDK是提供给应用开发的工具包&#xff0c;跟随DevEco Studio下载&#xff0c;不包含系统应用所需要的高权限API。full-SDK是提供给OEM厂商开发应用的工具包&#xff0c;不能随DevEco Studio下载&#xff0c;包含了系统应用…

了解请求参数与响应参数的区别:初学者指南

在 Web 的开发领域&#xff0c;无论你是前端开发还是后端开发人员&#xff0c;把握请求与响应参数的核心差异是极其重要的。这些参数在客户端和服务器之间的互动中扮演着关键角色。 请求参数的定义及类别 定义 当客户端向服务器提交信息时所使用的数据被称为请求参数。这些参…

Fine-tuning在垂直领域的最佳实践指南

对于Fine-tuning是深度学习和机器学习领域一个特别重要的概念&#xff0c;并且每个企业的实践方式也会有所不同&#xff0c;今天我们就来聊一聊Fine-tuning。 什么是Fine-tuning Fine-tuning指的是模型微调&#xff0c;通常是指在一个预训练模型的基础上&#xff0c;通过在特…

【剖析】为什么说RBF神经网络的误差为0

本文来自《老饼讲解-BP神经网络》https://www.bbbdata.com/ 机器学习中的模型非常的多&#xff0c;但如果要问有没有这样的一个模型&#xff0c;它的训练误差为0&#xff0c;那么就非RBF神经网络莫属了&#xff01;下面我们来聊聊&#xff0c;为什么RBF神经网络的训练误差为0。…

Springboot多模块项目从0构建打包运行

今天复习了一下Springboot的多模块的构建&#xff0c;其实一直以来都对单体项目使用多模块感到不太理解&#xff0c;不知道到底有什么样的优势&#xff0c;目前切身体会到的优势就是确实可以让依赖的划分更加清晰&#xff08;每个模块下的pom文件只引入该模块需要的依赖&#x…

数据分析的线上云端数据库搭建及Excel和Tableau连接

数据分析的线上云端数据库搭建及Excel和Tableau连接 SQL基础知识 线上SQL训练&#xff1a; SQlZOO: https://www.sqlzoo.net/wiki/SQL_Tutorial 牛客网SQL真题&#xff1a;https://www.nowcoder.com/ta/sql select,from,where, order by, limit, group by, having, substr(),…

HTML 之<title> 标签

一.HTML <title> 标签 二.实例 为您的 HTML 文档定义标题&#xff1a; <html> <head> <meta charset"utf-8"> <title>文档标题</title> </head> <body> 文档内容...... </body> </html> 尝试一下 三…