--Fangen Sie Ausnahmen ab, die in der Controller-Klasse in der Spring Boot-Anwendung auftreten -Fangen Sie in der Klasse mit @ControllerAdvice jede Ausnahmeklasse mit der Methode mit @ExceptionHandler ab
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── example
│ └── my
│ ├── MyApplication.java
│ ├── MyController.java
│ ├── MyControllerAdvice.java
│ ├── MyException.java
│ └── MyHandlerExceptionResolver.java
└── resources
└── templates
└── myview.html
MyApplication.java
Spring Boot Boot Klasse.
package com.example.my;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
MyException.java
Eine einfache Ausnahmeklasse, die für diese Operationsprüfung vorbereitet wurde.
package com.example.my;
public class MyException extends Exception {
}
MyController.java
Eine Controller-Klasse, die das Routing übernimmt. Lösen Sie eine MyException-Ausnahme aus, wenn Sie auf http: // localhost: 8080 / myexception zugreifen. Lösen Sie eine Ausnahmebedingung aus, wenn der Zugriff auf http: // localhost: 8080 / exception erfolgt.
package com.example.my;
import org.springframework.boot.SpringApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class MyController {
public static void main(String[] args) {
SpringApplication.run(MyController.class, args);
}
@RequestMapping("/")
public ModelAndView handleTop(ModelAndView mav) {
mav.addObject("mymessage", "Hello, world.");
mav.setViewName("myview");
return mav;
}
@RequestMapping("/myexception")
public ModelAndView handleMyException(ModelAndView mav) throws MyException {
throw new MyException();
}
@RequestMapping("/exception")
public ModelAndView handleException(ModelAndView mav) throws Exception {
throw new Exception();
}
}
MyControllerAdvice.java
MyException Eine Klasse zum Abfangen von Ausnahmen. Kommentieren Sie die Klasse mit @ControllerAdvice. Die Annotation @ExceptionHandler wird der Methode zum Abfangen der Ausnahme hinzugefügt, und MyException.class wird angegeben. Referenz: [ExceptionHandler \ (Spring Framework 5 \ .1 \ .9 \ .RELEASE API )](https://docs.spring.io/spring/docs/5.1.9.RELEASE/javadoc-api/org/springframework /web/bind/annotation/ExceptionHandler.html)
package com.example.my;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class MyControllerAdvice {
@ExceptionHandler({MyException.class})
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ModelAndView handleMyException(Exception e, WebRequest req) {
System.out.println("MyControllerAdvice#handleMyException");
ModelAndView mav = new ModelAndView();
mav.addObject("myerror", "MyControllerAdvice#handleMyException");
mav.setViewName("myview");
return mav;
}
}
MyHandlerExceptionResolver.java
Eine Klasse zum Abfangen von Ausnahmen, die @ExceptionHandler nicht verarbeitet. Implementiert die HandlerExceptionResolver-Schnittstelle. Fügen Sie der Klasse die Annotation @Component hinzu, um sie im DI-Container als Bean zu registrieren. Referenz: [HandlerExceptionResolver \ (Spring Framework 5 \ .1 \ .9 \ .RELEASE API )](https://docs.spring.io/spring/docs/5.1.9.RELEASE/javadoc-api/org/springframework /web/servlet/HandlerExceptionResolver.html)
package com.example.my;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("MyHandlerExceptionResolver#resolveException");
System.out.println(handler.getClass());
System.out.println(handler);
ModelAndView mav = new ModelAndView();
mav.addObject("myerror", "MyHandlerExceptionResolver#resolveException");
mav.setViewName("myview");
mav.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
return mav;
}
}
myview.html
Thymeleaf-Vorlagendatei für die HTML-Ausgabe. Informationen wie Fehler anzeigen.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div th:if="${myerror}">
<div>Error: <span th:text="${myerror}"></span></div>
</div>
<div th:if="${mymessage}">
<div>Message: <span th:text="${mymessage}"></span></div>
</div>
</body>
</html>
pom.xml
Konfigurationsdatei zum Erstellen mit Maven.
<?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.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>my</artifactId>
<version>0.0.1</version>
<name>my</name>
<description>My project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Generieren Sie eine JAR-Datei mit dem Befehl mvn package von Maven.
$ mvn package
Geben Sie die generierte JAR-Datei an und starten Sie den Webserver durch Spring Boot mit dem Befehl java.
$ java -jar target/my-0.0.1.jar
http://localhost:8080/myexception
Zugang mit Locken. Sie können sehen, dass es von der handleMyException-Methode der MyControllerAdvice-Klasse behandelt wird.
$ curl http://localhost:8080/myexception
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<div>Error: <span>MyControllerAdvice#handleMyException</span></div>
</div>
</body>
</html>
Spring Boot Server-seitige Ausgabe.
MyControllerAdvice#handleMyException
Zugang mit Locken. Sie können sehen, dass es von der resolveException-Methode der MyHandlerExceptionResolver-Klasse behandelt wird.
$ curl http://localhost:8080/exception
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<div>Error: <span>MyHandlerExceptionResolver#resolveException</span></div>
</div>
</body>
</html>
Spring Boot Server-seitige Ausgabe.
MyHandlerExceptionResolver#resolveException
class org.springframework.web.method.HandlerMethod
public org.springframework.web.servlet.ModelAndView com.example.my.MyController.handleException(org.springframework.web.servlet.ModelAndView) throws java.lang.Exception
Die DispatcherServlet-Klasse verarbeitet mehrere HandlerExceptionResolver-Objekte.
ExceptionHandlerExceptionResolver-Klasse, ResponseStatusExceptionResolver-Klasse, DefaultHandlerExceptionResolver-Klasse werden vorbereitet, und diese Klassen behandeln Ausnahmen mit ihren jeweiligen Rollen.
Unter diesen wird die ExceptionHandlerExceptionResolver-Klasse verarbeitet, um die Methode mit der Annotation @ExceptionHandler aufzurufen.
DispatcherServlet (Spring Framework 5.1.9.RELEASE API)
The dispatcher's exception resolution strategy can be specified via a HandlerExceptionResolver, for example mapping certain exceptions to error pages. Default are ExceptionHandlerExceptionResolver, ResponseStatusExceptionResolver, and DefaultHandlerExceptionResolver. These HandlerExceptionResolvers can be overridden through the application context. HandlerExceptionResolver can be given any bean name (they are tested by type).
Zeigen Sie den Quellcode für die Spring Web MVC DispatcherServlet-Klasse an.
spring-framework/DispatcherServlet.java at v5.1.9.RELEASE · spring-projects/spring-framework
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler, Exception ex) throws Exception {
// Success and error responses may use different content types
request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
// Check registered HandlerExceptionResolvers...
ModelAndView exMv = null;
if (this.handlerExceptionResolvers != null) {
for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
exMv = resolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
}
In der processHandlerException-Methode wird das HandlerExceptionResolver-Objekt einzeln von this.handlerExceptionResolvers erfasst und die resolveException-Methode aufgerufen. Die resolveException-Methode jedes Objekts behandelt die Ausnahme und gibt ein ModelAndView-Objekt zurück.
Schauen wir uns das Objekt an, das vom IntelliJ IDEA-Debugger verarbeitet wird.
Sie können sehen, dass das HandlerExceptionResolverComposite-Objekt den ExceptionHandlerExceptionResolver, ResponseStatusExceptionResolver und DefaultHandlerExceptionResolver verwaltet.
Das ExceptionHandlerExceptionResolver-Objekt verfügt über eine Instanzvariable namens exceptionHandlerAdviceCache, die ein Objekt der mit @ControllerAdvice kommentierten Klasse enthält.
Wenn Sie sich den Quellcode von ExceptionHandlerExceptionResolver ansehen, können Sie sehen, dass er in exceptionHandlerAdviceCache registriert ist.
private void initExceptionHandlerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
AnnotationAwareOrderComparator.sort(adviceBeans);
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);
if (resolver.hasExceptionMappings()) {
this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
}
if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
this.responseBodyAdvice.add(adviceBean);
}
}
private void detectAnnotationExceptionMappings(Method method, List<Class<? extends Throwable>> result) {
ExceptionHandler ann = AnnotatedElementUtils.findMergedAnnotation(method, ExceptionHandler.class);
Assert.state(ann != null, "No ExceptionHandler annotation");
result.addAll(Arrays.asList(ann.value()));
}
Recommended Posts