如何解決springboot參數傳中文亂碼


前言

本文案例來自業務部門的一個業務場景。他們的業務場景是他們部門研發了一個微服務上下文透傳組件,其透傳原理也挺簡單的,就是通過springboot攔截器把請求參數塞進threadlocal,然后下游通過threadlocal取到值,服務之間進行feign調用時,再把threadlocal的參數塞到header頭里面。這個組件一直用得好好的,突然有一天因為傳的參數值是中文,導致亂碼。他們通過嘗試下面的各種方案,都無法解決。最后就讓我們部門排查處理。

業務部門的實現思路

他們一開始的思路方向是參數編碼不一致導致中文亂碼。於是他們就朝這個方向努力着,於是就有了如下方案

方案一:

String value = new String("我是中文亂碼".getBytes("ISO-8859-1"),"UTF-8");

這個是常用解決字符串中文亂碼的方法之一

方案二:編寫字符編碼過濾器

@WebFilter(urlPatterns = "/*",filterName = "CharacterEncodingFilter")
public class CharacterEncodingFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
 
        filterChain.doFilter(request , response);
    }
    @Override
    public void destroy() {
    }
}

然后啟動類上加上@ServletComponentScan。@WebFilter是servlet3.0才有的注解。當然這個過濾器你還可以這么寫

public class CharacterEncodingFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
 
        filterChain.doFilter(request , response);
    }
    @Override
    public void destroy() {
    }
}

寫個bean配置類,如下

    @Bean
    public FilterRegistrationBean registerAuthFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new CharacterEncodingFilter();
        registration.addUrlPatterns("/*");
        registration.setName("CharacterEncodingFilter");
        registration.setOrder(1); 
        return registration;
    }

方案三:在application.yml指定編碼格式為utf-8

spring:
  http:
    encoding:
      charset: utf-8
      enabled: true
      force: true

server:
  tomcat:
    uri-encoding: UTF-8

方案四:寫個StringHttpMessageConverter

image.png
百度來的基本上都是長這樣。不過在spring5版本WebMvcConfigurerAdapter這個類已經過時。其替代方式是實現WebMvcConfigurer接口或者繼承WebMvcConfigurationSupport。不過如果使用WebMvcConfigurationSupport,則會使springboot的mvc自動裝配失效。失效的原因是
image.png
拓展一點小知識,加上@EnableWebMvc同樣也會springboot的mvc自動裝配失效。其原因是
image.png
org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration這個配置類繼承WebMvcConfigurationSupport
image.png
介紹那么多種方案,並沒有解決按例的問題。那問題點出在哪里?前邊案例我們提到過,在feign調用時,會把threadlocal的參數塞到header里面。真正亂碼的問題點就在這里,header是不支持中文傳輸的,如果你硬要傳輸,基本上接收方接到就是???這種看似亂碼的符號

破題關鍵

在把threadlocal的值塞到header里面時,先做下URLEncoder編碼,形如

URLEncoder.encode(“我是中文亂碼”,"UTF-8")

在接收header參數時,做下URLDecoder.解碼,形如下

URLDecoder.decode(header中待解碼的參數值, "UTF-8")

總結

方向錯了,雖然再怎么努力看似也啥沒卵用,不過至少可能會收獲其他意想不到的東西


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM