Spring中ResponseBodyAdvice的使用詳解
ResponseBodyAdvice
可以在注解@ResponseBody
將返回值處理成相應(yīng)格式之前操作返回值。實現(xiàn)這個接口即可完成相應(yīng)操作??捎糜趯esponse 數(shù)據(jù)的一些統(tǒng)一封裝或者加密等操作
1 ResponseBodyAdvice的簡介
ResponseBodyAdvice接口和之前記錄的RequestBodyAdvice接口類似, RequestBodyAdvice是請求到Controller之前攔截,做相應(yīng)的處理操作, 而ResponseBodyAdvice是對Controller返回的{@code @ResponseBody}or a {@code ResponseEntity}
后,{@code HttpMessageConverter}
類型轉(zhuǎn)換之前攔截, 進(jìn)行相應(yīng)的處理操作后,再將結(jié)果返回給客戶端.
ResponseBodyAdvice的源代碼:
/** 數(shù)據(jù)的處理順序向下 * Allows customizing the response after the execution of an {@code @ResponseBody} * or a {@code ResponseEntity} controller method but before the body is written * with an {@code HttpMessageConverter}. * * <p>Implementations may be registered directly with * {@code RequestMappingHandlerAdapter} and {@code ExceptionHandlerExceptionResolver} * or more likely annotated with {@code @ControllerAdvice} in which case they * will be auto-detected by both. * * @author Rossen Stoyanchev * @since 4.1 * @param <T> the body type */ public interface ResponseBodyAdvice<T> { /** * Whether this component supports the given controller method return type * and the selected {@code HttpMessageConverter} type. * @param returnType the return type 方法返回的類型 * @param converterType the selected converter type 參數(shù)類型裝換 * @return {@code true} if {@link #beforeBodyWrite} should be invoked; * {@code false} otherwise * 返回 true 則下面 beforeBodyWrite方法被調(diào)用, 否則就不調(diào)用下述方法 */ boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType); /** * Invoked after an {@code HttpMessageConverter} is selected and just before * its write method is invoked. * @param body the body to be written * @param returnType the return type of the controller method * @param selectedContentType the content type selected through content negotiation * @param selectedConverterType the converter type selected to write to the response * @param request the current request * @param response the current response * @return the body that was passed in or a modified (possibly new) instance */ @Nullable T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response); }
說明:
- supports方法: 判斷是否要執(zhí)行beforeBodyWrite方法,true為執(zhí)行,false不執(zhí)行. 通過該方法可以選擇哪些類或那些方法的response要進(jìn)行處理, 其他的不進(jìn)行處理.
- beforeBodyWrite方法: 對response方法進(jìn)行具體操作處理
{@code @ResponseBody} 返回響應(yīng)體, 例如List集合
{@code ResponseEntity} 返回響應(yīng)實體對象,例如User對象
2 ResponseBodyAdvice的使用
1 準(zhǔn)備一個SpringBoot項目環(huán)境
2 添加一個響應(yīng)攔截類
@ControllerAdvice public class BaseResponseBodyAdvice implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter returnType, Class converterType) { return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { // 遇到feign接口之類的請求, 不應(yīng)該再次包裝,應(yīng)該直接返回 // 上述問題的解決方案: 可以在feign攔截器中,給feign請求頭中添加一個標(biāo)識字段, 表示是feign請求 // 在此處攔截到feign標(biāo)識字段, 則直接放行 返回body. System.out.println("響應(yīng)攔截成功"); if (body instanceof BaseResponse) { return body; } else if (body == null) { return BaseResponse.ok(); } else { return BaseResponse.ok(body); } } }
3 添加一個返回包裝類
@Data @AllArgsConstructor @NoArgsConstructor public class BaseResponse<T> { private T data; private int status = 200; private String message; private long srvTime = System.currentTimeMillis(); public BaseResponse(String message) { this.message = message; } public BaseResponse<T> setData(T data) { this.data = data; return this; } public static <T> BaseResponse<T> ok() { return new BaseResponse<>("操作成功"); } public static <T> BaseResponse<T> ok(T data) { return new BaseResponse<T>("操作成功").setData(data); } }
4 添加控制類
@Controller @RequestMapping("/hello") public class HelloWorld { // 此處數(shù)據(jù)從數(shù)據(jù)庫中查詢, 案例中也可以使用偽數(shù)據(jù)代替 @Autowired private UserMapper userMapper; // {@code ResponseEntity} 案列 @GetMapping("/one") @ResponseBody public User one() { List<User> users = userMapper.selectAll(); System.out.println(users.get(0)); return users.get(0); } // {@code @ResponseBody} 案列 @GetMapping("/list") @ResponseBody public List<User> list() { List<User> users = userMapper.selectAll(); System.out.println(users); return users; } }
5 接口測試
瀏覽器訪問: http://localhost:8080/hello/one
User(id=1, username=李子柒, phone=77777, icon=李子柒的頭像, queryTime=Wed Oct 27 20:47:02 CST 2021) 響應(yīng)攔截成功
瀏覽器訪問: http://localhost:8080/hello/list
[User(id=1, username=李子柒, phone=77777, icon=李子柒的頭像, queryTime=Wed Oct 27 20:46:58 CST 2021)] 響應(yīng)攔截成功
ps: 如果直接響應(yīng)字符串返回,則會報類型轉(zhuǎn)換異常.
到此這篇關(guān)于Spring中ResponseBodyAdvice的使用的文章就介紹到這了,更多相關(guān)Spring中ResponseBodyAdvice使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring中@RestController和@Controller的區(qū)別小結(jié)
@RestController和@Controller這兩個注解用于創(chuàng)建Web應(yīng)用程序的控制器類,那么這兩個注解有哪些區(qū)別,本文就來介紹一下,并用示例代碼說明,感興趣的可以了解一下2023-09-09springboot使用spring-data-jpa操作MySQL數(shù)據(jù)庫
這篇文章主要介紹了springboot使用spring-data-jpa操作MySQL數(shù)據(jù)庫,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07SpringBoot+SpringCache實現(xiàn)兩級緩存(Redis+Caffeine)
這篇文章主要介紹了SpringBoot+SpringCache實現(xiàn)兩級緩存(Redis+Caffeine),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04