解决Spring MVC中文乱码的编码配置

 更新时间:2023年10月26日 09:00:39   作者:福  
这篇文章主要为大家介绍了解决SpringMVC中文乱码的编码配置示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

SpringMVC配置编码方式

SpringMVC的中文乱码问题其实已经不是什么问题了,无非就是配置编码方式->解决问题。

但是由于SpringMVC可以通过:xml方式配置、Servlet3.0方式配置,以及是否使用@EnableWebMvc等,不同配置方式下,解决中文乱码问题的方案有所不同。

xml配置的方式

xml配置方式的解决方案最简单:

<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceRequestEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>forceResponseEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

在web.xml文件中加编码过滤器,并强制过滤器对Request和Response都生效,可以解决request请求、以及response返回参数中的中文乱码问题。

但是返回体,也就是response body中的中文乱码问题,以上过滤器方案无法解决。

Response body中的中文乱码问题需要在spring MVC中增加以下配置:

<mvc:annotation-driven >
        <!--设置响应输出字符集-->
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=utf-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

前面一篇文章[Spring MVC 五:DispatcherServlet初始化之 mvc:annotation-driven] 分析过<mvc:annotation-driven />标签的解析过程,该标签在创建RequestMappingHandlerAdapter的过程中,会读取到xml文件中messageConverters的定义并设置到RequestMappingHandlerAdapter对象的messageConverters属性中并最终在DispatcherServlet处理请求的过程中生效。

Servlet3.0配置

Servlet3.0的配置方式,是指通过WebApplicationInitializer接口完成SpringMVC配置的方式。

可以通过接口方法getServletFilters增加编码过滤器:

public class MvcInitializer
        extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
//        return null;
        return new Class[] {RootConfiguration.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
//        return null;
        return new Class[] {MvcConfiguration.class,CommonConfiguration.class};
    }
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }
    @Override
    protected Filter[] getServletFilters() {
//        ShallowEtagHeaderFilter shallowEtagHeaderFilter = new ShallowEtagHeaderFilter();
//        shallowEtagHeaderFilter.setWriteWeakETag(true);
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("utf-8");
        characterEncodingFilter.setForceEncoding(true);
        return new Filter[]{characterEncodingFilter};
    }
}

以上方式增加过滤器后,可以解决request和response请求及返回参数中的中文编码问题。

但是无法解决response body的中文乱码问题。

由于WebApplicationInitializer接口并没有提供任何关于messageConverters的接口,看了很多遍源码也并没有找到可以配置的地方,网上也没有找到相关解决方案......所以解决这个问题还是费了很多周折。

由于我们已经知道,response body的中文乱码问题最终是通过RequestMappingHandlerAdapter对象的messageConverters解决的,所以还是想通过定制化RequestMappingHandlerAdapter的初始化过程、设置其messageConverters的方式解决问题。

如果没有定制化处理的话,DispatcherServlet在初始化的过程中是在initStrategies方法中创建DispatcherServlet.properties文件中默认的RequestMappingHandlerAdapter,是通过反射机制直接new出来的,最终会调用到RequestMappingHandlerAdapter的默认构造器:

public RequestMappingHandlerAdapter() {
        this.messageConverters = new ArrayList<>(4);
        this.messageConverters.add(new ByteArrayHttpMessageConverter());
        this.messageConverters.add(new StringHttpMessageConverter());
        try {
            this.messageConverters.add(new SourceHttpMessageConverter<>());
        }
        catch (Error err) {
            // Ignore when no TransformerFactory implementation is available
        }
        this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
    }

默认构造器会直接new一个StringHttpMessageConverter()加进来,不修改的话StringHttpMessageConverter的默认字符集是ISO_8859_1,一定会出现中文乱码问题:

public static final Charset DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;

所以我们必须找到某种方式可以定制化RequestMappingHandlerAdapter的初始化过程。

继续分析源码:

private void initHandlerAdapters(ApplicationContext context) {
        this.handlerAdapters = null;
        if (this.detectAllHandlerAdapters) {
            // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
            Map<String, HandlerAdapter> matchingBeans =
                    BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerAdapters = new ArrayList<>(matchingBeans.values());
                // We keep HandlerAdapters in sorted order.
                AnnotationAwareOrderComparator.sort(this.handlerAdapters);
            }
        }
        else {
            try {
                HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
                this.handlerAdapters = Collections.singletonList(ha);
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Ignore, we'll add a default HandlerAdapter later.
            }
        }
        // Ensure we have at least some HandlerAdapters, by registering
        // default HandlerAdapters if no other adapters are found.
        if (this.handlerAdapters == null) {
            this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
            if (logger.isTraceEnabled()) {
                logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
                        "': using default strategies from DispatcherServlet.properties");
            }
        }
    }

发现initHandlerAdapters方法首先会从Spring容器中获取HandlerAdapter!

我们是否有办法定制一个HandlerAdapter、加入到Spring容器中?Spring当然给我们提供了这种机会,回想一下@Configuration+@Bean注解,是否就可以解决?

在MvcConfig文件中增加如下代码:

