1. 程式人生 > >Spring Boot 菜鳥教程 6 全域性異常處理

Spring Boot 菜鳥教程 6 全域性異常處理

GitHub

@ControllerAdvice原始碼

package org.springframework.web.bind.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang
.annotation.Target; import org.springframework.core.annotation.AliasFor; import org.springframework.stereotype.Component; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface ControllerAdvice { @AliasFor("basePackages") String[] value() default {};
@AliasFor("value") String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<?>[] assignableTypes() default {}; Class<? extends Annotation>[] annotations() default {}; }

原始碼分析

@ ControllerAdvice是一個@ Component,
用於定義@ ExceptionHandler的,@InitBinder和@ModelAttribute方法,適用於所有使用@ RequestMapping方法,並處理所有@ RequestMapping標註方法出現異常的統一處理

專案圖片

這裡寫圖片描述

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jege.spring.boot</groupId>
    <artifactId>spring-boot-controller-advice</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-boot-controller-advice</name>
    <url>http://maven.apache.org</url>

    <!-- 公共spring-boot配置,下面依賴jar檔案不用在寫版本號 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.1.RELEASE</version>
        <relativePath />
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <!-- web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 持久層 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!-- h2記憶體資料庫 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- 測試 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <!-- 只在test測試裡面執行 -->
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <finalName>spring-boot-controller-advice</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

全域性異常處理類CommonExceptionAdvice

package com.jege.spring.boot.exception;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.jege.spring.boot.json.AjaxResult;

/**
 * @author JE哥
 * @email [email protected]
 * @description:全域性異常處理
 */
@ControllerAdvice
@ResponseBody
public class CommonExceptionAdvice {

  private static Logger logger = LoggerFactory.getLogger(CommonExceptionAdvice.class);

  /**
   * 400 - Bad Request
   */
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  @ExceptionHandler(MissingServletRequestParameterException.class)
  public AjaxResult handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
    logger.error("缺少請求引數", e);
    return new AjaxResult().failure("required_parameter_is_not_present");
  }

  /**
   * 400 - Bad Request
   */
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  @ExceptionHandler(HttpMessageNotReadableException.class)
  public AjaxResult handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
    logger.error("引數解析失敗", e);
    return new AjaxResult().failure("could_not_read_json");
  }

  /**
   * 400 - Bad Request
   */
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  @ExceptionHandler(MethodArgumentNotValidException.class)
  public AjaxResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
    logger.error("引數驗證失敗", e);
    BindingResult result = e.getBindingResult();
    FieldError error = result.getFieldError();
    String field = error.getField();
    String code = error.getDefaultMessage();
    String message = String.format("%s:%s", field, code);
    return new AjaxResult().failure(message);
  }

  /**
   * 400 - Bad Request
   */
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  @ExceptionHandler(BindException.class)
  public AjaxResult handleBindException(BindException e) {
    logger.error("引數繫結失敗", e);
    BindingResult result = e.getBindingResult();
    FieldError error = result.getFieldError();
    String field = error.getField();
    String code = error.getDefaultMessage();
    String message = String.format("%s:%s", field, code);
    return new AjaxResult().failure(message);
  }

  /**
   * 400 - Bad Request
   */
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  @ExceptionHandler(ConstraintViolationException.class)
  public AjaxResult handleServiceException(ConstraintViolationException e) {
    logger.error("引數驗證失敗", e);
    Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
    ConstraintViolation<?> violation = violations.iterator().next();
    String message = violation.getMessage();
    return new AjaxResult().failure("parameter:" + message);
  }

  /**
   * 400 - Bad Request
   */
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  @ExceptionHandler(ValidationException.class)
  public AjaxResult handleValidationException(ValidationException e) {
    logger.error("引數驗證失敗", e);
    return new AjaxResult().failure("validation_exception");
  }

  /**
   * 405 - Method Not Allowed
   */
  @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
  @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
  public AjaxResult handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
    logger.error("不支援當前請求方法", e);
    return new AjaxResult().failure("request_method_not_supported");
  }

  /**
   * 415 - Unsupported Media Type
   */
  @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
  @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
  public AjaxResult handleHttpMediaTypeNotSupportedException(Exception e) {
    logger.error("不支援當前媒體型別", e);
    return new AjaxResult().failure("content_type_not_supported");
  }

  /**
   * 500 - Internal Server Error
   */
  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  @ExceptionHandler(ServiceException.class)
  public AjaxResult handleServiceException(ServiceException e) {
    logger.error("業務邏輯異常", e);
    return new AjaxResult().failure("業務邏輯異常:" + e.getMessage());
  }

  /**
   * 500 - Internal Server Error
   */
  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  @ExceptionHandler(Exception.class)
  public AjaxResult handleException(Exception e) {
    logger.error("通用異常", e);
    return new AjaxResult().failure("通用異常:" + e.getMessage());
  }

  /**
   * 操作資料庫出現異常:名稱重複,外來鍵關聯
   */
  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  @ExceptionHandler(DataIntegrityViolationException.class)
  public AjaxResult handleException(DataIntegrityViolationException e) {
    logger.error("操作資料庫出現異常:", e);
    return new AjaxResult().failure("操作資料庫出現異常:欄位重複、有外來鍵關聯等");
  }
}

