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

【Spring MVC】这一篇,带你从入门到进阶

目录

1、什么是MVC?

2、什么是 Spring MVC

3、如何学好 Spring MVC?

3.1、如何创建 Spring MVC 项目

3.1.1、使用Spring Initializr创建(推荐)

3.2、将 Spring 程序与用户(浏览器)联通

3.3、基础注解

3.3.1、@RequestMapping

3.3.2、GET/POST方法、

3.4、获取参数注解

3.4.1、传递单个/多个参数

3.4.2、传递对象

3.4.3、参数重命名

3.4.4、接收 JSON 对象

3.4.5、获取URL中参数@PathVariable

3.4.6、上传文件

3.5.7、获取Cookie数据

更简单的读取Cookie数据如下方式:

3.4.8、存储Session数据

3.4.9、读取Session数据

 更简单的读取Session数据如下方式:

3.5、返回其他格式的数据

3.5.1、返回静态页面

3.5.2、返回JSON对象


1、什么是MVC?


MVC是 Model View Controller 的缩写,是一种软件设计模式,将软件分为模型、视图和控制器三部分,大体工作流程:客户端向服务器发起请 HTTP 请求,被 Controller 接收,从 Model 中请求信息(通常模型对象负责在数据库中存取数据),并将响应信息返回给 Controller,接着交由给 View 显示数据,最后将 HTTP 响应传递给用户。

2、什么是 Spring MVC


简单来说,是一个构建在 Servlet(API)之上,来自于 Spring Web 模块的的 Web框架(HTTP)

通常我们所说的 SSM 就等于 Spring + Spring MVC + MyBatis,后来又有了一种更新的说法:SSM = Spring Boot + Spring Web(Spring MVC) + MyBatis

3、如何学好 Spring MVC?


想要学好 Spring MVC 需要掌握以下3个功能:

1.连接功能:将用户(浏览器)和 Java 程序连接起来,也就是访问一个能够调用 Spring 程序的地址;

2.获取参数功能:用户访问时会带一些参数(例如 query string),在程序中想办法获取参数。

3.输出数据功能:根据请求计算响应,将响应结果返回给用户。

3.1、如何创建 Spring MVC 项目

3.1.1、使用Spring Initializr创建(推荐)

a)如果你是使用的IDEA社区版,需要安装以下插件(不是社区版可以跳过此步骤)

所需插件:Spring Boot Helper(如下图)

注意:此插件在IDEA社区版2022.1.x之前都免费,IDEA社区版2022.2.x之后开始收费,所以IDEA社区版版本的选择,大家自行选择。

这个插件就是用来构建 Spring Boot 框架的,之后,你在创建一个项目的时候可以看到这样一个选项(就是通过来创建Spring Boot框架),如下图:

b)接下来就是创建Spring-MVC项目的步骤: 

关键是要选择Spring Web选项,这里就包含了MVC,如下:

最后一路Next即可,最终目录结构如下:

如果你得到了上图这个目录结构,说明你的项目已经创建好了,但是还没有初始化,因此还需要以下步骤:

然后点击OK,接着就是一个,漫长的等待过程,当你的项目出现了下图变化,才说明你的Spring-Boot项目已经创建并初始化完成:

3.2、将 Spring 程序与用户(浏览器)联通

