Tomcat中文乱码处理之URIEncoding、useBodyEncodingForURI及CharacterEncodingFilter

大家知道tomcat5.0开始,对网页的中文字符的post或者get,经常会出现乱码现象。具体是因为Tomcat默认是按ISO-8859-1进行URL解码,ISO-8859-1并未包括中文字符,这样的话中文字符肯定就不能被正确解析了。常见的解决方法是在tomcat的server.xml下的connetor属性中增加URIEncoding或者useBodyEncodingForURI属性。但是,这两种方式有什么区别呢?

       简单谈一下自己的理解:

       按照tomcat-docs/config/http.html文档的说明:

       URIEncoding:This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used. 

       useBodyEncodingForURI:This specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding.

       也就是说,useBodyEncodingForURI参数表示是否用request.setCharacterEncoding参数对URL提交的数据和表单中GET方式提交的数据进行重新编码,默认情况下,该参数为false。URIEncoding参数指定对所有GET方式请求进行统一的重新编码(解码)的编码。

        URIEncoding和useBodyEncodingForURI区别是:URIEncoding是对所有GET方式的请求的数据进行统一的重新编码; 而useBodyEncodingForURI则是根据响应该请求的页面的request.setCharacterEncoding参数对数据进行的重新编码,不同的页面可以有不同的重新编码的编码。

        下面详细分析Tomcat的两个参数设置URIEncoding和useBodyEncodingForURI。 对于一个请求,常用的有两种编码方式,如下: 

Java代码  收藏代码

  1. <!DOCTYPE html>  
  2. <html>  
  3.     <head>  
  4.         <meta charset="utf-8" />  
  5.         <title></title>  
  6.     </head>  
  7.     <body>  
  8.         <form action="http://127.0.0.1:8080/string?name=中国" method="post">  
  9.             <input type="text" name="user" value="张三"/>  
  10.             <input type="submit" value="提交"/>  
  11.         </form>  
  12.     </body>  
  13. </html>  

 

       首先说说结论: 
       上述请求有两处含有中文,一处是请求参数中,即?name='中国',另一处是请求体中,即user='张三'。对于这两处tomcat7是分两种编码方式的。URIEncoding就是针对请求参数的编码设置的,而filter的request.setCharacterEncoding('UTF-8')或者请求header中的content-type中的编码都是针对请求体的。 

       useBodyEncodingForURI=true是说,请求参数的编码方式要采用请求体的编码方式。当useBodyEncodingForURI=true时,若请求体采用utf-8解析,则请求参数也要采用utf-8来解析。这两个属性值的设置在tomcat的conf/server.xml文件中配置,如下: 

Java代码  收藏代码

  1. <Service name="Catalina">  
  2.   
  3.    <!--The connectors can use a shared executor, you can define one or more named thread pools-->  
  4.    <!--  
  5.    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"  
  6.        maxThreads="150" minSpareThreads="4"/>  
  7.    -->  
  8.   
  9.   
  10.    <!-- A "Connector" represents an endpoint by which requests are received  
  11.         and responses are returned. Documentation at :  
  12.         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)  
  13.         Java AJP  Connector: /docs/config/ajp.html  
  14.         APR (HTTP/AJP) Connector: /docs/apr.html  
  15.         Define a non-SSL HTTP/1.1 Connector on port 8080  
  16.    -->  
  17.    <Connector port="8080" protocol="HTTP/1.1"  
  18.               connectionTimeout="20000"  
  19.               redirectPort="8443" useBodyEncodingForURI='true' URIEncoding='UTF-8' />  
  20.    <!-- A "Connector" using the shared thread pool-->  


        这样写只是说明这两者的配置位置,并不是两个属性要同时配置,不要理解错了。 继续说CharacterEncodingFilter的作用。 使用方式,将如下代码加入web.xml文件中: 

