最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中的@ControllerAdvice和@ExceptionHandler注解處理全局異常

 更新時間:2024年01月09日 09:23:19   作者:Java架構(gòu)何哥  
這篇文章主要介紹了Spring中的@ControllerAdvice和@ExceptionHandler注解處理全局異常,@ControllerAdvice ,@ControllerAdvice是一個非常有用的注解,顧名思義,這是一個增強的 Controller,一般配合@ExceptionHandler使用來處理全局異常,需要的朋友可以參考下

前言

開發(fā)過程中,難免有的程序會因為某些原因拋出異常,而這些異常一般都是利用try ,catch的方式處理異?;蛘遲hrow,throws的方式拋出異常不管。

這種方法對于程序員來說處理也比較麻煩,對客戶來說也不太友好,所以我們希望既能方便程序員編寫代碼,不用過多的自己去處理各種異常編寫重復的代碼又能提升用戶的體驗,這時候全局異常處理就顯得很重要也很便捷了。

一、@ControllerAdvice和@ExceptionHandler簡介

在構(gòu)建RestFul接口的今天,我們一般會限定好返回數(shù)據(jù)的格式,有利于前端調(diào)用解析,比如:

{
  "code": 0,
  "data": {},
  "msg": "操作成功"
}

但有時卻往往會產(chǎn)生一些bug,這時候就破壞了返回數(shù)據(jù)的一致性,導致調(diào)用者無法解析。所以我們常常會定義一個全局的異常攔截器。

1.1、@ControllerAdvice

@ControllerAdvice 是Spring 3.2提供的新注解,可以對Controller中使用到@RequestMapping注解的方法做邏輯處理。

@ControllerAdvice ,很多初學者可能都沒有聽說過這個注解,實際上這是一個非常有用的注解。顧名思義,這是一個增強的 Controller,一般配合@ExceptionHandler使用來處理全局異常。注意不能自己try和catch異常,否則就不會被全局異常處理捕獲到。

使用這個注解 ,可以實現(xiàn)三個方面的功能:

  • 全局異常處理
  • 全局數(shù)據(jù)綁定
  • 全局數(shù)據(jù)預處理

靈活使用這三個功能,可以幫助我們簡化很多工作,需要注意的是,這是 SpringMVC 提供的功能,在 Spring Boot 中可以直接使用,這里只介紹全局異常處理,需要其他功能可以訪問參考鏈接。

1.2、全局異常處理

Springboot對于全局異常的處理做了不錯的支持,它提供了兩個可用的注解。

@ControllerAdvice:用來開啟全局的異常捕獲

@ExceptionHandler:說明捕獲哪些異常,對哪些異常進行處理。

使用 @ControllerAdvice結(jié)合@ExceptionHandler 實現(xiàn)全局異常處理,只需要定義類,添加該注解即可定義方式如下:

//可以使Spring自動把要返回的對象轉(zhuǎn)化成json文本寫入到響應體中,比如自定義的ResultBean
@ResponseBody
@ControllerAdvice
public class MyGlobalExceptionHandler 
{
    // 專門用來捕獲和處理Controller層的異常
    @ExceptionHandler(Exception.class)
    public ModelAndView customException(Exception e) 
    {
        ModelAndView mv = new ModelAndView();
        mv.addObject("message", e.getMessage());
        mv.setViewName("myerror");
        return mv;
    }
    // 專門用來捕獲和處理Controller層的空指針異常
    @ExceptionHandler(NullPointerException.class)
    public ModelAndView nullPointerExceptionHandler(NullPointerException e)
    {
        ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
        mv.addObject("success",false);
        mv.addObject("mesg","請求發(fā)生了空指針異常,請稍后再試");
        return mv;
   }
}

在該類中,可以定義多個方法,不同的方法處理不同的異常,例如專門處理空指針的方法、專門處理數(shù)組越界的方法...,也可以直接向上面代碼一樣,在一個方法中處理所有的異常信息。

@ExceptionHandler 注解用來指明異常的處理類型,即如果這里指定為 NullpointerException,則數(shù)組越界異常就不會進到這個方法中來。

二、為什么要做Controller層的異常統(tǒng)一處理以及統(tǒng)一結(jié)果返回

不知道你平時在寫Controller層接口的時候,有沒有注意過拋出異常該怎么處理,是否第一反應是想著用個try-catch來捕獲異常?但是這樣地處理只適合那種編譯器主動提示的檢查時異常,因為你不用try-catch就過不了編譯檢查,所以你能主動地抓獲異常并進行處理。但是,如果存在運行時異常且你沒有來得及想到去處理它的時候會發(fā)生什么呢?我們可以來先看看下面的這個沒有處理運行時異常的例子:

@RestController
public class ExceptionRest {
    @GetMapping("getNullPointerException")
    public Map<String,Object> getNullPointerException(){
        throw new NullPointerException("出現(xiàn)了空指針異常");
    }
}

以上代碼在基于maven的SpringMVC項目中,使用tomcat啟動后,瀏覽器端發(fā)起如下請求:

//localhost:8080/zxtest/getNullPointerException

訪問后得到的結(jié)果是這樣的,瀏覽器收到的報錯信息:

 可以看到,我們在Controller接口層拋出了一個空指針異常,然后沒有捕獲,結(jié)果異常堆棧就會返回給前端瀏覽器,給用戶造成了非常不好的體驗。

除此之外,前端從報錯信息中能看到后臺系統(tǒng)使用的服務器及中間件類型、所采用的框架信息及類信息,甚至如果后端拋出的是SQL異常,那么還可以看到SQL異常的具體查詢的參數(shù)信息,這是一個中危安全漏洞,是必須要修復的。

三、使用@ExceptionHandler和@ControllerAdvice做到統(tǒng)一處理

當出現(xiàn)這種運行時異常的時候,我們想到的最簡單的方法也許就是給可能會拋出異常的代碼加上異常處理,如下所示:

@RestController
public class ExceptionRest {
    private Logger log = LoggerFactory.getLogger(ExceptionRest.class);
    @GetMapping("getNullPointerException")
    public Map<String,Object> getNullPointerException(){
        Map<String,Object> returnMap = new HashMap<String,Object>();
        try{
            throw new NullPointerException("出現(xiàn)了空指針異常");
        }catch(NullPointerException e){
            log.error("出現(xiàn)了空指針異常",e);
            returnMap.put("success",false);
            returnMap.put("mesg","請求發(fā)生異常,請稍后再試");
        }
        return returnMap;
    }
}

因為我們手動地在拋出異常的地方加上了處理,并妥善地返回發(fā)生異常時該返回給前端的內(nèi)容,因此,當我們再次在瀏覽器發(fā)起相同的請求時得到就是以下內(nèi)容:

{
  success: false,
  mesg: "請求發(fā)生異常,請稍后再試"
}

貌似問題得到了解決,但是你能確保你可以在所有可能會發(fā)生異常的地方都正好捕獲了異常并處理嗎?你能確保團隊的其他人也這么做?

很明顯,你需要一個統(tǒng)一的異常捕獲與處理方案。

Spring3.2以后,SpringMVC引入了ExceptionHandler的處理方法,使得對異常的處理變得更加簡單和精確,你唯一需要做的就是新建一個Controller,然后再里面加上兩個注解即可完成Controller層所有異常的捕獲與處理。

3.1、@ExceptionHandler和@ControllerAdvice基本使用

新建一個Controller如下:

@ControllerAdvice
public class ExceptionConfigController {
    @ExceptionHandler
    public ModelAndView exceptionHandler(Exception e){
        ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
        mv.addObject("success",false);
        mv.addObject("mesg","請求發(fā)生了異常,請稍后再試");
        return mv;
    }
}

我們在如上的代碼中,類上加了@ControllerAdvice注解,表示它是一個增強版的controller,然后在里面創(chuàng)建了一個返回ModelAndView對象的exceptionHandler方法,其上加上@ExceptionHandler注解,表示這是一個異常處理方法,然后在方法里面寫上具體的異常處理及返回參數(shù)邏輯即可,如此就完成了所有的工作,真的是太方便了。

我們在瀏覽器發(fā)起調(diào)用后就返回了如下的結(jié)果:

{
success: false,
mesg: "請求發(fā)生了異常,請稍后再試"
}

3.2、@ExceptionHandler具體異常的處理

相比與HandlerExceptionResolver而言,使用@ExceptionHandler更能靈活地對不同的異常進行分別的處理。并且,當拋出的異常是指定異常的子類,那么照樣能夠被捕獲和處理。

我們改變下controller層的代碼如下:

@RestController
public class ExceptionController {
 
    @GetMapping("getNullPointerException")
    public Map<String, Object> getNullPointerException() {
        throw new NullPointerException("出現(xiàn)了空指針異常");
    }
 
    @GetMapping("getClassCastException")
    public Map<String, Object> getClassCastException() {
        throw new ClassCastException("出現(xiàn)了類型轉(zhuǎn)換異常");
    }
 
    @GetMapping("getIOException")
    public Map<String, Object> getIOException() throws IOException {
        throw new IOException("出現(xiàn)了IO異常");
    }
}

已知NullPointerException和ClassCastException都繼承RuntimeException,而RuntimeException和IOException都繼承Exception。

我們在ExceptionConfigController做這樣的處理:

@ControllerAdvice
public class ExceptionConfigController 
{
    // 專門用來捕獲和處理Controller層的空指針異常
    @ExceptionHandler(NullPointerException.class)
    public ModelAndView nullPointerExceptionHandler(NullPointerException e){
        ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
        mv.addObject("success",false);
        mv.addObject("mesg","請求發(fā)生了空指針異常,請稍后再試");
        return mv;
    }
 
    // 專門用來捕獲和處理Controller層的運行時異常
    @ExceptionHandler(RuntimeException.class)
    public ModelAndView runtimeExceptionHandler(RuntimeException e){
        ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
        mv.addObject("success",false);
        mv.addObject("mesg","請求發(fā)生了運行時異常,請稍后再試");
        return mv;
    }
 
    // 專門用來捕獲和處理Controller層的異常
    @ExceptionHandler(Exception.class)
    public ModelAndView exceptionHandler(Exception e){
        ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
        mv.addObject("success",false);
        mv.addObject("mesg","請求發(fā)生了異常,請稍后再試");
        return mv;
    }
}

當我們在Controller層拋出NullPointerException時,就會被nullPointerExceptionHandler進行處理,然后攔截。

{
success: false,
mesg: "請求發(fā)生了空指針異常,請稍后再試"
}

當我們在Controller層拋出ClassCastException時,就會被runtimeExceptionHandler進行處理,然后攔截。

{
success: false,
mesg: "請求發(fā)生了運行時異常,請稍后再試"
}

當我們在Controller層拋出IOException時,就會被exceptionHandler進行處理,然后攔截。

{
success: false,
mesg: "請求發(fā)生了異常,請稍后再試"
}

SpringMVC為我們提供的Controller層異常處理真的是太方便了,尤其是@ExceptionHandler,推薦大家使用。

四、自定義異常處理類CustomUserException

4.1、自定義異常處理類

在程序中,可能會遇到JDK提供的任何標準異常類都無法充分描述清楚我們想要表達的問題,又或者捕捉數(shù)據(jù)庫異常時候不知道具體異常名字,這種情況下可以創(chuàng)建自己的異常類,即自定義異常類,在需要的時候手動throw出,然后再全局異常統(tǒng)一處理。

自定義異常類只需從Exception類或者它的子類派生一個子類即可。自定義異常類如果繼承Exception類,則為受檢查異常,必須對其進行處理;如果不想處理,可以讓自定義異常類繼承運行時異常RuntimeException類。習慣上,自定義異常類應該包含2個構(gòu)造器:一個是默認的構(gòu)造器,另一個是帶有詳細信息的構(gòu)造器。

/**
*   自定義異常的步驟:
*  (1)繼承 Exception 或 RuntimeException
*  (2)定義構(gòu)造方法
*/
public class CustomUserException extends RuntimeException {
    private Integer code;
    public CustomUserException(UserResponseEnum userResponseEnum){
        super(userResponseEnum.getDescription());
        this.code = userResponseEnum.getCode();
    }
    public Integer getCode() {
        return code;
    }
}

在構(gòu)造自定義業(yè)務異常對象時使用了枚舉的方式,將常見的業(yè)務錯誤提示語對應的錯誤代碼進行映射,枚舉類如下所示:

public enum UserResponseEnum {
    USER_NOT_FOUND(50001,"用戶不存在"),
    USER_AUTHENTICATION_ERROR(50002,"用戶密碼不正確");
    private Integer code;
    private String description;
    UserResponseEnum(Integer code, String description) {
        this.code = code;
        this.description = description;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }

4.2、通過@ControllerAdvice和@ExceptionHandler注解,實現(xiàn)統(tǒng)一異常捕獲

@RestController
@ControllerAdvice(basePackages = {"com.hs.controller"})
public class CustomExceptionAdvice 
{
    private static final Logger logger = LoggerFactory.getLogger(CustomExceptionAdvice.class);
    /**
     * 處理與用戶相關的業(yè)務異常
     * @return
     */
    @ExceptionHandler(CustomUserException.class)
    public BaseResult UserExceptionHandler(HttpServletRequest request,CustomUserException e){
        logger.error("用戶信息異常:Host:{} invoke URL:{},錯誤信息:{}",request.getRemoteHost(),request.getRequestURL(),e.getMessage());
        return new BaseResult(e.getCode(),false,e.getMessage());
    }
}
 

4.3、在業(yè)務代碼中在需要拋出異常的地方拋出對應的異常即可

	/**
     * 根據(jù)主鍵獲取用戶實體
     * @param id
     * @return
     */
    public User selectById(String id) 
    {
        User user = userMapper.selectByPrimaryId(id);
        if (user == null) {
            throw new CustomUserException(UserResponseEnum.USER_NOT_FOUND);
        }
        return user;
    }
 