具体代码如下:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller //让 Spring 项目启动时,将这个注解下的类加载到容器中
@ResponseBody //使其返回的响应是数据,而非页面
@RequestMapping("/user") //注册路由
public class UserController {@RequestMapping("/hi") //路由注册public String sayHi() {return "hi! Spring MVC!";}}

输入URl即可访问到sayHi方法,如下结果:

3.3、基础注解

3.3.1、@RequestMapping

@RequestMapping 是⽤来注册接⼝的路由映射的,当用户输入一个url,就可以通过url访问程序某个类的某个方法(@RequestMapping 即可修饰类,也可以修饰⽅法,当修饰类和⽅法时,访问的地址是类 + 方法。),如下图:

3.3.2、GET/POST方法、

可以通过 @RequestMapping 或 @GetMapping/@PostMapping 获取请求的数据。

get请求的写法有如下三种:

// 写法1
@RequestMapping("/index")// 写法2
@RequestMapping(value = "/index",method = RequestMethod.GET)// 写法3
@GetMapping("/index")

post请求的写法有如下两种:

// 写法1
@RequestMapping(value = "/index",method = RequestMethod.POST)// 写法2
@PostMapping("/index")

3.4、获取参数注解

Spring MVC中可以直接通过方法中的参数来传参,要注意的有以下几点:

Ps:

1、当有多个参数进行参数匹配时,是按照参数的名称进行匹配的,因此参数的位置不影响参数的获取;

2、Spring MVC 中通过前端传参时,方法的参数一定要是包装类类型,而非基础类型(因为如果方法的参数是基础类型,但又忘记传递时,程序就会报500错误,而保证类型为包装类类型忘记传参时,只会值为null);

3.4.1、传递单个/多个参数

由于传递单个和多个参数的写法方式一样,所以这里就以多参数为例~

代码如下:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller //让 Spring 项目启动时,将这个注解下的类加载到容器中
@ResponseBody //使其返回的响应是数据,而非页面
@RequestMapping("/user") //注册路由
public class UserController {@RequestMapping("/message")public void getUserMessage(String name, String age) {System.out.println("name:" + name);System.out.println("age:" + age);}

方法参数对应 url 中 query string 的 key 值,如下使用 Postman 访问方法:

执行结果如下:

3.4.2、传递对象

在 Spring MVC 中可以创建一个实体类对象(含getter和setter方法),最后通过方法的参数对象的getter方法获取属性。

如下实体类对象:

@Controller //让 Spring 项目启动时,将这个注解下的类加载到容器中
@ResponseBody //使其返回的响应是数据,而非页面
@RequestMapping("/user") //注册路由
public class UserController {@RequestMapping("/message")public void getMessage(User user) {System.out.println("id:" + user.getId());System.out.println("name:" + user.getName());System.out.println("age:" + user.getAge());}}

前端访问:

执行结果:

3.4.3、参数重命名

情况一:必传参数设置

有些情况下,前端传递的参数 key 的字段和后端接收的 key 的字段可以不一致,例如前端传输一个 time ,后端就可以使用 @RequestParam 来重命名后端的参数为 startTime 字段来接收。

例如前端两个参数key字段分别为t1,t2,后端使用 startTime 和 endTime 字段来接收如下代码:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;@Controller //让 Spring 项目启动时,将这个注解下的类加载到容器中
@ResponseBody //使其返回的响应是数据,而非页面
@RequestMapping("/user") //注册路由
public class UserController {@RequestMapping("/time")public void getTime(@RequestParam("t1") String startTime,@RequestParam("t2") String endTime) {System.out.println("起始时间:" + startTime);System.out.println("结束时间" + endTime);}}

 前端访问地址如下:

执行结果:

情况二:非必传参数设置

情况一中,若前端传递了一个非time的参数,程序就会出现报错的情况,我们可以通过设置 @RequestParam 中的 required=false 来避免不传递时报错,具体实现如下:

    @RequestMapping("/time")public void getTime(@RequestParam(value = "t1", required = false) String startTime,@RequestParam(value = "t2", required = false) String endTime) {System.out.println("起始时间:" + startTime);System.out.println("结束时间" + endTime);}

3.4.4、接收 JSON 对象

代码如下:

import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;@Controller //让 Spring 项目启动时,将这个注解下的类加载到容器中
@ResponseBody //使其返回的响应是数据,而非页面
@RequestMapping("/user") //注册路由
public class UserController {@PostMapping("/message")public String getMessage(@RequestBody User user) {return user.toString();}}

前端发送请求,结果如下:

Ps:注意这里传递的是JSON对象,向后端提交数据,需要搭配着POST请求。

3.4.5、获取URL中参数@PathVariable

前端地址:

后端接收:

    @PostMapping("/urlValue/{name}/{age}")public String getUrlValue(@PathVariable("name") String name,@PathVariable("age") String age) {return "name:" + name + ", age:" + age;}

执行结果:

注意:以上写法@PostMapping("/urlValue/{name}/{age}")中{name}和{age}是必须要传的参数,若只传age,不传name,则可以使用如下写法:

    @PostMapping("/urlValue/{name}/{age}")public String getUrlValue(@PathVariable(value = "name", required = false) String name,@PathVariable("age") String age) {return "name:" + name + ", age:" + age;}

Ps:

1.需要获取的参数要在 @PostMapping 注解中用大括号{}括起来。

2.这种写法的URl对比之前的 query string 在SEO上效果更好(浏览器搜索以后会排在更前面)!

3.4.6、上传文件

前端通过from表单请求的请求文件数据:

后端接收:

    @PostMapping("/upfile")public String upfile(@RequestPart("myfile") MultipartFile file) throws IOException {String path = "D:\\其他\\滑稽2.webp";file.transferTo(new File(path));return path;}

 

3.5.7、获取Cookie数据

由于 Spring MVC(Spring Web)是基于 Servlet 实现的,所以获取 Cooike 数据也是通过 HttpServletResponse 的 getCookie 方法获取到的,如下后端代码(这里为了方便观察结果,使用 @Slf4j 来打印日志信息):

