最近我在把Spring 項目改造Springboot,遇到一個問題@ResponseBody返回中文亂碼,因為response返回的content-type一直是application/json;charset=ISO-8859-1。經過幾天的努力,終於找到最終原因,希望能幫助大家!
推薦1:在@ResponseBody的方法中加入produces="application/json;charset=utf-8" 這樣絕對能保證返回的字符串絕對是application/json; charset=utf-8,不會出現ISO-8859-1
@ResponseBody @RequestMapping(value="/getUsersByPage",produces = "application/json; charset=utf-8") public String getUsersByPage(){
return "張三";
}
推薦2:因為我們在項目中,是Spring項目改造Sringboot ,所以在Springboot 引入了一些Spring.xml文件,然后就是因為這些spring.xml文件才會導致這次問題的產生,也讓我對Spring更加了解
<mvc:annotation-driven> <mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/plain;charset=utf-8</value> <value>text/html;charset=UTF-8</value> </list> </property> </bean> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> </mvc:message-converters>
</mvc:annotation-driven>
網上都很多都是這種寫法,個人不是特別推薦,因為我看過源碼,發現發現spring 接頭部時,會加入默認的字符集!個人推薦寫法如下——
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8"/> </bean> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> </mvc:message-converters> </mvc:annotation-driven>
如果沒有什么大的問題,一般這樣就可以解決問題!但是我發現無論我怎么加,怎么改!前端返回的response的application/json;charset=ISO-8859-1!后面我跟蹤源碼、推理、實驗才發現問題。
Spring能識別json,xml轉換我們需要的格式數據,是通過一個非常重要接口HttpMessageConverter
進行我們需要的格式轉換,而StringHttpMessageConverter和 MappingJacksonHttpMessageConverter 則是HttpMessageConverter 實現類。
StringHttpMessageConverter的作用:負責讀取字符串格式的數據和寫出二進制格式的數據(當返回值時或者接受值是String類型時,是由這個處理)
MappingJacksonHttpMessageConverter: 負責讀取和寫入json格式的數據;(當返回值是對象或者List,就由這個處理)
ByteArrayHttpMessageConverter: 負責讀取二進制格式的數據和寫出二進制格式的數據;
FormHttpMessageConverter:負責讀取form提交的數據(能讀取的數據格式為 application/x-www-form-urlencoded,不能讀取multipart/form-data格式數據);負責寫入application/x-www-from-urlencoded和multipart/form-data格式的數據;ResourceHttpMessageConverter:負責讀取資源文件和寫出資源文件數據;
SourceHttpMessageConverter: 負責讀取和寫入 xml 中javax.xml.transform.Source定義的數據;
Jaxb2RootElementHttpMessageConverter: 負責讀取和寫入xml 標簽格式的數據;
AtomFeedHttpMessageConverter: 負責讀取和寫入Atom格式的數據;
RssChannelHttpMessageConverter: 負責讀取和寫入RSS格式的數據;
轉載這篇文章https://www.jb51.net/article/88091.htm
其中<mvc:annotation>非常重要
<mvc:annotation-driven />會自動注冊DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個bean,是spring MVC為@Controllers分發請求所必須的。
並提供了數據綁定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,讀寫XML的支持(JAXB),讀寫JSON的支持(Jackson)。
后面,我們處理響應ajax請求時,就使用到了對json的支持。
當我們需要controller返回一個map的json對象時,可以設定<mvc:annotation-driven />,同時設定<mvc:message-converters> 標簽,設定字符集和json處理類。
轉載 https://www.cnblogs.com/shuo1208/p/5552134.html
一直困擾我很多天原因就是這個注解,在我們項目原本已經加入如下注解,可是又在后面加上<mvc:annotation-driven />,導致Spring 在加載自定義的轉換器以后又加載一次,還覆蓋原來的配置,導致一直content-type 是ISO-8859-1,然后原項目是Spring項目還沒問題,改成Springboot 就出問題了!當我發現這個問題,竟然波瀾不驚,心態越來越好了。
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8"/> </bean> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> </mvc:message-converters> </mvc:annotation-driven>
<mvc:annotation-driven />
推薦三 java配置@Configuration
@EnableWebMvc
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Bean public HttpMessageConverter<String> responseBodyConverter() { StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8")); return converter; } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { super.configureMessageConverters(converters); converters.add(responseBodyConverter());
converters.add(new MappingJacksonHttpMessageConverter());
}
@Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false); //支持后綴匹配 }
其中@EnableWebMvc相當於<mvc:annotation-driven> 如果不加,會有一點小小的問題!請注意以下。
推薦4、SpringBoot2.0及Spring 5.0 WebMvcConfigurerAdapter已被廢棄,有兩種可以添加控制轉換器
直接實現WebMvcConfigurer 和繼承WebMvcConfigurationSupport
WebMvcConfigurerAdapter不太推薦,因為如果要繼承WebMvcConfigurationSupport,但是替換之后之前的靜態資源文件會被攔截,導致無法可用。需要重新添加
代碼如下
@Configuration public class MyWebAppConfigurer extends WebMvcConfigurationSupport{ @Override protected void configureMessageConverters(List> converters) { // TODO Auto-generated method stub super.configureMessageConverters(converters); converters.add(responseBodyConverter()); } @Bean public HttpMessageConverter responseBodyConverter() { StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8")); return converter; } // 如果不加,則靜態資源會被攔截,導致訪問不到靜態資源 @Override protected void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/**") .addResourceLocations("classpath:/META-INF/resources/") .addResourceLocations("classpath:/resources/") .addResourceLocations("classpath:/static/") .addResourceLocations("classpath:/public/"); super.addResourceHandlers(registry); } }
方式二
@Configuration public class WebConfig implements WebMvcConfigurer { /** * 跨域支持 * @param registry */ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT") .maxAge(3600 * 24); } /** * * @param converters */ @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8")); converters.add(converter); }