Spring Boot
对于异常的处理也做了不错的支持,它提供了一个@ControllerAdvice
注解以及 @ExceptionHandler
注解,前者是用来开启全局的异常捕获,后者则是说明捕获哪些异常,对这些捕获的异常进行处理。
测试代码
项目结构图:
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 https://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.6.2</version>
</parent>
<packaging>jar</packaging>
<groupId>com.kaven</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot</name>
<description>springboot</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.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>
DeepLearningTrainException
类(自定义异常):
package com.kaven.springboot.exception;
public class DeepLearningTrainException extends RuntimeException{
public String gpuMessage;
public DeepLearningTrainException(String message) {
this.gpuMessage = message;
}
public String addHandler(String handler) {
return this.gpuMessage + handler;
}
}
ResponseVO
类(自定义响应封装类):
package com.kaven.springboot.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Setter;
@Setter
@Builder
@AllArgsConstructor
public class ResponseVO<T> {
public Integer code;
public String message;
public T data;
}
DeepLearningController
类(定义接口):
package com.kaven.springboot.controller;
import com.kaven.springboot.exception.DeepLearningTrainException;
import com.kaven.springboot.vo.ResponseVO;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DeepLearningController {
@GetMapping("/train/{gpu}")
public ResponseVO<String> train(@PathVariable(name = "gpu") boolean gpu) {
System.out.println("方面级情感分析模型正在训练...");
System.out.println("GPU显存不足");
if(gpu) throw new DeepLearningTrainException("方面级情感分析模型训练失败,GPU显存不足");
else System.out.println("方面级情感分析模型训练成功");
return new ResponseVO<>(HttpStatus.OK.value(), HttpStatus.OK.name(), "训练成功");
}
}
GlobalExceptionHandler
类(全局异常处理):
package com.kaven.springboot.handler.exception;
import com.kaven.springboot.exception.DeepLearningTrainException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(DeepLearningTrainException.class)
public String DeepLearningTrainExceptionHandler(Exception e) {
DeepLearningTrainException exception = (DeepLearningTrainException) e;
return exception.addHandler("[DeepLearningTrainExceptionHandler]");
}
}
@RestControllerAdvice
注解组合了@ControllerAdvice
和@ResponseBody
这两个注解,因此全局异常处理方法可以以JSON
数据进行响应。
SpringbootApplication
类(启动类):
package com.kaven.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringbootApplication.class);
application.run(args);
}
}
application.properties
(配置文件):
server.port=8080
Spring Boot
应用的默认启动端口也是8080
,这里只是为了演示。
启动应用,访问http://localhost:8080/train/true
,响应如下图所示。
很显然针对自定义异常DeepLearningTrainException
的全局异常处理起作用了。
访问http://localhost:8080/train/false
,响应如下图所示。
404异常特殊处理
默认情况下,Spring Boot
是不会抛出404
异常,所以@ControllerAdvice
也不能捕获到404
异常,比如访问http://localhost:8080/kaven
。
就算添加针对异常NoHandlerFoundException
的全局异常处理,也不能捕获到404
异常。
@ExceptionHandler(NoHandlerFoundException.class)
public String NoHandlerFoundExceptionHandler(Exception e) {
NoHandlerFoundException exception = (NoHandlerFoundException) e;
return exception.getMessage() + "[NoHandlerFoundException]";
}
可以通过以下配置来让这个全局异常处理捕获到404
异常(NoHandlerFoundException
)。
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false
很显然针对异常NoHandlerFoundException
的全局异常处理起作用了。
spring.mvc.throw-exception-if-no-handler-found=true
当发现404
异常时直接抛出异常。
spring.web.resources.add-mappings=false
关闭默认的静态资源路径映射,这样404
错误就能被捕获到,但是这个配置会让静态资源访问出现问题,也就是不适合前后端不分离的情况。
添加访问静态资源的接口,IndexController
类(定义接口):
package com.kaven.springboot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class IndexController {
@GetMapping("/index")
public String index() {
return "index";
}
}
index.html
(静态资源):
添加配置:
spring.mvc.view.suffix=.html
访问http://localhost:8080/index
,也被全局异常处理捕获了。
添加如下配置类,就能正常访问静态资源了。
package com.kaven.springboot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class ResourceConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
再添加配置:
spring.mvc.view.prefix=/static/
访问http://localhost:8080/index
,就可以正常访问静态资源了,这些配置博主以后都会详细介绍。
也能正常请求其他接口。Spring Boot
全局异常处理就介绍到这里,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。