    @GetMapping("/getCookie")public String getCookie(HttpServletRequest request) {Cookie[] cookies = request.getCookies();for(Cookie ans : cookies) {log.error("key:" + ans.getName() + ",value:" + ans.getValue());}return "get Cookie Success!";}

前端可以通过F12检测里的Application中的Cookie自定义数据,如下:

前端请求如下:

 访问结果:

更简单的读取Cookie数据如下方式:

@RequestMapping("/cookie")
@ResponseBodypublic String cookie(@CookieValue("zhangsan") String name) {return "cookie:" + name;
}

Ps:如果 zhangsan 这个参数是一个非必要的参数,那么也可以再在@CookieValue注解后面加上一个false参数;

3.4.8、存储Session数据

由于 Spring MVC(Spring Web)是基于 Servlet 实现的,所以获取 Session 数据也是通过 HttpServletResponse 的 getSesion 方法获取到的,如下后端代码:

    @RequestMapping("setSession")public String setSession(HttpServletRequest request) {HttpSession session = request.getSession(true);session.setAttribute("jay chou", "nb");return "set Session Success!";}

前端请求:

3.4.9、读取Session数据

由于 Spring MVC(Spring Web)是基于 Servlet 实现的,所以获取 Session 数据也是通过 HttpServletResponse 的 getSesion 方法获取到的,如下后端代码:

    @RequestMapping("getSession")public String getSession(HttpServletRequest request) {HttpSession session = request.getSession(false);if(session == null || session.getAttribute("jay chou") == null) {return "当前会话参数错误";}return "get Session Success!";}

前端先通过2.5.7中的后端代码存储Session数据,就可以观察到生成如下SessionId:

再进行前端访问就可以得到如下结果:

 更简单的读取Session数据如下方式:

    @RequestMapping("getSessionEasy")public String getSession(@SessionAttribute(value = "jay chou", required = false) String name) {return name;}

Ps:这里表示 jay chou 这个字符串是一个非必要参数,去掉false参数他就是一个必要参数。

3.5、返回其他格式的数据

3.5.1、返回静态页面

Spring MVC 和 Spring Boot 默认情况下都是返回View视图(xxx.html),通过@ResponseBody注解就可以让后端返回的是数据,而非页面。那么如果现在需要返回一个页面,我们应该怎么做?

a)创建一个前端页面 index.html

前端代码如下:

<!doctype html><html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.
0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>hello,spring mvc</title><script src="index.js"></script>
</head>
<body><h1>Hello,Spring MVC.</h1>
</body>
</html>

后端代码如下:

@Controller
@RequestMapping("/html")
public class IndexController {@RequestMapping("/index")public String retIndex() {//执行业务逻辑...return "/index.html";}}

客户发送请求后的结果:

3.5.2、返回JSON对象

在 Spring MVC 中返回 HashMap 对象,实际上就是在返回JSON对象,如下后端代码:

