首頁 > 軟體

詳解SpringBoot客製化@ResponseBody註解返回的Json格式

2020-11-06 12:05:47

 1、引言

在SpringMVC的使用中,後端與前端的互動一般是使用Json格式進行資料傳輸,SpringMVC的@ResponseBody註解可以很好的幫助我們進行轉換,但是後端返回資料給前端往往都有約定固定的格式,這時候我們在後端返回的時候都要組拼成固定的格式,每次重複的操作非常麻煩。

2、SpringMVC對@ResponseBody的處理

SpringMVC處理@ResponseBody註解宣告的Controller是使用預設的.RequestResponseBodyMethodProcessor類來實現,RequestResponseBodyMethodProcessor類實現了HandlerMethodReturnValueHandler介面並實現了介面中的supportsReturnType()和handleReturnValue()方法。

/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.method.support;

import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.context.request.NativeWebRequest;

/**
 * Strategy interface to handle the value returned from the invocation of a
 * handler method .
 *
 * @author Arjen Poutsma
 * @since 3.1
 * @see HandlerMethodArgumentResolver
 */
public interface HandlerMethodReturnValueHandler {

 /**
 * Whether the given {@linkplain MethodParameter method return type} is
 * supported by this handler.
 * @param returnType the method return type to check
 * @return {@code true} if this handler supports the supplied return type;
 * {@code false} otherwise
 */
 boolean supportsReturnType(MethodParameter returnType);

 /**
 * Handle the given return value by adding attributes to the model and
 * setting a view or setting the
 * {@link ModelAndViewContainer#setRequestHandled} flag to {@code true}
 * to indicate the response has been handled directly.
 * @param returnValue the value returned from the handler method
 * @param returnType the type of the return value. This type must have
 * previously been passed to {@link #supportsReturnType} which must
 * have returned {@code true}.
 * @param mavContainer the ModelAndViewContainer for the current request
 * @param webRequest the current request
 * @throws Exception if the return value handling results in an error
 */
 void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
  ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;

}

3、實現思路

知道@ResponseBody是由RequestResponseBodyMethodProcessor進行處理的,這時候我們可以自己定義一個處理返回資料的Handler來實現我們的客製化化Json格式資料返回,但是如果直接把我們客製化的Handler加入到SpringMVC的ReturnValueHandlers中,因為我們客製化的Handler在RequestResponseBodyMethodProcessor之後,所以我們客製化的Handler還是不會生效,這時候我們可以想辦法把RequestResponseBodyMethodProcessor替換成我們客製化的Handler。

4、程式碼實現

4.1、客製化Json返回格式實體

package com.autumn.template;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

/**
 * JSON資訊互動物件模板
 * @Author Autumn、
 * @Date 2019/4/8 23:46
 * @Description
 */
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Result implements BaseBean {

  ......(這裡只展示一些必要欄位)
  /** 響應碼 */
  private Integer code;
  /** 響應資訊 */
  private String message;
  /** 資料 */
  private Object data;
  /** 請求地址 */
  private String url;

  ......
}

4.2、定義客製化Json返回格式Handler

package com.autumn.component.handler;

import com.autumn.template.Result;

import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 * 統一處理ResponseBody資料格式
 * @Author: Autumn、
 * @Date: 2019/4/24 23:59
 * @Description:
 **/
public class ResultWarpReturnValueHandler implements HandlerMethodReturnValueHandler {

  private final HandlerMethodReturnValueHandler delegate;

  /** 委託 */
  public ResultWarpReturnValueHandler(HandlerMethodReturnValueHandler delegate) {
    this.delegate = delegate;
  }

  /**
   * 判斷返回型別是否需要轉成字串返回
   * @param returnType 方法返回型別
   * @return 需要轉換返回true,否則返回false
   */
  @Override
  public boolean supportsReturnType(MethodParameter returnType) {
    return delegate.supportsReturnType(returnType);
  }

  /**
   * 返回值轉換
   */
  @Override
  public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
   // 委託SpringMVC預設的RequestResponseBodyMethodProcessor進行序列化
    delegate.handleReturnValue(returnValue instanceof Result ? returnValue : Result.succeed(returnValue), returnType, mavContainer, webRequest);
  }
}

4.3、替換預設的RequestResponseBodyMethodProcessor

package com.autumn.config;

import com.autumn.component.handler.ResultWarpReturnValueHandler;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import java.util.ArrayList;
import java.util.List;

import lombok.extern.slf4j.Slf4j;

/**
 * 替換預設的RequestResponseBodyMethodProcessor
 * @Author Autumn、
 * @Date 2019/4/8 23:46
 * @Description
 */
@Slf4j
@Configuration
@EnableCaching
public class ApplicationContext implements WebMvcConfigurer, InitializingBean {

  @Autowired(required = false)
  private RequestMappingHandlerAdapter adapter;

  @Override
  public void afterPropertiesSet() throws Exception {
    // 獲取SpringMvc的ReturnValueHandlers
    List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers();
    // 新建一個List來儲存替換後的Handler的List
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(returnValueHandlers);
    // 迴圈遍歷找出RequestResponseBodyMethodProcessor
    for (HandlerMethodReturnValueHandler handler : handlers) {
      if (handler instanceof RequestResponseBodyMethodProcessor) {
       // 建立客製化的Json格式處理Handler
        ResultWarpReturnValueHandler decorator = new ResultWarpReturnValueHandler(handler);
        // 使用客製化的Json格式處理Handler替換原有的RequestResponseBodyMethodProcessor
        int index = handlers.indexOf(handler);
        handlers.set(index, decorator);
        break;
      }
    }
    // 重新設定SpringMVC的ReturnValueHandlers
    adapter.setReturnValueHandlers(handlers);
  }
}

5、總結

至此完成了客製化@ResponseBody註解返回的Json格式,在Controller中返回任何的字串都可以客製化成為我們想要的Json格式。此外SpringMVC還提供了非常多的Handler介面來進行Controller的增強,可以使用此思路對引數等進行客製化化。

到此這篇關於詳解SpringBoot客製化@ResponseBody註解返回的Json格式的文章就介紹到這了,更多相關SpringBoot @ResponseBody返回Json內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com