servlet篇(附)【response、request 的 “乱码”】

编码问题总是为难我小小程序员

1 response 输出乱码问题

response 有两个输出方法,即 getOutputStream()getWriter()

1.1 调用getOutputStream()方法向浏览器输出数据

当调用 getOutputStream()方法向浏览器输出数据时,该方法可以使用 print() (ServletOutputStream的方法,输出字符串)或 write()(OutputStream的方法,输出 byte[]) 执行输出,下面分别看看它们的使用方法和区别(也可以查看源码看看两种方法的实现):

1)print()

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String s1 = "IO Stream";
		//获取response的OutputStream流
		ServletOutputStream out = response.getOutputStream();
		//输出结果显示到浏览器
		out.print(s1);
	}

浏览器输出结果:
在这里插入图片描述
成功输出,貌似没什么问题!但试着输出中文:

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String s1 = "字节输出流";
		ServletOutputStream out = response.getOutputStream();
		out.print(s1);
	}

结果却是报了异常:
在这里插入图片描述
报异常的原因:OutputStream 输出二进制数据,print() 方法接收了一个中文字符串,且 print() 要将中文字符串改为二进制数据输出,而 Tomcat 使用 ISO 8859-1编码使其进行转换,ISO 8859-1 自身是不能显示中文的。

2)write()

英文字符是都能正常输出的,下面就直接试试中文字符:

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String s1 = "字节输出流";
		ServletOutputStream out = response.getOutputStream();
		out.write(s1.getBytes());
	}

浏览器输出结果:
在这里插入图片描述
正确输出了。这是因为 s1.getBytes() 将字符串转化为 byte[] 数组后默认的编码方式是 GB 2312 ;而 GB 2312 支持简体中文的输出(print 输出内容只能是字符串,不能转化为 byte[])。

但是,程序要实现通用性,就需要使用 UTF-8 编码,若是在字节数组中指定使用 UTF-8 编码,则会出现乱码:

out.write(s1.getBytes("utf-8"));

在这里插入图片描述
乱码的原因是因为服务器指定使用 UTF-8 编码,但浏览器显示往往不是采用 UTF-8 编码(如 GBK,GB2312等等),这样就导致乱码!

解决:http 响应消息有对浏览器说明响应数据是什么类型的响应头字段,即为 Content-Type,通过设置 Content-Type 的值即可解决。

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//设置浏览器使用 utf-8 编码显示数据
		response.setHeader("Content-Type", "text/html;charset=UTF-8");
		//等效
		//response.setContentType("text/html;charset=UTF-8");
		
		String s1 = "字节输出流";
		ServletOutputStream out = response.getOutputStream();
		out.write(s1.getBytes("utf-8"));
	}

在这里插入图片描述

1.2 调用getWriter()方法向浏览器输出数据

PrintWriter 是 Writer 的子类,只能向浏览器输出字符数据,而不能输出二进制数据。getWriter() 是response 获取 PrintWriter 对象的方法,同样,它也可以通过 print()write() 输出数据到浏览器显示。

PrintWriter 中的 print() 和 write()【多看看源码】
PrintWriter 中的 print() 方法的实现都是调用 write() 方法,但是 print() 提供了更多的参数类型,write() 输出字符串,如:

//诸如此类
public void print(Object obj) {
    write(String.valueOf(obj));
}

public void print(String s) {
	if (s == null) {
		s = "null";
	}
    write(s);
}

那么,就说说 write() 输出时的编码问题:

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String s2 = "字符输出流";
		PrintWriter out = response.getWriter();
		out.write(s2);
	}

在这里插入图片描述
又是乱码!!!!

原因:Tomcat 对浏览器进行响应时默认采用 IOS 8859-1 编码,而这个编码方式不支持中文。response.setCharacterEncoding("UTF-8") 可以设置 Tomcat 的编码为 UTF-8(但需要注意浏览器的显示编码方式,往往浏览器显示的编码方式不是 UTF-8 又容易产生乱码)。

那么就需要进行设置编码。设置编码的方式有很多:设置 Content-Type 头字段的值,或者输出标签模拟消息头等等。最简单的可以只通过一个方法 setContentType 就ok。

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//设置编码(它不仅设置浏览器用UTF-8显示数据,内部还把中文转码的码表设置成UTF-8了)
		response.setContentType("text/html;charset=UTF-8");
		String s2 = "字符输出流";
		PrintWriter out = response.getWriter();
		out.write(s2);
	}

在这里插入图片描述

2 request 获取数据乱码问题

request 对于 POST 和 GET 两种方式的请求处理中文乱码的方式有所不同。

2.1 POST 中文乱码解决

表单:

//前端显示/提交数据编码
<meta charset="UTF-8">
....
//post方法提交表单数据
<form action="Test01Servlet" method="post">
		姓名: <input type="text" name="name"><br>
		简介:<input type="text" name="intro">
		<input type="submit" />
	</form>

提交数据:
在这里插入图片描述
后台获取数据:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//设置服务端接收数据编码(重点)
		request.setCharacterEncoding("utf-8");
		
		String name = request.getParameter("name");
		String intro = request.getParameter("intro");
		
		System.out.println(name);
		System.out.println(intro);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

获取数据:
在这里插入图片描述
request.setCharacterEncoding("utf-8") 语句可解决 post 方式提交表单出现的中文乱码。若没有该语句,控制台打印结果:
在这里插入图片描述
这是因为 Tomcat 默认编码为 ISO-8859-1,浏览器页面使用的 UTF-8(<meta charset="UTF-8">);这样的话,Servlet 读取数据时自然就得到乱码,在 post 提交方式下,简单通过 request.setCharacterEncoding("utf-8") 设置编码即可解决。

2.1 GET 中文乱码解决

不仅表单指定的 GET 方式,超链接默认也是 GET 提交方式。

先看看 GET 提交数据的方式与 POST 有何不同!

POST提交数据:点击提交时,数据封装进了 From Data 中,然后 http 请求将消息主体发送给服务端,此时 request 对象封装有 http 请求,自然就可以解析 http 中的 From Data 数据,这时只要把request 编码设置为 UTF-8 即可
在这里插入图片描述
GET提交数据:GET 的数据时通过消息行带给服务端的,而没有封装到 request 对象中,此时,即使设置 request 编码也不起作用
在这里插入图片描述
那么,GET 方式出现的中文乱码又怎么解决???

方法一:将 GET 的数据反向查 ISO 8859-1 编码(既然它是因为 ISO 8859-1 而乱码,就先找到它的未经编码的原始数据)

//获取数据(经ISO 8859-1编码后的字符串,乱码)
String name = request.getParameter("name");
String intro = request.getParameter("intro");

//乱码通过反向查ISO 8859-1得到原始的数据	 
byte[] bytename = name.getBytes("ISO8859-1");
byte[] byteintro = intro.getBytes("ISO8859-1");

//对原始的数据,设置编码,构建字符串	
String name_1 = new String(bytename,"UTF-8");
String intro_1 = new String(byteintro,"UTF-8");

System.out.println(name_1 );
System.out.println(intro_1 );

方法二:除了上面的手工转换,还可以通过修改 Tomcat 服务器的配置解决服务器在解析数据时造成的中文乱码

<!-- URIEncoding="utf-8"的增加使得get方法编码问题得到纠正   -->
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8888" protocol="HTTP/1.1" redirectPort="8443"/>  

这种改法是固定使用 UTF-8 编码的(过于依赖服务器)

一般来说,能使用 POST 方式提交数据的就用 POST。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章