    返回信息如下:
    {
        "code": 50001,
        "data": false,
        "message": "用戶不存在"
    }

前端即可根據(jù)返回信息對用戶進行友好的提示。

到此這篇關于Spring中的@ControllerAdvice和@ExceptionHandler注解處理全局異常的文章就介紹到這了,更多相關@ControllerAdvice和@ExceptionHandler注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java基于中介者模式實現(xiàn)多人聊天室功能示例

    Java基于中介者模式實現(xiàn)多人聊天室功能示例

    這篇文章主要介紹了Java基于中介者模式實現(xiàn)多人聊天室功能,詳細分析了中介者模式的概念、原理以及使用中介模式實現(xiàn)多人聊天的步驟、操作技巧與注意事項,需要的朋友可以參考下
    2018-05-05
  • mybatis配置mapper-locations位置的三種方式小結(jié)

    mybatis配置mapper-locations位置的三種方式小結(jié)

    這篇文章主要給大家介紹了關于mybatis配置mapper-locations位置的三種方式,Mybatis-Plus的初衷是為了簡化開發(fā),而不建議開發(fā)者自己寫SQL語句的,但是有時客戶需求比較復雜,需要的朋友可以參考下
    2023-08-08
  • IDEA啟動Tomcat時控制臺出現(xiàn)亂碼問題及解決

    IDEA啟動Tomcat時控制臺出現(xiàn)亂碼問題及解決

    這篇文章主要介紹了IDEA啟動Tomcat時控制臺出現(xiàn)亂碼問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Springboot中依賴注入的三種方式詳解

    Springboot中依賴注入的三種方式詳解

    這篇文章主要介紹了Springboot中依賴注入的三種方式詳解,Setter Injection需要依賴@Autowired注解,使用方式與Field Injection有所不同,Field Injection時@Autowired是用在成員變量上,需要的朋友可以參考下
    2023-09-09
  • Java 冒泡排序、快速排序?qū)嵗a

    Java 冒泡排序、快速排序?qū)嵗a

    這篇文章主要介紹了Java 冒泡排序、快速排序?qū)嵗a,需要的朋友可以參考下
    2017-05-05
  • 實戰(zhàn)分布式醫(yī)療掛號系統(tǒng)之設置微服務接口開發(fā)模塊

    實戰(zhàn)分布式醫(yī)療掛號系統(tǒng)之設置微服務接口開發(fā)模塊

    這篇文章主要為大家介紹了實戰(zhàn)分布式醫(yī)療掛號系統(tǒng)之接口開發(fā)醫(yī)院設置微服務模塊,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-04-04
  • Mybatis中動態(tài)SQL,if,where,foreach的使用教程詳解

    Mybatis中動態(tài)SQL,if,where,foreach的使用教程詳解

    MyBatis的動態(tài)SQL是基于OGNL表達式的,它可以幫助我們方便的在SQL語句中實現(xiàn)某些邏輯。這篇文章主要介紹了Mybatis中動態(tài)SQL,if,where,foreach的使用教程,需要的朋友可以參考下
    2017-11-11
  • Java實現(xiàn)圖片百葉窗效果(附源碼)

    Java實現(xiàn)圖片百葉窗效果(附源碼)

    在數(shù)字圖像處理領域,各種特效的實現(xiàn)不僅能夠提升圖片的美觀性,也能為后續(xù)的視頻合成、動畫制作提供基礎素材,使用 Java 語言結(jié)合 AWT/Swing 或 JavaFX,可以實現(xiàn)對圖像的像素級操作,以達到百葉窗特效,本文給大家介紹的非常詳細,感興趣的小伙伴跟著小編一起來看看吧
    2025-05-05
  • 一文帶你掌握springBoot如何做到優(yōu)雅停機的

    一文帶你掌握springBoot如何做到優(yōu)雅停機的

    在分布式系統(tǒng)中,服務的優(yōu)雅停機(Graceful Shutdown)是確保業(yè)務連續(xù)性的重要機制,下面就跟隨小編一起來深入了解下springBoot實現(xiàn)優(yōu)雅停機的具體方式吧
    2025-04-04
  • Java enum實現(xiàn)自增賦值方式

    Java enum實現(xiàn)自增賦值方式

    這篇文章主要介紹了Java enum實現(xiàn)自增賦值方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05

最新評論

湖口县| 土默特右旗| 元江| 彩票| 阿克苏市| 商水县| 常德市| 东兰县| 凤山县| 湘乡市| 桑日县| 威远县| 八宿县| 武胜县| 安庆市| 舟山市| 顺平县| 云阳县| 泰宁县| 鄂尔多斯市| 黄大仙区| 车致| 宁津县| 青冈县| 水富县| 毕节市| 响水县| 区。| 镇远县| 霍邱县| 湄潭县| 瓦房店市| 高雄市| 太湖县| 内江市| 西吉县| 法库县| 禹州市| 芦山县| 米脂县| 汉川市|