SpringBoot?@RestControllerAdvice注解對返回值統(tǒng)一封裝的處理方法
一. 需求場景
如下圖所示,后臺向前臺響應(yīng)數(shù)據(jù)的時候,所有的數(shù)據(jù)都需要放入自定義的封裝Entity才返回給前臺。現(xiàn)在想要每個Controller中的方法將原數(shù)據(jù)直接返回,然后通過某種方法統(tǒng)一封裝處理。

二. 前期準(zhǔn)備
?獲取狀態(tài)碼的接口
public interface IStatusCode {
int getCode();
String getMsg();
}
?響應(yīng)狀態(tài)碼的枚舉類
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum ResultCodeEnum implements IStatusCode {
SUCCESS(1000, "請求成功"),
FAILED(1001, "請求失敗"),
VALIDATE_ERROR(1002, "參數(shù)校驗失敗"),
RESPONSE_PACK_ERROR(1003, "response返回包裝失敗");
private int code;
private String msg;
}
?業(yè)務(wù)狀態(tài)碼的枚舉類
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum BusinessCodeEnum implements IStatusCode {
APP_ERROR(2000, "業(yè)務(wù)異常"),
PRICE_ERROR(2001, "價格異常");
private int code;
private String msg;
}
?自定義業(yè)務(wù)異常類
import lombok.Getter;
@Getter
public class BusinessException extends RuntimeException {
private int code;
private String msg;
// 手動設(shè)置異常
public BusinessException(IStatusCode codeEnum, String message) {
// message用于用戶設(shè)置拋出錯誤詳情
super(message);
// 狀態(tài)碼
this.code = codeEnum.getCode();
// 狀態(tài)碼配套的msg
this.msg = codeEnum.getMsg();
}
// 默認異常使用APP_ERROR狀態(tài)碼
public BusinessException(String message) {
super(message);
this.code = BusinessCodeEnum.APP_ERROR.getCode();
this.msg = BusinessCodeEnum.APP_ERROR.getMsg();
}
}
?自定義注解,標(biāo)記該注解的方法不進行響應(yīng)增強
讓我們的方法更加靈活,可以選擇增強封裝或者不增強。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotControllerResponseAdvice {
}
三. 使用@RestControllerAdvice對響應(yīng)進行增強
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.Arrays;
import java.util.List;
// 對指定包下面的Controller進行增強
@RestControllerAdvice(basePackages = {"com.example.jmw.controller"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {
List<Boolean> judgeResultList = Arrays.asList(
// ?判斷相應(yīng)的類型是否為ResultVo類型
methodParameter.getParameterType().isAssignableFrom(ResultVo.class),
// ?判斷響應(yīng)的方法上是否包含 NotControllerResponseAdvice 注解
methodParameter.hasMethodAnnotation(NotControllerResponseAdvice.class)
);
// 若包含其中一項,則不進行封裝
return !judgeResultList.contains(true);
}
@Override
public Object beforeBodyWrite(Object body
, MethodParameter returnType
, MediaType selectedContentType
, Class<? extends HttpMessageConverter<?>> selectedConverterType
, ServerHttpRequest request
, ServerHttpResponse response
) {
// String類型不能直接包裝
if (returnType.getGenericParameterType().equals(String.class)) {
ObjectMapper objectMapper = new ObjectMapper();
try {
// 將數(shù)據(jù)包裝在ResultVo里后轉(zhuǎn)換為json串進行返回
return objectMapper.writeValueAsString(ResultVo.build(body));
} catch (JsonProcessingException e) {
// 拋出自定義的業(yè)務(wù)異常
throw new BusinessException(ResultCodeEnum.RESPONSE_PACK_ERROR, e.getMessage());
}
}
// 否則直接包裝成ResultVo返回
return ResultVo.build(body);
}
}
四. 效果
4.1 直接返回List
@Controller
@RequestMapping("/test12")
public class Test12Controller {
@PostMapping("/test")
@ResponseBody
public List<String> test() {
return Arrays.asList("1", "2", "3");
}
}
?List被包裝之后返回給前臺

4.2 標(biāo)記NotControllerResponseAdvice注解后返回List
?List未被包裝,直接返回數(shù)據(jù)給前臺

4.3 直接返回字符串

4.4 直接返回ResultVo類型數(shù)據(jù)
?返回的就是ResultVo類型,無需包裝,直接返回數(shù)據(jù)給前臺

參考資料:
正規(guī)軍springboot如何處理:參數(shù)校驗、統(tǒng)一異常、統(tǒng)一響應(yīng)
到此這篇關(guān)于SpringBoot @RestControllerAdvice注解對返回值統(tǒng)一封裝的文章就介紹到這了,更多相關(guān)SpringBoot返回值統(tǒng)一封裝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot中@RestControllerAdvice注解實現(xiàn)全局異常處理類
- springboot的統(tǒng)一異常處理,使用@RestControllerAdvice詳解
- SpringBoot項目中@RestControllerAdvice全局異常失效問題的解決
- SpringBoot中@RestControllerAdvice @ExceptionHandler異常統(tǒng)一處理類失效原因分析
- SpringBoot中@RestControllerAdvice注解的使用
- SpringBoot的@RestControllerAdvice作用詳解
- SpringBoot常用注解@RestControllerAdvice詳解
- SpringBoot中的@RestControllerAdvice注解詳解
- SpringBoot中@RestControllerAdvice 全局異常處理的實現(xiàn)
相關(guān)文章
Mybatis SqlSessionFactory與SqlSession詳細講解
SqlSessionFactory是MyBatis的核心類之一,其最重要的功能就是提供創(chuàng)建MyBatis的核心接口SqlSession,所以我們需要先創(chuàng)建SqlSessionFactory,為此我們需要提供配置文件和相關(guān)的參數(shù)2022-11-11
詳解Mybatis攔截器安全加解密MySQL數(shù)據(jù)實戰(zhàn)
本文主要介紹了Mybatis攔截器安全加解密MySQL數(shù)據(jù)實戰(zhàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01
Java復(fù)制一個對象并且不想復(fù)制其中的空值屬性問題
這篇文章主要介紹了Java復(fù)制一個對象并且不想復(fù)制其中的空值屬性問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
MybatisPlus創(chuàng)建時間不想用默認值的問題
MybatisPlus通過FieldFill注解和MpMetaObjectHandler類支持自動填充字段功能,特別地,可以設(shè)置字段在插入或更新時自動填充創(chuàng)建時間和更新時間,但在特定場景下,如導(dǎo)入數(shù)據(jù)時,可能需要自定義創(chuàng)建時間2024-09-09
SpringBoot實現(xiàn)數(shù)據(jù)源動態(tài)切換的最佳姿勢
這篇文章主要為大家詳細介紹一下SpringBoot實現(xiàn)數(shù)據(jù)源動態(tài)切換的最佳姿勢,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-03-03

