请求与响应的中文乱码问题产生原因及解决


中文乱码问题产生的原因:


Http协议中规定,数据的传输采用字节编码方式,即无论浏览器提交的数据所包含的中文是什么字符编码格式,一旦由服务器经过Http协议传输,则这些数据均将以字节的形式上传给服务器,因为Http协议的底层使用的时TCP传输协议。TCP(Transmission Control Protocol):传输控制协议,是一种面向连接的,可靠的,基于字节流的,端对端的通信协议,在请求中,这些字节均以%开头,以十六进制的形式出现,比如:%7A%9B%3D。

当用户通过表单向浏览器提交一个包含UTF-8编码格式的两个字的中文请求时,浏览器会将这两个中文字符变为六个字节(一般一个UTF-8汉字占用三个字节),形如:%7A%9B%3D%7A%9B%3D,并上传给Tomcat服务器,Tomcat接收到这六个字节,并不知道这六个字节采用的是什么字符编码。而自身默认的编码格式为ISO8859-1,所以会将这六个字节以ISO8859-1的格式进行编码,编码后在控制台显示乱码。

Http请求与响应包含内容:
请求:请求行,请求头,空行,请求正文(如果是GET方法提交,请求参数会附加到请求行,请求正文就会没内容;如果是POST方法提交,请求参数显示到请求正文中)
响应:状态行,响应头,空行,响应正文

1,POST提交时中文乱码问题的解决

setCharacterEncoding()方法设置请求正文中的字符编码,可以解决POST提交时的中文乱码问题,但无法解决GET提交时的中文乱码
req.setCharacterEncoding(“UTF-8”);

2,GET提交时中文乱码问题的解决
第一种方式:在Tomcat服务器下的server.xml文件中找到`

    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
  

并将它改为:

    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

该种方式并不适用,因为Tomacat里有许多虚拟主机,发布着许多应用,修改服务器的server.xml就必须重启服务器,会导致所有应用重启。

第二种方式:
通过字符串按原字符编码打散成字节数组,再将字节数组按指定字符编码组装成字符串
缺点:当出现较多的中文乱码问题时比较麻烦。

package com.ixat.servlets;

//GET提交时中文乱码问题的解决

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RegisterServlet extends HttpServlet {
	public void doGet(HttpServletRequest req,HttpServletResponse res) 
			throws ServletException ,IOException{
			
		//对于请求中的中文乱码问题的万能解决方案
		//这里接收到的name,其字符编码为ISO8850-1
		String name = req.getParameter("name");//通过表单提交的参数
		
		//打散:将name字符串按照原字符编码进行打散
		byte[] bytes=name.getBytes("ISO8859-1");
		
		//组装:将bytes字节数组按照指定字符编码组装,组装为String
		name=new String(bytes,"UTF-8");
		
		String age = req.getParameter("age");
		System.out.println("name="+name);
		System.out.println("age="+age);
	}
}

标准输出流

需要获取客户端提交请求的相关信息,需要从HttpServletRequest对象中获取,需要向客户端的发送数据,则需要通过HttpServletResponse对象来完成

ServletResponse接口的getWriter()方法,用于获取一个输出流对象PrintWriter,该输出流对象专门向客户端浏览器输出字符数据,称为标准输出流。

package com.ixat.servlets;

//Response的PrintWriter
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SomeServlet extends HttpServlet {
	public void doGet(HttpServletRequest req,HttpServletResponse res) 
			throws ServletException,IOException{
		//获取标准输出流
		PrintWriter pw=res.getWriter();
	
		//向标准输出流中写入数据,那么客户端浏览器会直接看到这些数据
		pw.print("abc");
		pw.println("asd");
		pw.write("mno");
		pw.append("rst");
		//对标准输出流的关闭,可以不关闭,因为系统会在请求和响应结束的时候,req和res对象销毁,在销毁响应对象时会自动将标准输出流关闭
		//pw.close();过滤器要对标准输出流进行处理,不必关闭
	}
	
}

3,ServletResponse的中文乱码问题的解决

res.setContentType(“text/html;charset=UTF-8”);

package com.ixat.servlets;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SomeServlet extends HttpServlet {
	public void doGet(HttpServletRequest req,HttpServletResponse res) 
			throws ServletException,IOException{
		
		//res.setCharacterEncoding("UTF-8");  //address闄曡タ瑗垮畨  设置后出现的乱码问题  
		
		//设置相应的MIME类型(video/mp4,image/jpg等也属于MIME类型)
		res.setContentType("text/html;charset=UTF-8");//其中可以指定MIME的字符编码,即响应体的字符编码
	
		/*
			res.setContentType("text/html;charset=ISO8859-1");
			res.setCharacterEncoding("UTF-8");此方法的使用前提:之前必须要先使用setContentPath()方法, 作用:用于修改ContentType的MIME类型字符编码
		*/
		
		//获取标准输出流
		PrintWriter pw=res.getWriter();
		
		//res.setCharacterEncoding("UTF-8"); //不能设置在标准输出流对象之后,无效。
		pw.write("address");
		pw.write("中国上海");
	}
	
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值