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

Spring Boot 学习之路 -- 处理 HTTP 请求

前言

  1. 最近因为业务需要,被拉去研究后端的项目,代码框架基于 Spring Boot,对我来说完全小白,需要重新学习研究…
  2. 出于个人习惯,会以 Blog 文章的方式做一些记录,文章内容基本来源于「 Spring Boot 从入门到精通(明日科技) 」一书,做了一些整理,更易于个人理解和回顾查找,所以大家如果希望更系统性的学习,可以阅读此书(比较适合我这种新手)。

HTTP 请求是指从客户端到服务器的请求消息。对于一个 Spring Boot 项目而言,服务器就是 Spring Boot,客户端就是用户本地的浏览器。启动 Spring Boot 项目后,首先用户通过 URL 地址发送请求,然后 Spring Boot 通过解析 URL 地址处理请求,最后 Spring Boot 把处理结果返回给用户。

HTTP 请求有 3 种很常见的请求类型,它们分别是 GET、POST 和 DELETE

其中:

  • GET:表示请求从服务器获取特定资源;
  • POST:表示在服务器上创建一个新的资源;
  • DELETE:表示从服务器删除特定的资源。

本文将介绍 Spring Boot 是如何使用注解解析 URL 地址,进而处理上述 3 种类型的 HTTP 请求的。


一、处理 HTTP 请求的注解

在开发 Spring Boot 项目的过程中,Spring Boot 的典型应用是处理 HTTP 请求。所谓处理 HTTP 请求,就是 Spring Boot 把用户通过 URL 地址发送的请求交给不同的业务代码进行处理的过程。

1.1 使用 @Controller 声明控制器类

Spring Boot 提供了用于声明控制器类的 @Controller 注解。也就是说,在 Spring Boot 项目中,把被 @Controller 注解标注的类称作控制器类。控制器类在 Spring Boot 项目中发挥的作用是处理用户发送的 HTTP 请求。Spring Boot 会把不同的用户请求交给不同的控制器进行处理,而控制器则会把处理后得到的结果反馈给用户。

说明:

控制器(controller)定义了应用程序的行为,它负责对用户发送的请求进行解释,并把这些请求映射成相应的行为。

因为 @Controller 注解本身被 @Component 注解标注,所以控制器类属于组件。这说明在启动 Spring Boot 项目时,控制器类会被扫描器自动扫描。这样,程序开发人员就可以在控制器类中注入 Bean。例如,在控制器中注入 Environment 环境组件,代码如下:

​​​​@Controller
​​​​public class TestController {
​​​​    @Autowired
​​​​    Environment env;
​​​​}​​

1.2 使用 @RequestMapping 映射 URL 地址

Spring Boot 提供了用于映射 URL 地址的 @RequestMapping 注解。@RequestMapping 注解可以标注类和方法。如果一个类或者方法被 @RequestMapping 注解标注,那么这个类或者方法就能够处理用户通过 @RequestMapping 注解映射的 URL 地址发送的请求。

下面将首先介绍 @RequestMapping 注解的属性,然后介绍如何使用 @RequestMapping 注解映射包含层级关系的 URL 地址。

注意:

@Controller 注解要结合 @RequestMapping 注解一起使用。

1.2.1 @RequestMapping 注解的属性

@RequestMapping 有几个常用属性,下面分别对这些属性予以介绍。

value 属性

value 属性是 @RequestMapping 注解的默认属性,用于指定映射的 URL 地址。在单独使用 value 属性时,value 属性可以被隐式调用。调用 value 属性的语法如下:

​​​​@RequestMapping("test")
​​​​@RequestMapping("/test")
​​​​@RequestMapping(value= "/test")
​​​​@RequestMapping(value={"/test"})​​

上面这 4 种语法所映射的 URL 地址均为“域名/test”。其中,域名指的是当前 Spring Boot 项目所在的域。如果在 IntelliJ IDEA 中启动一个 Spring Boot 项目,那么域名就是 127.0.0.1:8080。

比如我们修改之前文章的 BeanTestController:

