提交 7b894fe7 编写于 作者: J Juergen Hoeller

ResponseEntityExceptionHandler rethrows unknown exception (for further...

ResponseEntityExceptionHandler rethrows unknown exception (for further processing in DispatcherServlet's HandlerExceptionResolver chain)

Issue: SPR-16743
上级 fb898e17
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -129,8 +129,8 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
*/
@Override
@Nullable
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler, Exception ex) {
public ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
if (shouldApplyTo(request, handler)) {
if (this.logger.isDebugEnabled()) {
......
......@@ -70,7 +70,7 @@ import org.springframework.web.util.WebUtils;
* using view resolution (e.g., via {@code ContentNegotiatingViewResolver}),
* then {@code DefaultHandlerExceptionResolver} is good enough.
*
* <p>Note that in order for an {@code @ControllerAdvice} sub-class to be
* <p>Note that in order for an {@code @ControllerAdvice} subclass to be
* detected, {@link ExceptionHandlerExceptionResolver} must be configured.
*
* @author Rossen Stoyanchev
......@@ -121,8 +121,9 @@ public abstract class ResponseEntityExceptionHandler {
AsyncRequestTimeoutException.class
})
@Nullable
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) {
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception {
HttpHeaders headers = new HttpHeaders();
if (ex instanceof HttpRequestMethodNotSupportedException) {
HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED;
return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request);
......@@ -181,38 +182,17 @@ public abstract class ResponseEntityExceptionHandler {
}
else if (ex instanceof AsyncRequestTimeoutException) {
HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE;
return handleAsyncRequestTimeoutException(
(AsyncRequestTimeoutException) ex, headers, status, request);
return handleAsyncRequestTimeoutException((AsyncRequestTimeoutException) ex, headers, status, request);
}
else {
if (logger.isWarnEnabled()) {
logger.warn("Unknown exception type: " + ex.getClass().getName());
}
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
return handleExceptionInternal(ex, null, headers, status, request);
// Unknown exception, typically a wrapper with a common MVC exception as cause
// (since @ExceptionHandler type declarations also match first-level causes):
// We only deal with top-level MVC exceptions here, so let's rethrow the given
// exception for further processing through the HandlerExceptionResolver chain.
throw ex;
}
}
/**
* A single place to customize the response body of all Exception types.
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
* request attribute and creates a {@link ResponseEntity} from the given
* body, headers, and status.
* @param ex the exception
* @param body the body for the response
* @param headers the headers for the response
* @param status the response status
* @param request the current request
*/
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, @Nullable Object body,
HttpHeaders headers, HttpStatus status, WebRequest request) {
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
}
return new ResponseEntity<>(body, headers, status);
}
/**
* Customize the response for HttpRequestMethodNotSupportedException.
* <p>This method logs a warning, sets the "Allow" header, and delegates to
......@@ -223,8 +203,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(
HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
pageNotFoundLogger.warn(ex.getMessage());
......@@ -245,8 +225,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(
HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
List<MediaType> mediaTypes = ex.getSupportedMediaTypes();
if (!CollectionUtils.isEmpty(mediaTypes)) {
......@@ -265,8 +245,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(
HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -281,8 +261,8 @@ public abstract class ResponseEntityExceptionHandler {
* @return a {@code ResponseEntity} instance
* @since 4.2
*/
protected ResponseEntity<Object> handleMissingPathVariable(MissingPathVariableException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleMissingPathVariable(
MissingPathVariableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -296,8 +276,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleMissingServletRequestParameter(
MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -311,8 +291,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleServletRequestBindingException(
ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -326,8 +306,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleConversionNotSupported(ConversionNotSupportedException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleConversionNotSupported(
ConversionNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -341,8 +321,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleTypeMismatch(TypeMismatchException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleTypeMismatch(
TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -356,8 +336,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleHttpMessageNotReadable(
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -371,8 +351,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleHttpMessageNotWritable(HttpMessageNotWritableException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleHttpMessageNotWritable(
HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -386,8 +366,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -401,8 +381,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleMissingServletRequestPart(MissingServletRequestPartException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleMissingServletRequestPart(
MissingServletRequestPartException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -416,8 +396,8 @@ public abstract class ResponseEntityExceptionHandler {
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleBindException(
BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
......@@ -467,4 +447,24 @@ public abstract class ResponseEntityExceptionHandler {
return handleExceptionInternal(ex, null, headers, status, webRequest);
}
/**
* A single place to customize the response body of all Exception types.
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
* request attribute and creates a {@link ResponseEntity} from the given
* body, headers, and status.
* @param ex the exception
* @param body the body for the response
* @param headers the headers for the response
* @param status the response status
* @param request the current request
*/
protected ResponseEntity<Object> handleExceptionInternal(
Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
}
return new ResponseEntity<>(body, headers, status);
}
}
......@@ -53,9 +53,9 @@ import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
/**
* Default implementation of the {@link org.springframework.web.servlet.HandlerExceptionResolver
* HandlerExceptionResolver} interface that resolves standard Spring exceptions and translates
* them to corresponding HTTP status codes.
* The default implementation of the {@link org.springframework.web.servlet.HandlerExceptionResolver}
* interface, resolving standard Spring MVC exceptions and translating them to corresponding
* HTTP status codes.
*
* <p>This exception resolver is enabled by default in the common Spring
* {@link org.springframework.web.servlet.DispatcherServlet}.
......@@ -169,54 +169,59 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
try {
if (ex instanceof HttpRequestMethodNotSupportedException) {
return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, request,
response, handler);
return handleHttpRequestMethodNotSupported(
(HttpRequestMethodNotSupportedException) ex, request, response, handler);
}
else if (ex instanceof HttpMediaTypeNotSupportedException) {
return handleHttpMediaTypeNotSupported((HttpMediaTypeNotSupportedException) ex, request, response,
handler);
return handleHttpMediaTypeNotSupported(
(HttpMediaTypeNotSupportedException) ex, request, response, handler);
}
else if (ex instanceof HttpMediaTypeNotAcceptableException) {
return handleHttpMediaTypeNotAcceptable((HttpMediaTypeNotAcceptableException) ex, request, response,
handler);
return handleHttpMediaTypeNotAcceptable(
(HttpMediaTypeNotAcceptableException) ex, request, response, handler);
}
else if (ex instanceof MissingPathVariableException) {
return handleMissingPathVariable((MissingPathVariableException) ex, request,
response, handler);
return handleMissingPathVariable(
(MissingPathVariableException) ex, request, response, handler);
}
else if (ex instanceof MissingServletRequestParameterException) {
return handleMissingServletRequestParameter((MissingServletRequestParameterException) ex, request,
response, handler);
return handleMissingServletRequestParameter(
(MissingServletRequestParameterException) ex, request, response, handler);
}
else if (ex instanceof ServletRequestBindingException) {
return handleServletRequestBindingException((ServletRequestBindingException) ex, request, response,
handler);
return handleServletRequestBindingException(
(ServletRequestBindingException) ex, request, response, handler);
}
else if (ex instanceof ConversionNotSupportedException) {
return handleConversionNotSupported((ConversionNotSupportedException) ex, request, response, handler);
return handleConversionNotSupported(
(ConversionNotSupportedException) ex, request, response, handler);
}
else if (ex instanceof TypeMismatchException) {
return handleTypeMismatch((TypeMismatchException) ex, request, response, handler);
return handleTypeMismatch(
(TypeMismatchException) ex, request, response, handler);
}
else if (ex instanceof HttpMessageNotReadableException) {
return handleHttpMessageNotReadable((HttpMessageNotReadableException) ex, request, response, handler);
return handleHttpMessageNotReadable(
(HttpMessageNotReadableException) ex, request, response, handler);
}
else if (ex instanceof HttpMessageNotWritableException) {
return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, request, response, handler);
return handleHttpMessageNotWritable(
(HttpMessageNotWritableException) ex, request, response, handler);
}
else if (ex instanceof MethodArgumentNotValidException) {
return handleMethodArgumentNotValidException((MethodArgumentNotValidException) ex, request, response,
handler);
return handleMethodArgumentNotValidException(
(MethodArgumentNotValidException) ex, request, response, handler);
}
else if (ex instanceof MissingServletRequestPartException) {
return handleMissingServletRequestPartException((MissingServletRequestPartException) ex, request,
response, handler);
return handleMissingServletRequestPartException(
(MissingServletRequestPartException) ex, request, response, handler);
}
else if (ex instanceof BindException) {
return handleBindException((BindException) ex, request, response, handler);
}
else if (ex instanceof NoHandlerFoundException) {
return handleNoHandlerFoundException((NoHandlerFoundException) ex, request, response, handler);
return handleNoHandlerFoundException(
(NoHandlerFoundException) ex, request, response, handler);
}
else if (ex instanceof AsyncRequestTimeoutException) {
return handleAsyncRequestTimeoutException(
......@@ -225,7 +230,7 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
}
catch (Exception handlerException) {
if (logger.isWarnEnabled()) {
logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);
logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in exception", handlerException);
}
}
return null;
......@@ -550,7 +555,6 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
protected void sendServerError(Exception ex, HttpServletRequest request, HttpServletResponse response)
throws IOException {
request.setAttribute("javax.servlet.error.exception", ex);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
......
......@@ -20,6 +20,7 @@ import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import javax.servlet.ServletException;
import org.junit.Before;
import org.junit.Test;
......@@ -38,6 +39,8 @@ import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.mock.web.test.MockServletConfig;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
......@@ -48,11 +51,13 @@ import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
......@@ -86,9 +91,9 @@ public class ResponseEntityExceptionHandlerTests {
this.defaultExceptionResolver = new DefaultHandlerExceptionResolver();
}
@Test
public void supportsAllDefaultHandlerExceptionResolverExceptionTypes() throws Exception {
Class<ResponseEntityExceptionHandler> clazz = ResponseEntityExceptionHandler.class;
Method handleExceptionMethod = clazz.getMethod("handleException", Exception.class, WebRequest.class);
ExceptionHandler annotation = handleExceptionMethod.getAnnotation(ExceptionHandler.class);
......@@ -205,36 +210,109 @@ public class ResponseEntityExceptionHandlerTests {
@Test
public void controllerAdvice() throws Exception {
StaticWebApplicationContext cxt = new StaticWebApplicationContext();
cxt.registerSingleton("exceptionHandler", ApplicationExceptionHandler.class);
cxt.refresh();
StaticWebApplicationContext ctx = new StaticWebApplicationContext();
ctx.registerSingleton("exceptionHandler", ApplicationExceptionHandler.class);
ctx.refresh();
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
resolver.setApplicationContext(cxt);
resolver.setApplicationContext(ctx);
resolver.afterPropertiesSet();
ServletRequestBindingException ex = new ServletRequestBindingException("message");
resolver.resolveException(this.servletRequest, this.servletResponse, null, ex);
assertNotNull(resolver.resolveException(this.servletRequest, this.servletResponse, null, ex));
assertEquals(400, this.servletResponse.getStatus());
assertEquals("error content", this.servletResponse.getContentAsString());
assertEquals("someHeaderValue", this.servletResponse.getHeader("someHeader"));
}
@Test
public void controllerAdviceWithNestedException() {
StaticWebApplicationContext ctx = new StaticWebApplicationContext();
ctx.registerSingleton("exceptionHandler", ApplicationExceptionHandler.class);
ctx.refresh();
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
resolver.setApplicationContext(ctx);
resolver.afterPropertiesSet();
IllegalStateException ex = new IllegalStateException(new ServletRequestBindingException("message"));
assertNull(resolver.resolveException(this.servletRequest, this.servletResponse, null, ex));
}
@Test
public void controllerAdviceWithinDispatcherServlet() throws Exception {
StaticWebApplicationContext ctx = new StaticWebApplicationContext();
ctx.registerSingleton("controller", ExceptionThrowingController.class);
ctx.registerSingleton("exceptionHandler", ApplicationExceptionHandler.class);
ctx.refresh();
DispatcherServlet servlet = new DispatcherServlet(ctx);
servlet.init(new MockServletConfig());
servlet.service(this.servletRequest, this.servletResponse);
assertEquals(400, this.servletResponse.getStatus());
assertEquals("error content", this.servletResponse.getContentAsString());
assertEquals("someHeaderValue", this.servletResponse.getHeader("someHeader"));
}
@Test
public void controllerAdviceWithNestedExceptionWithinDispatcherServlet() throws Exception {
StaticWebApplicationContext ctx = new StaticWebApplicationContext();
ctx.registerSingleton("controller", NestedExceptionThrowingController.class);
ctx.registerSingleton("exceptionHandler", ApplicationExceptionHandler.class);
ctx.refresh();
DispatcherServlet servlet = new DispatcherServlet(ctx);
servlet.init(new MockServletConfig());
try {
servlet.service(this.servletRequest, this.servletResponse);
}
catch (ServletException ex) {
assertTrue(ex.getCause() instanceof IllegalStateException);
assertTrue(ex.getCause().getCause() instanceof ServletRequestBindingException);
}
}
private ResponseEntity<Object> testException(Exception ex) {
ResponseEntity<Object> responseEntity = this.exceptionHandlerSupport.handleException(ex, this.request);
try {
ResponseEntity<Object> responseEntity = this.exceptionHandlerSupport.handleException(ex, this.request);
// SPR-9653
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(responseEntity.getStatusCode())) {
assertSame(ex, this.servletRequest.getAttribute("javax.servlet.error.exception"));
}
this.defaultExceptionResolver.resolveException(this.servletRequest, this.servletResponse, null, ex);
assertEquals(this.servletResponse.getStatus(), responseEntity.getStatusCode().value());
// SPR-9653
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(responseEntity.getStatusCode())) {
assertSame(ex, this.servletRequest.getAttribute("javax.servlet.error.exception"));
return responseEntity;
}
catch (Exception ex2) {
throw new IllegalStateException("handleException threw exception", ex2);
}
}
@Controller
private static class ExceptionThrowingController {
this.defaultExceptionResolver.resolveException(this.servletRequest, this.servletResponse, null, ex);
@RequestMapping("/")
public void handleRequest() throws Exception {
throw new ServletRequestBindingException("message");
}
}
assertEquals(this.servletResponse.getStatus(), responseEntity.getStatusCode().value());
return responseEntity;
@Controller
private static class NestedExceptionThrowingController {
@RequestMapping("/")
public void handleRequest() throws Exception {
throw new IllegalStateException(new ServletRequestBindingException("message"));
}
}
......@@ -242,8 +320,8 @@ public class ResponseEntityExceptionHandlerTests {
private static class ApplicationExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleServletRequestBindingException(
ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
headers.set("someHeader", "someHeaderValue");
return handleExceptionInternal(ex, "error content", headers, status, request);
......
......@@ -2448,8 +2448,8 @@ in `@ControllerAdvice` classes to apply them globally.
====
Note that Spring WebFlux does not have an equivalent for the Spring MVC
`ResponseEntityExceptionHandler` because WebFlux only raises `ResponseStatusException`
(or sub-classes of), which and those do not need to be translated translation to an HTTP
status code.
(or subclasses thereof), which and those do not need to be translated translation to
an HTTP status code.
====
......
......@@ -2977,7 +2977,7 @@ Applications that implement global exception handling with error details in the
body should consider extending
{api-spring-framework}/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.html[ResponseEntityExceptionHandler]
which provides handling for exceptions that Spring MVC raises along with hooks to
customize the response body. To make use of this, create a sub-class of
customize the response body. To make use of this, create a subclass of
`ResponseEntityExceptionHandler`, annotate with `@ControllerAdvice`, override the
necessary methods, and declare it as a Spring bean.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册