    @RequestMapping("getJson")public HashMap<String, Integer> resJson() {HashMap<String, Integer> map = new HashMap<>();map.put("zhangsan", 1);map.put("lisi", 2);map.put("wangwu", 3);return map;}

客户端输入url得到如下结果:


 

相关文章:

【Spring MVC】这一篇,带你从入门到进阶

目录 1、什么是MVC&#xff1f; 2、什么是 Spring MVC 3、如何学好 Spring MVC&#xff1f; 3.1、如何创建 Spring MVC 项目 3.1.1、使用Spring Initializr创建&#xff08;推荐&#xff09; 3.2、将 Spring 程序与用户&#xff08;浏览器&#xff09;联通 3.3、基础注解…...

InstallAware Multi-Platform updated

InstallAware Multi-Platform updated 原生ARM&#xff1a;为您的内置设置、IDE和整个工具链添加了Apple macOS和Linux ARM构建。 本地化&#xff1a;引擎内多语言感知&#xff0c;可再分发工具&#xff0c;具有资产隔离功能&#xff0c;使您的IP保持安全。 模板&#xff1a;将…...

Spring Batch 高级篇-多线程步骤

目录 引言 概念 案例 转视频版 引言 接着上篇&#xff1a;Spring Batch ItemWriter组件&#xff0c;了解Spring Batch ItemWriter处理组件后&#xff0c;接下来一起学习一下Spring Batch 高级功能-多线程步骤 概念 默认的情况下&#xff0c;步骤基本上在单线程中执行&…...

关于iframe一些通讯的记录(可适用工作流审批)

一.知识点(1).我们可以通过postMessage(发送方)和onmessage(接收方)这两个HTML5的方法, 来解决跨页面通信问题&#xff0c;或者通过iframe嵌套的不同页面之间的通信a.父页面代码如下<div v-if"src" class"iframe"><iframeref"iframe"id…...

JavaWeb

1、静态Web html、css 2、动态Web 提供给所有人看的数据始终会发生变化。技术栈&#xff1a;Servlet/JSP&#xff0c;ASP&#xff0c;PHP。 Web应用程序&#xff1a;可以提供浏览器访问的程序。 1、这个统一的web资源会被放在同一个文件夹下&#xff0c;web应用程序-->Tom…...

ip段192.168.1.0/24和192.168.0.0/16

192.168.1.0/24192.168.1.1 ~ 192.168.1.254前24位为网络前缀&#xff0c;后8位代表主机号。如下1100 0000&#xff0c;1010 1000&#xff0c;0000 0001&#xff0c;0000 0000192.168.0.0/16192.168.0.1 ~ 192.168.255.254前16位为网络前缀&#xff0c;后16位代表主机号。如下1…...

《爆肝整理》保姆级系列教程python接口自动化(二十二)--unittest执行顺序隐藏的坑(详解)

简介 大多数的初学者在使用 unittest 框架时候&#xff0c;不清楚用例的执行顺序到底是怎样的。对测试类里面的类和方法分不清楚&#xff0c;不知道什么时候执行&#xff0c;什么时候不执行。虽然或许通过代码实现了&#xff0c;也是稀里糊涂的一知半解&#xff0c;这样还好&am…...

【第二章 IOC操作bean管理(XML注入其他类型属性(字面量,外部bean,内部bean,级联赋值)、XML注入集合属性)】

第二章 IOC操作bean管理&#xff08;XML注入其他类型属性&#xff08;字面量&#xff0c;外部bean&#xff0c;内部bean&#xff0c;级联赋值&#xff09;、XML注入集合属性&#xff09; 1.IOC操作bean管理&#xff08;XML注入其他类型属性&#xff09; &#xff08;1&#xf…...

Kotlin-枚举和印章

kotlin-枚举 枚举也是一个对象&#xff0c;枚举对象的定义需要使用enum关键字 枚举对象可以定义函数 假设定义一个星期枚举对象。就是一下写法 enum class Week {星期一,星期二,星期三,星期四,星期五,星期六,星期日;//打印星期几fun printWeek(){println("这是星期枚举对…...

_linux (TCP协议通讯流程)

文章目录TCP协议通讯流程TCP 和 UDP 对比TCP协议通讯流程 下图是基于TCP协议的客户端/服务器程序的一般流程: 服务器初始化: 调用socket, 创建文件描述符;调用bind, 将当前的文件描述符和ip/port绑定在一起;如果这个端口已经被其他进程占用了, 就会bind失 败;调用listen, 声…...

PMP考试详解,新考纲有什么变化?

一&#xff0c;为什么优先考虑PMP持证人员&#xff1f; PMP证书在我国大型企业、跨国企业、央企/国企等单位的招聘中都比较重视&#xff0c;特别是在许多项目投标环节中&#xff0c;明确标明需要有PMP持证人员&#xff0c;才能在投标、竞标中代表公司有资格承担项目。 除此之…...

C++学习笔记-日期和时间

C中可以使用的日期时间API主要分为两类&#xff1a; C-style 日期时间库&#xff0c;位于头文件中。这是原先<time.h>头文件的C版本。 chrono库&#xff1a;C 11中新增API&#xff0c;增加了时间点&#xff0c;时长和时钟等相关接口。 在C11之前&#xff0c;C编程只能使…...

Nordic nRF芯片FDS模块学习

FDS系统学习 文章目录FDS系统学习一、ROM&#xff0c;RAM&#xff0c;FLASH作用二、ROM,RAM和FLASH在单片中的运作原理三、Flash访问模块FDS用法1. FDS在sdk_config.h中的配置2. fds_register()注册3. fds_record_write()写记录4. fds_record_find()查找5. fds_record_open()读…...

JVM 学习(1)—JVM 与 JMM 内存模型简单理解

一、JVM 内存模型概述 (1) 为什么会出现 JVM 内存模型呢&#xff1f; JVM 内存模型是为规范描述 Java 虚拟机在执行 Java 程序时&#xff0c;将程序中的数据和代码存储到计算机内存中的方式和规则。JVM 内存模型定义 Java 虚拟机所使用的内存结构以及内存区域之间的关系&…...

NMS详解

(类别&#xff0c;坐标1&#xff0c;坐标2&#xff0c;坐标3&#xff0c;坐标4&#xff0c;类别分数) step1&#xff1a;对最后一列分数进行排序 &#xff0c;可以看到类别就被打乱了 step2&#xff1a; 弹出得到selected_bboxes作为基准&#xff0c;减少bbox_list。其实就是准…...

考出PMP证书到底有没有用?

我们将从三方面分享&#xff1a; 1. PMP 证书在国内的含金量怎么样&#xff1f; 2. HR 如何看待 PMP 证书&#xff1f; 3. 拿到 PMP 证书后&#xff0c;有哪些变化&#xff1f; 一&#xff0c;PMP证书的含金量 说到 PMP 证书的含金量&#xff0c;相信这个问题是所有学员都…...

寻路库recastnavigation改造

本文是介绍对寻路库recastnavigation 改造&#xff0c;使得使用更加友好。 Git仓库: https://github.com/jiangguilong2000/recastnavigation 首先&#xff0c;我们要做一些前置操作 SDL: 开放源代码的跨平台多媒体开发库 Premake&#xff1a;量跨平台构建系统 环境: VS 2019…...

pandas 一些设置随记

显示所有的行、列 # 显示所有列 pd.set_option(display.max_columns, None) # 显示所有行 pd.set_option(display.max_rows, None)不换行显示 pd.set_option(display.width, 1000) 输出对其 pd.set_option(display.unicode.ambiguous_as_wide, True) pd.set_option(display.…...

SSIM学习

SSIM原文链接&#xff1a;https://www.researchgate.net/profile/Eero-Simoncelli/publication/3327793_Image_Quality_Assessment_From_Error_Visibility_to_Structural_Similarity/links/542173b20cf203f155c6bf1a/Image-Quality-Assessment-From-Error-Visibility-to-Struct…...

selenium自动化测试用例需要关注的几点

自动化测试设计简介注&#xff1a;参看文章地址 我们在本章提供的信息&#xff0c;对自动化测试领域的新人和经验丰富的老手都是有用的。本篇中描述最常见的自动化测试类型&#xff0c; 还描述了可以增强您的自动化测试套件可维护性和扩展性的“设计模式”。还没有使用这些技术…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天&#xff0c;今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案&#xff0c;它们不仅提供了优雅的设计思路&#xff0c;还能显著提升系统的性能…...

数据分析六部曲?

引言 上一章我们说到了数据分析六部曲&#xff0c;何谓六部曲呢&#xff1f; 其实啊&#xff0c;数据分析没那么难&#xff0c;只要掌握了下面这六个步骤&#xff0c;也就是数据分析六部曲&#xff0c;就算你是个啥都不懂的小白&#xff0c;也能慢慢上手做数据分析啦。 第一…...

【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架

文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构C.1 指令微调阶段C.2 排名与生成的总和指令微调阶段C.3 RankRAG推理&#xff1a;检索-重排-生成 D 实验设计E 个人总结 A 论文出处 论文题目&#xff1a;RankRAG&#xff1a;Unifying Context Ranking…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。

2024 年&#xff0c;高端封装市场规模为 80 亿美元&#xff0c;预计到 2030 年将超过 280 亿美元&#xff0c;2024-2030 年复合年增长率为 23%。 细分到各个终端市场&#xff0c;最大的高端性能封装市场是“电信和基础设施”&#xff0c;2024 年该市场创造了超过 67% 的收入。…...

LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考

目录 lua脚本 记录流水 记录流水的作用 流水什么时候删除 我们在做库存扣减的时候&#xff0c;显示基于Lua脚本和Redis实现的预扣减 这样可以在秒杀扣减的时候保证操作的原子性和高效性 lua脚本 // ... 已有代码 ...Overridepublic InventoryResponse decrease(Inventor…...

第22节 Node.js JXcore 打包

Node.js是一个开放源代码、跨平台的、用于服务器端和网络应用的运行环境。 JXcore是一个支持多线程的 Node.js 发行版本&#xff0c;基本不需要对你现有的代码做任何改动就可以直接线程安全地以多线程运行。 本文主要介绍JXcore的打包功能。 JXcore 安装 下载JXcore安装包&a…...

react更新页面数据,操作页面,双向数据绑定

// 路由不是组件的直接跳转use client&#xff0c;useEffect&#xff0c;useRouter&#xff0c;需3个结合&#xff0c; use client表示客户端 use client; import { Button,Card, Space,Tag,Table,message,Input } from antd; import { useEffect,useState } from react; impor…...