@Controller
public class BeanTestController {@RequestMapping("/index")       // 映射的 URL 地址为 /index@ResponseBody                   // 直接将字符串显示在页面上 public String test(){return "欢迎访问我的主页!";}
}

在浏览器上访问 http://127.0.0.1:8080/index 地址:

在这里插入图片描述

说明:

如果一个方法被 @ResponseBody 注解标注,那么由这个方法返回的字符串将被直接显示在浏览器的页面上。

@RequestMapping 注解映射的 URL 地址可以是多层的。例如:

​​​​@RequestMapping("/shop/books/computer")​​

上述代码映射的完整URL地址是 http://127.0.0.1:8080/shop/books/computer。需要特别注意的是,这个 URL 地址中的任何一层都是不可或缺的,否则将引发 404 错误。

@RequestMapping 注解允许一个方法同时映射多个 URL 地址。其语法如下:

​​​​@RequestMapping(value = { "/address1", "/address2", "/address3", ....... })​​

method 属性

method 属性能够指定用户通过 @RequestMapping 注解映射的 URL 地址发送的请求的类型。这样,使用 method 属性就能够让不同的方法处理由相同 URL 地址发送的不同类型的请求。

下面将通过一个实例演示 method 属性的用法,我们修改 controller 类,如果由 “/index” 地址发送的请求的类型是 GET,则打印“处理 GET 请求”;如果由 “/index” 地址发送的请求的类型是 POST 请求,则打印“处理 POST 请求”,代码如下:

@Controller
public class BeanTestController {@RequestMapping(value = "/index", method = RequestMethod.GET)@ResponseBodypublic String get(){return "处理 GET 请求";}@RequestMapping(value = "/index", method = RequestMethod.POST)@ResponseBodypublic String post(){return "处理 POST 请求";}
}

使用 Postman 模拟 GET 请求和 POST 请求,所示结果如下。如果发送的请求既不是 GET 类型也不是 POST 类型,则会触发 405 错误。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

由 URL 地址发送的请求具有多种类型,详见 RequestMethod 枚举类。

RequestMethod 枚举类的代码如下:

public enum RequestMethod {
​​​​    GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
​​​​}

params 属性

params 属性能够指定在用户通过 @RequestMapping 注解映射的 URL 地址发送的请求中须包含哪些参数。因为 params 属性的类型是字符串数组,所以通过 params 属性能够同时指定多个参数。

下面将通过一个实例演示 params 属性的用法,我们修改 Controller:

@Controller
public class BeanTestController {@RequestMapping(value = "/index", params = { "name", "id" })@ResponseBodypublic String haveParams(){return "欢迎回来~";}@RequestMapping(value = "/index")@ResponseBodypublic String noParams(){return "忘传参数了...";}
}

使用 Postman 模拟用户通过 URL 地址发送的请求。查看结果:

在这里插入图片描述
在这里插入图片描述

headers 属性

headers 属性能够指定在用户通过 @RequestMapping 注解映射的 URL 地址发送的请求中须包含哪些指定的请求头。也就是说,在一个 headers 属性中,可以包含若干个请求头。通过这些请求头,服务器能够得知客户端环境以及与请求正文相关的一些信息,例如浏览器的版本、请求参数的长度等。

headers 属性在 @RequestMapping 注解中的格式如下:

​​​​@RequestMapping(headers = {"键1=值1", "键2=值2", ......})​​

说明:

请求头指的是 HTTP 请求中的头部信息,即用于 HTTP 通信的操作参数。

从 headers 属性在 @RequestMapping 注解中的格式,能够非常清晰地看到请求头在 headers 属性中的格式:

​​​​"键=值"​​

我们测试下,修改 Controller,在控制器类中编写 noParams() 和 haveParams() 这两个方法。如果用户通过 URL 地址发送的请求包含 headers 属性,就交由 noParams() 方法处理,让用户直接进入欢迎界面;否则,就交由 haveParams() 方法处理,让用户进入登录界面。

