基于@RestControllerAdvice與@ControllerAdvice的區(qū)別說明
@RestControllerAdvice與@ControllerAdvice的區(qū)別
@RestControllerAdvice注解與@ControllerAdvice注解位于同一個(gè)依賴包下面,其pom依賴為:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.3</version>
</dependency>
有時(shí)會(huì)發(fā)現(xiàn)在不同的項(xiàng)目中,全局異常處理部分,有的自定義類添加@RestControllerAdvice注解,有的自定義類添加@ControllerAdvice注解。
其實(shí)這兩個(gè)注解的作用基本上是一致的,都是為了實(shí)現(xiàn)自定義全局異常處理,
唯一的區(qū)別是:@RestControllerAdvice注解包含了@ControllerAdvice注解和@ResponseBody注解。
@ControllerAdvice注解的源碼為
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
}
@RestControllerAdvice注解的源碼為
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice {
}
當(dāng)自定義類加@ControllerAdvice注解時(shí),方法需要返回json數(shù)據(jù)時(shí),每個(gè)方法還需要添加@ResponseBody注解
當(dāng)自定義類加@RestControllerAdvice注解時(shí),方法自動(dòng)返回json數(shù)據(jù),每個(gè)方法無需再添加@ResponseBody注解
/**
* 全局異常處理類
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result<String> ExceptionHandler(Exception e) {
log.error("出現(xiàn)異常:", e);
return Result.failed(e.getMessage());
}
}
@RestControllerAdvice @ControllerAdvice注解無效 通用異常處理
簡單記錄下,今天打算寫一個(gè)公共異常處理切面,主要是將所有拋出的異常攔截,然后返回給前端的時(shí)候,統(tǒng)一是錯(cuò)誤碼,錯(cuò)誤原因等。防止直接在前端拋出錯(cuò)誤。
@RestControllerAdvice 或者 @ControllerAdvice 可以直接作為錯(cuò)誤處理的切面對(duì)待。但是使用過程中發(fā)現(xiàn)這兩個(gè)注解無效,原因是我將GlobalExceptionHandler定義在另一個(gè)包里面,@SpringBootApplication無法自動(dòng)加載到該注解(springboot啟動(dòng)類的默認(rèn)掃描路徑是該類所在的包下面的所有java類。
如:啟動(dòng)類在“com.galen.cloud.portal”包下,那么只有com.galen.cloud.portal包下的類會(huì)被掃描加載)。所以添加上對(duì)應(yīng)的scanBasePackages 即可(我這邊改為掃描所有匹配com.galen.*的包):
啟動(dòng)類
package com.galen.cloud.portal;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.galen.*")
public class galenPortalApplication {
public static void main(String[] args) {
SpringApplication.run(galenPortalApplication.class, args);
}
}
錯(cuò)誤處理類
package com.galen.common.exception;
import com.galen.common.core.domain.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 異常處理器
* @author galen
*/
@RestControllerAdvice
public class GlobalExceptionHandler
{
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 請(qǐng)求方式不支持
*/
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
@ResponseStatus(code = HttpStatus.METHOD_NOT_ALLOWED)
public R handleException(HttpRequestMethodNotSupportedException e)
{
logger.error(e.getMessage(), e);
return R.error("不支持' " + e.getMethod() + "'請(qǐng)求");
}
/**
* 攔截未知的運(yùn)行時(shí)異常
*/
@ExceptionHandler(RuntimeException.class)
public R notFount(RuntimeException e)
{
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
{
throw e;
}
logger.error("運(yùn)行時(shí)異常:", e);
return R.error("運(yùn)行時(shí)異常:" + e.getMessage());
}
/**
* 處理自定義異常
*/
@ExceptionHandler(galenException.class)
public R handleWindException(galenException e)
{
return R.error(e.getCode(), e.getMessage());
}
@ExceptionHandler(DuplicateKeyException.class)
public R handleDuplicateKeyException(DuplicateKeyException e)
{
logger.error(e.getMessage(), e);
return R.error("數(shù)據(jù)庫中已存在該記錄");
}
@ExceptionHandler(Exception.class)
public R handleException(Exception e) throws Exception
{
logger.error(e.getMessage(), e);
return R.error("服務(wù)器錯(cuò)誤,請(qǐng)聯(lián)系管理員");
}
/**
* 捕獲并處理未授權(quán)異常
*
* @param e 授權(quán)異常
* @return 統(tǒng)一封裝的結(jié)果類, 含有代碼code和提示信息msg
*/
@ExceptionHandler(UnauthorizedException.class)
public R handle401(UnauthorizedException e)
{
return R.error(401, e.getMessage());
}
// 驗(yàn)證碼錯(cuò)誤
@ExceptionHandler(ValidateCodeException.class)
public R handleCaptcha(ValidateCodeException e)
{
return R.error(e.getMessage());
}
}
最后攔截效果圖如下:

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于JavaMail實(shí)現(xiàn)簡單郵件發(fā)送
這篇文章主要為大家詳細(xì)介紹了基于JavaMail實(shí)現(xiàn)簡單郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
Java實(shí)現(xiàn)synchronized鎖同步機(jī)制
synchronized是java內(nèi)置的同步鎖實(shí)現(xiàn),本文就詳細(xì)的介紹一下Java實(shí)現(xiàn)synchronized鎖同步機(jī)制,具有一定的參考價(jià)值,感興趣的可以了解一下2021-11-11
SpringBoot使用Async注解失效原因分析及解決(spring異步回調(diào))
這篇文章主要介紹了SpringBoot使用Async注解失效原因分析及解決(spring異步回調(diào)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
Spring?Boot日志基礎(chǔ)使用之如何設(shè)置日志級(jí)別
這篇文章主要介紹了Spring?Boot日志基礎(chǔ)使用設(shè)置日志級(jí)別的方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
Spring @Cacheable redis異常不影響正常業(yè)務(wù)方案
這篇文章主要介紹了Spring @Cacheable redis異常不影響正常業(yè)務(wù)方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
Maven?Web項(xiàng)目使用Cargo插件實(shí)現(xiàn)自動(dòng)化部署的詳細(xì)步驟
cargo ,它是一組幫助用戶實(shí)現(xiàn)自動(dòng)化部署,操作Web容器的工具,并且?guī)缀踔С炙械腤eb容器,這篇文章主要介紹了Maven?Web項(xiàng)目使用Cargo實(shí)現(xiàn)自動(dòng)化部署,需要的朋友可以參考下2023-02-02
Java(TM) Platform SE binary 打開jar文件的操作
這篇文章主要介紹了Java(TM) Platform SE binary 打開jar文件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02

