Spring Boot @RestControllerAdvice全局異常處理最佳實(shí)踐
前言
在開發(fā)Spring Boot應(yīng)用時(shí),優(yōu)雅地處理異常是保證系統(tǒng)健壯性和用戶體驗(yàn)的關(guān)鍵。本文將詳細(xì)介紹如何使用@RestControllerAdvice實(shí)現(xiàn)全局異常處理,并分享實(shí)際開發(fā)中的最佳實(shí)踐。
一、為什么要使用全局異常處理?
代碼復(fù)用:避免在每個(gè)Controller中重復(fù)編寫try-catch
統(tǒng)一響應(yīng)格式:標(biāo)準(zhǔn)化錯(cuò)誤返回結(jié)構(gòu)
異常分類處理:針對(duì)不同類型異常定制處理邏輯
減少樣板代碼:讓業(yè)務(wù)邏輯更專注于核心流程
二、核心注解解析
1. @RestControllerAdvice
@RestControllerAdvice是@ControllerAdvice和@ResponseBody的組合注解,主要功能:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice {
// 可指定包路徑或控制器類
@AliasFor(annotation = ControllerAdvice.class)
String[] value() default {};
}2. @ExceptionHandler
用于標(biāo)注處理特定異常的方法:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
// 指定要處理的異常類數(shù)組
Class<? extends Throwable>[] value() default {};
}三、實(shí)戰(zhàn)代碼實(shí)現(xiàn)
以下是完整全局異常處理器實(shí)現(xiàn):
他會(huì)對(duì)于ExceptionHandler指定的異常進(jìn)行處理,底層是通過(guò)AOP的技術(shù)實(shí)現(xiàn)的。
import com.sheep.shrine.result.JSONResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局異常處理器
* @RestControllerAdvice = @ControllerAdvice + @ResponseBody
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 處理自定義業(yè)務(wù)異常
*/
@ExceptionHandler(GlobleException.class)
public JSONResult handleBusinessException(GlobleException e) {
e.printStackTrace();
return JSONResult.error(e.getMessage());
}
/**
* 處理所有未捕獲異常
*/
@ExceptionHandler(Exception.class)
public JSONResult handleSystemException(Exception e) {
e.printStackTrace();
return JSONResult.error("系統(tǒng)異常,正在毆打程序員...", "50000");
}
}四、進(jìn)階使用技巧
1. 異常分類處理
// 處理數(shù)據(jù)校驗(yàn)異常
@ExceptionHandler(MethodArgumentNotValidException.class)
public JSONResult handleValidException(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getAllErrors()
.stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining("; "));
return JSONResult.error(message);
}
// 處理數(shù)據(jù)庫(kù)異常
@ExceptionHandler(DataAccessException.class)
public JSONResult handleDataAccessException(DataAccessException e) {
log.error("數(shù)據(jù)庫(kù)操作異常", e);
return JSONResult.error("數(shù)據(jù)庫(kù)服務(wù)異常");
}2. 響應(yīng)狀態(tài)碼控制
@ExceptionHandler(UnauthorizedException.class)
@ResponseStatus(HttpStatus.FORBIDDEN)
public JSONResult handleUnauthorizedException(UnauthorizedException e) {
return JSONResult.error("無(wú)權(quán)限訪問(wèn)", "403");
}3. 日志記錄優(yōu)化
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public JSONResult handleException(Exception e) {
log.error("系統(tǒng)異常: {}", e.getMessage(), e);
return JSONResult.error("系統(tǒng)繁忙");
}
}五、最佳實(shí)踐建議
異常分類細(xì)化:不要只用一個(gè)Exception.class處理所有異常
敏感信息過(guò)濾:生產(chǎn)環(huán)境不要返回堆棧信息
錯(cuò)誤碼規(guī)范:制定統(tǒng)一的錯(cuò)誤碼體系
日志完善:關(guān)鍵異常必須記錄完整上下文
性能考慮:異常處理邏輯應(yīng)盡量輕量
六、常見問(wèn)題解答
Q1:全局異常處理器不生效怎么辦?
檢查是否在Spring掃描路徑下
確認(rèn)沒(méi)有其他異常處理器覆蓋
檢查是否有Filter提前處理了異常
Q2:如何測(cè)試全局異常處理器?
@SpringBootTest
class GlobalExceptionHandlerTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@BeforeEach
void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
void testBusinessException() throws Exception {
mockMvc.perform(get("/api/test-exception"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value("50000"));
}
}Q3:如何與FeignClient集成?
@Configuration
public class FeignConfig {
@Bean
public ErrorDecoder errorDecoder() {
return (methodKey, response) -> {
// 將Feign異常轉(zhuǎn)換為自定義異常
return new BusinessException("遠(yuǎn)程服務(wù)調(diào)用失敗");
};
}
}七、總結(jié)
通過(guò)@RestControllerAdvice實(shí)現(xiàn)全局異常處理可以:
提高代碼可維護(hù)性
增強(qiáng)系統(tǒng)健壯性
改善用戶體驗(yàn)
便于監(jiān)控報(bào)警
到此這篇關(guān)于Spring Boot @RestControllerAdvice全局異常處理最佳實(shí)踐的文章就介紹到這了,更多相關(guān)Spring Boot @RestControllerAdvice全局異常內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決Hmily與Feign沖突報(bào)錯(cuò) NullPointerException的問(wèn)題
這篇文章主要介紹了解決Hmily與Feign沖突報(bào)錯(cuò) NullPointerException的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
springboot jdbctemplate如何實(shí)現(xiàn)多數(shù)據(jù)源
這篇文章主要介紹了springboot jdbctemplate如何實(shí)現(xiàn)多數(shù)據(jù)源問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
Java實(shí)現(xiàn)抽獎(jiǎng)算法的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)抽獎(jiǎng)算法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下2022-04-04
Java中字節(jié)流和字符流的區(qū)別與聯(lián)系
Java中的字節(jié)流和字符流是用于處理輸入和輸出的兩種不同的流,本文主要介紹了Java中字節(jié)流和字符流的區(qū)別與聯(lián)系,字節(jié)流以字節(jié)為單位進(jìn)行讀寫,適用于處理二進(jìn)制數(shù)據(jù),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2024-12-12
Springboot訪問(wèn)html頁(yè)面的教程詳解
這篇文章主要介紹了Springboot訪問(wèn)html頁(yè)面的教程,本文圖文并茂給大家介紹的非常詳細(xì),需要的朋友可以參考下2018-03-03
Spring中的SpringData詳細(xì)說(shuō)明
這篇文章主要介紹了Spring中的SpringData詳細(xì)說(shuō)明,Spring Data 是Spring 的一個(gè)子項(xiàng)目, 旨在統(tǒng)一和簡(jiǎn)化對(duì)各類型持久化存儲(chǔ), 而不拘泥于是關(guān)系型數(shù)據(jù)庫(kù)還是NoSQL 數(shù)據(jù)存儲(chǔ),需要的朋友可以參考下2023-11-11
java.lang.UnsatisfiedLinkError: %1 不是有效的Win32應(yīng)用程序錯(cuò)誤解決
這篇文章主要給大家介紹了關(guān)于java.lang.UnsatisfiedLinkError: %1 不是有效的Win32應(yīng)用程序錯(cuò)誤的解決方法,文中介紹的非常詳細(xì),需要的朋友們可以參考學(xué)習(xí),下面來(lái)一起看看吧。2017-03-03