@Controller
public class BeanTestController {@RequestMapping(value = "/index")@ResponseBodypublic String haveParams(){return "请重新登录!";}@RequestMapping(value = "/index", headers = { "Cookie=JSESSIONID=123456789"})@ResponseBodypublic String noParams(){return "欢迎回来~";}
}

说明:

Cookie 是某些网站为了辨别用户身份、进行 Session 跟踪而储存在用户本地终端上的数据。Cookie 会被暂时地或永久地保存在用户客户端计算机中。

对于本示例,如果用户在某个登录界面选择了“自动登录”选项,那么服务器就会将用户登录的 session id 写在浏览器的 Cookie 中。

使用 Postman 模拟用户通过 URL 地址发送的请求。

  1. 如果在请求中不包含 headers 属性,直接访问 http://127.0.0.1:8080/index 地址:

在这里插入图片描述

  1. 如果为请求头添加 Cookie,值为“JSESSIONID=123456789”,再访问同一个地址:

在这里插入图片描述

consumes 属性

consumes 属性能够指定用户通过 @RequestMapping 注解映射的 URL 地址发送的请求的数据类型。其中,常见的类型有 “application/json”、“text/html” 等。

下面将通过一个实例演示 consumes 属性的用法。

修改 Controller 类,将 @RequestMapping 注解的 consumes 属性设置为“application/json”。在控制器类中编写 formatError() 和 hello() 这两个方法。如果用户发送的请求的数据类型是 JSON,就交由 hello() 方法处理,并提示“成功进入接口”的信息;否则,就交由 formatError() 方法处理,并提示“数据格式错误!”的信息。

@Controller
public class BeanTestController {@RequestMapping(value = "/index")@ResponseBodypublic String formatError(){return "数据格式错误!";}@RequestMapping(value = "/index", consumes = "application/json")@ResponseBodypublic String hello(){return "成功进入接口";}
}

使用 Postman 模拟用户通过URL地址发送的请求。如果直接访问 http://127.0.0.1:8080/index 地址,结果如下:

在这里插入图片描述

如果在请求体(Body)中填写 JSON 数据,再访问上述地址就可以看到下图结果:

在这里插入图片描述

1.2.2 映射包含层级关系的 URL 地址

通常一个 URL 地址不只是简单的一层地址,而是根据业务分类形成的多层地址。那么,如何理解在一个 URL 地址中包含多层地址呢?例如,在某电商平台通过访问 “/shop/books” 地址查看图书信息;其中,“/shop” 是这个电商平台的地址,“/books” 表示图书类。那么,应该如何使用 @RequestMapping 注解映射这个包含层级关系的 URL 地址呢?代码如下:

@Controller
public class BeanTestController {@RequestMapping("/shop/books")@ResponseBodypublic String books() {return "图书类";}
}

不难发现,在表示电商平台的控制器类中包含一个 book() 方法。通过使用 @RequestMapping 注解标注这个 book() 方法,就能够实现映射一个多层的 URL 地址的功能。

如果这个电商平台还卖服装,那么就会含有表示服装类的 “/clothes” 地址。那么,又应该如何使用 @RequestMapping 注解既映射 “/shop/books” 地址,又映射 “/shop/clothes” 地址呢?代码如下:

@Controller
public class BeanTestController {@RequestMapping("/shop/clothes")@ResponseBodypublic String cloths() {return "服饰类";}@RequestMapping("/shop/books")@ResponseBodypublic String books() {return "图书类";}
}

不难发现,“/shop/books” 和 “/shop/clothes” 这两个地址具有相同的上层地址 “/shop”。那么,有没有什么编码方式能够优化上述代码呢?答案是使用 @RequestMapping(“/shop”) 注解标注表示电商平台的控制器类。

优化后的代码如下:

@Controller
@RequestMapping("/shop")
public class BeanTestController {@RequestMapping("/clothes")@ResponseBodypublic String cloths() {return "服饰类";}@RequestMapping("/books")@ResponseBodypublic String books() {return "图书类";}
}

说明:

@RequestMapping 注解不仅可以标注方法,还可以标注类。

