SpringBoot?@RestControllerAdvice注解對(duì)返回值統(tǒng)一封裝的處理方法
一. 需求場(chǎng)景
如下圖所示,后臺(tái)向前臺(tái)響應(yīng)數(shù)據(jù)的時(shí)候,所有的數(shù)據(jù)都需要放入自定義的封裝Entity才返回給前臺(tái)?,F(xiàn)在想要每個(gè)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, "請(qǐng)求成功"),
FAILED(1001, "請(qǐng)求失敗"),
VALIDATE_ERROR(1002, "參數(shù)校驗(yàn)失敗"),
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, "價(jià)格異常");
private int code;
private String msg;
}
?自定義業(yè)務(wù)異常類
import lombok.Getter;
@Getter
public class BusinessException extends RuntimeException {
private int code;
private String msg;
// 手動(dòng)設(shè)置異常
public BusinessException(IStatusCode codeEnum, String message) {
// message用于用戶設(shè)置拋出錯(cuò)誤詳情
super(message);
// 狀態(tài)碼
this.code = codeEnum.getCode();
// 狀態(tài)碼配套的msg
this.msg = codeEnum.getMsg();
}
// 默認(rèn)異常使用APP_ERROR狀態(tài)碼
public BusinessException(String message) {
super(message);
this.code = BusinessCodeEnum.APP_ERROR.getCode();
this.msg = BusinessCodeEnum.APP_ERROR.getMsg();
}
}
?自定義注解,標(biāo)記該注解的方法不進(jìn)行響應(yīng)增強(qiáng)
讓我們的方法更加靈活,可以選擇增強(qiáng)封裝或者不增強(qiá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對(duì)響應(yīng)進(jìn)行增強(qiá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;
// 對(duì)指定包下面的Controller進(jìn)行增強(qiáng)
@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)
);
// 若包含其中一項(xiàng),則不進(jìn)行封裝
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串進(jìn)行返回
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被包裝之后返回給前臺(tái)

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

4.3 直接返回字符串

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

參考資料:
正規(guī)軍springboot如何處理:參數(shù)校驗(yàn)、統(tǒng)一異常、統(tǒng)一響應(yīng)
到此這篇關(guān)于SpringBoot @RestControllerAdvice注解對(duì)返回值統(tǒng)一封裝的文章就介紹到這了,更多相關(guān)SpringBoot返回值統(tǒng)一封裝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot中@RestControllerAdvice注解實(shí)現(xiàn)全局異常處理類
- springboot的統(tǒng)一異常處理,使用@RestControllerAdvice詳解
- SpringBoot項(xiàng)目中@RestControllerAdvice全局異常失效問題的解決
- SpringBoot中@RestControllerAdvice @ExceptionHandler異常統(tǒng)一處理類失效原因分析
- SpringBoot中@RestControllerAdvice注解的使用
- SpringBoot的@RestControllerAdvice作用詳解
- SpringBoot常用注解@RestControllerAdvice詳解
- SpringBoot中的@RestControllerAdvice注解詳解
- SpringBoot中@RestControllerAdvice 全局異常處理的實(shí)現(xiàn)
相關(guān)文章
Mybatis SqlSessionFactory與SqlSession詳細(xì)講解
SqlSessionFactory是MyBatis的核心類之一,其最重要的功能就是提供創(chuàng)建MyBatis的核心接口SqlSession,所以我們需要先創(chuàng)建SqlSessionFactory,為此我們需要提供配置文件和相關(guān)的參數(shù)2022-11-11
SpringBoot整合HTTPS的項(xiàng)目實(shí)踐
HTTPS的主要作用是通過SSL證書保護(hù)用戶數(shù)據(jù)的安全與隱私,增加網(wǎng)站信任度,防止數(shù)據(jù)被竊取和篡改,保護(hù)網(wǎng)站免受釣魚攻擊,本文就來介紹一下,感興趣的可以了解一下2024-10-10
詳解Mybatis攔截器安全加解密MySQL數(shù)據(jù)實(shí)戰(zhàn)
本文主要介紹了Mybatis攔截器安全加解密MySQL數(shù)據(jù)實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Java復(fù)制一個(gè)對(duì)象并且不想復(fù)制其中的空值屬性問題
這篇文章主要介紹了Java復(fù)制一個(gè)對(duì)象并且不想復(fù)制其中的空值屬性問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
解讀RabbitMQ和kafka的相同點(diǎn)和不同點(diǎn)是什么
RabbitMQ和Kafka都是消息中間件,支持分布式系統(tǒng)、高可用性和可靠性,RabbitMQ使用隊(duì)列模型,適合復(fù)雜路由場(chǎng)景;Kafka使用主題-分區(qū)模型,適合大規(guī)模數(shù)據(jù)流處理,RabbitMQ在低延遲方面表現(xiàn)更好,Kafka在高吞吐量方面表現(xiàn)更好2024-12-12
MybatisPlus創(chuàng)建時(shí)間不想用默認(rèn)值的問題
MybatisPlus通過FieldFill注解和MpMetaObjectHandler類支持自動(dòng)填充字段功能,特別地,可以設(shè)置字段在插入或更新時(shí)自動(dòng)填充創(chuàng)建時(shí)間和更新時(shí)間,但在特定場(chǎng)景下,如導(dǎo)入數(shù)據(jù)時(shí),可能需要自定義創(chuàng)建時(shí)間2024-09-09
SpringBoot實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)切換的最佳姿勢(shì)
這篇文章主要為大家詳細(xì)介紹一下SpringBoot實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)切換的最佳姿勢(shì),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-03-03

