DefaultHandlerExceptionResolver.java 24.1 KB
Newer Older
1
/*
2
 * Copyright 2002-2021 the original author or authors.
3 4 5 6 7
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
S
Spring Operator 已提交
8
 *      https://www.apache.org/licenses/LICENSE-2.0
9 10 11 12 13 14 15 16
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

17
package org.springframework.web.servlet.mvc.support;
18

19
import java.io.IOException;
20
import java.util.List;
21

22 23 24 25 26
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
27

28
import org.springframework.beans.ConversionNotSupportedException;
29 30 31 32 33
import org.springframework.beans.TypeMismatchException;
import org.springframework.core.Ordered;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
34
import org.springframework.lang.Nullable;
35
import org.springframework.util.CollectionUtils;
36
import org.springframework.util.StringUtils;
37 38
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
J
Juergen Hoeller 已提交
39
import org.springframework.web.HttpMediaTypeNotAcceptableException;
40 41
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
42
import org.springframework.web.bind.MethodArgumentNotValidException;
43
import org.springframework.web.bind.MissingPathVariableException;
44
import org.springframework.web.bind.MissingServletRequestParameterException;
45
import org.springframework.web.bind.ServletRequestBindingException;
46
import org.springframework.web.bind.annotation.ModelAttribute;
47 48
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestPart;
49
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
50 51
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
52
import org.springframework.web.servlet.ModelAndView;
53
import org.springframework.web.servlet.NoHandlerFoundException;
54
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
55 56

/**
57 58 59
 * 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.
J
Juergen Hoeller 已提交
60
 *
61 62
 * <p>This exception resolver is enabled by default in the common Spring
 * {@link org.springframework.web.servlet.DispatcherServlet}.
63
 *
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
 * <p>
 * <table>
 * <caption>Supported Exceptions</caption>
 * <thead>
 * <tr>
 * <th class="colFirst">Exception</th>
 * <th class="colLast">HTTP Status Code</th>
 * </tr>
 * </thead>
 * <tbody>
 * <tr class="altColor">
 * <td><p>HttpRequestMethodNotSupportedException</p></td>
 * <td><p>405 (SC_METHOD_NOT_ALLOWED)</p></td>
 * </tr>
 * <tr class="rowColor">
 * <td><p>HttpMediaTypeNotSupportedException</p></td>
 * <td><p>415 (SC_UNSUPPORTED_MEDIA_TYPE)</p></td>
 * </tr>
 * <tr class="altColor">
 * <td><p>HttpMediaTypeNotAcceptableException</p></td>
 * <td><p>406 (SC_NOT_ACCEPTABLE)</p></td>
 * </tr>
 * <tr class="rowColor">
 * <td><p>MissingPathVariableException</p></td>
 * <td><p>500 (SC_INTERNAL_SERVER_ERROR)</p></td>
 * </tr>
 * <tr class="altColor">
 * <td><p>MissingServletRequestParameterException</p></td>
92
 * <td><p>400 (SC_BAD_REQUEST)</p></td>
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
 * </tr>
 * <tr class="rowColor">
 * <td><p>ServletRequestBindingException</p></td>
 * <td><p>400 (SC_BAD_REQUEST)</p></td>
 * </tr>
 * <tr class="altColor">
 * <td><p>ConversionNotSupportedException</p></td>
 * <td><p>500 (SC_INTERNAL_SERVER_ERROR)</p></td>
 * </tr>
 * <tr class="rowColor">
 * <td><p>TypeMismatchException</p></td>
 * <td><p>400 (SC_BAD_REQUEST)</p></td>
 * </tr>
 * <tr class="altColor">
 * <td><p>HttpMessageNotReadableException</p></td>
 * <td><p>400 (SC_BAD_REQUEST)</p></td>
 * </tr>
 * <tr class="rowColor">
 * <td><p>HttpMessageNotWritableException</p></td>
 * <td><p>500 (SC_INTERNAL_SERVER_ERROR)</p></td>
 * </tr>
 * <tr class="altColor">
 * <td><p>MethodArgumentNotValidException</p></td>
 * <td><p>400 (SC_BAD_REQUEST)</p></td>
 * </tr>
 * <tr class="rowColor">
 * <td><p>MissingServletRequestPartException</p></td>
 * <td><p>400 (SC_BAD_REQUEST)</p></td>
 * </tr>
 * <tr class="altColor">
 * <td><p>BindException</p></td>
 * <td><p>400 (SC_BAD_REQUEST)</p></td>
 * </tr>
 * <tr class="rowColor">
 * <td><p>NoHandlerFoundException</p></td>
S
Sola 已提交
128
 * <td><p>404 (SC_NOT_FOUND)</p></td>
129 130 131 132 133 134 135 136
 * </tr>
 * <tr class="altColor">
 * <td><p>AsyncRequestTimeoutException</p></td>
 * <td><p>503 (SC_SERVICE_UNAVAILABLE)</p></td>
 * </tr>
 * </tbody>
 * </table>
 *
137
 * @author Arjen Poutsma
138
 * @author Rossen Stoyanchev
139
 * @author Juergen Hoeller
J
Juergen Hoeller 已提交
140
 * @since 3.0
141
 * @see org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
 */
public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionResolver {

	/**
	 * Log category to use when no mapped handler is found for a request.
	 * @see #pageNotFoundLogger
	 */
	public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound";

	/**
	 * Additional logger to use when no mapped handler is found for a request.
	 * @see #PAGE_NOT_FOUND_LOG_CATEGORY
	 */
	protected static final Log pageNotFoundLogger = LogFactory.getLog(PAGE_NOT_FOUND_LOG_CATEGORY);

J
Juergen Hoeller 已提交
157 158 159 160

	/**
	 * Sets the {@linkplain #setOrder(int) order} to {@link #LOWEST_PRECEDENCE}.
	 */
161 162
	public DefaultHandlerExceptionResolver() {
		setOrder(Ordered.LOWEST_PRECEDENCE);
163
		setWarnLogCategory(getClass().getName());
164 165
	}

J
Juergen Hoeller 已提交
166

167
	@Override
168
	@Nullable
J
Juergen Hoeller 已提交
169 170
	protected ModelAndView doResolveException(
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
J
Juergen Hoeller 已提交
171

172
		try {
173
			if (ex instanceof HttpRequestMethodNotSupportedException) {
174 175
				return handleHttpRequestMethodNotSupported(
						(HttpRequestMethodNotSupportedException) ex, request, response, handler);
176 177
			}
			else if (ex instanceof HttpMediaTypeNotSupportedException) {
178 179
				return handleHttpMediaTypeNotSupported(
						(HttpMediaTypeNotSupportedException) ex, request, response, handler);
180
			}
181
			else if (ex instanceof HttpMediaTypeNotAcceptableException) {
182 183
				return handleHttpMediaTypeNotAcceptable(
						(HttpMediaTypeNotAcceptableException) ex, request, response, handler);
184
			}
185
			else if (ex instanceof MissingPathVariableException) {
186 187
				return handleMissingPathVariable(
						(MissingPathVariableException) ex, request, response, handler);
188
			}
189
			else if (ex instanceof MissingServletRequestParameterException) {
190 191
				return handleMissingServletRequestParameter(
						(MissingServletRequestParameterException) ex, request, response, handler);
192
			}
193
			else if (ex instanceof ServletRequestBindingException) {
194 195
				return handleServletRequestBindingException(
						(ServletRequestBindingException) ex, request, response, handler);
196
			}
197
			else if (ex instanceof ConversionNotSupportedException) {
198 199
				return handleConversionNotSupported(
						(ConversionNotSupportedException) ex, request, response, handler);
200
			}
201
			else if (ex instanceof TypeMismatchException) {
202 203
				return handleTypeMismatch(
						(TypeMismatchException) ex, request, response, handler);
204 205
			}
			else if (ex instanceof HttpMessageNotReadableException) {
206 207
				return handleHttpMessageNotReadable(
						(HttpMessageNotReadableException) ex, request, response, handler);
208 209
			}
			else if (ex instanceof HttpMessageNotWritableException) {
210 211
				return handleHttpMessageNotWritable(
						(HttpMessageNotWritableException) ex, request, response, handler);
212
			}
213
			else if (ex instanceof MethodArgumentNotValidException) {
214 215
				return handleMethodArgumentNotValidException(
						(MethodArgumentNotValidException) ex, request, response, handler);
216
			}
217
			else if (ex instanceof MissingServletRequestPartException) {
218 219
				return handleMissingServletRequestPartException(
						(MissingServletRequestPartException) ex, request, response, handler);
220
			}
221 222 223
			else if (ex instanceof BindException) {
				return handleBindException((BindException) ex, request, response, handler);
			}
224
			else if (ex instanceof NoHandlerFoundException) {
225 226
				return handleNoHandlerFoundException(
						(NoHandlerFoundException) ex, request, response, handler);
227
			}
228 229 230 231
			else if (ex instanceof AsyncRequestTimeoutException) {
				return handleAsyncRequestTimeoutException(
						(AsyncRequestTimeoutException) ex, request, response, handler);
			}
232 233
		}
		catch (Exception handlerEx) {
J
Juergen Hoeller 已提交
234 235 236
			if (logger.isWarnEnabled()) {
				logger.warn("Failure while trying to resolve exception [" + ex.getClass().getName() + "]", handlerEx);
			}
237
		}
J
Juergen Hoeller 已提交
238
		return null;
239 240 241
	}

	/**
J
Juergen Hoeller 已提交
242 243 244 245
	 * Handle the case where no request handler method was found for the particular HTTP request method.
	 * <p>The default implementation logs a warning, sends an HTTP 405 error, sets the "Allow" header,
	 * and returns an empty {@code ModelAndView}. Alternatively, a fallback view could be chosen,
	 * or the HttpRequestMethodNotSupportedException could be rethrown as-is.
246 247 248
	 * @param ex the HttpRequestMethodNotSupportedException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
249
	 * @param handler the executed handler, or {@code null} if none chosen
J
Juergen Hoeller 已提交
250
	 * at the time of the exception (for example, if multipart resolution failed)
251
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
252
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
253 254
	 */
	protected ModelAndView handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
255
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
256 257 258 259 260 261 262 263 264 265 266

		String[] supportedMethods = ex.getSupportedMethods();
		if (supportedMethods != null) {
			response.setHeader("Allow", StringUtils.arrayToDelimitedString(supportedMethods, ", "));
		}
		response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, ex.getMessage());
		return new ModelAndView();
	}

	/**
	 * Handle the case where no {@linkplain org.springframework.http.converter.HttpMessageConverter message converters}
267 268 269 270
	 * were found for the PUT or POSTed content.
	 * <p>The default implementation sends an HTTP 415 error, sets the "Accept" header,
	 * and returns an empty {@code ModelAndView}. Alternatively, a fallback view could
	 * be chosen, or the HttpMediaTypeNotSupportedException could be rethrown as-is.
271 272 273
	 * @param ex the HttpMediaTypeNotSupportedException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
274 275
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
276
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
277 278
	 */
	protected ModelAndView handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex,
