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

由前端接口入门学习后端的controller层

由前端接口入门学习后端的controller层

  • 一、简单介绍一下controller层:
  • 二、前端调用后端接口时,一般会传递参数给后端,后端的控制层是如何接收的呢?
  • 三、更深入地介绍一下关于请求体参数
    • DTO作为入参
    • Map作为入参

本文是以一个前端工程师,后端小白的视角,详细介绍了关于controller的一些基本信息。大部分知识点还加上了简单的demo,真正做到了在实践中学习。

一、简单介绍一下controller层:

主要责任是接收来自用户界面(通常是Web浏览器)的请求,并根据请求的内容执行适当的操作。【即前端调用接口时就是在这里接收】

控制器通常是应用程序的入口点。它负责路由请求到正确的处理程序,并将处理后的结果返回给用户界面。控制器还可以负责验证用户输入、管理会话状态和处理异常情况等。

相当于是用户界面【前端web】和应用程序逻辑【后端代码逻辑】之间的中介。

二、前端调用后端接口时,一般会传递参数给后端,后端的控制层是如何接收的呢?

在后端的控制器层,接收前端传递的参数通常有以下几种方式,根据不同的方式,给出基于Spring Boot框架,使用了Spring Web模块提供的注解和API。你可以根据自己的实际需求和业务逻辑进行适当调整。记得在应用程序的启动类上添加@SpringBootApplication注解以启用Spring Boot的自动配置和组件扫描功能。

  1. 查询参数(Query Parameters):【GET】

    • 前端可以将参数作为URL的一部分通过查询字符串的形式传递,例如/api/users?name=John&age=25

      const param1 = 'name';
      const param2 = 'age';const url = `/api/users?param1=${encodeURIComponent(param1)}&param2=${encodeURIComponent(param2)}`;fetch(url).then(response => response.json()).then(data => {// 处理响应数据}).catch(error => {// 处理错误});
      
    • 在控制器中,可以通过读取请求对象的查询参数来获取这些值。

      @RestController
      @RequestMapping("/api/users")
      public class UserController {@GetMappingpublic ResponseEntity<List<User>> getUsers(@RequestParam("name") String name, @RequestParam("age") int age) {// 执行相应的逻辑,例如根据参数查询用户列表List<User> users = userService.getUsersByNameAndAge(name, age);return ResponseEntity.ok(users);}// 其他控制器方法...
      }
      
  2. 路径参数(Path Parameters):【GET】

    • 前端可以将参数作为URL的一部分通过路径参数的形式传递,例如/api/users/123,其中123为用户ID。

      下面是一个示例,展示了如何在前端使用路径参数传递多个参数给后端:

      const param1 = 'id';const url = `/api/users/${param1}`;fetch(url).then(response => response.json()).then(data => {// 处理响应数据}).catch(error => {// 处理错误});
      

      在上述示例中,我们使用 ${param1} 将两个参数拼接到 URL 的末尾,并将其作为请求的路径参数。最终的 URL 类似于 /api/users/id。

    • 在控制器中,可以通过路由配置或路由参数的方式来提取路径参数的值。

      @RestController
      @RequestMapping("/api/users")
      public class UserController {@GetMapping("/{id}")public ResponseEntity<User> getUser(@PathVariable("id") Long id) {// 执行相应的逻辑,例如根据参数获取特定用户User user = userService.getUserById(id);return ResponseEntity.ok(user);}// 其他控制器方法...
      }
      
  3. 请求体参数(Request Body Parameters):【POST、PUT 或 PATCH】

    • 对于一些HTTP方法(如POST、PUT等),前端可以将参数作为请求体的一部分发送。这通常用于传递较大或复杂的数据。下面是一个使用 fetch 发送带有 JSON 参数的 POST 请求的示例:

      const data = {name: 'John',email: 'john@example.com'
      };fetch('/api/users', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify(data)
      }).then(response => response.json()).then(data => {// 处理响应数据}).catch(error => {// 处理错误});
      
    • 在控制器中,可以通过读取请求对象的请求体来获取这些参数的值。

      @RestController
      @RequestMapping("/api/users")
      public class UserController {@PostMappingpublic ResponseEntity<User> createUser(@RequestBody CreateUserRequest request) {// 执行相应的逻辑,例如根据参数创建新用户User user = userService.createUser(request);return ResponseEntity.ok(user);}// 其他控制器方法...
      }
      
  4. 请求头参数(Request Header Parameters):

    • 前端可以将参数作为请求头的一部分发送,例如在请求头中添加Authorization字段来传递身份验证令牌。

      下面是一个使用 fetch 发送带有请求头的 GET 请求的示例:

      fetch('/api/users', {method: 'GET',headers: {'Content-Type': 'application/json','Authorization': 'Bearer your_token','Custom-Header': 'custom_value'}
      }).then(response => response.json()).then(data => {// 处理响应数据}).catch(error => {// 处理错误});
      

      在上述示例中,通过设置 headers 选项来添加请求头。你可以根据实际需求添加自定义的请求头字段,如 'Authorization''Custom-Header',并为其指定相应的值。

    • 在控制器中,可以通过读取请求对象的请求头来获取这些参数的值。

      @RestController
      @RequestMapping("/api/users")
      public class UserController {@GetMappingpublic ResponseEntity<List<User>> getUsers(@RequestHeader("Authorization") String authToken) {// 执行相应的逻辑,例如根据身份验证令牌获取用户列表List<User> users = userService.getUsersByAuthToken(authToken);return ResponseEntity.ok(users);}// 其他控制器方法...
      }
      

三、更深入地介绍一下关于请求体参数

请求体参数可以是DTO 也可以是Map,通常来说,推荐使用 DTO 对象,因为它提供了更好的类型安全性和代码可读性,尤其是当参数具有明确的属性结构的时候。

DTO作为入参

DTO 是一个用于封装数据的对象,通常用于传输数据或承载多个属性的复杂对象。如果你的请求参数具有多个属性,那么使用 DTO 是一个不错的选择。使用 DTO 可以使代码更具可读性,并且在开发过程中可以方便地对数据进行验证和处理。例如:

// DTO类
public class UserDTO {private String username;private String password;// 其他属性和方法// Getters and setters
}// 控制器方法
@PostMapping("/users")
public ResponseEntity<UserDTO> createUser(@RequestBody UserDTO userDTO) {// 使用 userDTO 对象进行处理// ...return ResponseEntity.ok(userDTO);
}

在上述示例中,UserDTO 是一个包含 usernamepassword 属性的 DTO 类。前端使用 JSON数据作为请求参数,控制器方法 createUser 使用 @RequestBody 注解将请求的 JSON 数据映射到 UserDTO 对象中,然后可以直接使用 userDTO 对象进行处理。

DTO 需要定义和维护DTO类:使用 DTO 需要创建相应的类,并定义属性和方法。

优点:

  • 明确定义类型和属性,减少类型错误;
  • 代码可读性强和可维护性;
  • DTO 对象可以包含验证逻辑和转换方法,用于对请求参数进行验证和处理,提供更严谨和一致的数据处理;
  • 可扩展性:DTO 对象可以根据业务需求灵活扩展,添加新的属性和方法,而不会影响控制器方法的签名。

缺点:

  • 很麻烦。如果请求参数很简单,还要特地建一个类,才一两个属性,因此如果请求参数很简单,尽量使用Map。

  • 上述的例子使用的是 @RequestBody 注解将请求的 JSON 数据映射到 UserDTO 对象。实际上,还有一些情况是没有办法使用这个注解 直接将 JSON 数据→ UserDTO 对象。

    而是需要我们使用一些对象映射工具(如 ModelMapper、Dozer、MapStruct)或手动进行属性赋值。

    • 例如,使用 ModelMapper:

      @PostMapping("/users")
      public ResponseEntity<UserDTO> createUser(@RequestBody UserCreateRequest request) {ModelMapper modelMapper = new ModelMapper();UserDTO userDTO = modelMapper.map(request, UserDTO.class);// 处理 userDTO 对象// ...return ResponseEntity.ok(userDTO);
      }
      

    常见的情况比如:

    1. 表单提交:如果请求是通过 HTML 表单提交的,而不是以 JSON 数据的形式发送,则无法直接使用 @RequestBody 注解将请求参数映射到 DTO 对象。在这种情况下,通常会使用 @ModelAttribute 注解或直接将表单字段作为方法参数来获取请求参数。

      例如:

      当使用 HTML 表单提交数据时,可以使用 @ModelAttribute 注解将请求参数映射到 DTO 对象。下面是一个使用 @ModelAttribute 注解的简单示例:

      @Controller
      public class UserController {@PostMapping("/users")public String createUser(@ModelAttribute UserDTO userDTO) {// 处理 userDTO 对象// ...return "redirect:/users";}}

      在上面的示例中,@PostMapping 注解指定了处理 POST 请求的路径为 /users。而 @ModelAttribute 注解应用于 UserDTO 类型的参数,它告诉 Spring MVC 框架将请求参数映射到该对象。

      假设有一个 HTML 表单,包含以下字段:

      <form action="/users" method="post"><input type="text" name="name" /><input type="email" name="email" /><input type="submit" value="Submit" />
      </form>

      当用户填写表单并提交时,表单中的字段名将与 UserDTO 对象的属性名相匹配。Spring MVC 框架将自动将请求参数映射到 UserDTO 对象的对应属性。例如,name 字段值将映射到 UserDTOname 属性,email 字段值将映射到 UserDTOemail 属性。

      createUser 方法中,你可以对接收到的 UserDTO 对象进行处理,例如将其保存到数据库中。然后,可以使用重定向 (redirect) 将用户重定向到另一个页面,例如用户列表页面 (/users)。

      需要注意的是,@ModelAttribute 注解可以不写,因为它是 Spring MVC 默认的参数绑定方式。但为了增加代码的可读性和明确性,显式地添加 @ModelAttribute 注解是一个好习惯。

      这是一个简单的示例,展示了如何使用 @ModelAttribute 注解将表单数据映射到 DTO 对象。根据实际需求,你可以在 DTO 对象中定义更多的属性,以便处理更多的请求参数。

    2. 文件上传:当请求涉及文件上传时,@RequestBody 注解通常无法直接处理文件数据。文件上传通常需要使用 MultipartFile 或类似的类型来处理文件数据,并可能需要其他额外的注解和配置来支持文件上传功能。

    3. 自定义请求处理:在某些情况下,你可能需要对请求进行自定义处理,使用特定的解析逻辑或处理器来解析请求的内容。这种情况下,你可能不会使用 @RequestBody 注解,而是手动处理请求的输入流或使用其他自定义的方式来映射请求数据到 DTO 对象。 这种方法适用于简单的场景,当 DTO 对象的属性较少时,手动赋值可能更加直观和简单。

        // 在控制器方法中,根据请求参数的名称,逐个从请求对象中获取值,并将其赋值给 DTO 对象的对应属性。@PostMapping("/users")public ResponseEntity<UserDTO> createUser(@RequestBody UserCreateRequest request) {UserDTO userDTO = new UserDTO();userDTO.setName(request.getName());userDTO.setEmail(request.getEmail());// 手动赋值其他属性// ...// 处理 userDTO 对象// ...return ResponseEntity.ok(userDTO);}

Map作为入参

如果你的请求参数是一组松散的键值对,并且你更关注请求中的数据而不是明确的对象结构,那么使用 Map 作为入参可能更合适。Map 可以接收各种参数,并以键值对的形式提供访问参数的灵活性。但是,使用 Map 作为入参可能会降低代码的可读性,因为你需要通过键来获取参数。例如:

@PostMapping("/users")
public ResponseEntity<UserDTO> createUser(@RequestBody Map<String, Object> requestMap) {String username = (String) requestMap.get("username");String password = (String) requestMap.get("password");// 处理用户名和密码// ...return ResponseEntity.ok(userDTO);
}

在上述示例中,控制器方法 createUser 使用 @RequestBody 注解将请求的 JSON 数据映射到 Map<String, Object> 对象中。然后,通过键值对的方式从 requestMap 中获取 usernamepassword 属性的值,并使用它们进行处理。注意需要手动进行类型转换,并且无法获得编译时的类型安全性。因此,确保请求的参数和键的名称保持一致,并进行适当的类型检查。

Map不用像DTO特地去维护一个类:

优点:

  • 灵活和简单:Map 可以接收各种键值对形式的请求参数,适用于不确定或变化的请求结构,不需要在DTO类中去维护。
  • 可以直接操作键值对:通过键值对的方式,可以直接获取和操作请求参数,适用于对请求数据的灵活处理。

缺点:

  1. 需要手动进行类型转换和验证,容易引入类型错误。
  2. 较低的可维护性:由于 Map 不提供明确的结构和属性,对于复杂的请求参数处理,可能需要在控制器方法中编写更多的逻辑来处理参数。
  3. 可读性较差:相对于 DTO,使用 Map 作为入参可能会降低代码的可读性,因为需要通过键来获取具体的参数值。

相关文章:

由前端接口入门学习后端的controller层

由前端接口入门学习后端的controller层 一、简单介绍一下controller层&#xff1a;二、前端调用后端接口时&#xff0c;一般会传递参数给后端&#xff0c;后端的控制层是如何接收的呢&#xff1f;三、更深入地介绍一下关于请求体参数DTO作为入参Map作为入参 本文是以一个前端工…...

HJ71 字符串通配符

Powered by:NEFU AB-IN Link 文章目录 HJ71 字符串通配符题意思路代码 HJ71 字符串通配符 题意 问题描述&#xff1a;在计算机中&#xff0c;通配符一种特殊语法&#xff0c;广泛应用于文件搜索、数据库、正则表达式等领域。现要求各位实现字符串通配符的算法。 要求&#xff…...

ffmpeg 开发笔记

参考&#xff1a; FFmpeg音视频处理 - 知乎 通过python实时生成音视频数据并通过ffmpeg推送和混流 - 知乎 直播常用 FFmpeg & ffplay 命令 - 知乎 音视频 FFMPEG 滤镜使用 - 知乎 官网&#xff1a; ffmpeg Documentation...

一种基于注意机制的快速、鲁棒的混合气体识别和浓度检测算法,配备了具有双损失函数的递归神经网络

A fast and robust mixture gases identification and concentration detection algorithm based on attention mechanism equipped recurrent neural network with double loss function 摘要 提出一个由注意力机制组成的电子鼻系统。首先采用端到端的编码器译码器&#xff…...

[运维|系统] go程序设置开机启动踩坑笔记

参考文献 记systemctl启动go程序 在Ubuntu上作为systemctl服务运行时Go找不到文件 go语言程序设置开机启动&#xff0c;配置不生效 需要在服务配置文件中加入工作目录配置&#xff0c;示例 WorkingDirectory/path/to/go/program/directory...

CRC原理介绍及STM32 CRC外设的使用

1. CRC简介 循环冗余校验&#xff08;英语&#xff1a;Cyclic redundancy check&#xff0c;简称CRC&#xff09;&#xff0c;由 W. Wesley Peterson 于 1961 年首次提出的一种纠错码理论。 CRC是一种数据纠错方法&#xff0c;主要应用于数据通信或者数据存储的场合&#xff…...

Python 操作 Word

上次给大家介绍了 Python 如何操作 Excel &#xff0c;是不是感觉还挺有趣的&#xff0c;今天为大家再介绍下&#xff0c;用 Python 如何操作 Word &#xff0c;这个可能跟数据处理关系不大&#xff0c;用的也不多&#xff0c;不过可以先了解下都能实现什么功能&#xff0c;以备…...

Linux--进程创建(fork)-退出--孤儿进程

进程创建&#xff1a; ①使用fork函数创建一个进程&#xff0c;创建的新进程被称为子进程。 #include <unistd.h>//头文件 pid_t fork(void); fork函数调用成功&#xff0c;返回两次&#xff1a; 返回值为0&#xff0c; 代表当前进程为子进程&#xff1b; 返回值为非负数…...

LeetCode 热题 HOT 100:链表专题

LeetCode 热题 HOT 100&#xff1a;https://leetcode.cn/problem-list/2cktkvj/ 文章目录 2. 两数相加19. 删除链表的倒数第 N 个结点21. 合并两个有序链表23. 合并 K 个升序链表141. 环形链表142. 环形链表 II148. 排序链表160. 相交链表206. 反转链表234. 回文链表 2. 两数相…...

Redis发布订阅

在现代的软件开发中&#xff0c;数据存储和管理是至关重要的一环。Redis&#xff0c;作为一个开源的、内存中的数据结构存储系统&#xff0c;以其出色的性能和灵活的数据结构&#xff0c;赢得了开发者们的广泛喜爱。它不仅可以用作数据库&#xff0c;还可以用作缓存和消息代理。…...

在Windows操作系统上安装PostgreSQL数据库

在Windows操作系统上安装PostgreSQL数据库 一、在Windows操作系统上安装PostgreSQL数据库 一、在Windows操作系统上安装PostgreSQL数据库 点击 PostgreSQL可跳转至PostGreSQL的官方下载地址。 &#xff08;1&#xff09; &#xff08;2&#xff09;选择安装的目录&#xff…...

【云原生】Kubeadmin部署Kubernetes集群

目录 ​编辑 一、环境准备 1.2调整内核参数 二、所有节点部署docker 三、所有节点安装kubeadm&#xff0c;kubelet和kubectl 3.1定义kubernetes源 3.2开机自启kubelet 四、部署K8S集群 4.1查看初始化需要的镜像 4.2在 master 节点上传 v1.20.11.zip 压缩包至 /opt 目录…...

Java中wait和notify详解

线程的调度是无序的&#xff0c;随机的&#xff0c;但是也是有一定的需求场景&#xff0c;希望能够有序执行&#xff0c;join算是一种控制顺序的方式&#xff08;功能有限&#xff09;——》一个线程执行完&#xff0c;才能执行另一个线程&#xff01; 本文主要讲解的&#xf…...

算法竞赛个人注意事项

浅浅记录一下自己在算法竞赛中的注意事项。 数据类 注意看数大小&#xff0c;数学库中的函数尽量加上 * 1.0&#xff0c;转成double&#xff0c;防止整型溢出。&#xff0c;int型相乘如果可能溢出&#xff0c;乘 * 1LL。 数据范围大于1e6&#xff0c;注意用快读。 浮点数输…...

ClickHouse和Doris超大数据集存储

文章目录 一. ClickHouse1. 性能2. 可靠性3. 可扩展性4. 支持SQL和复杂查询5. 适用场景 二. Doris1. 性能2. 可靠性3. 易用性4. 适用场景 三. ClickHouse和Doris的比较1. 架构2. 性能3. 可靠性4. 易用性5. 适用场景 四. 总结 ClickHouse和Doris是两种流行的超大数据集存储方案。…...

02-Flask-对象初始化参数

对象初始化参数 前言对象初始化参数import_namestatic_url_pathstatic_foldertemplate_floder 前言 本篇来学习Flask中对象初始化参数 对象初始化参数 import_name Flask程序所在的包(模块)&#xff0c;传__name__就可以 _name_ 是一个标识 Python 模块的名字的变量&#x…...

第5篇 vue的通信框架axios和ui框架-element-ui以及node.js

一 axios的使用 1.1 介绍以及作用 axios是独立于vue的一个项目&#xff0c;基于promise用于浏览器和node.js的http客户端。 在浏览器中可以帮助我们完成 ajax请求的发送在node.js中可以向远程接口发送请求 1.2 案例使用axios实现前后端数据交互 1.后端代码 2.前端代码 &…...

RabbitMQ 知识点解读

1、AMQP 协议 1.1、AMQP 生产者的流转过程 当客户端与Broker 建立连接的时候&#xff0c;会调用factory .newConnection 方法&#xff0c;这个方法会进一步封装成Protocol Header 0-9-1 的报文头发送给Broker &#xff0c;以此通知Broker 本次交互采用的是AMQPO-9-1 协议&…...

SimVODIS++: Neural Semantic Visual Odometry in Dynamic Environments 论文阅读

论文信息 题目&#xff1a;SimVODIS: Neural Semantic Visual Odometry in Dynamic Environments 作者&#xff1a;Ue-Hwan Kim , Se-Ho Kim , and Jong-Hwan Kim , Fellow, IEEE 时间&#xff1a;2022 来源&#xff1a; IEEE ROBOTICS AND AUTOMATION LETTERS&#xff08;RAL…...

7.Xaml Image控件

1.运行图片 2.运行源码 a.xaml源码 <!--Source="/th.gif" 图像源--><!--Stretch="Fill" 填充模式--><Image x:Name...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...