Spring Boot 简明教程

Spring Boot - Exception Handling

在 API 中处理异常和错误,并向客户端发送适当响应,这对于企业应用程序而言十分有益。在本章中,我们将学习如何在 Spring Boot 中处理异常。

Handling exceptions and errors in APIs and sending the proper response to the client is good for enterprise applications. In this chapter, we will learn how to handle exceptions in Spring Boot.

在开始异常处理之前,让我们了解一下以下注解。

Before proceeding with exception handling, let us gain an understanding on the following annotations.

Controller Advice

@ControllerAdvice 是一种注解,用于全局处理异常。

The @ControllerAdvice is an annotation, to handle the exceptions globally.

Exception Handler

@ExceptionHandler 是一种注解,用于处理特定异常并向客户端发送自定义响应。

The @ExceptionHandler is an annotation used to handle the specific exceptions and sending the custom responses to the client.

你可以使用以下代码来创建 @ControllerAdvice 类以全局处理异常−

You can use the following code to create @ControllerAdvice class to handle the exceptions globally −

package com.tutorialspoint.demo.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;

@ControllerAdvice
   public class ProductExceptionController {
}

定义一个扩展 RuntimeException 类的类。

Define a class that extends the RuntimeException class.

package com.tutorialspoint.demo.exception;

public class ProductNotfoundException extends RuntimeException {
   private static final long serialVersionUID = 1L;
}

你可以定义 @ExceptionHandler 方法来处理异常,如下所示。这种方法应该用于编写控制器建议类文件。

You can define the @ExceptionHandler method to handle the exceptions as shown. This method should be used for writing the Controller Advice class file.

@ExceptionHandler(value = ProductNotfoundException.class)

public ResponseEntity<Object> exception(ProductNotfoundException exception) {
}

现在,使用下面给出的代码从 API 中抛出异常。

Now, use the code given below to throw the exception from the API.

@RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
public ResponseEntity<Object> updateProduct() {
   throw new ProductNotfoundException();
}

处理异常的完整代码如下所示。在这个示例中,我们使用 PUT API 来更新产品。这里,在更新产品时,如果未找到产品,则返回响应错误消息“未找到产品”。请注意, ProductNotFoundException 异常类应该扩展 RuntimeException

The complete code to handle the exception is given below. In this example, we used the PUT API to update the product. Here, while updating the product, if the product is not found, then return the response error message as “Product not found”. Note that the ProductNotFoundException exception class should extend the RuntimeException.

package com.tutorialspoint.demo.exception;
public class ProductNotfoundException extends RuntimeException {
   private static final long serialVersionUID = 1L;
}

全局处理异常的控制器建议类如下所示。我们可以在这个类文件中定义任何异常处理方法。

The Controller Advice class to handle the exception globally is given below. We can define any Exception Handler methods in this class file.

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);
   }
}

产品服务 API 控制器文件如下所示,用于更新产品。如果未找到产品,则会抛出 ProductNotFoundException 类。

The Product Service API controller file is given below to update the Product. If the Product is not found, then it throws the ProductNotFoundException class.

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 主应用程序类文件的代码如下 -

The code for main Spring Boot application class file is given below −

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);
   }
}

POJO class 的代码如下所示 −

The code for POJO class for Product is given below −

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 的代码如下所示 −

The code for Maven build – pom.xml is shown below −

<?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 的代码如下所示 −

The code for Gradle Build – build.gradle is given below −

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')
}

你可以创建一个可执行的 JAR 文件,并使用 Maven 或 Gradle 命令运行 Spring Boot 应用程序 −

You can create an executable JAR file, and run the Spring Boot application by using the Maven or Gradle commands −

对于 Maven,可以使用以下命令:

For Maven, you can use the following command −

mvn clean install

“BUILD SUCCESS”之后,您可以在目标目录中找到 JAR 文件。

After “BUILD SUCCESS”, you can find the JAR file under the target directory.

对于 Gradle,可以使用以下命令:

For Gradle, you can use the following command −

gradle clean build

“BUILD SUCCESSFUL”之后,您可以在 build/libs 目录中找到 JAR 文件。

After “BUILD SUCCESSFUL”, you can find the JAR file under the build/libs directory.

你可以使用以下命令运行 JAR 文件 −

You can run the JAR file by using the following command −

java –jar <JARFILE>

这将启动 8080 端口上的应用程序,如下所示 −

This will start the application on the Tomcat port 8080 as shown below −

exception handling tomcat application startded

现在在 POSTMAN 应用程序中访问下面的 URL,你就可以看到如下所示的输出 −

Now hit the below URL in POSTMAN application and you can see the output as shown below −

更新 URL: [role="bare"] [role="bare"]http://localhost:8080/products/3

Update URL: [role="bare"]http://localhost:8080/products/3

postman application update url