在访问一个多层的 URL 地址时,输入的 URL 地址必须是完整的,比如下面的效果图:

在这里插入图片描述
在这里插入图片描述

1.3 @ResponseBody

在上文讲解的所有实例中,其中的方法都被 @RequestMapping 和 @ResponseBody 注解同时标注。在掌握了 @RequestMapping 注解的相关内容后,下面将介绍 @ResponseBody 注解的作用。

@ResponseBody 注解的作用是把被 @ResponseBody 注解标注的方法的返回值转换为页面数据。

  • 如果被 @ResponseBody 注解标注的方法的返回值是字符串,页面就会显示字符串;
  • 如果被 @ResponseBody 注解标注的方法的返回值是其他类型的数据,这些数据就会先被自动封装成 JSON 格式的字符串,再显示在页面中。

下面将介绍在使用 @ResponseBody 注解时会遇到的另外一种情况:如果控制器类中的某个方法被 @RequestMapping 注解标注,却没有被 @ResponseBody 标注,那么这个方法的返回值会是什么呢?

答案是即将跳转的 URL 地址。例如:

@Controller
public class BeanTestController {@RequestMapping("/index")                  // 映射 "/index" 地址,未标注 @ResponseBodypublic ModelAndView index(){return new ModelAndView("/welcome");   // 跳转至 "/welcome" 地址}
}

在上述代码中,index() 方法被 @RequestMapping 注解标注,却没有被 @ResponseBody 标注。该方法的返回值是 org.springframework.web.servlet.ModelAndView 类型。

因为上述代码的功能是当用户访问 “/index” 地址时,页面就会跳转至与 “/welcome” 地址对应的页面,所以可以把 index() 方法的返回值修改为字符串。修改后的代码如下:

@Controller
public class BeanTestController {@RequestMapping("/index")                  // 映射 "/index" 地址,未标注 @ResponseBodypublic String index(){return "/welcome";                     // 跳转至 "/welcome" 地址}
}

通过上述代码,是不是就能够实现跳转页面的功能了呢?答案是否定的。为了实现跳转页面的功能,还需要向上述代码添加用于映射 “/welcome” 地址的方法,并且这个方法要被 @RequestMapping 和 @ResponseBody 注解同时标注。添加用于映射 “/welcome” 地址的方法后的代码如下:

@Controller
public class BeanTestController {@RequestMapping("/index")public String index(){return "/welcome";}@RequestMapping("/welcome")@ResponseBodypublic String welcome(){return "欢迎来到我的主页";}
}

启动项目后,打开浏览器访问 http://127.0.0.1:8080/index 地址,即可看到页面会跳转至与 “/welcome” 地址对应的页面:

在这里插入图片描述

此外,在使用 @ResponseBody 注解时还需要特别注意一个问题:@ResponseBody 注解虽然也可以标注控制器类,但是控制器类中的所有方法的返回值都会直接显示在页面上。例如,把上述代码中的 @ResponseBody 注解标注在控制器类上,代码如下:

@Controller
@ResponseBody  // 将注解标注在类上
public class BeanTestController {@RequestMapping("/index")public String index(){return "/welcome";}@RequestMapping("/welcome")public String welcome(){return "欢迎来到我的主页";}
}

启动项目,打开浏览器访问 http://127.0.0.1:8080/index 地址,会发现页面没有发生跳转,并且显示的结果是index()方法的返回值:

在这里插入图片描述

1.4 @RestController

@RestController 注解虽然是 Spring Boot 的新增注解,但实质上是 @Controller 和 @ResponseBody 这两个注解的综合体。也就是说,当控制器类同时被 @Controller 和 @ResponseBody 这两个注解标注时,这两个注解可以被 @RestController 注解替代。这样就可以起到简化代码的作用。例如:

​​​​@Controller
​​​​@ResponseBody
​​​​public class TestController {
​​​​}​​

使用 @RestController 注解可以简化上述代码。简化后的代码如下:

​​​​@RestControlle
​​​​public class TestController {
​​​​}​​

