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