在 RESTful接口 盛行的現在, 讓接口返回 JSON 格式的字符串,已經成為了大家幾乎共同的選擇。
之前的項目,通過 spring 來實現了 RESTful,接口返回的就是 JSON的。而且,我一直以為,只要在spring的xml配置文件中開啟了<mvc:annotation-driven />
之後,系統就會自動加載 MappingJackson2HttpMessageConverter 這個用於將 HashMap
、List
、POJO
對象轉換為 JSON 的 message converter的。
但是,今天自己在新建一個項目之後,按照上面的配置,卻怎麼也不行。後來看了一下源碼,才發現問題所有:
必須將 jackson 對應的jar包引入,spring 才會自動加載上面這個 message converter
為什麼會這樣?可以先移步至我的另一篇博客大概看一下:mvc:annotation-driven 的變更
從上面這篇blog中,可以看出裡面已經有了介紹了。但我還是忘了這一點,導致走了彎路。今天決定看一下源碼,增加一下印象,避免以後再走彎路。
具體可以參考以下源碼 (RequestMappingHandlerAdapter):
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
...
public RequestMappingHandlerAdapter() {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316
this.messageConverters = new ArrayList<HttpMessageConverter<?>>(4);
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(stringHttpMessageConverter);
this.messageConverters.add(new SourceHttpMessageConverter<Source>());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}
...
}
最重要的是最後這一句:this.messageConverters.add(new AllEncompassingFormHttpMessageConverter())
,
其中,AllEncompassingFormHttpMessageConverter 的實現為:
public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConverter {
private static final boolean jaxb2Present =
ClassUtils.isPresent("javax.xml.bind.Binder", AllEncompassingFormHttpMessageConverter.class.getClassLoader());
private static final boolean jackson2Present =
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", AllEncompassingFormHttpMessageConverter.class.getClassLoader()) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", AllEncompassingFormHttpMessageConverter.class.getClassLoader());
private static final boolean jackson2XmlPresent =
ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", AllEncompassingFormHttpMessageConverter.class.getClassLoader());
private static final boolean gsonPresent =
ClassUtils.isPresent("com.google.gson.Gson", AllEncompassingFormHttpMessageConverter.class.getClassLoader());
public AllEncompassingFormHttpMessageConverter() {
addPartConverter(new SourceHttpMessageConverter<Source>());
if (jaxb2Present && !jackson2XmlPresent) {
addPartConverter(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
addPartConverter(new MappingJackson2HttpMessageConverter());
}
else if (gsonPresent) {
addPartConverter(new GsonHttpMessageConverter());
}
if (jackson2XmlPresent) {
addPartConverter(new MappingJackson2XmlHttpMessageConverter());
}
}
}
相信大家看到這裡的時候,就明白了吧。 : )