All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.boot.autoconfigure.web.HttpMessageConverters Maven / Gradle / Ivy

/*
 * Copyright 2012-2015 the original author or authors.
 *
 * 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
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

package org.springframework.boot.autoconfigure.web;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

/**
 * Bean used to manage the {@link HttpMessageConverter}s used in a Spring Boot
 * application. Provides a convenient way to add and merge additional
 * {@link HttpMessageConverter}s to a web application.
 * 

* An instance of this bean can be registered with specific * {@link #HttpMessageConverters(HttpMessageConverter...) additional converters} if * needed, otherwise default converters will be used. *

* NOTE: The default converters used are the same as standard Spring MVC (see * {@link WebMvcConfigurationSupport#getMessageConverters} with some slight re-ordering to * put XML converters at the back of the list. * * @author Dave Syer * @author Phillip Webb * @author Andy Wilkinson * @see #HttpMessageConverters(HttpMessageConverter...) * @see #HttpMessageConverters(Collection) * @see #getConverters() */ public class HttpMessageConverters implements Iterable> { private static final List> NON_REPLACING_CONVERTERS; static { List> nonReplacingConverters = new ArrayList>(); addClassIfExists(nonReplacingConverters, "org.springframework.hateoas.mvc." + "TypeConstrainedMappingJackson2HttpMessageConverter"); NON_REPLACING_CONVERTERS = Collections.unmodifiableList(nonReplacingConverters); } private final List> converters; /** * Create a new {@link HttpMessageConverters} instance with the specified additional * converters. * @param additionalConverters additional converters to be added. New converters will * be added to the front of the list, overrides will replace existing items without * changing the order. The {@link #getConverters()} methods can be used for further * converter manipulation. */ public HttpMessageConverters(HttpMessageConverter... additionalConverters) { this(Arrays.asList(additionalConverters)); } /** * Create a new {@link HttpMessageConverters} instance with the specified additional * converters. * @param additionalConverters additional converters to be added. Items are added just * before any default converter of the same type (or at the front of the list if no * default converter is found) The {@link #postProcessConverters(List)} method can be * used for further converter manipulation. */ public HttpMessageConverters( Collection> additionalConverters) { this(true, additionalConverters); } /** * Create a new {@link HttpMessageConverters} instance with the specified converters. * @param addDefaultConverters if default converters should be added * @param converters converters to be added. Items are added just before any default * converter of the same type (or at the front of the list if no default converter is * found) The {@link #postProcessConverters(List)} method can be used for further * converter manipulation. */ public HttpMessageConverters(boolean addDefaultConverters, Collection> converters) { List> combined = getCombinedConverters(converters, addDefaultConverters ? getDefaultConverters() : Collections.>emptyList()); combined = postProcessConverters(combined); this.converters = Collections.unmodifiableList(combined); } private List> getCombinedConverters( Collection> converters, List> defaultConverters) { List> combined = new ArrayList>(); List> processing = new ArrayList>( converters); for (HttpMessageConverter defaultConverter : defaultConverters) { Iterator> iterator = processing.iterator(); while (iterator.hasNext()) { HttpMessageConverter candidate = iterator.next(); if (isReplacement(defaultConverter, candidate)) { combined.add(candidate); iterator.remove(); } } combined.add(defaultConverter); if (defaultConverter instanceof AllEncompassingFormHttpMessageConverter) { configurePartConverters( (AllEncompassingFormHttpMessageConverter) defaultConverter, converters); } } combined.addAll(0, processing); return combined; } private boolean isReplacement(HttpMessageConverter defaultConverter, HttpMessageConverter candidate) { for (Class nonReplacingConverter : NON_REPLACING_CONVERTERS) { if (nonReplacingConverter.isInstance(candidate)) { return false; } } return ClassUtils.isAssignableValue(defaultConverter.getClass(), candidate); } private void configurePartConverters( AllEncompassingFormHttpMessageConverter formConverter, Collection> converters) { List> partConverters = extractPartConverters( formConverter); List> combinedConverters = getCombinedConverters( converters, partConverters); combinedConverters = postProcessPartConverters(combinedConverters); formConverter.setPartConverters(combinedConverters); } @SuppressWarnings("unchecked") private List> extractPartConverters( FormHttpMessageConverter formConverter) { Field field = ReflectionUtils.findField(FormHttpMessageConverter.class, "partConverters"); ReflectionUtils.makeAccessible(field); return (List>) ReflectionUtils.getField(field, formConverter); } /** * Method that can be used to post-process the {@link HttpMessageConverter} list * before it is used. * @param converters a mutable list of the converters that will be used. * @return the final converts list to use */ protected List> postProcessConverters( List> converters) { return converters; } /** * Method that can be used to post-process the {@link HttpMessageConverter} list * before it is used to configure the part converters of * {@link AllEncompassingFormHttpMessageConverter}. * @param converters a mutable list of the converters that will be used. * @return the final converts list to use * @since 1.3.0 */ protected List> postProcessPartConverters( List> converters) { return converters; } private List> getDefaultConverters() { List> converters = new ArrayList>(); if (ClassUtils.isPresent("org.springframework.web.servlet.config.annotation." + "WebMvcConfigurationSupport", null)) { converters.addAll(new WebMvcConfigurationSupport() { public List> defaultMessageConverters() { return super.getMessageConverters(); } }.defaultMessageConverters()); } else { converters.addAll(new RestTemplate().getMessageConverters()); } reorderXmlConvertersToEnd(converters); return converters; } private void reorderXmlConvertersToEnd(List> converters) { List> xml = new ArrayList>(); for (Iterator> iterator = converters.iterator(); iterator .hasNext();) { HttpMessageConverter converter = iterator.next(); if ((converter instanceof AbstractXmlHttpMessageConverter) || (converter instanceof MappingJackson2XmlHttpMessageConverter)) { xml.add(converter); iterator.remove(); } } converters.addAll(xml); } @Override public Iterator> iterator() { return getConverters().iterator(); } /** * Return an immutable list of the converters in the order that they will be * registered. * @return the converters */ public List> getConverters() { return this.converters; } private static void addClassIfExists(List> list, String className) { try { list.add(Class.forName(className)); } catch (ClassNotFoundException ex) { // Ignore } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy