1
1
/*
2
- * Copyright 2002-2012 the original author or authors.
2
+ * Copyright 2002-2016 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
13
13
* See the License for the specific language governing permissions and
14
14
* limitations under the License.
15
15
*/
16
+
16
17
package org .springframework .web .servlet .mvc .method .annotation ;
17
18
18
19
import java .util .List ;
19
20
import java .util .Set ;
20
21
21
22
import org .apache .commons .logging .Log ;
22
23
import org .apache .commons .logging .LogFactory ;
24
+
23
25
import org .springframework .beans .ConversionNotSupportedException ;
24
26
import org .springframework .beans .TypeMismatchException ;
25
27
import org .springframework .http .HttpHeaders ;
43
45
import org .springframework .web .context .request .WebRequest ;
44
46
import org .springframework .web .multipart .support .MissingServletRequestPartException ;
45
47
import org .springframework .web .servlet .mvc .multiaction .NoSuchRequestHandlingMethodException ;
48
+ import org .springframework .web .util .WebUtils ;
46
49
47
50
/**
48
51
* A convenient base class for {@link ControllerAdvice @ControllerAdvice} classes
49
52
* that wish to provide centralized exception handling across all
50
53
* {@code @RequestMapping} methods through {@code @ExceptionHandler} methods.
51
54
*
52
- * <p>This base class provides an {@code @ExceptionHandler} for handling standard
53
- * Spring MVC exceptions that returns a {@code ResponseEntity} to be written with
54
- * {@link HttpMessageConverter message converters}. This is in contrast to
55
+ * <p>This base class provides an {@code @ExceptionHandler} method for handling
56
+ * internal Spring MVC exceptions. This method returns a {@code ResponseEntity}
57
+ * for writing to the response with a {@link HttpMessageConverter message converter}.
58
+ * in contrast to
55
59
* {@link org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
56
- * DefaultHandlerExceptionResolver} which returns a {@code ModelAndView} instead.
60
+ * DefaultHandlerExceptionResolver} which returns a
61
+ * {@link org.springframework.web.servlet.ModelAndView ModelAndView}.
57
62
*
58
- * <p>If there is no need to write error content to the response body, or if using
59
- * view resolution, e.g. {@code ContentNegotiatingViewResolver}, then use
60
- * {@code DefaultHandlerExceptionResolver} instead .
63
+ * <p>If there is no need to write error content to the response body, or when
64
+ * using view resolution ( e.g., via {@code ContentNegotiatingViewResolver}),
65
+ * then {@code DefaultHandlerExceptionResolver} is good enough .
61
66
*
62
67
* <p>Note that in order for an {@code @ControllerAdvice} sub-class to be
63
68
* detected, {@link ExceptionHandlerExceptionResolver} must be configured.
64
69
*
65
70
* @author Rossen Stoyanchev
66
71
* @since 3.2
67
- *
72
+ * @see #handleException(Exception, WebRequest)
68
73
* @see org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
69
74
*/
70
75
public abstract class ResponseEntityExceptionHandler {
71
76
72
- protected final Log logger = LogFactory .getLog (getClass ());
73
-
74
77
/**
75
78
* Log category to use when no mapped handler is found for a request.
76
79
* @see #pageNotFoundLogger
77
80
*/
78
81
public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound" ;
79
82
80
83
/**
81
- * Additional logger to use when no mapped handler is found for a request.
84
+ * Specific logger to use when no mapped handler is found for a request.
82
85
* @see #PAGE_NOT_FOUND_LOG_CATEGORY
83
86
*/
84
87
protected static final Log pageNotFoundLogger = LogFactory .getLog (PAGE_NOT_FOUND_LOG_CATEGORY );
85
88
89
+ /**
90
+ * Common logger for use in subclasses.
91
+ */
92
+ protected final Log logger = LogFactory .getLog (getClass ());
93
+
86
94
87
95
/**
88
96
* Provides handling for standard Spring MVC exceptions.
89
97
* @param ex the target exception
90
98
* @param request the current request
91
99
*/
92
- @ ExceptionHandler (value = {
100
+ @ ExceptionHandler ({
93
101
NoSuchRequestHandlingMethodException .class ,
94
102
HttpRequestMethodNotSupportedException .class ,
95
103
HttpMediaTypeNotSupportedException .class ,
@@ -105,9 +113,7 @@ public abstract class ResponseEntityExceptionHandler {
105
113
BindException .class
106
114
})
107
115
public final ResponseEntity <Object > handleException (Exception ex , WebRequest request ) {
108
-
109
116
HttpHeaders headers = new HttpHeaders ();
110
-
111
117
if (ex instanceof NoSuchRequestHandlingMethodException ) {
112
118
HttpStatus status = HttpStatus .NOT_FOUND ;
113
119
return handleNoSuchRequestHandlingMethod ((NoSuchRequestHandlingMethodException ) ex , headers , status , request );
@@ -169,27 +175,27 @@ else if (ex instanceof BindException) {
169
175
170
176
/**
171
177
* A single place to customize the response body of all Exception types.
172
- * This method returns {@code null} by default.
178
+ * <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
179
+ * request attribute and creates a {@link ResponseEntity} from the given
180
+ * body, headers, and status.
173
181
* @param ex the exception
174
- * @param body the body to use for the response
175
- * @param headers the headers to be written to the response
176
- * @param status the selected response status
182
+ * @param body the body for the response
183
+ * @param headers the headers for the response
184
+ * @param status the response status
177
185
* @param request the current request
178
186
*/
179
187
protected ResponseEntity <Object > handleExceptionInternal (Exception ex , Object body ,
180
188
HttpHeaders headers , HttpStatus status , WebRequest request ) {
181
189
182
190
if (HttpStatus .INTERNAL_SERVER_ERROR .equals (status )) {
183
- request .setAttribute ("javax.servlet.error.exception" , ex , WebRequest .SCOPE_REQUEST );
191
+ request .setAttribute (WebUtils . ERROR_EXCEPTION_ATTRIBUTE , ex , WebRequest .SCOPE_REQUEST );
184
192
}
185
-
186
193
return new ResponseEntity <Object >(body , headers , status );
187
194
}
188
195
189
196
/**
190
197
* Customize the response for NoSuchRequestHandlingMethodException.
191
- * This method logs a warning and delegates to
192
- * {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest)}.
198
+ * <p>This method logs a warning and delegates to {@link #handleExceptionInternal}.
193
199
* @param ex the exception
194
200
* @param headers the headers to be written to the response
195
201
* @param status the selected response status
@@ -206,8 +212,8 @@ protected ResponseEntity<Object> handleNoSuchRequestHandlingMethod(NoSuchRequest
206
212
207
213
/**
208
214
* Customize the response for HttpRequestMethodNotSupportedException.
209
- * This method logs a warning, sets the "Allow" header, and delegates to
210
- * {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
215
+ * <p> This method logs a warning, sets the "Allow" header, and delegates to
216
+ * {@link #handleExceptionInternal}.
211
217
* @param ex the exception
212
218
* @param headers the headers to be written to the response
213
219
* @param status the selected response status
@@ -223,14 +229,13 @@ protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequest
223
229
if (!supportedMethods .isEmpty ()) {
224
230
headers .setAllow (supportedMethods );
225
231
}
226
-
227
232
return handleExceptionInternal (ex , null , headers , status , request );
228
233
}
229
234
230
235
/**
231
236
* Customize the response for HttpMediaTypeNotSupportedException.
232
- * This method sets the "Accept" header and delegates to
233
- * {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
237
+ * <p> This method sets the "Accept" header and delegates to
238
+ * {@link #handleExceptionInternal}.
234
239
* @param ex the exception
235
240
* @param headers the headers to be written to the response
236
241
* @param status the selected response status
@@ -250,7 +255,7 @@ protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNo
250
255
251
256
/**
252
257
* Customize the response for HttpMediaTypeNotAcceptableException.
253
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
258
+ * <p> This method delegates to {@link #handleExceptionInternal}.
254
259
* @param ex the exception
255
260
* @param headers the headers to be written to the response
256
261
* @param status the selected response status
@@ -265,7 +270,7 @@ protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(HttpMediaTypeN
265
270
266
271
/**
267
272
* Customize the response for MissingServletRequestParameterException.
268
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
273
+ * <p> This method delegates to {@link #handleExceptionInternal}.
269
274
* @param ex the exception
270
275
* @param headers the headers to be written to the response
271
276
* @param status the selected response status
@@ -280,7 +285,7 @@ protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingSer
280
285
281
286
/**
282
287
* Customize the response for ServletRequestBindingException.
283
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
288
+ * <p> This method delegates to {@link #handleExceptionInternal}.
284
289
* @param ex the exception
285
290
* @param headers the headers to be written to the response
286
291
* @param status the selected response status
@@ -295,7 +300,7 @@ protected ResponseEntity<Object> handleServletRequestBindingException(ServletReq
295
300
296
301
/**
297
302
* Customize the response for ConversionNotSupportedException.
298
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
303
+ * <p> This method delegates to {@link #handleExceptionInternal}.
299
304
* @param ex the exception
300
305
* @param headers the headers to be written to the response
301
306
* @param status the selected response status
@@ -310,7 +315,7 @@ protected ResponseEntity<Object> handleConversionNotSupported(ConversionNotSuppo
310
315
311
316
/**
312
317
* Customize the response for TypeMismatchException.
313
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
318
+ * <p> This method delegates to {@link #handleExceptionInternal}.
314
319
* @param ex the exception
315
320
* @param headers the headers to be written to the response
316
321
* @param status the selected response status
@@ -325,7 +330,7 @@ protected ResponseEntity<Object> handleTypeMismatch(TypeMismatchException ex, Ht
325
330
326
331
/**
327
332
* Customize the response for HttpMessageNotReadableException.
328
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
333
+ * <p> This method delegates to {@link #handleExceptionInternal}.
329
334
* @param ex the exception
330
335
* @param headers the headers to be written to the response
331
336
* @param status the selected response status
@@ -340,7 +345,7 @@ protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotRead
340
345
341
346
/**
342
347
* Customize the response for HttpMessageNotWritableException.
343
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
348
+ * <p> This method delegates to {@link #handleExceptionInternal}.
344
349
* @param ex the exception
345
350
* @param headers the headers to be written to the response
346
351
* @param status the selected response status
@@ -355,7 +360,7 @@ protected ResponseEntity<Object> handleHttpMessageNotWritable(HttpMessageNotWrit
355
360
356
361
/**
357
362
* Customize the response for MethodArgumentNotValidException.
358
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
363
+ * <p> This method delegates to {@link #handleExceptionInternal}.
359
364
* @param ex the exception
360
365
* @param headers the headers to be written to the response
361
366
* @param status the selected response status
@@ -370,7 +375,7 @@ protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotV
370
375
371
376
/**
372
377
* Customize the response for MissingServletRequestPartException.
373
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
378
+ * <p> This method delegates to {@link #handleExceptionInternal}.
374
379
* @param ex the exception
375
380
* @param headers the headers to be written to the response
376
381
* @param status the selected response status
@@ -385,7 +390,7 @@ protected ResponseEntity<Object> handleMissingServletRequestPart(MissingServletR
385
390
386
391
/**
387
392
* Customize the response for BindException.
388
- * This method delegates to {@link #handleExceptionInternal(Exception, Object, HttpHeaders, HttpStatus, WebRequest) }.
393
+ * <p> This method delegates to {@link #handleExceptionInternal}.
389
394
* @param ex the exception
390
395
* @param headers the headers to be written to the response
391
396
* @param status the selected response status
0 commit comments