当前位置: 首页 > 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...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

如何做好一份技术文档?从规划到实践的完整指南

如何做好一份技术文档&#xff1f;从规划到实践的完整指南 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...

使用ch340继电器完成随机断电测试

前言 如图所示是市面上常见的OTA压测继电器&#xff0c;通过ch340串口模块完成对继电器的分路控制&#xff0c;这里我编写了一个脚本方便对4路继电器的控制&#xff0c;可以设置开启时间&#xff0c;关闭时间&#xff0c;复位等功能 软件界面 在设备管理器查看串口号后&…...