16
16
17
17
package org .springframework .web .servlet .config ;
18
18
19
+ import java .util .Arrays ;
20
+ import java .util .HashMap ;
19
21
import java .util .List ;
22
+ import java .util .Map ;
20
23
21
24
import org .springframework .beans .factory .config .BeanDefinition ;
22
25
import org .springframework .beans .factory .config .BeanDefinitionHolder ;
29
32
import org .springframework .beans .factory .xml .ParserContext ;
30
33
import org .springframework .format .support .DefaultFormattingConversionService ;
31
34
import org .springframework .format .support .FormattingConversionServiceFactoryBean ;
35
+ import org .springframework .http .MediaType ;
32
36
import org .springframework .http .converter .ByteArrayHttpMessageConverter ;
33
37
import org .springframework .http .converter .HttpMessageConverter ;
34
38
import org .springframework .http .converter .ResourceHttpMessageConverter ;
44
48
import org .springframework .util .xml .DomUtils ;
45
49
import org .springframework .validation .beanvalidation .LocalValidatorFactoryBean ;
46
50
import org .springframework .web .HttpRequestHandler ;
51
+ import org .springframework .web .accept .ContentNegotiationManager ;
52
+ import org .springframework .web .accept .HeaderContentNegotiationStrategy ;
53
+ import org .springframework .web .accept .PathExtensionContentNegotiationStrategy ;
47
54
import org .springframework .web .bind .annotation .ExceptionHandler ;
48
55
import org .springframework .web .bind .annotation .ResponseStatus ;
49
56
import org .springframework .web .bind .support .ConfigurableWebBindingInitializer ;
102
109
* </ul>
103
110
*
104
111
* <p>Both the {@link RequestMappingHandlerAdapter} and the
105
- * {@link ExceptionHandlerExceptionResolver} are configured with default
106
- * instances of the following kind, unless custom instances are provided :
112
+ * {@link ExceptionHandlerExceptionResolver} are configured with instances of
113
+ * the following by default :
107
114
* <ul>
115
+ * <li>A {@link ContentNegotiationManager}
108
116
* <li>A {@link DefaultFormattingConversionService}
109
117
* <li>A {@link LocalValidatorFactoryBean} if a JSR-303 implementation is
110
118
* available on the classpath
@@ -143,11 +151,14 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
143
151
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition (element .getTagName (), source );
144
152
parserContext .pushContainingComponent (compDefinition );
145
153
146
- RootBeanDefinition methodMappingDef = new RootBeanDefinition (RequestMappingHandlerMapping .class );
147
- methodMappingDef .setSource (source );
148
- methodMappingDef .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
149
- methodMappingDef .getPropertyValues ().add ("order" , 0 );
150
- String methodMappingName = parserContext .getReaderContext ().registerWithGeneratedName (methodMappingDef );
154
+ RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager (element , source , parserContext );
155
+
156
+ RootBeanDefinition handlerMappingDef = new RootBeanDefinition (RequestMappingHandlerMapping .class );
157
+ handlerMappingDef .setSource (source );
158
+ handlerMappingDef .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
159
+ handlerMappingDef .getPropertyValues ().add ("order" , 0 );
160
+ handlerMappingDef .getPropertyValues ().add ("contentNegotiationManager" , contentNegotiationManager );
161
+ String methodMappingName = parserContext .getReaderContext ().registerWithGeneratedName (handlerMappingDef );
151
162
152
163
RuntimeBeanReference conversionService = getConversionService (element , source , parserContext );
153
164
RuntimeBeanReference validator = getValidator (element , source , parserContext );
@@ -164,22 +175,23 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
164
175
ManagedList <?> argumentResolvers = getArgumentResolvers (element , source , parserContext );
165
176
ManagedList <?> returnValueHandlers = getReturnValueHandlers (element , source , parserContext );
166
177
167
- RootBeanDefinition methodAdapterDef = new RootBeanDefinition (RequestMappingHandlerAdapter .class );
168
- methodAdapterDef .setSource (source );
169
- methodAdapterDef .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
170
- methodAdapterDef .getPropertyValues ().add ("webBindingInitializer" , bindingDef );
171
- methodAdapterDef .getPropertyValues ().add ("messageConverters" , messageConverters );
178
+ RootBeanDefinition handlerAdapterDef = new RootBeanDefinition (RequestMappingHandlerAdapter .class );
179
+ handlerAdapterDef .setSource (source );
180
+ handlerAdapterDef .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
181
+ handlerAdapterDef .getPropertyValues ().add ("contentNegotiationManager" , contentNegotiationManager );
182
+ handlerAdapterDef .getPropertyValues ().add ("webBindingInitializer" , bindingDef );
183
+ handlerAdapterDef .getPropertyValues ().add ("messageConverters" , messageConverters );
172
184
if (element .hasAttribute ("ignoreDefaultModelOnRedirect" )) {
173
185
Boolean ignoreDefaultModel = Boolean .valueOf (element .getAttribute ("ignoreDefaultModelOnRedirect" ));
174
- methodAdapterDef .getPropertyValues ().add ("ignoreDefaultModelOnRedirect" , ignoreDefaultModel );
186
+ handlerAdapterDef .getPropertyValues ().add ("ignoreDefaultModelOnRedirect" , ignoreDefaultModel );
175
187
}
176
188
if (argumentResolvers != null ) {
177
- methodAdapterDef .getPropertyValues ().add ("customArgumentResolvers" , argumentResolvers );
189
+ handlerAdapterDef .getPropertyValues ().add ("customArgumentResolvers" , argumentResolvers );
178
190
}
179
191
if (returnValueHandlers != null ) {
180
- methodAdapterDef .getPropertyValues ().add ("customReturnValueHandlers" , returnValueHandlers );
192
+ handlerAdapterDef .getPropertyValues ().add ("customReturnValueHandlers" , returnValueHandlers );
181
193
}
182
- String methodAdapterName = parserContext .getReaderContext ().registerWithGeneratedName (methodAdapterDef );
194
+ String handlerAdapterName = parserContext .getReaderContext ().registerWithGeneratedName (handlerAdapterDef );
183
195
184
196
RootBeanDefinition csInterceptorDef = new RootBeanDefinition (ConversionServiceExposingInterceptor .class );
185
197
csInterceptorDef .setSource (source );
@@ -191,13 +203,14 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
191
203
mappedCsInterceptorDef .getConstructorArgumentValues ().addIndexedArgumentValue (1 , csInterceptorDef );
192
204
String mappedInterceptorName = parserContext .getReaderContext ().registerWithGeneratedName (mappedCsInterceptorDef );
193
205
194
- RootBeanDefinition methodExceptionResolver = new RootBeanDefinition (ExceptionHandlerExceptionResolver .class );
195
- methodExceptionResolver .setSource (source );
196
- methodExceptionResolver .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
197
- methodExceptionResolver .getPropertyValues ().add ("messageConverters" , messageConverters );
198
- methodExceptionResolver .getPropertyValues ().add ("order" , 0 );
206
+ RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition (ExceptionHandlerExceptionResolver .class );
207
+ exceptionHandlerExceptionResolver .setSource (source );
208
+ exceptionHandlerExceptionResolver .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
209
+ exceptionHandlerExceptionResolver .getPropertyValues ().add ("contentNegotiationManager" , contentNegotiationManager );
210
+ exceptionHandlerExceptionResolver .getPropertyValues ().add ("messageConverters" , messageConverters );
211
+ exceptionHandlerExceptionResolver .getPropertyValues ().add ("order" , 0 );
199
212
String methodExceptionResolverName =
200
- parserContext .getReaderContext ().registerWithGeneratedName (methodExceptionResolver );
213
+ parserContext .getReaderContext ().registerWithGeneratedName (exceptionHandlerExceptionResolver );
201
214
202
215
RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition (ResponseStatusExceptionResolver .class );
203
216
responseStatusExceptionResolver .setSource (source );
@@ -213,9 +226,9 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
213
226
String defaultExceptionResolverName =
214
227
parserContext .getReaderContext ().registerWithGeneratedName (defaultExceptionResolver );
215
228
216
- parserContext .registerComponent (new BeanComponentDefinition (methodMappingDef , methodMappingName ));
217
- parserContext .registerComponent (new BeanComponentDefinition (methodAdapterDef , methodAdapterName ));
218
- parserContext .registerComponent (new BeanComponentDefinition (methodExceptionResolver , methodExceptionResolverName ));
229
+ parserContext .registerComponent (new BeanComponentDefinition (handlerMappingDef , methodMappingName ));
230
+ parserContext .registerComponent (new BeanComponentDefinition (handlerAdapterDef , handlerAdapterName ));
231
+ parserContext .registerComponent (new BeanComponentDefinition (exceptionHandlerExceptionResolver , methodExceptionResolverName ));
219
232
parserContext .registerComponent (new BeanComponentDefinition (responseStatusExceptionResolver , responseStatusExceptionResolverName ));
220
233
parserContext .registerComponent (new BeanComponentDefinition (defaultExceptionResolver , defaultExceptionResolverName ));
221
234
parserContext .registerComponent (new BeanComponentDefinition (mappedCsInterceptorDef , mappedInterceptorName ));
@@ -261,6 +274,42 @@ else if (jsr303Present) {
261
274
}
262
275
}
263
276
277
+ private RuntimeBeanReference getContentNegotiationManager (Element element , Object source , ParserContext parserContext ) {
278
+ RuntimeBeanReference contentNegotiationManagerRef ;
279
+ if (element .hasAttribute ("content-negotiation-manager" )) {
280
+ contentNegotiationManagerRef = new RuntimeBeanReference (element .getAttribute ("content-negotiation-manager" ));
281
+ }
282
+ else {
283
+ RootBeanDefinition managerDef = new RootBeanDefinition (ContentNegotiationManager .class );
284
+ managerDef .setSource (source );
285
+ managerDef .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
286
+ PathExtensionContentNegotiationStrategy strategy1 = new PathExtensionContentNegotiationStrategy (getDefaultMediaTypes ());
287
+ HeaderContentNegotiationStrategy strategy2 = new HeaderContentNegotiationStrategy ();
288
+ managerDef .getConstructorArgumentValues ().addIndexedArgumentValue (0 , Arrays .asList (strategy1 ,strategy2 ));
289
+
290
+ String beanName = "mvcContentNegotiationManager" ;
291
+ parserContext .getReaderContext ().getRegistry ().registerBeanDefinition (beanName , managerDef );
292
+ parserContext .registerComponent (new BeanComponentDefinition (managerDef , beanName ));
293
+ contentNegotiationManagerRef = new RuntimeBeanReference (beanName );
294
+ }
295
+ return contentNegotiationManagerRef ;
296
+ }
297
+
298
+ private Map <String , MediaType > getDefaultMediaTypes () {
299
+ Map <String , MediaType > map = new HashMap <String , MediaType >();
300
+ if (romePresent ) {
301
+ map .put ("atom" , MediaType .APPLICATION_ATOM_XML );
302
+ map .put ("rss" , MediaType .valueOf ("application/rss+xml" ));
303
+ }
304
+ if (jackson2Present || jacksonPresent ) {
305
+ map .put ("json" , MediaType .APPLICATION_JSON );
306
+ }
307
+ if (jaxb2Present ) {
308
+ map .put ("xml" , MediaType .APPLICATION_XML );
309
+ }
310
+ return map ;
311
+ }
312
+
264
313
private RuntimeBeanReference getMessageCodesResolver (Element element , Object source , ParserContext parserContext ) {
265
314
if (element .hasAttribute ("message-codes-resolver" )) {
266
315
return new RuntimeBeanReference (element .getAttribute ("message-codes-resolver" ));
0 commit comments