Как настроить пользовательский MediaType в Spring MVC?

Используя Spring MVC, у меня уже есть контроллеры, работающие как с медиаформатами JSON, так и с XML. В конфигурации согласования содержимого я хотел бы полагаться только на заголовок Accept и ввести тип носителя с пользовательским именем, например: «myXml»

Моя конфигурация:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer
           .favorPathExtension(false)
           .favorParameter(false)
           .ignoreAcceptHeader(false)
           .useJaf(false)
           .mediaType(MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON)
           .mediaType(MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_XML)
           .mediaType("myXml", MediaType.APPLICATION_XML)
           .defaultContentType(MediaType.APPLICATION_JSON);
    }
}

Мой контроллер:

@RequestMapping(value = "/manager/{id}",
        method = RequestMethod.GET,
        produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}
)
@ResponseBody public Manager managers(@PathVariable long id){
    return repo.getManagerById(id);
}

Это работает довольно хорошо, заголовок Accept: application/json создает JSON, application/xml создает XML. Все остальное возвращает 406 Not Acceptable, даже myXml.

Хотя я ожидал xml...


person István Békési    schedule 28.11.2014    source источник


Ответы (1)


С этой конфигурацией вы в основном:

  • игнорирование согласования содержимого с использованием параметров или расширений пути
  • зарегистрировал "json -> application/json" "xml -> application/xml" "myXml -> application/xml" в качестве возможных расширений/параметров пути для согласования с этими типами мультимедиа. (подробнее об этом здесь)
  • сообщил Spring MVC, что всякий раз, когда HTTP-клиент отправляет "Accept: */*" или вообще не отправляет заголовок Accept, ContentType по умолчанию должен быть «application/xml»

Я не думаю, что вы собирались так вести переговоры о содержании.

Возможно, вы захотите настроить HttpMessageConverters (см. здесь), например зарегистрировать Jaxb2RootElementHttpMessageConverter (при использовании JAXB) или MappingJackson2XmlHttpMessageConverter (при использовании Jackson) и зарегистрировать их как с типами носителей "application/xml", так и с "myXml".

Кроме того, не забудьте добавить «myXml» в часть «производит» аннотации RequestMapping — ваш метод контроллера должен объявить его как тип носителя, который он может создать, иначе он снова выдаст ошибку 406.

Мой совет

Вам определенно следует использовать тип носителя, такой как «application/vnd.foobar.v.1.0+xml», поскольку:

  • это что-то актуальное для http-клиентов
  • xml HttpMessageConverters в Spring уже зарегистрированы для работы с «application/xml» и «application/*+xml».

В этом случае вы можете просто сохранить часть defaultContentType в своей конфигурации (и, возможно, установить ее на свой пользовательский тип носителя) и выбросить все остальное.

В любом случае вы все равно должны объявить этот пользовательский тип носителя в разделе «Производит» ваших аннотаций сопоставления.

person Brian Clozel    schedule 29.11.2014
comment
Большое спасибо за ответ! Хотя mediaType() также влияет на заголовок Accept, а не только на конфигурацию расширения. - person István Békési; 02.12.2014
comment
Я только что проверил, потому что это действительно немного вводит в заблуждение... docs.spring.io/spring-framework/docs/4.1.2.RELEASE/javadoc-api/ - спасибо за подсказку - person Brian Clozel; 02.12.2014