如果你正在尋找一種方法來規范化你的RESTful API的返回值,那么這篇文章將是你的理想選擇。通過閱讀這篇文章,你將了解到如何使用Spring ResponseBodyAdvice來改善你的API設計和實現。
為什么要統一接口返回值?
定義統一返回值的包裝類
public class R { private Integer code ; private Object data ; private String message ; public R(Integer code, Object data, String message) { this.code = code ; this.data = data ; this.message = message ; } public static R success(Object data) { return new R(200, data, "success") ; } public static R failure(String message) { return new R(500, null, message) ; }}
自定義ResponseBodyAdvice
@RestControllerAdvicepublic class PackResponseBodyAdvice implements ResponseBodyAdvice<Object> { @Resource private ObjectMapper objectMapper ; @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { // 只有返回值不是R類型的時候才通過該Advice進行處理 return !returnType.getParameterType().equals(R.class) ; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { // 統一返回值處理 return R.success(body) ; }}
測試接口
@RestController@RequestMapping("/advices")public class AdviceController { @GetMapping("/str") public String str() { return "success" ; } @GetMapping("/{id}") public User body(@PathVariable("id") Long id) { return new User(id, "張三 - " + new Random().nextInt(1000)) ; }}
首先,測試接口/advices/{id}
圖片
處理了最終的返回結果。
繼續測試/advices/str
圖片
程序出錯了
控制臺輸出
java.lang.ClassCastException: class com.pack.common.dto.R cannot be cast to class java.lang.String (com.pack.common.dto.R is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap') at org.springframework.http.converter.StringHttpMessageConverter.addDefaultHeaders(StringHttpMessageConverter.java:44) ~[spring-web-5.3.27.jar:5.3.27] at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:211) ~[spring-web-5.3.27.jar:5.3.27]
出現ClassCastException錯誤,是由于Controller接口返回值是String,那么匹配到的HttpMessageConverter是StringHttpMessageConverter處理,而該轉換器的調用是在ResponseBodyAdvice之后執行,這時候的字符串已經被轉換成了R對象,所以最后在write時就出現了類型轉換錯誤。通過如下方式處理
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof String) { try { return this.objectMapper.writeValueAsString(R.success(body)) ; } catch (JsonProcessingException e) { e.printStackTrace(); } } return R.success(body) ;}
針對返回值是String類型的正常了。
通過自定義注解排除那些不需要處理的接口
@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface NoR {}
修改PackResponseBodyAdvice#supports方法,添加NoR注解的判斷
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { // 方法上或者是類上沒有NoR注解 return (!returnType.hasMethodAnnotation(NoR.class) || AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), NoR.class)) && !returnType.getParameterType().equals(R.class) ;}
這樣就可以控制具體哪些方法不進行處理了。
通過自定義ResponseBodyAdvice,我們可以實現接口統一返回值的處理,從而提高了接口的可讀性、擴展性和錯誤處理能力。同時,這也有助于保持代碼的清晰和規范。通過學習和實踐,我們可以更好地利用SpringMVC相應的功能,開發出更優秀的應用程序。
本文鏈接:http://www.www897cc.com/showinfo-26-38112-0.html優雅地統一處理接口返回值的最佳實踐
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 一次 K8s 升級,竟然導致滴滴故障 12 小時?
下一篇: Python中的單例模式,這些你都會嗎?