最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring MVC 接口 ResponseBodyAdvice 及其應(yīng)用最佳實(shí)踐記錄

 更新時(shí)間:2025年04月15日 09:56:37   作者:法天象地 日月同輝  
ResponseBodyAdvice?是 Spring MVC 提供的一個(gè)強(qiáng)大接口,允許你在響應(yīng)體被寫入 HTTP 響應(yīng)之前對(duì)其進(jìn)行全局處理,下面我將全面介紹它的工作原理、使用場(chǎng)景和最佳實(shí)踐,感興趣的朋友一起看看吧

ResponseBodyAdvice 是 Spring MVC 提供的一個(gè)強(qiáng)大接口,允許你在響應(yīng)體被寫入 HTTP 響應(yīng)之前對(duì)其進(jìn)行全局處理。

下面我將全面介紹它的工作原理、使用場(chǎng)景和最佳實(shí)踐。

基本概念

接口定義

public interface ResponseBodyAdvice<T> {
    boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
    @Nullable
    T beforeBodyWrite(@Nullable T body, MethodParameter returnType, 
                     MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
                     ServerHttpRequest request, ServerHttpResponse response);
}

核心方法

supports()

  • 決定是否對(duì)該方法的返回值應(yīng)用 advice
  • 參數(shù):
    • returnType: 控制器方法的返回類型信息
    • converterType: 將用于序列化響應(yīng)體的消息轉(zhuǎn)換器類型

beforeBodyWrite()

  • 在消息轉(zhuǎn)換器寫入響應(yīng)體之前對(duì)其進(jìn)行處理
  • 參數(shù):
    • body: 控制器返回的原始響應(yīng)體
    • 其他參數(shù)與 supports() 相同
    • request/response: 當(dāng)前請(qǐng)求和響應(yīng)對(duì)象

典型應(yīng)用場(chǎng)景

1. 統(tǒng)一響應(yīng)封裝

最常見的用途是將所有控制器的返回值包裝成統(tǒng)一格式:

@RestControllerAdvice
public class UnifiedResponseAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, 
                                MediaType selectedContentType,
                                Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof ApiResponse) {
            return body;
        }
        return ApiResponse.success(body);
    }
}

2. 響應(yīng)數(shù)據(jù)脫敏

對(duì)敏感數(shù)據(jù)進(jìn)行自動(dòng)處理:

@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, 
                            MediaType selectedContentType,
                            Class<? extends HttpMessageConverter<?>> selectedConverterType,
                            ServerHttpRequest request, ServerHttpResponse response) {
    if (body instanceof UserInfo) {
        UserInfo user = (UserInfo) body;
        user.setIdCard(desensitize(user.getIdCard()));
    }
    return body;
}

3. 響應(yīng)數(shù)據(jù)緩存

緩存特定響應(yīng):

@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, 
                            MediaType selectedContentType,
                            Class<? extends HttpMessageConverter<?>> selectedConverterType,
                            ServerHttpRequest request, ServerHttpResponse response) {
    if (request.getURI().getPath().contains("/api/cacheable")) {
        cacheManager.put(generateCacheKey(request), body);
    }
    return body;
}

高級(jí)用法與最佳實(shí)踐

1. 精確控制應(yīng)用范圍

通過(guò) supports() 方法精確控制哪些方法需要處理:

@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    // 只處理標(biāo)注了@ResponseWrap注解的方法
    return returnType.hasMethodAnnotation(ResponseWrap.class);
    // 或者排除特定包下的控制器
    // return !returnType.getDeclaringClass().getPackage().getName().startsWith("org.springdoc");
}

2. 處理特殊情況 處理String類型返回值

@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, 
                            MediaType selectedContentType,
                            Class<? extends HttpMessageConverter<?>> selectedConverterType,
                            ServerHttpRequest request, ServerHttpResponse response) {
    if (body instanceof String) {
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        return objectMapper.writeValueAsString(ApiResponse.success(body));
    }
    // 其他處理...
}

處理文件下載等非JSON響應(yīng)

@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    // 排除文件下載等場(chǎng)景
    return !ResourceHttpMessageConverter.class.isAssignableFrom(converterType);
}

3. 性能優(yōu)化

@RestControllerAdvice
public class CustomResponseAdvice implements ResponseBodyAdvice<Object> {
    // 重用ObjectMapper實(shí)例
    private static final ObjectMapper objectMapper = new ObjectMapper();
    // 預(yù)定義的成功響應(yīng)
    private static final ApiResponse<?> EMPTY_SUCCESS = ApiResponse.success(null);
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, 
                                MediaType selectedContentType,
                                Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                ServerHttpRequest request, ServerHttpResponse response) {
        if (body == null) {
            return EMPTY_SUCCESS;
        }
        // 其他處理...
    }
}

常見問(wèn)題解決方案

1. 與Swagger的兼容性問(wèn)題

@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    // 排除Swagger相關(guān)的控制器
    return !returnType.getDeclaringClass().getPackage().getName().startsWith("springfox.documentation");
}

2. 循環(huán)引用問(wèn)題

當(dāng)包裝的對(duì)象存在循環(huán)引用時(shí),需要在ObjectMapper中配置:

objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false);

3. 異常處理

雖然ResponseBodyAdvice不處理異常,但可以與@ExceptionHandler配合使用:

@ExceptionHandler(Exception.class)
public ApiResponse<?> handleException(Exception e) {
    return ApiResponse.failure(e.getMessage());
}

完整示例