279
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
280 281

		List<MediaType> mediaTypes = ex.getSupportedMediaTypes();
282
		if (!CollectionUtils.isEmpty(mediaTypes)) {
283
			response.setHeader("Accept", MediaType.toString(mediaTypes));
284 285 286
			if (request.getMethod().equals("PATCH")) {
				response.setHeader("Accept-Patch", MediaType.toString(mediaTypes));
			}
287
		}
288
		response.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
289 290 291
		return new ModelAndView();
	}

292 293 294
	/**
	 * Handle the case where no {@linkplain org.springframework.http.converter.HttpMessageConverter message converters}
	 * were found that were acceptable for the client (expressed via the {@code Accept} header.
J
Juergen Hoeller 已提交
295 296 297
	 * <p>The default implementation sends an HTTP 406 error and returns an empty {@code ModelAndView}.
	 * Alternatively, a fallback view could be chosen, or the HttpMediaTypeNotAcceptableException
	 * could be rethrown as-is.
298 299 300
	 * @param ex the HttpMediaTypeNotAcceptableException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
301 302
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
303
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
304 305
	 */
	protected ModelAndView handleHttpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex,
306
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
307 308 309 310 311

		response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE);
		return new ModelAndView();
	}

312 313 314 315 316 317 318 319 320 321
	/**
	 * Handle the case when a declared path variable does not match any extracted URI variable.
	 * <p>The default implementation sends an HTTP 500 error, and returns an empty {@code ModelAndView}.
	 * Alternatively, a fallback view could be chosen, or the MissingPathVariableException
	 * could be rethrown as-is.
	 * @param ex the MissingPathVariableException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
322
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
323 324 325
	 * @since 4.2
	 */
	protected ModelAndView handleMissingPathVariable(MissingPathVariableException ex,
326
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
327 328 329 330 331

		response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage());
		return new ModelAndView();
	}