Java代码  收藏代码

  1. <filter>  
  2.         <filter-name>encoding</filter-name>  
  3.         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
  4.         <init-param>  
  5.             <param-name>encoding</param-name>  
  6.             <param-value>UTF-8</param-value>  
  7.         </init-param>  
  8.         <init-param>  
  9.             <param-name>forceEncoding</param-name>  
  10.             <param-value>true</param-value>  
  11.         </init-param>  
  12.     </filter>  
  13.   
  14.     <filter-mapping>  
  15.         <filter-name>encoding</filter-name>  
  16.         <url-pattern>/*</url-pattern>  
  17.     </filter-mapping>  

 

       作用是,当forceEncoding为false的前提下(默认为false),当request没有指定content-type或content-type不含编码时,该filter将会为这个request设定请求体的编码为filter的encoding值。 当forceEncoding为true的前提下,就会为request的请求体和response都设定为这个filter的encoding值。 
CharacterEncodingFilter源码如下:  

Java代码  收藏代码

  1. public class CharacterEncodingFilter extends OncePerRequestFilter {  
  2.   
  3.     private String encoding;  
  4.   
  5.     private boolean forceEncoding = false;  
  6.   
  7.   
  8.     /** 
  9.      * Set the encoding to use for requests. This encoding will be passed into a 
  10.      * {@link javax.servlet.http.HttpServletRequest#setCharacterEncoding} call. 
  11.      * <p>Whether this encoding will override existing request encodings 
  12.      * (and whether it will be applied as default response encoding as well) 
  13.      * depends on the {@link #setForceEncoding "forceEncoding"} flag. 
  14.      */  
  15.     public void setEncoding(String encoding) {  
  16.         this.encoding = encoding;  
  17.     }  
  18.   
  19.     /** 
  20.      * Set whether the configured {@link #setEncoding encoding} of this filter 
  21.      * is supposed to override existing request and response encodings. 
  22.      * <p>Default is "false", i.e. do not modify the encoding if 
  23.      * {@link javax.servlet.http.HttpServletRequest#getCharacterEncoding()} 
  24.      * returns a non-null value. Switch this to "true" to enforce the specified 
  25.      * encoding in any case, applying it as default response encoding as well. 
  26.      * <p>Note that the response encoding will only be set on Servlet 2.4+ 
  27.      * containers, since Servlet 2.3 did not provide a facility for setting 
  28.      * a default response encoding. 
  29.      */  
  30.     public void setForceEncoding(boolean forceEncoding) {  
  31.         this.forceEncoding = forceEncoding;  
  32.     }  
  33.   
  34.   
  35.     @Override  
  36.     protected void doFilterInternal(  
  37.             HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)  
  38.             throws ServletException, IOException {  
  39.   
  40.         if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {  
  41.             request.setCharacterEncoding(this.encoding);  
  42.             if (this.forceEncoding) {  
  43.                 response.setCharacterEncoding(this.encoding);  
  44.             }  
  45.         }  
  46.         filterChain.doFilter(request, response);  
  47.     }  
  48.   
  49. }  

 

        这个filter有两个属性,encoding和forceEncoding,我们可以在web.xml文件中来设定这两个属性值。 
        每次request请求到来执行方法doFilterInternal,首先调用request.getCharacterEncoding(),本质就是从请求header content-type中获取编码值,如果没有,则调用request.setCharacterEncoding(this.encoding)将该filter的encoding值设置为请求体的编码方式,记住该编码方式只对请求体,不针对请求参数。当forceEncoding=true时,不管请求header content-type有没有编码方式,始终将该filter的encoding值设置到request和response中,同样此设置只针对request的请求体。 

已标记关键词 清除标记
相关推荐
<p> <strong><span style="font-size:20px;color:#FF0000;">本课程主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者</span></strong> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">1. 包含:<span style="color:#FFFF00;background-color:#FF0000;">项目源码、</span><span style="color:#FFFF00;background-color:#FF0000;">项目文档、数据库脚本、软件工具</span>等所有资料</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">2. 手把手的带你从零开始部署运行本套系统</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">3. 该项目附带的源码资料可作为毕设使用</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">4. 提供技术答疑和远程协助指导</span></strong></span><strong><span style="font-size:18px;"></span></strong> </p> <p> <br /> </p> <p> <span style="font-size:18px;"><strong>项目运行截图:</strong></span> </p> <p> <strong><span style="font-size:18px;">1)系统登陆界面</span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015433522.png" alt="" /><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">2)学生模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015575966.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">3)教师模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016127898.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">4)系统管理员</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016281177.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016369884.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">更多Java毕设项目请关注我的毕设系列课程 <a href="https://edu.csdn.net/lecturer/2104">https://edu.csdn.net/lecturer/2104</a></span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p>
©️2020 CSDN 皮肤主题: 终极编程指南 设计师:CSDN官方博客 返回首页