Java Web中常见乱码问题的分析与解决

本文详细介绍了JavaWeb中常见的各种乱码问题及其解决方案,包括GET和POST请求的乱码处理,以及如何统一处理编码问题,确保数据传输正确。

Java Web中出现乱码的现象:

第一类:前台参数传输至服务端后乱码

1. get请求参数中文发送到服务器端乱码

2. post请求参数中文发送到服务器乱码

第二类:服务端响应到达浏览器后乱码

3. 在jsp页面中,中文显示乱码


Java Web中出现的各种编码:


1. JSP文件自身的编码

Jsp文件中会出现下面所示的编码指定方式:

<%@ page language=“java” contentType=“text/html; charset=UTF-8″    pageEncoding=“UTF-8″%>

 

<meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8″>


1)pageEncoding="utf-8" --该jsp文件自身采用的编码格式,也就是告诉服务器使用什么编码翻译jsp文件成java文件

jsp中post表单的编码由pageEncoding和contentType参数决定,以pageEncoding为准,如果没有pageEncoding则以contentType为准,如果没有contentType以Meta标签中的charset为准,都没有则以ISO-8859-1编码

2)contentType="text/html;charset=utf-8"服务器发送浏览器的数据类型和内容编码。其中charset="utf-8"--用来指定Tomcat返回响应时采用的编码,也是post方式提交参数的编码方式。

3)Meta标签中的charset是在contentType未指定编码时采用的默认编码格式

 

2. Tomcat读取JSP文件时采用的编码

参考1)

3. Tomcat返回响应时采用的编码

参考2)

4. 浏览器显示HTML时采用的编码

浏览器的编码格式的设置

 

根据现象分析解决方案:


1. get请求参数乱码

2. post请求参数乱码

POST表单参数是通过http的body传递到服务器的。前面已经说过,表单项参数是采用contentType中的charset指定的编码格式进行编码的。服务器端也是用contentType中的charset指定的编码进行解码操作,所以一般不会出现乱码问题。

这个编码我们可以通过request.setCharacterEncoding()来进行设置,该设置只对POST参数有效。注意,这个函数必须在第一次调用request.getParameter()之前使用。


3. 同时处理Get和Post两种提交方式的编码问题

GET和POST两种方式的不同表现使得处理起来比较麻烦。

根据1和2,使用组合方法可以确定多种解决策略。

解决方案1:分别处理get和post请求

处理get请求:在Tomcat的server.xml下的connector属性中添加参数URIEncoding=’UTF-8’;

处理post请求:在Servlet中设置request.setCharacterEncoding()

解决方案2:都使用手动重新解码

 

以上两种方式存在一个共同的问题,那就是只要请求中有中文,每一个servlet都要进行重复的处理。应该抽取出这个过程。

解决方案3:使用参数useBodyEncodingForURI=’true’

在Tomcat的server.xml下的connector属性中添加参数useBodyEncodingForURI=’true’(注意,并不是对整个URI都采用BodyEncoding,只是应用于Query String而已)。这样,Tomcat便会用request.setCharacterEncoding()指定的编码来解析GET参数了。

解决方案4:使用过滤器Filter并运用动态代理实现编码统一处理

[java]  view plain  copy
  1. package EncodingFilter;  
  2.   
  3. import java.io.IOException;  
  4. import java.lang.reflect.InvocationHandler;  
  5. import java.lang.reflect.Method;  
  6. import java.lang.reflect.Proxy;  
  7.   
  8. import javax.servlet.Filter;  
  9. import javax.servlet.FilterChain;  
  10. import javax.servlet.FilterConfig;  
  11. import javax.servlet.ServletException;  
  12. import javax.servlet.ServletRequest;  
  13. import javax.servlet.ServletResponse;  
  14. import javax.servlet.http.HttpServletRequest;  
  15. import javax.servlet.http.HttpServletResponse;  
  16.   
  17. public class EncodingFilter implements Filter {  
  18.   
  19.     public void destroy() {  
  20.     }  
  21.   
  22.     public void doFilter(ServletRequest req, ServletResponse resp,  
  23.             FilterChain chain) throws IOException, ServletException {  
  24.   
  25.         // 如果希望匿名内部类使用一个在外部定义的对象,那么编译器会要求其参数引用是final的  
  26.         final HttpServletRequest request = (HttpServletRequest) req;  
  27.         HttpServletResponse response = (HttpServletResponse) resp;  
  28.   
  29.         request.setCharacterEncoding("UTF-8");// POST提交有效  
  30.         response.setContentType("text/html;charset=UTF-8");  
  31.   
  32.         // 解决:对HttpServletRequest接口的getParameter方法进行功能扩展,识别GET请求,可以使用动态代理!  
  33.         HttpServletRequest proxyRequest = (HttpServletRequest) Proxy.newProxyInstance(request.getClass().getClassLoader(),  
  34.                 new Class[] { HttpServletRequest.class },  
  35.                 new InvocationHandler() {  
  36.   
  37.                     // args对象数组,代表被调用方法的参数  
  38.                     public Object invoke(Object proxy, Method method,  
  39.                             Object[] args) throws Throwable {  
  40.                         String methodName = method.getName();  
  41.                         if ("getParameter".equals(methodName)) {  
  42.                             String value = request.getParameter(args[0]  
  43.                                     .toString());  
  44.                             String requestMethodName = request.getMethod();  
  45.                             if ("GET".equals(requestMethodName)) {  
  46.                                 // 不为空 也不为 空字符串  
  47.                                 if (value != null && !"".equals(value.trim())) {  
  48.                                     value = new String(value  
  49.                                             .getBytes("iso-8859-1"), "utf-8");  
  50.                                 }                                 
  51.                             }  
  52.                             return value;  
  53.                         } else {  
  54.                             return method.invoke(request, args);  
  55.                         }  
  56.                     }  
  57.   
  58.                 });  
  59.         //放行 (执行下一个过滤器或者servlet)  
  60.         chain.doFilter(proxyRequest, response);  
  61.     }  
  62.   
  63.     public void init(FilterConfig filterConfig) throws ServletException {  
  64.     }  
  65.   
  66. }  

再在web.xml中配置filter和filter-mapping,搞定

4. 服务器发送给浏览器的乱码问题

5. 在jsp页面中,中文显示乱码

总结

开发时应注意工作区编码,前端编码,服务器编码,数据库编码一致。

造成乱码的原因就是因为使用了错误的字符编码去解码字节流 因此当我们在思考任何跟文本显示有关的问题时,请时刻保持清醒:当前使用的字符编码是什么
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值