1. Post获取请求参数导致乱码
案例:提交中文数据,通过servlet回显在浏览器上
结果
前端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>中文回显</h3>
<form action="demo4" method="post">
请输入中文:<input type="text" name="chinese"/><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
servlet
package com.zmysna.demo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/demo4")
public class Demo04Show extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//不对request的数据进行编码的情况下获取post提交的汉字
String value = request.getParameter("chinese");
PrintWriter writer = response.getWriter();
//回显到浏览器上
writer.print(value);
}
}
分析:post提交时,请求参数放在请求体中,Tomcat对于请求体中的数据,默认的编码是ISO-8859-1欧洲编码,不支持汉字,所以汉字会有乱码的问题。地址栏上使用的是UTF-8编码。因为我们提交数据使用的是UTF-8的编码,而Tomcat服务器使用的是ISO-8859-1编码,所以会出现乱码的问题。
解决方法:在servlet中添加一行代码request.setCharacterEncoding("utf-8");
使页面编码和服务器对请求体使用的编码一致。
2. 打印输出流乱码问题
回显案例添加request.setCharacterEncoding("utf-8")
解决post提交请求体乱码问题之后,回显数据依然出现乱码。
代码如下
package com.zmysna.demo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/demo4")
public class Demo04Show extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//对request的数据进行编码的情况下获取post提交的汉字
String value = request.getParameter("chinese");
//在控制台上打印
System.out.println(value);
//回显到浏览器上
PrintWriter writer = response.getWriter();
writer.print(value);
}
}
结果
分析:打印汉字,输出的是乱码。为什么会有乱码?因为 Tomcat 打印流默认编码是 ISO-8859-1 编码,不支持汉字。设置响应的编码为 UTF-8。指定打印流的编码为 utf-8。
解决方法:添加以下两行代码任意一行。
-
response.setCharacterEncoding("utf-8");
设置打印流的编码 -
response.setContentType("text/html;charset=utf-8");
设置响应类型,打印流和响应的编码。
推荐第二种。
3. 下载中文名文件乱码问题
案例:实现中文名附件下载
效果:
未编码的情况
package com.zmysna.servlet;
import org.apache.commons.io.IOUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
@WebServlet(urlPatterns = "/downLoad")
public class DownLoadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置字符集
response.setContentType("image/jpg;charset=utf-8");
//用输入流读取WEB目录下的一张图片
ServletContext application = getServletContext();
InputStream in = application.getResourceAsStream("WEB-INF/e7e49ed2b25a6e9f (1).jpg");
//设置附件形式下载图片资源
response.setHeader("Content-Disposition", "attachment;filename=" + "苹果手机.jpg");
//获取一个字节输出流将图片输出到页面
ServletOutputStream out = response.getOutputStream();
//IO流工具进行资源的传输(需要导入common.io包)
IOUtils.copy(in,out);
out.close();
in.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
结果:默认下载文件名不是 苹果手机.jpg
分析:filename如果是汉字,需要对汉字进行编码,浏览器会自动进行解码。
解决方案:设置响应头时对文件名进行编码。
response.setHeader("Content-Disposition", "attachment;filename="
+ URLEncoder.encode("苹果手机","utf-8")+".jpg");
4. Cookie中使用非法字符需要编码
- 在 cookie 值中不能使用分号(;)、逗号(,)、等号(=)以及空格,Tomcat8 中可以直接使用汉字。如果需要使用非法字符需要进行编解码。
java.net.URLEncoder.encode(" 字符串","utf-8") 把字符串使用 utf-8 进行编码
java.net.URLDecoder.decode(" 字符串","utf-8") 把字符串使用 utf-8 进行解码
案例:
-
得到用户上次访问的时间
-
如果用户是第一次访问,则输出:您好,您是第1次访问,欢迎您的加入!并且把这次访问服务器的时间写到Cookie中。
-
如果之前已经访问过,则从Cookie中得到上次访问的时间,显示:您好,欢迎您再次访问。您上次访问的时间是:xxxx
时间显示的字符串包含空格,设置为Cookie值时需要编解码。
代码演示
CookieUtils工具类
package com.zmysna.cookie;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
public class CookieUtils {
public static String getValue(HttpServletRequest request, String visitor) {
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals(visitor)) {
return cookie.getValue();
}
}
return null;
}
}
package com.zmysna.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.Date;
@WebServlet("/visit")
public class VisitServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//从Cookie中获取时间字符串,已经编过码,需要解码
String visitTime = CookieUtils.getValue(request, "visitTime");
String count = CookieUtils.getValue(request, "count");
if(count == null) count = "1";
//获取当前时间的字符串,包含空格,需要编码
String now = new Timestamp(new Date().getTime()).toString();
if(value == null) {
System.out.println("你好,你第一次登录,现在的时间是" + time + "<hr>");
}else {
//对获取的时间字符串进行解码
value = URLDecoder.decode(value, "utf-8");
System.out.println("你好,你第" + count + "次登录,现在时间是" + time + "<hr>");
System.out.println("你上一次登录的登录的时间是" + value);
}
//对当前时间字符串进行编码
Cookie visitor = new Cookie("visitTime", URLEncoder.encode(now,"utf-8"));
Cookie cntCookie = new Cookie("count", (Integer.parseInt(count) + 1) + "");
//添加到Cookie中。
response.addCookie(visitor);
response.addCookie(cntCookie);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}