Spring Boot @ExceptionHandler 教程展示了如何使用 Spring @ExceptionHandler 处理异常。
Spring 是流行的 Java 应用框架,而 Spring Boot 是 Spring 的演进,可以帮助轻松地创建独立的,生产级的基于 Spring 的应用。
@ExceptionHandler
是用于在特定处理程序类或处理程序方法中处理异常的注解。 在 Servlet 环境中,我们可以将@ExceptionHandler
注解与@ResponseStatus
结合起来以定义 HTTP 响应的响应状态。
Spring Boot @ExceptionHandler
示例
在以下应用中,我们演示@ExceptionHandler
的用法。 主页中的 HTML 链接调用控制器的方法,该方法将返回数据或引发异常。
pom.xml
src
├── main
│ ├── java
│ │ └── com
│ │ └── zetcode
│ │ ├── Application.java
│ │ ├── controller
│ │ │ └── MyController.java
│ │ ├── exception
│ │ │ └── MyDataException.java
│ │ └── service
│ │ ├── IDataService.java
│ │ └── MyDataService.java
│ └── resources
│ ├── static
│ │ ├── index.html
│ │ └── showError.html
│ └── templates
│ └── showData.ftl
└── test
└── java
这是 Spring 应用的项目结构。
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.zetcode</groupId>
<artifactId>springbootexceptionhandlerex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
这是 Maven pom.xml
文件。 spring-boot-starter-freemarker
是 Freemarker 模板引擎的依赖项; spring-boot-maven-plugin
将 Spring 应用打包到可执行的 JAR 或 WAR 归档文件中。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import com.zetcode.exception.MyDataException;
import com.zetcode.service.IDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.HashMap;
import java.util.Map;
@Controller
public class MyController {
@Autowired
private IDataService dataService;
@RequestMapping(value = "/getData")
public ModelAndView getData() {
var data = dataService.findAll();
Map<String, Object> params = new HashMap<>();
params.put("values", data);
return new ModelAndView("showData", params);
}
@ExceptionHandler(MyDataException.class)
public String handleError(MyDataException e) {
return "redirect:/showError.html";
}
}
MyController's
getData()
方法调用服务方法,并将检索到的数据存储到列表中。 数据被发送到showData
视图。 如果是MyDataException
,则控制器将重定向到错误页面。
@ExceptionHandler(MyDataException.class)
public String handleError(MyDataException e) {
return "redirect:/showError.html";
}
handleError()
用@ExceptionHandler
装饰。 MyDataException
的处理程序已激活。 在方法的主体中,我们重定向到showError.html
页面。
com/zetcode/exception/MyDataException.java
package com.zetcode.exception;
public class MyDataException extends RuntimeException {
public MyDataException(String message) {
super(message);
}
}
我们定义一个自定义MyDataException
。
com/zetcode/service/IDataService.java
package com.zetcode.service;
import java.util.List;
public interface IDataService {
List<String> findAll();
}
IDataService
包含合同方法。
com/zetcode/service/MyDataService.java
package com.zetcode.service;
import com.zetcode.exception.MyDataException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.springframework.stereotype.Service;
@Service
public class MyDataService implements IDataService {
@Override
public List<String> findAll() {
var r = new Random();
if (r.nextBoolean()) {
throw new MyDataException("Failed to retrieve data");
}
var data = new ArrayList<String>();
data.add("yellow moon");
data.add("brisk pace");
data.add("empty bottle");
data.add("beautiful weather");
return data;
}
}
MyDataService
实现IDataService's
findAll()
方法。 该方法返回数据或抛出MyDataException
。
var r = new Random();
if (r.nextBoolean()) {
throw new MyDataException("Failed to retrieve data");
}
findAll()
方法随机抛出MyDataException
。 然后在控制器中处理异常。
var data = new ArrayList<>();
data.add("yellow moon");
data.add("brisk pace");
data.add("empty bottle");
data.add("beautiful weather");
return data;
如果没有例外,我们将返回一个字符串列表。
resources/static/index.html
<!DOCTYPE html>
<html>
<head>
<title>Home page</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<a href="/getData">Get data</a>
</body>
</html>
这是主页。 它包含一个链接,该链接调用我们的控制器方法以获取一些数据。
resources/static/showError.html
<!DOCTYPE html>
<html>
<head>
<title>Error</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>Failed to retrieve data</p>
</body>
</html>
这是一个错误页面。 抛出MyDataException
时显示。
resources/templates/showData.ftl
<!DOCTYPE html>
<html>
<head>
<title>Data</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h2>Data</h2>
<ul>
<#list values as val>
<li>${val}</td>
</#list>
</ul>
</body>
</html>
showData.ftl
是一个 Freemarker 模板文件,它在 HTML 列表中显示所有检索到的数据。
com/zetcode/Application.java
package com.zetcode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Application
是引导 Spring Boot 应用的入口点。
在本教程中,我们展示了如何使用@ExceptionHandler
在 Spring 应用中处理异常。