自定義異常ServiceException

package com.jege.spring.boot.exception;

/**
 * @author JE哥
 * @email [email protected]
 * @description:自定義異常類
 */
public class ServiceException extends RuntimeException {
  public ServiceException(String msg) {
    super(msg);
  }
}

不需要application.properties

控制器AdviceController

package com.jege.spring.boot.controller;

import java.util.List;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.jege.spring.boot.exception.ServiceException;

/**
 * @author JE哥
 * @email [email protected]
 * @description:全域性異常處理演示入口
 */
@RestController
public class AdviceController {

  @RequestMapping("/hello1")
  public String hello1() {
    int i = 1 / 0;
    return "hello";
  }

  @RequestMapping("/hello2")
  public String hello2(Long id) {
    String string = null;
    string.length();
    return "hello";
  }

  @RequestMapping("/hello3")
  public List<String> hello3() {
    throw new ServiceException("test");
  }
}

訪問


  • {“meta”:{“success”:false,”message”:”通用異常:/ by zero”},”data”:null}

  • {“meta”:{“success”:false,”message”:”通用異常:null”},”data”:null}

  • {“meta”:{“success”:false,”message”:”業務邏輯異常:test”},”data”:null}

原始碼地址

如果覺得我的文章或者程式碼對您有幫助,可以請我喝杯咖啡。
您的支援將鼓勵我繼續創作!謝謝!
微信打賞
支付寶打賞

相關推薦

Spring Boot 教程 6 全域性異常處理

GitHub @ControllerAdvice原始碼 package org.springframework.web.bind.annotation; import java.lang.annotation.Annotation; impor

Spring Boot 教程 24 返回XML

GitHub 需求產生 一般RESTful都是返回json,有時候可能需要返回xml,那又怎樣操作呢? 方案1-Jackson Maven增加jar檔案匯入 <dependency> <groupId>

Spring Boot 教程 7 EasyUI datagrid

GitHub jQueryEasyUI jQuery EasyUI是一組基於jQuery的UI外掛集合體,而jQuery EasyUI的目標就是幫助web開發者更輕鬆的打造出功能豐富並且美觀的UI介面。 開發者不需要編寫複雜的javascript,

Spring Boot 教程 application.properties 常用配置

SPRING CONFIG (ConfigFileApplicationListener) spring.config.name  配置檔名稱,預設為application  spring.config.location  配置檔案存放位置

Spring Boot 教程 5 熱部署 devtools模組

GitHub devtools模組 devtools模組,是為開發者服務的一個模組。主要的功能就是程式碼修改後一般在5秒之內就會自動重新載入至伺服器,相當於restart成功。 原理分析 簡單原理 在發現程式碼有更改之後,自動重新啟動應

Spring Boot 教程 17 Cache-快取

GitHub 快取 快取就是資料交換的緩衝區(稱作Cache),當某一硬體要讀取資料時,會首先從快取中查詢需要的資料,如果找到了則直接執行,找不到的話則從記憶體中找。由於快取的執行速度比記憶體快得多,故快取的作用就是幫助硬體更快地執行。 因為快取往

Spring Boot 教程 27 內建tomcat訪問https

