Spring Boot快速入門之(十二):異常處理
【注】本文譯自:https://www.tutorialspoint.com/spring_boot/spring_boot_exception_handling.htm

? ? 對(duì)于企業(yè)應(yīng)用而言,在 API 中處理好異常和錯(cuò)誤是至關(guān)重要的。本文將帶你學(xué)習(xí)如果在?Spring Boot 中處理異常。
? ? 在學(xué)習(xí)異常處理前讓我們先來(lái)理解下面的注解:
Controller Advice
? ??@ControllerAdvice 注解用于處理全局異常。
Exception Handler
? ??@ExceptionHandler 注解是用于處理指定的異常并向客戶端發(fā)送一個(gè)自定義的響應(yīng)。
? ? 可以使用下面的代碼來(lái)創(chuàng)建?@ControllerAdvice 類以處理全局異常:
package com.tutorialspoint.demo.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
@ControllerAdvice
???public class ProductExceptionController {
}
? ? 定義一個(gè)繼承?RuntimeException 的類。
package com.tutorialspoint.demo.exception;
public class ProductNotfoundException extends RuntimeException {
???private static final long serialVersionUID = 1L;
}
? ??如下所示,可以定義 @ExceptionHandler 方法來(lái)處理異常。這個(gè)方法應(yīng)當(dāng)被用于編寫 Controller Advice 類文件。
@ExceptionHandler(value = ProductNotfoundException.class)
public ResponseEntity<Object> exception(ProductNotfoundException exception) {
}
? ??現(xiàn)在,使用以下代碼來(lái)拋出來(lái)自 API 的異常:
@RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
public ResponseEntity<Object> updateProduct() {
???throw new ProductNotfoundException();
}
? ? 完整的異常處理代碼如下所示。在這個(gè)例子中,我們使用?PUT API 來(lái)更新產(chǎn)品。當(dāng)更新產(chǎn)品時(shí),如果找不到產(chǎn)品,返回的響應(yīng)消息是 “Product not found”。注意?ProductNotFoundException?異常類應(yīng)當(dāng)繼承?RuntimeException。
package com.tutorialspoint.demo.exception;
public class ProductNotfoundException extends RuntimeException {
???private static final long serialVersionUID = 1L;
}
? ??Controller Advice 類處理全局異常,如下所示。我們可以在這個(gè)類文件中定義任何 Exception Handler 方法。
package com.tutorialspoint.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class ProductExceptionController {
???@ExceptionHandler(value = ProductNotfoundException.class)
???public ResponseEntity<Object> exception(ProductNotfoundException exception) {
??????return new ResponseEntity<>("Product not found", HttpStatus.NOT_FOUND);
???}
}
? ? 下面的?Product Service API controller 文件更新產(chǎn)品。如果產(chǎn)品不存在,就拋出?ProductNotFoundException?類。
package com.tutorialspoint.demo.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.tutorialspoint.demo.exception.ProductNotfoundException;
import com.tutorialspoint.demo.model.Product;
@RestController
public class ProductServiceController {
???private static Map<String, Product> productRepo = new HashMap<>();
???static {
??????Product honey = new Product();
??????honey.setId("1");
??????honey.setName("Honey");
??????productRepo.put(honey.getId(), honey);
??????
??????Product almond = new Product();
??????almond.setId("2");
??????almond.setName("Almond");
??????productRepo.put(almond.getId(), almond);
???}
???
???@RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
???public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody Product product) {
??????if(!productRepo.containsKey(id))throw new ProductNotfoundException();
??????productRepo.remove(id);
??????product.setId(id);
??????productRepo.put(id, product);
??????return new ResponseEntity<>("Product is updated successfully", HttpStatus.OK);
???}
}
? ??主 Spring Boot 應(yīng)用類文件如下:
package com.tutorialspoint.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
???public static void main(String[] args) {
??????SpringApplication.run(DemoApplication.class, args);
???}
}
? ? 產(chǎn)品?POJO 類?如下:
package com.tutorialspoint.demo.model;
public class Product {
???private String id;
???private String name;
???public String getId() {
??????return id;
???}
???public void setId(String id) {
??????this.id = id;
???}
???public String getName() {
??????return name;
???}
???public void setName(String name) {
??????this.name = name;
???}
}
? ??Maven build – pom.xml?代碼如下所示:
<?xml version = "1.0" encoding = "UTF-8"?>
<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.tutorialspoint</groupId>
???<artifactId>demo</artifactId>
???<version>0.0.1-SNAPSHOT</version>
???<packaging>jar</packaging>
???<name>demo</name>
???<description>Demo project for Spring Boot</description>
???<parent>
??????<groupId>org.springframework.boot</groupId>
??????<artifactId>spring-boot-starter-parent</artifactId>
??????<version>1.5.8.RELEASE</version>
??????<relativePath/>
???</parent>
???<properties>
??????<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
??????<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
??????<java.version>1.8</java.version>
???</properties>
???<dependencies>
??????<dependency>
?????????<groupId>org.springframework.boot</groupId>
?????????<artifactId>spring-boot-starter-web</artifactId>
??????</dependency>
??????<dependency>
?????????<groupId>org.springframework.boot</groupId>
?????????<artifactId>spring-boot-starter-test</artifactId>
?????????<scope>test</scope>
??????</dependency>
???</dependencies>
???<build>
??????<plugins>
?????????<plugin>
????????????<groupId>org.springframework.boot</groupId>
????????????<artifactId>spring-boot-maven-plugin</artifactId>
?????????</plugin>
??????</plugins>
???</build>
???
</project>
? ??Gradle Build – build.gradle?代碼如下:
buildscript {
???ext {
??????springBootVersion = '1.5.8.RELEASE'
???}
???repositories {
??????mavenCentral()
???}
???dependencies {
??????classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
???}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
???mavenCentral()
}
dependencies {
???compile('org.springframework.boot:spring-boot-starter-web')
???testCompile('org.springframework.boot:spring-boot-starter-test')
}
? ? 你可以使用?Maven 或 Gradle 命令構(gòu)建?JAR 并運(yùn)行 Spring Boot 應(yīng)用:
? ??Maven 命令如下:
mvn clean install
? ??“BUILD SUCCESS” 之后,你可以在 target 目錄下找到?JAR 文件。
? ??Gradle?可以使用如下命令:
gradle clean build
? ??“BUILD SUCCESSFUL” 后,你可以在 build/libs 目錄下找到 JAR 文件。
? ? 你可以使用下面的命令運(yùn)行?JAR 文件。
java –jar <JARFILE>
? ??在 Tomcat 8080 端口啟動(dòng)應(yīng)用,如下所示:

? ? 現(xiàn)在,在?POSTMAN 應(yīng)用中單擊下面的?URL,你可以看到如下輸出:
? ??更新 URL: http://localhost:8080/products/3