@Configuration
@ComponentScan({"org.example.controller"})
public class MvcConfiguration  {
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/pages/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
    //定制RequestMappingHandlerAdapter
    @Bean
    public RequestMappingHandlerAdapter handlerAdapter(){
        RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter();
        List<HttpMessageConverter<?>> messageConverters;
        messageConverters = new ArrayList<>(4);
        messageConverters.add(new ByteArrayHttpMessageConverter());
        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
        messageConverters.add(stringHttpMessageConverter);
        try {
            messageConverters.add(new SourceHttpMessageConverter<>());
        }
        catch (Error err) {
            // Ignore when no TransformerFactory implementation is available
        }
        messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        handlerAdapter.setMessageConverters(messageConverters);
        return  handlerAdapter;
    }

参考RequestMappingHandlerAdapter默认构造器的代码,修改其中StringHttpMessageConverter的创建过程、设置其默认字符集为UTF-8......验证后发现,问题已解决!

使用@EnableWebMvc

由于@EnableWebMvc是必须和@configuration配合使用的,所以,一定会存在配置类。这种情况下,配置类实现WebMvcConfigurer、通过扩展extendMessageConverters方法解决:

@Configuration
@EnableWebMvc
@ComponentScan({"org.example.controller"})
public class MvcConfiguration implements WebMvcConfigurer{
    public MvcConfiguration(){
        System.out.println("mvc configuration constructor...");
    }
//    通过@EnableWebMVC配置的时候起作用,
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for(HttpMessageConverter httpMessageConverter:converters){
            if(StringHttpMessageConverter.class.isAssignableFrom(httpMessageConverter.getClass())){
                ((StringHttpMessageConverter)httpMessageConverter).setDefaultCharset(Charset.forName("UTF-8"));
            }
        }
    }
}

以上就是解决Spring MVC中文乱码的编码配置的详细内容,更多关于Spring MVC中文乱码解决的资料请关注脚本之家其它相关文章!

相关文章

  • Java使用正则表达式截取重复出现的XML字符串功能示例

    Java使用正则表达式截取重复出现的XML字符串功能示例

    这篇文章主要介绍了Java使用正则表达式截取重复出现的XML字符串功能,涉及java针对xml字符串及指定格式字符串的正则匹配相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • 解决Eclipse发布到Tomcat丢失依赖jar包的问题

    解决Eclipse发布到Tomcat丢失依赖jar包的问题

    这篇文章介绍了如何在Eclipse中配置部署装配功能,以确保在将Web项目发布到Tomcat服务器时不会丢失任何依赖jar包,通过手动配置或使用构建工具脚本,可以自动化这个过程,提高开发效率和应用程序的稳定性,感兴趣的朋友跟随小编一起看看吧
    2025-01-01
  • java实现稀疏矩阵的压缩与解压的方法

    java实现稀疏矩阵的压缩与解压的方法

    这篇文章主要介绍了java实现稀疏矩阵的压缩与解压 ,把该稀疏矩阵压缩以三元组形式表示并以文件形式保存,再写另一个程序读取文件中的信息把压缩后的三元组还原成原来的稀疏矩阵,需要的朋友可以参考下
    2022-03-03
  • Java基础之TreeMap详解

    Java基础之TreeMap详解

    这篇文章主要介绍了Java基础之TreeMap详解,文中有非常详细的代码示例,对正在学习java基础的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • Java构造器使用方法及注意事项

    Java构造器使用方法及注意事项

    这篇文章主要介绍了Java构造器使用方法及注意事项的相关资料,这里举例说明如何使用构造器及需要注意的地方,需要的朋友可以参考下
    2017-07-07
  • Java Guava的使用技巧整理

    Java Guava的使用技巧整理

    Guava是Google发布的一个开源库,主要提供了一些在Java开发中非常有用的工具类和API,不管是工作还是学习都是非常值得我们去熟悉的,一起来看看吧
    2023-03-03
  • Spring Boot Jar 包部署脚本的实例讲解

    Spring Boot Jar 包部署脚本的实例讲解

    在本篇文章里小编给大家整理的是一篇关于Spring Boot Jar 包部署脚本的实例讲解内容,对此有兴趣的朋友们可以跟着学习下。
    2021-12-12
  • Java Lambda表达式的使用详解

    Java Lambda表达式的使用详解

    这篇文章主要介绍了Java Lambda表达式的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06
  • spring boot集成jasypt 并实现自定义加解密的详细步骤

    spring boot集成jasypt 并实现自定义加解密的详细步骤

    由于项目中的配置文件 配置的地方过多,现将配置文件统一放到nacos上集中管理 且密码使用加密的方式放在配置文件中,配置文件的加密使用加密库jasypt,本文给大家介绍spring boot集成jasypt并实现自定义加解密,感兴趣的朋友一起看看吧
    2023-08-08
  • Java实现PDF转为Word文档的示例代码

    Java实现PDF转为Word文档的示例代码

    众所周知,PDF文档除了具有较强稳定性和兼容性外, 还具有较强的安全性,在工作中可以有效避免别人无意中对文档内容进行修改。本文将分为以下两部分介绍如何在保持布局的情况下将PDF转为Word文档,希望对大家有所帮助
    2023-01-01

最新评论