17
17
package org .springframework .web .servlet .mvc .method .annotation ;
18
18
19
19
import java .lang .reflect .Method ;
20
+ import java .util .ArrayList ;
21
+ import java .util .List ;
20
22
import java .util .Map ;
21
23
import java .util .Set ;
22
24
import java .util .concurrent .ConcurrentHashMap ;
80
82
public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandlerMethodExceptionResolver implements
81
83
InitializingBean {
82
84
83
- private WebArgumentResolver [] customArgumentResolvers ;
85
+ private final List <HandlerMethodArgumentResolver > customArgumentResolvers =
86
+ new ArrayList <HandlerMethodArgumentResolver >();
84
87
85
- private HttpMessageConverter <?>[] messageConverters ;
88
+ private final List <HandlerMethodReturnValueHandler > customReturnValueHandlers =
89
+ new ArrayList <HandlerMethodReturnValueHandler >();
90
+
91
+ private List <HttpMessageConverter <?>> messageConverters ;
86
92
87
93
private final Map <Class <?>, ExceptionMethodMapping > exceptionMethodMappingCache =
88
94
new ConcurrentHashMap <Class <?>, ExceptionMethodMapping >();
@@ -99,95 +105,139 @@ public RequestMappingHandlerMethodExceptionResolver() {
99
105
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter ();
100
106
stringHttpMessageConverter .setWriteAcceptCharset (false ); // See SPR-7316
101
107
102
- this .messageConverters = new HttpMessageConverter [] { new ByteArrayHttpMessageConverter (),
103
- stringHttpMessageConverter , new SourceHttpMessageConverter <Source >(),
104
- new XmlAwareFormHttpMessageConverter () };
108
+ messageConverters = new ArrayList <HttpMessageConverter <?>>();
109
+ messageConverters .add (new ByteArrayHttpMessageConverter ());
110
+ messageConverters .add (stringHttpMessageConverter );
111
+ messageConverters .add (new SourceHttpMessageConverter <Source >());
112
+ messageConverters .add (new XmlAwareFormHttpMessageConverter ());
105
113
}
106
114
107
115
/**
108
- * Set one or more custom ArgumentResolvers to use for special method parameter types.
109
- * <p>Any such custom ArgumentResolver will kick in first, having a chance to resolve
110
- * an argument value before the standard argument handling kicks in.
111
- * <p>Note: this is provided for backward compatibility. The preferred way to do this is to
112
- * implement a {@link HandlerMethodArgumentResolver}.
116
+ * Set one or more custom argument resolvers to use with {@link ExceptionHandler} methods. Custom argument resolvers
117
+ * are given a chance to resolve argument values ahead of the standard argument resolvers registered by default.
118
+ * <p>Argument resolvers of type {@link HandlerMethodArgumentResolver} and {@link WebArgumentResolver} are
119
+ * accepted with instances of the latter adapted via {@link ServletWebArgumentResolverAdapter}. For new
120
+ * implementations {@link HandlerMethodArgumentResolver} should be preferred over {@link WebArgumentResolver }.
113
121
*/
114
- public void setCustomArgumentResolvers (WebArgumentResolver [] argumentResolvers ) {
115
- this .customArgumentResolvers = argumentResolvers ;
122
+ public void setCustomArgumentResolvers (List <?> argumentResolvers ) {
123
+ if (argumentResolvers == null ) {
124
+ return ;
125
+ }
126
+ List <HandlerMethodArgumentResolver > adaptedResolvers = new ArrayList <HandlerMethodArgumentResolver >();
127
+ for (Object resolver : argumentResolvers ) {
128
+ if (resolver instanceof WebArgumentResolver ) {
129
+ adaptedResolvers .add (new ServletWebArgumentResolverAdapter ((WebArgumentResolver ) resolver ));
130
+ }
131
+ else if (resolver instanceof HandlerMethodArgumentResolver ) {
132
+ adaptedResolvers .add ((HandlerMethodArgumentResolver ) resolver );
133
+ }
134
+ else {
135
+ throw new IllegalArgumentException (
136
+ "An argument resolver must be a HandlerMethodArgumentResolver or a WebArgumentResolver" );
137
+ }
138
+ }
139
+ this .customArgumentResolvers .addAll (adaptedResolvers );
140
+ }
141
+
142
+ /**
143
+ * Set the argument resolvers to use with {@link ExceptionHandler} methods.
144
+ * This is an optional property providing full control over all argument resolvers in contrast to
145
+ * {@link #setCustomArgumentResolvers(List)}, which does not override default registrations.
146
+ * @param argumentResolvers argument resolvers for {@link ExceptionHandler} methods
147
+ */
148
+ public void setArgumentResolvers (List <HandlerMethodArgumentResolver > argumentResolvers ) {
149
+ if (argumentResolvers != null ) {
150
+ this .argumentResolvers = new HandlerMethodArgumentResolverComposite ();
151
+ registerArgumentResolvers (argumentResolvers );
152
+ }
116
153
}
117
154
118
155
/**
119
- * Set the message body converters to use.
120
- * <p>These converters are used to convert from and to HTTP requests and responses.
156
+ * Set custom return value handlers to use to handle the return values of {@link ExceptionHandler} methods.
157
+ * Custom return value handlers are given a chance to handle a return value before the standard
158
+ * return value handlers registered by default.
159
+ * @param returnValueHandlers custom return value handlers for {@link ExceptionHandler} methods
121
160
*/
122
- public void setMessageConverters (HttpMessageConverter <?>[] messageConverters ) {
123
- this .messageConverters = messageConverters ;
161
+ public void setCustomReturnValueHandlers (List <HandlerMethodReturnValueHandler > returnValueHandlers ) {
162
+ if (returnValueHandlers != null ) {
163
+ this .customReturnValueHandlers .addAll (returnValueHandlers );
164
+ }
124
165
}
125
166
126
167
/**
127
- * Set the {@link HandlerMethodArgumentResolver}s to use to resolve argument values for
128
- * {@link ExceptionHandler} methods. This is an optional property.
129
- * @param argumentResolvers the argument resolvers to use
168
+ * Set the {@link HandlerMethodReturnValueHandler}s to use to use with {@link ExceptionHandler} methods.
169
+ * This is an optional property providing full control over all return value handlers in contrast to
170
+ * {@link #setCustomReturnValueHandlers(List)}, which does not override default registrations.
171
+ * @param returnValueHandlers the return value handlers for {@link ExceptionHandler} methods
130
172
*/
131
- public void setHandlerMethodArgumentResolvers ( HandlerMethodArgumentResolver [] argumentResolvers ) {
132
- this . argumentResolvers = new HandlerMethodArgumentResolverComposite ();
133
- for ( HandlerMethodArgumentResolver resolver : argumentResolvers ) {
134
- this . argumentResolvers . registerArgumentResolver ( resolver );
173
+ public void setReturnValueHandlers ( List < HandlerMethodReturnValueHandler > returnValueHandlers ) {
174
+ if ( returnValueHandlers != null ) {
175
+ this . returnValueHandlers = new HandlerMethodReturnValueHandlerComposite ();
176
+ registerReturnValueHandlers ( returnValueHandlers );
135
177
}
136
178
}
137
179
138
180
/**
139
- * Set the {@link HandlerMethodReturnValueHandler}s to use to handle the return values of
140
- * {@link ExceptionHandler} methods. This is an optional property.
141
- * @param returnValueHandlers the return value handlers to use
181
+ * Set the message body converters to use.
182
+ * <p>These converters are used to convert from and to HTTP requests and responses.
142
183
*/
143
- public void setHandlerMethodReturnValueHandlers (HandlerMethodReturnValueHandler [] returnValueHandlers ) {
144
- this .returnValueHandlers = new HandlerMethodReturnValueHandlerComposite ();
145
- for (HandlerMethodReturnValueHandler handler : returnValueHandlers ) {
146
- this .returnValueHandlers .registerReturnValueHandler (handler );
147
- }
184
+ public void setMessageConverters (List <HttpMessageConverter <?>> messageConverters ) {
185
+ this .messageConverters = messageConverters ;
148
186
}
149
187
150
188
public void afterPropertiesSet () throws Exception {
151
- initMethodArgumentResolvers ();
152
- initMethodReturnValueHandlers ();
189
+ if (argumentResolvers == null ) {
190
+ argumentResolvers = new HandlerMethodArgumentResolverComposite ();
191
+ registerArgumentResolvers (customArgumentResolvers );
192
+ registerArgumentResolvers (getDefaultArgumentResolvers ());
193
+ }
194
+ if (returnValueHandlers == null ) {
195
+ returnValueHandlers = new HandlerMethodReturnValueHandlerComposite ();
196
+ registerReturnValueHandlers (customReturnValueHandlers );
197
+ registerReturnValueHandlers (getDefaultReturnValueHandlers (messageConverters ));
198
+ }
199
+ }
200
+
201
+ private void registerArgumentResolvers (List <HandlerMethodArgumentResolver > argumentResolvers ) {
202
+ for (HandlerMethodArgumentResolver resolver : argumentResolvers ) {
203
+ this .argumentResolvers .registerArgumentResolver (resolver );
204
+ }
153
205
}
154
206
155
- private void initMethodArgumentResolvers ( ) {
156
- if ( argumentResolvers != null ) {
157
- return ;
207
+ private void registerReturnValueHandlers ( List < HandlerMethodReturnValueHandler > returnValueHandlers ) {
208
+ for ( HandlerMethodReturnValueHandler handler : returnValueHandlers ) {
209
+ this . returnValueHandlers . registerReturnValueHandler ( handler ) ;
158
210
}
159
- argumentResolvers = new HandlerMethodArgumentResolverComposite ();
160
-
161
- argumentResolvers .registerArgumentResolver (new ServletRequestMethodArgumentResolver ());
162
- argumentResolvers .registerArgumentResolver (new ServletResponseMethodArgumentResolver ());
163
-
164
- if (customArgumentResolvers != null ) {
165
- for (WebArgumentResolver customResolver : customArgumentResolvers ) {
166
- argumentResolvers .registerArgumentResolver (new ServletWebArgumentResolverAdapter (customResolver ));
167
- }
168
- }
169
211
}
170
212
171
- private void initMethodReturnValueHandlers () {
172
- if (returnValueHandlers != null ) {
173
- return ;
174
- }
175
- returnValueHandlers = new HandlerMethodReturnValueHandlerComposite ();
213
+ public static List <HandlerMethodArgumentResolver > getDefaultArgumentResolvers () {
214
+ List <HandlerMethodArgumentResolver > resolvers = new ArrayList <HandlerMethodArgumentResolver >();
215
+ resolvers .add (new ServletRequestMethodArgumentResolver ());
216
+ resolvers .add (new ServletResponseMethodArgumentResolver ());
217
+ return resolvers ;
218
+ }
176
219
220
+ public static List <HandlerMethodReturnValueHandler > getDefaultReturnValueHandlers (
221
+ List <HttpMessageConverter <?>> messageConverters ) {
222
+
223
+ List <HandlerMethodReturnValueHandler > handlers = new ArrayList <HandlerMethodReturnValueHandler >();
224
+
177
225
// Annotation-based handlers
178
- returnValueHandlers . registerReturnValueHandler (new RequestResponseBodyMethodProcessor (messageConverters ));
179
- returnValueHandlers . registerReturnValueHandler (new ModelAttributeMethodProcessor (false ));
226
+ handlers . add (new RequestResponseBodyMethodProcessor (messageConverters ));
227
+ handlers . add (new ModelAttributeMethodProcessor (false ));
180
228
181
229
// Type-based handlers
182
- returnValueHandlers . registerReturnValueHandler (new ModelAndViewMethodReturnValueHandler ());
183
- returnValueHandlers . registerReturnValueHandler (new ModelMethodProcessor ());
184
- returnValueHandlers . registerReturnValueHandler (new ViewMethodReturnValueHandler ());
185
- returnValueHandlers . registerReturnValueHandler (new HttpEntityMethodProcessor (messageConverters ));
230
+ handlers . add (new ModelAndViewMethodReturnValueHandler ());
231
+ handlers . add (new ModelMethodProcessor ());
232
+ handlers . add (new ViewMethodReturnValueHandler ());
233
+ handlers . add (new HttpEntityMethodProcessor (messageConverters ));
186
234
187
235
// Default handler
188
- returnValueHandlers .registerReturnValueHandler (new DefaultMethodReturnValueHandler (null ));
236
+ handlers .add (new DefaultMethodReturnValueHandler ());
237
+
238
+ return handlers ;
189
239
}
190
-
240
+
191
241
/**
192
242
* Attempts to find an {@link ExceptionHandler}-annotated method that can handle the thrown exception.
193
243
* The exception-handling method, if found, is invoked resulting in a {@link ModelAndView}.
0 commit comments