二、重定向 URL 地址

重定向 URL 地址是指用户通过原始的 URL 地址发送的请求指向了新的 URL 地址,并且请求中的数据不会被保留。也就是说,通过重定向 URL 地址,服务器可以把用户推送到其他网站上。

下面将介绍 Spring Boot 用于实现重定向的两种方法。

2.1 redirect:

前面一节,我们已经明确了如果控制器类中的某个方法被 @RequestMapping 注解标注,却没有被 @ResponseBody 标注,且这个方法的返回值是字符串,那么这个方法的作用是实现页面跳转的功能,这个方法返回的字符串表示的是即将跳转的 URL 地址。如果在即将跳转的 URL 地址的前面加上“redirect:”,就表示用户通过原始的 URL 地址发送的请求指向了这个 URL 地址。

下面通过一个实例演示“redirect:”前缀的用法。

@Controller
public class BeanTestController {@RequestMapping("/bd")public String bd(){return "redirect:https://www.baidu.com";}
}

启动项目后,打开浏览器访问 http://127.0.0.1:8080/bd 地址,浏览器会自动跳转至百度首页,并且地址栏中 URL 地址显示的也是百度首页的 URL 地址,原始的 URL 地址已经在地址栏中看不到了。

在这里插入图片描述

2.2 response

response 对象指的是 HttpServletResponse 类型的对象,可用于实现重定向 URL 的功能。那么,Spring Boot 是如何使用 response 对象实现这个功能的呢?Spring Boot 可以直接在控制器类的某个方法中创建 response 对象,通过这个对象调用 sendRedirect() 方法就可以指定重定向的 URL 地址。只不过,如果这个方法具有返回值,那么上述操作会导致这个返回值失效。因此,程序开发人员通常会把这个方法的返回值的类型设置为 void。

@Controller
public class BeanTestController {@RequestMapping("/bd")public void bd(HttpServletResponse response){try {response.sendRedirect("https://www.baidu.com");} catch (IOException e) {throw new RuntimeException(e);}}
}

启动项目后,打开浏览器访问 http://127.0.0.1:8080/bd 地址,即可看到百度首页。


http://www.mrgr.cn/news/35098.html

相关文章:

  • [智能车摄像头是一种安装在汽车上用于辅助驾驶和提高安全性的重要设备]
  • Spring 解析xml中的 BeanDefination 大概过程
  • 【activiti工作流源码集成】springboot+activiti+mysql+vue+redis工作流审批流集成整合业务绑定表单流程图会签驳回
  • C语言数据结构与算法--简单实现队列的入队和出队
  • 【鸿蒙开发】第四章 ArkTS语言UI范式-基础语法
  • 【css】html里面的图片宽度设为百分比,高度要与宽度一样
  • 基于深度学习的花卉智能分类识别系统
  • 仿黑神话悟空跑动-脚下波纹特效(键盘wasd控制走动)
  • 五种方式帮你提升独立站销售额
  • Frp经常连接不上?查看Frp常见问题排查
  • SSM+Vue共享单车管理系统
  • 分布式光伏监控系统 在鄂尔多斯市鄂托克旗某煤矿项目中的应用
  • 电路 - 笔记2
  • R包:gplots经典热图
  • 城市污水管网流量在线监测系统解决方案
  • 集成运放UA741的原理与应用的探索
  • 关于中断和异常的一些理解
  • 消息中间件常见面试题(RabbitMQ)
  • typeScript常用写法-请求篇
  • [spring]用MyBatis XML操作数据库 其他查询操作 数据库连接池 mysql企业开发规范
  • python教程修订版
  • harmonyos面试题
  • YoloV8改进策略:BackBone改进|PoolFormer赋能YoloV8,视觉检测性能显著提升的创新尝试
  • 数据库如何优化,怎么提升性能与效率呢?(建议收藏)
  • MySQL—触发器详解
  • 论文复现:考虑电网交互的风电、光伏与电池互补调度运行(MATLAB-Yalmip-Cplex全代码)