332
	/**
J
Juergen Hoeller 已提交
333 334 335 336
	 * Handle the case when a required parameter is missing.
	 * <p>The default implementation sends an HTTP 400 error, and returns an empty {@code ModelAndView}.
	 * Alternatively, a fallback view could be chosen, or the MissingServletRequestParameterException
	 * could be rethrown as-is.
337 338 339
	 * @param ex the MissingServletRequestParameterException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
340 341
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
342
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
343 344
	 */
	protected ModelAndView handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
345
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
346

347
		response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
348 349 350 351 352 353 354 355 356 357 358 359
		return new ModelAndView();
	}

	/**
	 * Handle the case when an unrecoverable binding exception occurs - e.g. required header, required cookie.
	 * <p>The default implementation sends an HTTP 400 error, and returns an empty {@code ModelAndView}.
	 * Alternatively, a fallback view could be chosen, or the exception could be rethrown as-is.
	 * @param ex the exception to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
360
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
361 362
	 */
	protected ModelAndView handleServletRequestBindingException(ServletRequestBindingException ex,
363
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
364

365
		response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
366 367 368
		return new ModelAndView();
	}

369
	/**
J
Juergen Hoeller 已提交
370 371
	 * Handle the case when a {@link org.springframework.web.bind.WebDataBinder} conversion cannot occur.
	 * <p>The default implementation sends an HTTP 500 error, and returns an empty {@code ModelAndView}.
372 373
	 * Alternatively, a fallback view could be chosen, or the ConversionNotSupportedException could be
	 * rethrown as-is.
374 375 376
	 * @param ex the ConversionNotSupportedException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
377 378
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
379
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
380 381
	 */
	protected ModelAndView handleConversionNotSupported(ConversionNotSupportedException ex,
382
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
J
Juergen Hoeller 已提交
383

384
		sendServerError(ex, request, response);
385 386 387
		return new ModelAndView();
	}

388
	/**
J
Juergen Hoeller 已提交
389 390 391
	 * Handle the case when a {@link org.springframework.web.bind.WebDataBinder} conversion error occurs.
	 * <p>The default implementation sends an HTTP 400 error, and returns an empty {@code ModelAndView}.
	 * Alternatively, a fallback view could be chosen, or the TypeMismatchException could be rethrown as-is.
392 393 394
	 * @param ex the TypeMismatchException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
395 396
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
397
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
398 399
	 */
	protected ModelAndView handleTypeMismatch(TypeMismatchException ex,
400
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
J
Juergen Hoeller 已提交
401

402 403 404 405 406
		response.sendError(HttpServletResponse.SC_BAD_REQUEST);
		return new ModelAndView();
	}

	/**
J
Juergen Hoeller 已提交
407
	 * Handle the case where a {@linkplain org.springframework.http.converter.HttpMessageConverter message converter}
408
	 * cannot read from an HTTP request.
J
Juergen Hoeller 已提交
409
	 * <p>The default implementation sends an HTTP 400 error, and returns an empty {@code ModelAndView}.
410
	 * Alternatively, a fallback view could be chosen, or the HttpMessageNotReadableException could be
411 412 413 414
	 * rethrown as-is.
	 * @param ex the HttpMessageNotReadableException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
415 416
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
417
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
418 419
	 */
	protected ModelAndView handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
420
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
421

422
		response.sendError(HttpServletResponse.SC_BAD_REQUEST);
423 424 425 426
		return new ModelAndView();
	}

	/**
J
Juergen Hoeller 已提交
427 428
	 * Handle the case where a
	 * {@linkplain org.springframework.http.converter.HttpMessageConverter message converter}
429
	 * cannot write to an HTTP request.
J
Juergen Hoeller 已提交
430
	 * <p>The default implementation sends an HTTP 500 error, and returns an empty {@code ModelAndView}.
431
	 * Alternatively, a fallback view could be chosen, or the HttpMessageNotWritableException could
J
Juergen Hoeller 已提交
432
	 * be rethrown as-is.
433 434 435
	 * @param ex the HttpMessageNotWritableException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
436 437
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
438
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
439 440
	 */
	protected ModelAndView handleHttpMessageNotWritable(HttpMessageNotWritableException ex,
441
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
442

443
		sendServerError(ex, request, response);
444 445 446
		return new ModelAndView();
	}

