ResponseBodyAdvice
可以在注解@ResponseBody
將返回值處理成相應格式之前操作返回值。實現這個接口即可完成相應操作。可用于對response 數據的一些統一封裝或者加密等操作
1 ResponseBodyAdvice的簡介
ResponseBodyAdvice接口和之前記錄的RequestBodyAdvice接口類似, RequestBodyAdvice是請求到Controller之前攔截,做相應的處理操作, 而ResponseBodyAdvice是對Controller返回的{@code @ResponseBody}or a {@code ResponseEntity}
后,{@code HttpMessageConverter}
類型轉換之前攔截, 進行相應的處理操作后,再將結果返回給客戶端.
ResponseBodyAdvice的源代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
/** 數據的處理順序向下 * 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 參數類型裝換 * @return {@code true} if {@link #beforeBodyWrite} should be invoked; * {@code false} otherwise * 返回 true 則下面 beforeBodyWrite方法被調用, 否則就不調用下述方法 */ 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方法: 判斷是否要執行beforeBodyWrite方法,true為執行,false不執行. 通過該方法可以選擇哪些類或那些方法的response要進行處理, 其他的不進行處理.
- beforeBodyWrite方法: 對response方法進行具體操作處理
{@code @ResponseBody} 返回響應體, 例如List集合
{@code ResponseEntity} 返回響應實體對象,例如User對象
2 ResponseBodyAdvice的使用
1 準備一個SpringBoot項目環境
2 添加一個響應攔截類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@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接口之類的請求, 不應該再次包裝,應該直接返回 // 上述問題的解決方案: 可以在feign攔截器中,給feign請求頭中添加一個標識字段, 表示是feign請求 // 在此處攔截到feign標識字段, 則直接放行 返回body. System.out.println( "響應攔截成功" ); if (body instanceof BaseResponse) { return body; } else if (body == null ) { return BaseResponse.ok(); } else { return BaseResponse.ok(body); } } } |
3 添加一個返回包裝類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@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 添加控制類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@Controller @RequestMapping ( "/hello" ) public class HelloWorld { // 此處數據從數據庫中查詢, 案例中也可以使用偽數據代替 @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
1
2
|
User(id= 1 , username=李子柒, phone= 77777 , icon=李子柒的頭像, queryTime=Wed Oct 27 20 : 47 : 02 CST 2021 ) 響應攔截成功 |
瀏覽器訪問: http://localhost:8080/hello/list
1
2
|
[User(id= 1 , username=李子柒, phone= 77777 , icon=李子柒的頭像, queryTime=Wed Oct 27 20 : 46 : 58 CST 2021 )] 響應攔截成功 |
ps: 如果直接響應字符串返回,則會報類型轉換異常.
到此這篇關于Spring中ResponseBodyAdvice的使用的文章就介紹到這了,更多相關Spring中ResponseBodyAdvice使用內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/ABestRookie/article/details/121003742