@RestControllerAdvice
public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {
    private final ObjectMapper objectMapper;
    public GlobalResponseAdvice(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 排除Swagger和Actuator端點(diǎn)
        return !(returnType.getDeclaringClass().getName().contains("springfox") || 
                returnType.getDeclaringClass().getName().contains("org.springframework.boot.actuate"));
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, 
                                MediaType selectedContentType,
                                Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                ServerHttpRequest request, ServerHttpResponse response) {
        // 非JSON響應(yīng)不處理
        if (!selectedContentType.includes(MediaType.APPLICATION_JSON)) {
            return body;
        }
        // 已經(jīng)是包裝類型不處理
        if (body instanceof ApiResponse) {
            return body;
        }
        // 處理String類型返回值
        if (body instanceof String) {
            try {
                response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
                return objectMapper.writeValueAsString(ApiResponse.success(body));
            } catch (JsonProcessingException e) {
                throw new RuntimeException("JSON序列化失敗", e);
            }
        }
        // 空值處理
        if (body == null) {
            return ApiResponse.success();
        }
        // 默認(rèn)包裝
        return ApiResponse.success(body);
    }
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class ApiResponse<T> {
        private int code;
        private String message;
        private T data;
        private long timestamp = System.currentTimeMillis();
        public static <T> ApiResponse<T> success() {
            return new ApiResponse<>(200, "success", null);
        }
        public static <T> ApiResponse<T> success(T data) {
            return new ApiResponse<>(200, "success", data);
        }
    }
}

通過(guò)合理使用ResponseBodyAdvice,你可以實(shí)現(xiàn)響應(yīng)處理的集中管理,使代碼更加整潔和一致。

到此這篇關(guān)于Spring MVC 接口 ResponseBodyAdvice 及其應(yīng)用最佳實(shí)踐記錄的文章就介紹到這了,更多相關(guān)Spring MVC ResponseBodyAdvice 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring中@ControllerAdvice注解的用法解析

    Spring中@ControllerAdvice注解的用法解析

    這篇文章主要介紹了Spring中@ControllerAdvice注解的用法解析,顧名思義,@ControllerAdvice就是@Controller 的增強(qiáng)版,@ControllerAdvice主要用來(lái)處理全局?jǐn)?shù)據(jù),一般搭配@ExceptionHandler、@ModelAttribute以及@InitBinder使用,需要的朋友可以參考下
    2023-10-10
  • 使用eclipse打包Maven項(xiàng)目的實(shí)現(xiàn)步驟

    使用eclipse打包Maven項(xiàng)目的實(shí)現(xiàn)步驟

    本文主要介紹了使用eclipse打包Maven項(xiàng)目的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • java web如何解決瞬間高并發(fā)

    java web如何解決瞬間高并發(fā)

    這篇文章主要為大家詳細(xì)介紹了java web解決瞬間高并發(fā)的策略,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 每日幾道java新手入門面試題,通往自由的道路

    每日幾道java新手入門面試題,通往自由的道路

    這篇文章主要為大家分享了最有價(jià)值的是幾道java面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對(duì)hashCode方法的設(shè)計(jì)、垃圾收集的堆和代進(jìn)行剖析,感興趣的小伙伴們可以參考一下
    2021-07-07
  • DTD驗(yàn)證xml格式的三種方式詳解

    DTD驗(yàn)證xml格式的三種方式詳解

    這篇文章主要介紹了DTD驗(yàn)證xml格式的三種方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • SpringBoot加載不出來(lái)application.yml文件的解決方法

    SpringBoot加載不出來(lái)application.yml文件的解決方法

    這篇文章主要介紹了SpringBoot加載不出來(lái)application.yml文件的解決方法,文中通過(guò)示例代碼講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作有一定的幫助,需要的朋友跟著小編來(lái)一起來(lái)學(xué)習(xí)吧
    2023-12-12
  • 使用SpringBoot實(shí)現(xiàn)Redis多數(shù)據(jù)庫(kù)緩存

    使用SpringBoot實(shí)現(xiàn)Redis多數(shù)據(jù)庫(kù)緩存

    在我的系統(tǒng)中,為了優(yōu)化用戶行為數(shù)據(jù)的存儲(chǔ)與訪問(wèn)效率,我引入了Redis緩存,并將數(shù)據(jù)分布在不同的Redis數(shù)據(jù)庫(kù)中,通過(guò)這種方式,可以減少單一數(shù)據(jù)庫(kù)的負(fù)載,提高系統(tǒng)的整體性能,所以本文給大家介紹了使用SpringBoot實(shí)現(xiàn)Redis多數(shù)據(jù)庫(kù)緩存,需要的朋友可以參考下
    2024-06-06
  • java的NIO管道用法代碼分享

    java的NIO管道用法代碼分享

    這篇文章主要介紹了java的NIO管道用法代碼分享,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • hibernate查詢緩存詳細(xì)分析

    hibernate查詢緩存詳細(xì)分析

    這篇文章主要介紹了hibernate查詢緩存詳細(xì)分析,包括查詢緩存配置方法及關(guān)閉二級(jí)緩存的詳細(xì)介紹,需要的朋友參考下本文吧
    2017-09-09
  • Java中Array、List、ArrayList的區(qū)別及說(shuō)明

    Java中Array、List、ArrayList的區(qū)別及說(shuō)明

    這篇文章主要介紹了Java中Array、List、ArrayList的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07

最新評(píng)論

台江县| 武强县| 海盐县| 富民县| 高邑县| 漾濞| 柳林县| 洮南市| 盐边县| 禄丰县| 鸡泽县| 延川县| 称多县| 黄大仙区| 承德县| 天津市| 宝鸡市| 剑河县| 浦北县| 磐安县| 卢湾区| 彰化市| 晋宁县| 来凤县| 鸡西市| 石柱| 民丰县| 西平县| 顺义区| 永城市| 武邑县| 当阳市| 龙胜| 南乐县| 广西| 襄城县| 喀喇| 芜湖县| 昭苏县| 建德市| 舟曲县|