46
46
import org .springframework .web .bind .annotation .InitBinder ;
47
47
import org .springframework .web .bind .annotation .ModelAttribute ;
48
48
import org .springframework .web .bind .annotation .PathVariable ;
49
+ import org .springframework .web .bind .annotation .RequestHeader ;
49
50
import org .springframework .web .bind .annotation .RequestParam ;
50
51
import org .springframework .web .bind .support .DefaultSessionAttributeStore ;
51
52
import org .springframework .web .bind .support .SessionAttributeStore ;
@@ -156,36 +157,47 @@ private Object[] resolveHandlerArguments(Method handlerMethod,
156
157
methodParam .initParameterNameDiscovery (this .parameterNameDiscoverer );
157
158
GenericTypeResolver .resolveParameterType (methodParam , handler .getClass ());
158
159
String paramName = null ;
159
- boolean paramRequired = false ;
160
- String paramDefaultValue = null ;
160
+ String headerName = null ;
161
+ boolean required = false ;
162
+ String defaultValue = null ;
161
163
String pathVarName = null ;
162
164
String attrName = null ;
165
+ int found = 0 ;
163
166
Annotation [] paramAnns = methodParam .getParameterAnnotations ();
164
167
165
168
for (Annotation paramAnn : paramAnns ) {
166
169
if (RequestParam .class .isInstance (paramAnn )) {
167
170
RequestParam requestParam = (RequestParam ) paramAnn ;
168
171
paramName = requestParam .value ();
169
- paramRequired = requestParam .required ();
170
- paramDefaultValue = requestParam .defaultValue ();
171
- break ;
172
+ required = requestParam .required ();
173
+ defaultValue = requestParam .defaultValue ();
174
+ found ++;
175
+ }
176
+ else if (RequestHeader .class .isInstance (paramAnn )) {
177
+ RequestHeader requestHeader = (RequestHeader ) paramAnn ;
178
+ headerName = requestHeader .value ();
179
+ required = requestHeader .required ();
180
+ defaultValue = requestHeader .defaultValue ();
181
+ found ++;
172
182
}
173
183
else if (ModelAttribute .class .isInstance (paramAnn )) {
174
184
ModelAttribute attr = (ModelAttribute ) paramAnn ;
175
185
attrName = attr .value ();
186
+ found ++;
176
187
}
177
188
else if (PathVariable .class .isInstance (paramAnn )) {
178
189
PathVariable pathVar = (PathVariable ) paramAnn ;
179
190
pathVarName = pathVar .value ();
191
+ found ++;
180
192
}
181
193
}
182
- if (( paramName != null && attrName != null ) || ( paramName != null && pathVarName != null ) ||
183
- ( pathVarName != null && attrName != null ) ) {
184
- throw new IllegalStateException ("@RequestParam, @PathVariable and @ModelAttribute are exclusive " +
185
- "choices - do not specify both on the same parameter: " + handlerMethod );
194
+
195
+ if ( found > 1 ) {
196
+ throw new IllegalStateException ("Handler parameter annotations are exclusive choices - " +
197
+ "do not specify more than one such annotation on the same parameter: " + handlerMethod );
186
198
}
187
199
188
- if (paramName == null && attrName == null && pathVarName == null ) {
200
+ if (found == 0 ) {
189
201
Object argValue = resolveCommonArgument (methodParam , webRequest );
190
202
if (argValue != WebArgumentResolver .UNRESOLVED ) {
191
203
args [i ] = argValue ;
@@ -212,8 +224,10 @@ else if (BeanUtils.isSimpleProperty(paramType)) {
212
224
}
213
225
214
226
if (paramName != null ) {
215
- args [i ] = resolveRequestParam (paramName , paramRequired , paramDefaultValue , methodParam , webRequest ,
216
- handler );
227
+ args [i ] = resolveRequestParam (paramName , required , defaultValue , methodParam , webRequest , handler );
228
+ }
229
+ else if (headerName != null ) {
230
+ args [i ] = resolveRequestHeader (headerName , required , defaultValue , methodParam , webRequest , handler );
217
231
}
218
232
else if (attrName != null ) {
219
233
WebDataBinder binder = resolveModelAttribute (attrName , methodParam , implicitModel , webRequest , handler );
@@ -333,18 +347,13 @@ else if (pathVarName != null) {
333
347
return initBinderArgs ;
334
348
}
335
349
336
- private Object resolveRequestParam (String paramName , boolean paramRequired , String paramDefaultValue ,
350
+ private Object resolveRequestParam (String paramName , boolean required , String defaultValue ,
337
351
MethodParameter methodParam , NativeWebRequest webRequest , Object handlerForInitBinderCall )
338
352
throws Exception {
339
353
340
354
Class paramType = methodParam .getParameterType ();
341
355
if (paramName .length () == 0 ) {
342
- paramName = methodParam .getParameterName ();
343
- if (paramName == null ) {
344
- throw new IllegalStateException (
345
- "No parameter specified for @RequestParam argument of type [" + paramType .getName () +
346
- "], and no parameter name information found in class file either." );
347
- }
356
+ paramName = getRequiredParameterName (methodParam );
348
357
}
349
358
Object paramValue = null ;
350
359
if (webRequest .getNativeRequest () instanceof MultipartRequest ) {
@@ -357,23 +366,64 @@ private Object resolveRequestParam(String paramName, boolean paramRequired, Stri
357
366
}
358
367
}
359
368
if (paramValue == null ) {
360
- if (StringUtils .hasText (paramDefaultValue )) {
361
- paramValue = paramDefaultValue ;
369
+ if (StringUtils .hasText (defaultValue )) {
370
+ paramValue = defaultValue ;
362
371
}
363
- else if (paramRequired ) {
372
+ else if (required ) {
364
373
raiseMissingParameterException (paramName , paramType );
365
374
}
366
- if (paramValue == null && paramType .isPrimitive ()) {
367
- throw new IllegalStateException ("Optional " + paramType + " parameter '" + paramName +
368
- "' is not present but cannot be translated into a null value due to being declared as a " +
369
- "primitive type. Consider declaring it as object wrapper for the corresponding primitive type." );
370
- }
375
+ checkValue (paramName , paramValue , paramType );
371
376
}
372
377
WebDataBinder binder = createBinder (webRequest , null , paramName );
373
378
initBinder (handlerForInitBinderCall , paramName , binder , webRequest );
374
379
return binder .convertIfNecessary (paramValue , paramType , methodParam );
375
380
}
376
381
382
+ private Object resolveRequestHeader (String headerName , boolean required , String defaultValue ,
383
+ MethodParameter methodParam , NativeWebRequest webRequest , Object handlerForInitBinderCall )
384
+ throws Exception {
385
+
386
+ Class paramType = methodParam .getParameterType ();
387
+ if (headerName .length () == 0 ) {
388
+ headerName = getRequiredParameterName (methodParam );
389
+ }
390
+ Object headerValue = null ;
391
+ String [] headerValues = webRequest .getHeaderValues (headerName );
392
+ if (headerValues != null ) {
393
+ headerValue = (headerValues .length == 1 ? headerValues [0 ] : headerValues );
394
+ }
395
+ if (headerValue == null ) {
396
+ if (StringUtils .hasText (defaultValue )) {
397
+ headerValue = defaultValue ;
398
+ }
399
+ else if (required ) {
400
+ raiseMissingHeaderException (headerName , paramType );
401
+ }
402
+ checkValue (headerName , headerValue , paramType );
403
+ }
404
+ WebDataBinder binder = createBinder (webRequest , null , headerName );
405
+ initBinder (handlerForInitBinderCall , headerName , binder , webRequest );
406
+ return binder .convertIfNecessary (headerValue , paramType , methodParam );
407
+ }
408
+
409
+ private String getRequiredParameterName (MethodParameter methodParam ) {
410
+ String name = methodParam .getParameterName ();
411
+ if (name == null ) {
412
+ throw new IllegalStateException ("No parameter name specified for argument of type [" +
413
+ methodParam .getParameterType ().getName () +
414
+ "], and no parameter name information found in class file either." );
415
+ }
416
+ return name ;
417
+ }
418
+
419
+ private void checkValue (String name , Object value , Class paramType ) {
420
+ if (value == null && paramType .isPrimitive ()) {
421
+ throw new IllegalStateException ("Optional " + paramType + " parameter '" + name +
422
+ "' is not present but cannot be translated into a null value due to being declared as a " +
423
+ "primitive type. Consider declaring it as object wrapper for the corresponding primitive type." );
424
+ }
425
+ }
426
+
377
427
private WebDataBinder resolveModelAttribute (String attrName , MethodParameter methodParam ,
378
428
ExtendedModelMap implicitModel , NativeWebRequest webRequest , Object handler )
379
429
throws Exception {
@@ -471,6 +521,10 @@ protected void raiseMissingParameterException(String paramName, Class paramType)
471
521
throw new IllegalStateException ("Missing parameter '" + paramName + "' of type [" + paramType .getName () + "]" );
472
522
}
473
523
524
+ protected void raiseMissingHeaderException (String headerName , Class paramType ) throws Exception {
525
+ throw new IllegalStateException ("Missing header '" + headerName + "' of type [" + paramType .getName () + "]" );
526
+ }
527
+
474
528
protected void raiseSessionRequiredException (String message ) throws Exception {
475
529
throw new IllegalStateException (message );
476
530
}
0 commit comments