zoukankan      html  css  js  c++  java
  • Spring boot 字符集编码

    来源

    近一段在开发接口平台,使用spring boot 开发,总体来说还是蛮顺利;
    接口平台不可避免的让别人调用服务,也会去调用其它的外部接口;
    突然有一天,某个服务商回调信息中出现了乱码,形如:��ֵʧ��,打破了宁静

    分析过程

    向服务商确认,该接口传递的参数使用GBK编码,WHT??现在还有用GBK的,不是用UTF8编码么?
    马上确认我的程序编码:

    server.tomcat.uri-encoding 未设置
    http.encoding.charset: UTF-8
    http.encoding.force-request: true

    可以看到uri的配置未定义,搜索文档说明spring boot默认使用UTF8编码
    下面两个是定义HTTP的字符集,用来设置request与response的字符集;
    跟踪源码,发现这个字符参数会在CharacterEncodingFilter中用到,核心的方法是使用:request.setCharacterEncoding("UTF-8"),并且是一个全局的内容

    解决过程

    1. 将得到的乱码用UTF-8编码再用GBK解码,如下代码,得到结果为:锟斤拷值失锟斤拷
      new String(source.getBytes("UTF-8"),"GBK"), 通过查资料得知,以GBK编码->UTF-8解码(出现乱码)->UTF-8编码(这步由于UTF8编码的特殊性,会增加部分头信息)->GBK解码(由于加了特殊部分,所以造成不可逆的结果)

    2. 在方法中调用request.getCharacterEncoding("UTF-8")无效,查询rquest的这个方法说明,只有在获取参数之前调用这个方法才有效,但在此之前spring 已帮我们做了很多事情,所以在这里无效;

    3. 自已写Filte来实现设置,但不知什么原因,还是无效

    4. 继承CharacterEncodingFilter,对特定url做特殊处理,结果是自定义的encoding生效了,原先的UTF8的 encodingFilter失效了,就算修改自己的Bean名字还不行

    5. 修改自定义EncodingFilter,实现多字符集的处理:
      定义encodingFilter:

    public class MutiCharacterEncodingFilter extends CharacterEncodingFilter implements Ordered{
    
        //最高优先级
        private int order = Integer.MIN_VALUE;
    
    
        private List<String> mutiUrls = new ArrayList();
    
        private String mutiCharset =  "GBK";
    
    
        public List<String> getMutiUrls() {
            return mutiUrls;
        }
    
        public void setMutiUrls(List<String> mutiUrls) {
            this.mutiUrls = mutiUrls;
        }
    
        public String getMutiCharset() {
            return mutiCharset;
        }
    
        public void setMutiCharset(String mutiCharset) {
            this.mutiCharset = mutiCharset;
        }
    
    
        /**
         *  @param charset
         * @param mutiCharset
         * @param mutiUrls
         * @param forceRequest
         * @param forceResponse
         */
        public MutiCharacterEncodingFilter(String charset, String mutiCharset , List<String> mutiUrls, boolean forceRequest, boolean forceResponse) {
            super(charset,forceRequest,forceResponse);
            this.mutiUrls = mutiUrls;
            this.mutiCharset = mutiCharset;
    
        }
    
        public MutiCharacterEncodingFilter() {
            super();
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    
            String path = request.getRequestURI();
    
            //如果是这个链接 执行mutyEncoding方法
            if(PathMatcherUtil.matchAny(mutiUrls,path)){
                if (mutiCharset != null) {
                    if (isForceRequestEncoding() || request.getCharacterEncoding() == null) {
                        request.setCharacterEncoding(mutiCharset);
                    }
                    if (isForceResponseEncoding()) {
                        response.setCharacterEncoding(mutiCharset);
                    }
                }
                filterChain.doFilter(request,response);
                return ;
            }
    
            //否则 使用默认方法
            super.doFilterInternal(request,response,filterChain);
    
        }
    
    
        @Override
        public int getOrder() {
            return order;
        }
    

    在配置中设置相应内容:

      http:
        encoding:
          charset: UTF-8
          force-request: true
          force-response: false
          mutiCharset: GBK
          mutiUrls:
            - /notify/test

    在config中生成实例

        //第一种字符集
        @Value(value = "${spring.http.encoding.charset}")
        private String charset;
        //是否强制应用到request
        @Value(value = "${spring.http.encoding.force-request}")
        private boolean forceRequest;
        //是否强制设置到response
        @Value(value = "${spring.http.encoding.force-response}")
        private boolean forceResponse;
    
    
    
        /**
         * 自定义HTTP字符集 默认使用charset字符集 在特定情况下使用第二字符集 用于欧飞回调GBK编码
         * 仅对POST中的表单参数有效 对于URI中的参数无效 只能去修改tomcat的字符集编码 应该不致于做的这么绝吧
         * @return
         */
        @Bean()
        @ConfigurationProperties(prefix = "spring.http.encoding")
        @ConfigurationPropertiesBinding
        public MutiCharacterEncodingFilter mutiCharacterEncodingFilter(){
            MutiCharacterEncodingFilter encodingFilter = new MutiCharacterEncodingFilter();
            encodingFilter.setEncoding(charset);
            encodingFilter.setForceRequestEncoding(forceRequest);
            encodingFilter.setForceResponseEncoding(forceResponse);
            return encodingFilter;
        }

    到此问题解决,可以接收GKB编码的内容;

    但同时也有缺陷,只适用于body的内容,不适用于链接到URL后面的请求参数,如果要支持,只能修改tomcat-uri-encoding为UTF-8,希望对大家有帮助.

  • 相关阅读:
    [LeetCode#114]Flatten Binary Tree to Linked List
    [LeetCode#103]Binary Tree Zigzag Level Order Traversal
    [LeetCode#102]Binary Tree Level Order Traversal
    [LeetCode#145]Binary Tree Postorder Traversal
    [LeetCode#]Binary Tree Preorder Traversal
    [LeetCode#144]Binary Tree Preorder Traversal
    [LeetCode#94]Binary Tree Inorder Traversal
    [LeetCode#101]Symmetric Tree
    [LeetCode#100]Same Tree
    [LeetCode#104, 111]Maximum Depth of Binary Tree, Minimum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/417xiaoliu/p/9655520e4472d403c9b45ac3e9a50fe3.html
Copyright © 2011-2022 走看看