GitHub HTTPS HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標的HTTP通道,簡單講是HTTP的安全版。 即HTTP下加入SSL層,HTTPS

Spring Boot 教程 28 多配置檔案

GitHub 需求產生 開發過程中可能會有如下需求:開發和部署的配置資訊可能不同,常規的方式就是在配置檔案裡面先寫好開發配置,在部署的時候再去修改這些配置,這樣可能會出現很多問題,比如使用者名稱、密碼忘記了修改或者改錯了等問題。 專案結構圖片

Spring Boot 教程 1 HelloWorld

GitHub 技能要求 最好對Spring有一定認識 最好對Maven有一定認識 簡介 Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行

spring boot 統一返回資料及全域性異常處理

記錄關於spring boot 統一返回資料及全域性異常處理的操作實現。 一、統一返回資料 1、定義一個超類:BaseResponseVo @Data @NoArgsConstructor public class BaseResponseVo{ protected Integer r

spring-boot-route(四)全域性異常處理

在開發中,我們經常會使用`try/catch塊`來捕獲異常進行處理,如果有些程式碼中忘記捕獲異常或者不可見的一些異常出現,就會響應給前端一些不友好的提示,這時候我們可以使用全域性異常處理。這樣就不用在程式碼中寫那些煩人的`try/catch塊了`,程式碼的可讀性也會提高。 SpringBoot提供的的註解`

JPA 教程 6 單向多對多

GitHub JPA中的@ManyToMany @ManyToMany註釋表示模型類是多對多關係的一端。 @JoinTable 描述了多對多關係的資料表關係。 name 屬性指定中間表名稱 joinColumns 定義中間表與Teach

spring-boot實戰【07】【轉】:Spring Boot中Web應用的統一異常處理

http integer private fin ima lex clas 友好 ref 我們在做Web應用的時候,請求處理過程中發生錯誤是非常常見的情況。Spring Boot提供了一個默認的映射:/error,當處理中拋出異常之後,會轉到該請求中處理,並且該請求有一個全

企業分布式微服務雲SpringCloud SpringBoot mybatis (五)Spring Boot中Web應用的統一異常處理

src one exception learn 微服務 public .net 可能 訪問 我們在做Web應用的時候,請求處理過程中發生錯誤是非常常見的情況。Spring Boot提供了一個默認的映射:/error,當處理中拋出異常之後,會轉到該請求中處理,並且該請求有一個

Spring Boot中Web應用的統一異常處理

通過 提示頁面 ret oot 頁面效果 tro ctype doctype ice   我們在做Web應用的時候,請求處理過程中發生錯誤是非常常見的情況。Spring Boot提供了一個默認的映射:/error,當處理中拋出異常之後,會轉到該請求中處理,並且該請求有一個全

Spring Boot中Web應用的統一異常處理實戰

 一 建立全域性異常處理類 package com.didispace.exception; import com.didispace.dto.ErrorInfo; import org.springframework.web.bind.annotation.Contr

spring boot restful api 方法引數 BindException 異常處理

  客戶端 post json 資料,api 方法 接收的引數綁定出現異常,丟擲  BindException 異常,可以按照如下的方式處理 1、方法引數中增加 BindingResult 引數,通過 bindingResult.hasErrors()

Spring Boot 資料校驗@Valid+統一異常處理

1.先在你需要校驗的實體類上面加上所需要的註解 為了測試,我自己就簡單寫了。@NotNull 和 @NotBlank 不能為空 @Entity @Table(name = "User") @Data public class User implement

Spring Boot-錯誤處理及自定義全域性異常處理機制

正常的Web應用開發時,需要考慮到應用執行發生異常時或出現錯誤時如何來被處理,例如捕獲必要的異常資訊,記錄日誌方便日後排錯,友好的使用者響應輸出等等。 當然應用發生錯誤,有可能是應用自身的問題,也有可能是客戶端操作的問題。 Spring Boot預設提供了一種錯誤處理機制。 預設錯誤處理機制

Spring Boot 全域性異常處理 與 Hibernate Validator校驗框架整合

Hibernate Validator校驗框架的使用 Spring boot已經集成了hibernate-validator,不需要引入maven,其他框架也可以自己引入: <dependency> <groupId>org.h