447
	/**
448 449
	 * Handle the case where an argument annotated with {@code @Valid} such as
	 * an {@link RequestBody} or {@link RequestPart} argument fails validation.
J
Juergen Hoeller 已提交
450
	 * <p>By default, an HTTP 400 error is sent back to the client.
451 452
	 * @param request current HTTP request
	 * @param response current HTTP response
453 454
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
455
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
456
	 */
457
	protected ModelAndView handleMethodArgumentNotValidException(MethodArgumentNotValidException ex,
458
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
459

460
		response.sendError(HttpServletResponse.SC_BAD_REQUEST);
461 462 463
		return new ModelAndView();
	}

464
	/**
465 466
	 * Handle the case where an {@linkplain RequestPart @RequestPart}, a {@link MultipartFile},
	 * or a {@code javax.servlet.http.Part} argument is required but is missing.
J
Juergen Hoeller 已提交
467
	 * <p>By default, an HTTP 400 error is sent back to the client.
468 469 470 471
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
472
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
473 474
	 */
	protected ModelAndView handleMissingServletRequestPartException(MissingServletRequestPartException ex,
475
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
476

477
		response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
478 479 480
		return new ModelAndView();
	}

481 482 483 484
	/**
	 * Handle the case where an {@linkplain ModelAttribute @ModelAttribute} method
	 * argument has binding or validation errors and is not followed by another
	 * method argument of type {@link BindingResult}.
J
Juergen Hoeller 已提交
485
	 * <p>By default, an HTTP 400 error is sent back to the client.
486 487 488 489
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param handler the executed handler
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
490
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
491 492
	 */
	protected ModelAndView handleBindException(BindException ex, HttpServletRequest request,
493
			HttpServletResponse response, @Nullable Object handler) throws IOException {
494

495 496 497 498
		response.sendError(HttpServletResponse.SC_BAD_REQUEST);
		return new ModelAndView();
	}

499 500
	/**
	 * Handle the case where no handler was found during the dispatch.
501 502
	 * <p>The default implementation sends an HTTP 404 error and returns an empty
	 * {@code ModelAndView}. Alternatively, a fallback view could be chosen,
503 504 505 506 507 508 509
	 * or the NoHandlerFoundException could be rethrown as-is.
	 * @param ex the NoHandlerFoundException to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param handler the executed handler, or {@code null} if none chosen
	 * at the time of the exception (for example, if multipart resolution failed)
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
510
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
511 512
	 * @since 4.0
	 */
513
	protected ModelAndView handleNoHandlerFoundException(NoHandlerFoundException ex,
514
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
515

516
		pageNotFoundLogger.warn(ex.getMessage());
517 518 519 520
		response.sendError(HttpServletResponse.SC_NOT_FOUND);
		return new ModelAndView();
	}

521 522 523 524 525 526 527 528 529
	/**
	 * Handle the case where an async request timed out.
	 * <p>The default implementation sends an HTTP 503 error.
	 * @param ex the {@link AsyncRequestTimeoutException }to be handled
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param handler the executed handler, or {@code null} if none chosen
	 * at the time of the exception (for example, if multipart resolution failed)
	 * @return an empty ModelAndView indicating the exception was handled
J
Juergen Hoeller 已提交
530
	 * @throws IOException potentially thrown from {@link HttpServletResponse#sendError}
531 532 533
	 * @since 4.2.8
	 */
	protected ModelAndView handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex,
534
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException {
535

536 537 538
		if (!response.isCommitted()) {
			response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
		}
J
Juergen Hoeller 已提交
539
		else {
540
			logger.warn("Async request timed out");
541
		}
542 543 544
		return new ModelAndView();
	}

545 546 547 548 549 550 551 552 553 554 555
	/**
	 * Invoked to send a server error. Sets the status to 500 and also sets the
	 * request attribute "javax.servlet.error.exception" to the Exception.
	 */
	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);
	}

556
}