優雅的處理Spring Boot異常資訊

羅摩爾發表於2019-04-10

Spring Boot 異常處理

異常處理是一種識別並響應錯誤的一致性機制,異常機制可以把程式中的異常處理程式碼和正常的業務邏輯程式碼分離,包裝程式的可讀性和健壯性。在Spring Boot應用程式中,能夠捕獲並及時的響應客戶端的錯誤操作是一件非常重要的事情。在本章節中,我將展示如何處理Spring Boot中的異常。

1. 相關注解說明

在進行演示之前,我們先了解一下在Spring Boot應用程式中與異常處理相關的幾個註解

註解名稱 說明
@ControllerAdvice 該標籤用於處理全域性的異常資訊
@ExceptionHadler 用於處理特定異常資訊,並返回相關的響應到客戶端

首先,我們需要使用**@ControllerAdvice**註解來定義一個全域性的異常資訊處理類,其語法如下:

package com.ramostear.exception.handler;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * @author : ramostear
 * @date : 2019/3/6 0006-16:33
 */
@ControllerAdvice
public class UserExceptionHandler {
	//TODO ...
}

複製程式碼

接下來,我們需要定義一個擴充套件了RuntimeException類的自定義異常處理類:

package com.ramostear.exception.handler;

/**
 * @author : ramostear
 * @date : 2019/3/6 0006-16:31
 */
public class UserNotFoundException extends RuntimeException{
    private static final long serialVersionUID = 5534028121297403043L;
}

複製程式碼

最後,我們使用**@ExceptionHandler**註解來定義一個處理具體異常資訊的方法,其語法如下:

@ExceptionHandler(value = UserNotFoundException.class)
    public ResponseEntity<Object> exception(UserNotFoundException ex){
        return new ResponseEntity<>("user not found.", HttpStatus.NOT_FOUND);
    }
複製程式碼

以上工作準備完成之後,我們可以使用如下的方式來處理API中的異常資訊:

@GetMapping("/users/{id}")
    public ResponseEntity<Object> getUser(@PathVariable(name = "id") long id){
        if(!userRepo.containsKey ( id )){
            throw new UserNotFoundException ();
        }
        return new ResponseEntity<> (userRepo.get (id), HttpStatus.OK);
    }
複製程式碼

在接下來的內容當中,我將給出完整的示例程式碼,使用HTTP GET方法請求一個使用者資訊,當使用者儲存庫中沒有相應的使用者資訊時,返回“user not found”提示資訊。

2. 自定義異常資訊類 — UserNotFoundException.java

package com.ramostear.exception.handler;

/**
 * @author : ramostear
 * @date : 2019/3/6 0006-16:31
 */
public class UserNotFoundException extends RuntimeException{
    private static final long serialVersionUID = 5534028121297403043L;
}

複製程式碼

說明:這裡只是做了一個簡單的擴充套件

2. 全域性異常處理類 —UserExceptionHandler.java

package com.ramostear.exception.handler;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * @author : ramostear
 * @date : 2019/3/6 0006-16:33
 */
@ControllerAdvice
public class UserExceptionHandler {


    @ExceptionHandler(value = UserNotFoundException.class)
    public ResponseEntity<Object> exception(UserNotFoundException ex){
        return new ResponseEntity<>("user not found.", HttpStatus.NOT_FOUND);
    }


}

複製程式碼

在UserExceptionHandler.java檔案中,我們定義了一個處理使用者不存在異常的方法,

3. API類 — UserServiceController.java

package com.ramostear.exception.handler.controller;

import com.ramostear.exception.handler.UserNotFoundException;
import com.ramostear.exception.handler.model.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * @author : ramostear
 * @date : 2019/3/6 0006-16:26
 */
@RestController
public class UserServiceController {

    private static Map<Long,User> userRepo = new HashMap<>();

    @PostConstruct
    public void initUserRepo(){
        User admin = new User ().setId ( 1 ).setName ( "admin" );
        userRepo.put ( admin.getId (),admin );

        User editor = new User ().setId ( 2 ).setName ( "editor" );
        userRepo.put ( editor.getId (),editor );
    }


    @GetMapping("/users/{id}")
    public ResponseEntity<Object> getUser(@PathVariable(name = "id") long id){
        if(!userRepo.containsKey ( id )){
            throw new UserNotFoundException ();
        }
        return new ResponseEntity<> (userRepo.get (id), HttpStatus.OK);
    }

}

複製程式碼

在getUser()方法中,如果使用者沒有找到,則丟擲UserNotFoundException異常。

4. 應用主類 —ExceptionHandlerApplication.java

package com.ramostear.exception.handler;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ExceptionHandlerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ExceptionHandlerApplication.class, args);
	}

}

複製程式碼

5. 使用者POJO類 — User.java

package com.ramostear.exception.handler.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * @author : ramostear
 * @date : 2019/3/6 0006-16:23
 */
@Getter
@Setter
@NoArgsConstructor
public class User {

    private long id;

    private String name;

    public User setId(long id){
        this.id = id;
        return this;
    }

    public User setName(String name){
        this.name = name;
        return this;
    }
}

複製程式碼

6. Maven構建檔案 — 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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.ramostear</groupId>
	<artifactId>exception-handler</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>exception-handler</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<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>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

複製程式碼

8. 執行測試

接下來,我們將打包執行我們的程式,本次教程演示將使用IDEA來執行程式,執行結果如下圖所示:

優雅的處理Spring Boot異常資訊

然後,啟動Postman應用程式,我們先在位址列輸入:http://localhost:8080/users/1 ,觀察正常情況下的測試資訊:

優雅的處理Spring Boot異常資訊

Postman的測試結果顯示,請求狀態為200,且返回了使用者的詳細資訊。現在,我們更新URL為:http://localhost:8080/users/3 ,再次觀察測試結果:

優雅的處理Spring Boot異常資訊

此時的HTTP Status為404,且返回了“user not found.”的提示資訊。

作者:譚朝紅 , 原文:優雅的處理Spring Boot異常資訊

相關文章