网站新闻关键词,网站建设的分阶段步骤,做百度网站找谁,数据网站建设前言#xff08;SpringBoot程序请求响应流程#xff09;
以上一章的程序为例#xff0c;一个基于SpringBoot的方式开发一个web应用#xff0c;浏览器发起请求 /hello 后 #xff0c;给浏览器返回字符串 “Hello World ~”。
而我们在开发web程序时呢#xff0c;定义了一…前言SpringBoot程序请求响应流程
以上一章的程序为例一个基于SpringBoot的方式开发一个web应用浏览器发起请求 /hello 后 给浏览器返回字符串 “Hello World ~”。
而我们在开发web程序时呢定义了一个控制器类Controller请求会被部署在Tomcat中的Controller接收然后Controller再给浏览器一个响应响应一个字符在浏览器发起请求请求了我们的后端web服务器(也就是内置串 “Hello World”。 而在请求响应的过程中是遵循HTTP协议的。
但是在Tomcat这类Web服务器中是不识别我们自己定义的Controller的。而Tomcat是一个Servlet容器支持Serlvet规范因此在tomcat中是可以识别 Servlet程序的。 Servlet服务器小程序是一种运行在 Web 服务器或应用服务器上的 Java 程序用于处理客户端如浏览器发送的 HTTP 请求并生成响应。它是 Java Web 开发的核心组件之一遵循 Java Servlet API 规范。简单来说当用户通过浏览器访问一个网站时浏览器会发送 HTTP 请求到 Web 服务器服务器中的 Servlet 程序就会接收并处理这些请求比如获取用户请求的页面内容、处理用户提交的表单数据等然后生成一个响应返回给浏览器这个响应可以是 HTML 页面、XML 数据、JSON 数据或者其他类型的内容。 那么在SpringBoot进行web程序开发时它其实内置了一个核心的Servlet程序 DispatcherServlet称之为 核心控制器也可以叫做 前端控制器。 DispatcherServlet 负责接收页面发送的请求然后根据执行的规则将请求再转发给后面的请求处理器Controller请求处理器处理完请求之后最终再由DispatcherServlet给浏览器响应数据。
那将来浏览器发送请求会携带请求数据包括请求行、请求头请求到达tomcat之后tomcat会负责解析这些请求数据然后呢将解析后的请求数据会传递给Servlet程序中的HttpServletRequest对象那也就意味着 HttpServletRequest 对象就可以获取到请求数据。 而Tomcat还给Servlet程序传递了一个参数 HttpServletResponse通过这个对象我们就可以给浏览器设置响应数据 。 一 请求 1、Postman接口测试工具
postman的安装使用教程 我已经在另一篇文章详细介绍 Postman安装使用教程-CSDN博客
2、简单参数
①、原始方式 Tomcat接收到http请求时把请求的相关信息封装到HttpServletRequest对象中
在Controller中我们要想获取Request对象可以直接在方法的形参中声明 HttpServletRequest 对象。然后就可以通过该对象来获取请求信息 ②、SpringBoot方法 在Springboot方法中可以自动进行类型转换。在Springboot的环境中对原始的API进行了封装接收参数的形式更加简单。 对于简单参数来讲只要保证请求参数名和Controller方法中的形参名保持一致就可以获取到请求参数中的数据值。 发送Post请求 如果形参与请求参数对应不上也可以通过注解RequestParam来进行映射 但是如果没有设置RequestParam注解且方法形参名与请求参数名不一致那么虽然会无法接收到请求数据但是它不会报错 注解RequestParam中的required属性默认为true代表该请求参数必须传递如果不传递就会报错 ③、小结 3、实体参数
在使用简单参数做为数据传递方式时前端传递了多少个请求参数后端controller方法中的形参就要书写多少个。如果请求参数比较多通过上述的方式一个参数一个参数的接收会比较繁琐。
①、简单实体对象
此时我们可以考虑将请求参数封装到一个实体类对象中。 要想完成数据封装需要遵守如下规则请求参数名与实体类的属性名相同 User类 定义在实体类Pojo中 ②、复杂实体对象 ③、小结 如果是复杂实体对象也只需按照对象层次结构关系即可接收嵌套实体类属性参数 4、数组集合参数
数组集合参数的使用场景在HTML的表单中有一个表单项是支持多选的(复选框)可以提交选择的多个值 多个值是怎么提交的呢其实多个值也是一个一个逐个提交的
①、数组 ②、集合 requestparam适用场景 **RequestParam注解的使用场景** 1- **绑定单个请求参数** - 当你需要从HTTP请求通常是GET或POST请求中获取单个参数时可以使用RequestParam。 例如在一个处理用户登录的方法中如果前端通过表单提交了用户的用户名和密码后端方法可以使用RequestParam来获取这些参数。 java RequestMapping(/login) public String login(RequestParam(username) String username, RequestParam(password) String password) { // 在这里进行登录验证逻辑 return loginSuccess; } - 这里RequestParam(username)和RequestParam(password)分别用于获取名为“username”和“password”的请求参数并将其绑定到对应的方法参数上。 2- **参数非必需情况** - RequestParam还可以处理参数不是必需的情况。你可以通过设置required属性来指定参数是否必需。例如 java RequestMapping(/search) public String search(RequestParam(name keyword, required false) String keyword) { if (keyword! null) { // 进行搜索逻辑 } return searchResult; } - 在这个例子中“keyword”参数不是必需的。如果前端没有传递“keyword”参数keyword方法参数将为null。 3- **设置默认值** - 当参数不是必需且你希望在参数未传递时给方法参数赋予一个默认值时可以使用RequestParam的defaultValue属性。 例如 java RequestMapping(/page) public String showPage(RequestParam(name pageNum, defaultValue 1) int pageNum) { // 根据pageNum进行分页逻辑 return pageContent; } - 这里如果前端没有传递“pageNum”参数pageNum方法参数将默认为1。 4- **绑定复杂类型列表或数组** - 除了单个参数RequestParam还可以用于绑定列表或数组类型的参数。例如当你希望从前端获取多个同名参数的值时比如多选框的值 java RequestMapping(/select) public String selectOptions(RequestParam(selectedOptions) ListString selectedOptions) { // 处理选中的选项 return selectionResult; } - 前端可能通过?selectedOptionsoption1selectedOptionsoption2这种形式传递参数后端使用RequestParam将这些同名参数值绑定到ListString中。 一个细节点 Array需要toString转换为字符串 而 List不需要 是因为 1. **String[]数组的情况** - 在Java中System.out.println()方法没有对数组类型进行特殊的重载处理。当直接传递一个数组给System.out.println()时它实际上是调用Object类的toString()方法。对于数组来说Object类的toString()方法返回的是一个类似[类型哈希码]的字符串这并不是我们想要的数组内容的表示形式。 - 而Arrays.toString()方法是java.util.Arrays类提供的一个工具方法它专门用于将数组转换为一个包含数组元素的字符串格式为[元素1, 元素2,...]。所以当我们有一个String[]类型的参数时需要使用Arrays.toString()来将数组内容以可读的形式输出。 2. **ListString列表的情况** - 对于List类型java.util.List继承自java.util.Collection而Collection类已经重写了toString()方法。当调用System.out.println()输出一个List对象时实际上调用的是List类重写后的toString()方法。 - 重写后的toString()方法会按照[元素1, 元素2,...]的格式返回列表中的元素。所以当我们有一个ListString类型的参数时可以直接将其传递给System.out.println()就能得到列表内容的可读形式输出。 5、日期参数
因为日期的格式多种多样如2022-12-12 10:05:45 、2022/12/12 10:05:45那么对于日期类型的参数在进行封装的时候需要通过DateTimeFormat注解以及其pattern属性来设置日期的格式 两个细节点 1. **关于日期时间格式化模式中的大小写** - 在SimpleDateFormat用于格式化java.util.Date类型以及相关的日期时间格式化模式中MM和HH大写是有特定含义的并且在DateTimeFormat注解用于格式化java.time.LocalDateTime等类型时也遵循类似规则。 - MM用于表示月份是月份的数字表示范围是01 - 12。如果写成mm则表示分钟范围是00 - 59。 - HH用于表示24小时制的小时数范围是00 - 23。如果写成hh则表示12小时制的小时数范围是01 - 12。 所以为了准确表示你想要的日期时间格式部分这些字母的大小写是很重要的。 2. **关于LocalDateTime输出中的T** - LocalDateTime是Java 8引入的日期时间类型它遵循ISO 8601日期时间格式标准。在ISO 8601格式中日期和时间部分是通过T来分隔的。 - 例如2024 - 12 - 08T15:25:05表示2024年12月8日15时25分05秒。T只是一个标准的分隔符用于清晰地区分日期部分yyyy - MM - dd和时间部分HH:mm:ss。当你将LocalDateTime对象打印输出或者序列化为字符串时就会按照这种标准格式来显示方便在不同系统和应用之间进行日期时间信息的统一表示和交换。 6、JSON参数
在前后端进行交互时如果是比较复杂的参数前后端通过会使用JSON格式的数据进行传输。 JSON是开发中最常用的前后端数据交互方式
①、Postman在发送请求时如何传递json格式的请求参数 ②、在服务端的controller方法中如何接收json格式的请求参数
服务端Controller方法接收JSON格式数据
- 传递json格式的参数在Controller中会使用实体类进行封装。
- 封装规则JSON数据键名与形参对象属性名相同定义POJO类型形参即可接收参数。需要使用 RequestBody标识。
- RequestBody注解将JSON数据映射到形参的实体类对象中JSON中的key和实体类中的属性名保持一致 requestbody注解 1. **处理HTTP请求体中的数据时使用RequestBody** - **接收JSON数据** - 在现代Web开发中当客户端如前端应用或者其他外部系统通过POST、PUT等请求方法发送JSON数据给后端服务时后端通常使用RequestBody来接收和解析这些数据。例如在一个基于Spring Boot的Web应用中有一个用户注册的功能。前端会收集用户的姓名、年龄、邮箱等信息并将这些信息组装成一个JSON对象像这样 json { name: John Doe, age: 30, email: johndoeexample.com } 后端的Spring Boot控制器方法可以这样接收数据 java RequestMapping(value /register, method RequestMethod.POST) public String registerUser(RequestBody User user) { // 将用户信息保存到数据库等操作 return success; } 这里假设User是一个Java类包含name、age、email等属性。RequestBody注解会自动将JSON数据解析并绑定到User对象的相应属性上。 - **接收XML数据虽然现在JSON更常用** - 如果客户端发送XML格式的数据也可以使用RequestBody来处理。例如假设客户端发送如下XML数据来表示一个订单 xml order productId 123 /productId quantity 5 /quantity customerName Alice /customerName /order 后端可以定义一个Order类来匹配XML数据的结构并且在控制器方法中使用RequestBody来接收 java RequestMapping(value /placeOrder, method RequestMethod.POST) public String placeOrder(RequestBody Order order) { // 处理订单逻辑如保存订单到数据库等 return orderPlaced; } - **复杂数据类型传输** - 当需要传输复杂的数据结构如包含嵌套对象或者集合的对象时RequestBody非常有用。例如一个包含多个商品信息的购物车对象其中每个商品对象又包含商品名称、价格、数量等信息。前端将购物车数据以JSON格式发送 json { cartId: C001, items: [ { productName: Book, price: 20.0, quantity: 2 }, { productName: Pen, price: 3.0, quantity: 5 } ] } 后端可以通过RequestBody接收并解析这个复杂的购物车对象 java RequestMapping(value /checkout, method RequestMethod.POST) public String checkout(RequestBody ShoppingCart cart) { // 计算总价、处理库存等结账逻辑 return checkoutSuccess; } requestmapping注解 RequestMapping注解的基本概念和用途 RequestMapping是 Spring MVC 中用于处理请求地址映射的注解。它可以用在类和方法级别上。 RequestMapping注解的属性 value属性或path属性它们是等价的用于指定请求路径。可以是一个简单的字符串路径也可以是一个包含多个路径的数组method属性用于指定请求方法。除了RequestMethod.GET和RequestMethod.POST外还可以指定RequestMethod.PUT、RequestMethod.DELETE、RequestMethod.HEAD、RequestMethod.OPTIONS等。consumes属性用于指定请求的MIME类型媒体类型。例如consumes application/json表示该方法只处理JSON格式的请求体。produces属性用于指定响应的MIME类型。例如produces application/json表示该方法返回的响应是JSON格式。 7、路径参数
传统的开发中请求参数是放在请求体(POST请求)传递或跟在URL后面通过?keyvalue的形式传递(GET请求)
而在现在的开发中还是经常会直接在请求的URL中传递参数。例如
http://localhost:8080/user/1
http://localhost:880/user/1/0
上述的这种传递请求参数的形式就称之为 路径参数
①、传递单个参数 ②、传递多个参数
和传递单个参数方法相同无非就是多写一个形参和注解需要注意的是形参要和传递的参数相同才能接收成功 8、相关代码
RequestController.java
package com.example.demo.controller;import com.example.demo.pojo.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;RestController
public class RequestController {/*RequestMapping(/simpleParam)public String simpleParam(String name, int age) {System.out.println(name age);return OK;}*///1 简单参数RequestMapping(/simpleParam)public String simpleParam(RequestParam(namename,required false) String username, int age) {System.out.println(username age);return OK;}//2 实体参数 简单实体参数 复杂实体参数RequestMapping(/simplePojo)public String simplePojo(User user) {System.out.println(user);return OK;}RequestMapping(/complexPojo)public String complexPojo(User user) {System.out.println(user);return OK;}//3 数组参数 集合参数RequestMapping(/arrayParam)public String arrayParam(String[] hobby) {System.out.println(Arrays.toString(hobby));return OK;}RequestMapping(/listParam)public String listParam(RequestParam ListString hobby) {System.out.println(hobby);return OK;}//4 日期参数RequestMapping(/dateParam)public String dateParam(DateTimeFormat(pattern yyyy-MM-dd HH:mm:ss) LocalDateTime updateTime) {System.out.println(updateTime);return OK;}//5 json参数RequestMapping(/jsonParam)public String jsonParam(RequestBody User user) {System.out.println(user);return OK;}//6 路径参数RequestMapping(/path/{id})public String pathParam(PathVariable Integer id) {System.out.println(id);return OK;}RequestMapping(/path/{id}/{name})public String pathParam(PathVariable Integer id, PathVariable String name) {System.out.println(id name);return OK;}
}二、响应
1、ResponseBody
在我们前面所编写的controller方法中都已经设置了响应数据那controller方法中的return的结果怎么就可以响应给浏览器呢 RestController是两个注解的组合RestController Controller ResponseBody 2、统一响应结果
大家有没有发现一个问题我们在前面所编写的这些Controller方法中返回值各种各样没有任何的规范 如果我们开发一个大型项目项目中controller方法将成千上万使用上述方式将造成整个项目难以维护。那在真实的项目开发中是什么样子的呢
①、定义一个统一响应结构类 Result
在真实的项目开发中无论是哪种方法我们都会定义一个统一的返回结果。方案如下 前端只需要按照统一格式的返回结果进行解析(仅一种解析方案)就可以拿到数据 定义在一个实体类Result来包含以上信息代码如下 public class Result { private Integer code;//响应码1 代表成功; 0 代表失败 private String msg; //响应码 描述字符串 private Object data; //返回的数据 public Result() { } public Result(Integer code, String msg, Object data) { this.code code; this.msg msg; this.data data; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg msg; } public Object getData() { return data; } public void setData(Object data) { this.data data; } //增删改 成功响应(不需要给前端返回数据) public static Result success(){ return new Result(1,success,null); } //查询 成功响应(把查询结果做为返回数据响应给前端) public static Result success(Object data){ return new Result(1,success,data); } //失败响应 public static Result error(String msg){ return new Result(0,msg,null); } } 效果展示 ②、小结