本文案例來自業務部門的一個業務場景。他們的業務場景是他們部門研發了一個微服務上下文透傳組件,其透傳原理也挺簡單的,就是經過springboot攔截器把請求參數塞進threadlocal,而後下游經過threadlocal取到值,服務之間進行feign調用時,再把threadlocal的參數塞到header頭裏面。這個組件一直用得好好的,忽然有一天由於傳的參數值是中文,致使亂碼。他們經過嘗試下面的各類方案,都沒法解決。最後就讓咱們部門排查處理。java
他們一開始的思路方向是參數編碼不一致致使中文亂碼。因而他們就朝這個方向努力着,因而就有了以下方案web
String value = new String("我是中文亂碼".getBytes("ISO-8859-1"),"UTF-8");
這個是經常使用解決字符串中文亂碼的方法之一spring
@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纔有的註解。固然這個過濾器你還能夠這麼寫tomcat
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配置類,以下springboot
@Bean public FilterRegistrationBean registerAuthFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new CharacterEncodingFilter(); registration.addUrlPatterns("/*"); registration.setName("CharacterEncodingFilter"); registration.setOrder(1); return registration; }
spring: http: encoding: charset: utf-8 enabled: true force: true server: tomcat: uri-encoding: UTF-8
百度來的基本上都是長這樣。不過在spring5版本WebMvcConfigurerAdapter這個類已通過時。其替代方式是實現WebMvcConfigurer接口或者繼承WebMvcConfigurationSupport。不過若是使用WebMvcConfigurationSupport,則會使springboot的mvc自動裝配失效。失效的緣由是
拓展一點小知識,加上@EnableWebMvc一樣也會springboot的mvc自動裝配失效。其緣由是
org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration這個配置類繼承WebMvcConfigurationSupport
介紹那麼多種方案,並無解決按例的問題。那問題點出在哪裏?前邊案例咱們提到過,在feign調用時,會把threadlocal的參數塞到header裏面。真正亂碼的問題點就在這裏,header是不支持中文傳輸的,若是你硬要傳輸,基本上接收方接到就是???這種看似亂碼的符號mvc
在把threadlocal的值塞到header裏面時,先作下URLEncoder編碼,形如app
URLEncoder.encode(「我是中文亂碼」,"UTF-8")
在接收header參數時,作下URLDecoder.解碼,形以下ide
URLDecoder.decode(header中待解碼的參數值, "UTF-8")
方向錯了,雖然再怎麼努力看似也啥沒卵用,不過至少可能會收穫其餘意想不到的東西微服務