<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot 響應(yīng) json 數(shù)據(jù)的后端源碼處理流程

          共 10291字,需瀏覽 21分鐘

           ·

          2024-04-12 00:15

          今天微信群里一位網(wǎng)友拋出了一個問題,我這里花幾分鐘時間給大家嘮叨嘮叨。

          我們先回憶一下,在 Spring Boot 中,處理 JSON 響應(yīng)的流程通常涉及的幾個代碼開發(fā)步驟。

          1. 定義數(shù)據(jù)模型:首先,你需要定義一個或多個 Java 類來表示你想要序列化或反序列化的數(shù)據(jù)。這些類通常使用 @Getter@Setter 注解來自動生成 getter 和 setter 方法,或者使用 Lombok 庫來簡化代碼。
          public class User {
             private String name;
             private int age;

             // Getters and setters...
          }
          1. 配置 Spring Boot 應(yīng)用程序:確保你的 application.propertiesapplication.yml 文件中包含了正確的配置,以便 Spring Boot 能夠自動配置 JSON 處理。默認情況下,Spring Boot 配置了 Jackson 或者 Gson 作為 JSON 序列化和反序列化的工具。
          # application.properties
          spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
          1. 創(chuàng)建控制器:創(chuàng)建一個或多個控制器(Controller)來處理 HTTP 請求。在控制器中,你可以定義路由(endpoints)和處理方法(handler methods),這些方法會返回 JSON 響應(yīng)。
          @RestController
          public class UserController {

             @GetMapping("/users")
             public List<User> getAllUsers() {
                 // ... 獲取用戶列表
                 return users;
             }

             @PostMapping("/users")
             public User createUser(@RequestBody User user) {
                 // ... 創(chuàng)建用戶
                 return user;
             }
          }
          1. 使用注解處理請求和響應(yīng):在控制器方法中,使用 @GetMapping、@PostMapping 等注解來處理不同類型的 HTTP 請求。使用 @RequestBody 注解來接收 JSON 格式的請求體,使用 @ResponseBody@RestController 注解來指示方法的返回值應(yīng)該被序列化為 JSON。

          2. 序列化和反序列化:Spring Boot 會自動處理 JSON 的序列化和反序列化。當你返回一個對象時,Spring Boot 會使用配置的 JSON 序列化器(如 Jackson)將其轉(zhuǎn)換為 JSON 字符串。當客戶端發(fā)送 JSON 數(shù)據(jù)時,Spring Boot 會使用 JSON 反序列化器將 JSON 字符串轉(zhuǎn)換為 Java 對象。

          3. 處理異常:在開發(fā)過程中,可能會遇到數(shù)據(jù)驗證失敗、資源找不到等異常情況。你可以使用 @ExceptionHandler 注解來處理這些異常,并返回適當?shù)?HTTP 狀態(tài)碼和 JSON 響應(yīng)體。

          @ExceptionHandler(RuntimeException.class)
          @ResponseStatus(HttpStatus.BAD_REQUEST)
          public String handleRuntimeException(RuntimeException ex
          {
             return ex.getMessage();
          }
          1. 測試:最后,編寫單元測試和集成測試來確保你的控制器方法按預(yù)期工作,并且返回的 JSON 數(shù)據(jù)是正確的。

          通過以上步驟,我們就可以在 Spring Boot 應(yīng)用程序中處理 JSON 響應(yīng)。當然,這里面有些步驟不是必須的。

          下面我們再來一起看看,SpringBoot 框架在響應(yīng) json 數(shù)據(jù)時的處理流程。

          先看一個示例代碼:

          訪問 localhost:8080/jsonTest —— 返回 json 格式的數(shù)據(jù)

          @Controller
          public class ResponseTestController {
              @ResponseBody // 標注 —— 自動返回json數(shù)據(jù)
              @GetMapping("/jsonTest")
              public Person testPerson(){
                  Person person = new Person();
                  person.setAge(20);
                  person.setUserName("Liuwanqing");
                  Pet pet = new Pet();
                  pet.setName("huahua");
                  pet.setAge("五個月");
                  person.setPet(pet);
                  return person;
              }
          }

          返回值解析原理

          SpringBoot 支持的返回值類型是由返回值解析器決定的,SpringBoot 返回值類型如下:

          ?

          ModelAndView
          Model
          View

          SpringBoot共含 15 種返回值解析器決定了其支持 15 種返回值:

          源代碼分析(debug)

          設(shè)置以下幾處斷點:

          step into —— 返回值處理器邏輯

          this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);

          先找返回值處理器

          HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);

          執(zhí)行下列代碼,找到符合要求的返回值處理器

          在眾多返回值處理器中找到符合要求的 —RequestResponseBodyMethodRrocessor
          即 RequestResponseBodyMethodRrocessor 可處理標注了 @ResponseBody 注解的返回值

          private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
              boolean isAsyncValue = this.isAsyncReturnValue(value, returnType);
              Iterator var4 = this.returnValueHandlers.iterator();

              HandlerMethodReturnValueHandler handler;
              do {
                  do {
                      if (!var4.hasNext()) {
                          return null;
                      }

                      handler = (HandlerMethodReturnValueHandler)var4.next();
                  } while(isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler));
              } while(!handler.supportsReturnType(returnType));

              return handler;
          }

          調(diào)用返回值處理器(interface HandlerMethodReturnValueHandler)處理:

          判斷是否支持這種類型的返回值,支持調(diào)用返回值處理器,調(diào)用 handleReturnValue 進行處理

          public interface HandlerMethodReturnValueHandler {
              boolean supportsReturnType(MethodParameter var1);

              void handleReturnValue(@Nullable Object var1, MethodParameter var2, ModelAndViewContainer var3, NativeWebRequest var4) throws Exception;
          }

          RequestResponseBodyMethodRrocessor工作原理

          關(guān)鍵代碼:

          public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
              mavContainer.setRequestHandled(true);
              ServletServerHttpRequest inputMessage = this.createInputMessage(webRequest);
              ServletServerHttpResponse outputMessage = this.createOutputMessage(webRequest);
              this.writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
          }

          處理返回值的方法

          使用消息轉(zhuǎn)換器(涉及內(nèi)容協(xié)商機制,請移步下文內(nèi)容協(xié)商機制)進行寫出操作,消息轉(zhuǎn)換器工作過程如下:

          ?
          1. 瀏覽器告知服務(wù)器其處理能力
          2. 服務(wù)器根據(jù)其自身能力,判斷服務(wù)器能生產(chǎn)什么樣的內(nèi)容
          3. SpringMVC 遍歷所有容器的底層 HttpMessageConverter, 看誰能處理

          內(nèi)容協(xié)商機制

          1. 內(nèi)容協(xié)商: 瀏覽器告知服務(wù)器其需要什么類型的服務(wù)類型

          瀏覽器可接受的類型:

          服務(wù)器得到瀏覽器的處理能力:

          服務(wù)器將返回內(nèi)容轉(zhuǎn)為瀏覽器能處理的形式

          2. 內(nèi)容協(xié)商原理重點源代碼

          protected List<MediaType> getProducibleMediaTypes(HttpServletRequest request, Class<?> valueClass, @Nullable Type targetType) {
              Set<MediaType> mediaTypes = (Set)request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
              if (!CollectionUtils.isEmpty(mediaTypes)) {
                  return new ArrayList(mediaTypes);
              } else if (this.allSupportedMediaTypes.isEmpty()) {
                  return Collections.singletonList(MediaType.ALL);
              } else {
                  List<MediaType> result = new ArrayList();
                  Iterator var6 = this.messageConverters.iterator();

                  while(true) {
                      while(var6.hasNext()) {
                          HttpMessageConverter<?> converter = (HttpMessageConverter)var6.next();
                          if (converter instanceof GenericHttpMessageConverter && targetType != null) {
                              if (((GenericHttpMessageConverter)converter).canWrite(targetType, valueClass, (MediaType)null)) {
                                  result.addAll(converter.getSupportedMediaTypes());
                              }
                          } else if (converter.canWrite(valueClass, (MediaType)null)) {
                              result.addAll(converter.getSupportedMediaTypes());
                          }
                      }

                      return result;
                  }
              }
          }

          HttpMessageConverters消息轉(zhuǎn)換器原理

          1. MessageConverter 規(guī)范
          1. 默認的MessageConverter
          1. 最終 MappingJackson2HttpMessageConverter 把對象轉(zhuǎn)為JSON(利用底層的jackson的objectMapper轉(zhuǎn)換的)

          總結(jié)

          ?
          1. 返回值處理器判斷是否支持這種類型的返回值( supportsReturnType)
          2. 返回值處理器調(diào)用handleReturnValue 進行處理
          3. 以 @ResponseBody 注解為例,RequestResponseBodyMethodProcessor 可以處理返回值標
          4. 最后,利用 MessageConverters 進行處理 將數(shù)據(jù)寫為json

          這個處理流程 debug 起來并不難,難在不少人想不到 debug 方法。以上,大致記住哦,面試中會被問到的。

          瀏覽 33
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费超碰网站 | 天堂在线在线 | 亚洲最大视频在线观看 | 国产黄色网页 | 五月丁香资源 |