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

这篇具有很好参考价值的文章主要介绍了由前端接口入门学习后端的controller层。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文是以一个前端工程师,后端小白的视角,详细介绍了关于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 {
          
          @GetMapping
          public 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 {
          
          @PostMapping
          public 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 {
          
          @GetMapping
          public 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 对象可以根据业务需求灵活扩展,添加新的属性和方法,而不会影响控制器方法的签名。

缺点:文章来源地址https://www.toymoban.com/news/detail-697107.html

  • 很麻烦。如果请求参数很简单,还要特地建一个类,才一两个属性,因此如果请求参数很简单,尽量使用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层的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端调接口下载(导出)后端返回.zip压缩文件流(的坑!)

    前言:基于vue2+element-ui的一个后台管理系统,需求评审要加一个导入导出文件的功能,由于可能导出的数据量过大(几十万条数据),下载时间过长,所以用.zip压缩文件替代excel文件 本人以前也做过导出文件的功能,但是用的方法是后端处理数据然后放到另一个服务器上,前

    2024年02月03日
    浏览(34)
  • JavaWeb前端/后端开发规范——接口文档概述及YApi平台的使用

    整理下笔记,打好基础,daydayup!!! 什么是接口文档? 目前主流的开发模式为前后端分离式开发,为了方便前后端的对接,就需要使用接口文件进行统一规范。 接口文档记载什么信息? 1,基本信息:请求路径,请求方式,接口描述 2,参数信息:参数名,参数类型,参数样例

    2024年04月17日
    浏览(43)
  • 前端Vue Node.js + Express + MongoDB 构建的后端服务API接口

    构建一个使用 Vue.js 作为前端, Node.js + Express + MongoDB 作为后端服务的全栈应用涉及到多个步骤。这里简要概述整个过程,并提供一些基本的代码示例来帮助你开始。 安装 MongoDB: 根据你的操作系统从 MongoDB 官网 下载并安装 MongoDB。 启动 MongoDB 服务: 安装完成后,根据 MongoDB 的

    2024年04月14日
    浏览(33)
  • json-server Node.js 服务,前端模拟后端提供json接口服务

    json-server Node.js 服务,前端模拟后端提供json接口服务 背景:    前后端分离的项目,如果前端写页面的话,必须的后端提供接口文件,作为前端等待时间太久,不便于开发进行,如果前端写的过程中自己搭建一个简要的后端的json服务接口,就是可以快速进行开发事项的进行,

    2024年02月16日
    浏览(29)
  • 从零实现一套低代码(保姆级教程)【后端服务】 --- 【18】实现页面接口对应的前端

    在上一篇中,我们已经把和页面相关的接口完成的差不多了。从创建页面,更新页面等等: 有了接口之后,我们就可以构建前端页面了。那这部分前端内容我们应该写在哪里呢? 有两种方式: 直接写在我们的XinBuilder项目里面,然后通过前端路由拆分成两个路由 在创建一个

    2024年01月22日
    浏览(40)
  • 不管是前端还是后端,都要看的Elasticsearch快速入门

    Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎,Elasticsearch和Mysql,Redis,MongoDb,Clickhouse等一样,都可以认为它 是一种数据库 设想一个场景: user表有6千多万条数据,我想查询nick中包含”大帅哥“的数据: Select nick from user where nick like \\\'%大帅哥%\\\' 比如,我

    2024年02月08日
    浏览(36)
  • 【后端学前端学习记录】学习计划

            写了足够久的后端了,常用的语言基本上都接触过,没有在工作中写过前端 一直想做一些前端的工作,但是前端技能不足加上自己审美不行,写出的界面总是很丑 所以一直对前端做不好,也没有真正下手。 种一棵树最好的时间是十年前,其次是现在   想做一个自己

    2024年02月04日
    浏览(30)
  • 【前端版】分布式医疗云平台【登陆页面修改、页面 title 修改、登陆接口准备说明、把前端和后端统一使用 git 管理、启动前端 VUE 项目、用户登陆】(十七)

    目录 2.8.【前端】登陆页面修改 2.8.1.主页退出 2.8.2.登陆页面修改 2.9.【前端】页面 title 修改

    2024年02月07日
    浏览(38)
  • vue怎么连接后端,获取后端的数据

    没有封装的情况: 封装的情况:  1、在封装好的api文件夹中创建相关的js文件 2、在需要引用的页面的

    2024年02月11日
    浏览(29)
  • 后端学习2.1:引入Junit,对接口做单元测试

    本文将对在Springboot中如何使用Junit进行单元测试进行简单示例和介绍,项目的完整目录层次如下图所示: (在和main文件夹同级的文件中有一个test文件,在其中添加对应的测试类,一般以testXXXX或XXXXTest命名) 操作步骤: 在Springboot中可以通过TestRestTemplate对Controller进行测试; 目

    2024年02月06日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包