区分UTF-8和GBK的背景GBK是在国标GB2312的基础上扩展后兼容GB2312的标准。专门用来解决中文编码,是双字节的,不管中文还是英文。是双字节的。UTF-8是一种国际编码方式,包括了世界上大部分的语言(简体中文、繁体中文、英文、日文、韩文等),同时也兼容ASCII码。虽然GBK比UTF-8少两个字节,但是GBK只包含中文,而UTF-8包含了世界各国都需要使用的字符,所以现在很多系统或者框架都默认使用UTF-8。但是,在业务开发接入系统界面时,经常会遇到一些老系统使用GBK编码的情况,尤其是国内的支付。这时候就需要兼容GBK和UTF-8编码。如何让项目兼容UTF-8和GBK我们使用springboot2.7版本。我们默认的API使用UTF-8,特殊API使用GBK。在springboot中,在解析请求之前,会通过CharacterEncodingFilter指定内容编码格式。@OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainfilterChain)throwsServletException,IOException{字符串编码=getEncoding();if(encoding!=null){//请求进来设置编码或者设置请求强制编码当header中没有设置编码时)if(isForceRequestEncoding()||request.getCharacterEncoding()==null){request.setCharacterEncoding(编码);}//设置响应的强制转码if(isForceResponseEncoding()){response.setCharacterEncoding(encoding);}}filterChain.doFilter(请求,响应);}项目的全局编码方式可以修改如下方式server:servlet:encoding:charset:UTF-8force-request:falseforce-response:false勾选默认接下来,编码格式UTF-8和强制转换每次,这是什么意思?即即使你请求headerapplication/json;charset=GBK,也不会按照header的编码进行解析,强制帮你转为UTF-8。如果内容是GBK的,就等着乱码吧!@Bean@ConditionalOnMissingBean公共CharacterEncodingFiltercharacterEncodingFilter(){CharacterEncodingFilterfilter=newOrderedCharacterEncodingFilter();filter.setEncoding(this.properties.getCharset().name());filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));筛选。setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));返回过滤器;}publicbooleanshouldForce(Typetype){Booleanforce=(type!=Type.REQUEST)?这个.forceResponse:这个.forceRequest;如果(force==null){force=this.force;}if(force==null){force=(type==Type.REQUEST);}返回力;现在有一个支付系统,它请求的内容是GBK编码的,有GET和POST两种方法。我们的系统接口默认为UTF-8,所以只有针对特定GBK接口的处理才需要支持以下请求情况。POST对方的请求内容采用GBK编码,在请求头中指定编码方式application/json;charset=GBK。POSTpeer的请求内容采用GBK编码,请求头中没有指定编码方式application/json。GET对方请求内容用GBK编码。第一种情况,我们只需要关闭强制转换即可。设置charset=gbk,就会使用gbk编码进行解析。如果不默认设置,它将使用utf-8进行解析。server:servlet:encoding:force:false对于第二种和第三种情况,我们需要先关闭强制转换,然后添加一个优先级高的过滤器,将指定的请求设置为GBK编码格式(即输入时spring解析之前一定要处理),如果使用tomcat容器,应该做如下处理。@Slf4j@ConfigurationpublicclassGBKFilterConfig{@BeanpublicFilterRegistrationBeangbkFilter(){FilterRegistrationBeanregistration=newFilterRegistrationBean();registration.setDispatcherTypes(DispatcherType.REQUEST);registration.setFilter(newFilter(){@Overridepublicvoidinit(javax.servlet.FilterConfigfilterConfig)throwsServletException{}@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{RequestFacadereq=(RequestFacade)request;Classclazz=req.getClass();log.info("GBKFilter...");try{Fieldfield=clazz.getDeclaredField("request");field.setAccessible(true);Requestr=(请求)field.get(req);org.apache.coyote.Requestp=r.getCoyoteRequest();//GET请求参数强烈使用GBK编码p.getParameters().setQueryStringCharset(Charset.forName("GBK"));//POST请求头没有指定编码,强制使用GBKp.getParameters().setCharset(Charset.forName("GBK"));p.setCharset(Charset.forName("GBK"));chain.doFilter(请求,响应);}catch(Exceptione){log.error("error",e)}}@Overridepublicvoiddestroy(){}});registration.addUrlPatterns("/api/gbk/**");registration.setName("gbkFilter");registration.setOrder(Integer.MIN_VALUE);返回注册;}}
