为什么我想servlet传递中文数据时会出现乱码的情况?
以下是我编写的servlet类:
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ActionServlet extends HttpServlet{
public void service(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String path = request.getRequestURI();
String uri = path.substring(path.lastIndexOf("/"),path.lastIndexOf("."));
//System.out.println(path);
//System.out.println(uri);
if(uri.equals("/showAllEmp")){
EmployeeDAO dao = (EmployeeDAO)FactoryDAO.getInstanceOf("EmployeeDAO");
List<Employee> list = dao.findAllEmp();
PrintWriter out = response.getWriter();
if(list.isEmpty()){
out.println("没有雇员,请<a href = 'addEmp.html'>添加</a>");
}else{
out.println("<table width='60%' border='2' cellspace='3' cellpadding='3'>");
out.println("<tr><td>ID</td><td>姓名</td><td>年龄</td><td>薪水</td><td>操作</td></tr>");
Iterator<Employee> it = list.iterator();
while(it.hasNext()){
Employee emp = it.next();
out.println("<tr><td>" + emp.getId() + "</td><td>" + emp.getName() +
"</td><td>" + emp.getAge() + "</td><td>" + emp.getSalary() +
"</td><td><a href='deleteEmp.do?id=" + emp.getId() + "'>删除</a>  " +
"<a href='showSingleEmp.do?id=" + emp.getId() + "'>修改</a></td></tr>");
}
out.println("</table>");
out.println("<a href='addEmp.html'>添加雇员</a>");
out.close();
}
}else if(uri.equals("/addEmp")){
int id = Integer.parseInt(request.getParameter("id"));
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
Long salary = Long.parseLong(request.getParameter("salary"));
Employee emp = new Employee();
emp.setId(id);
emp.setName(name);
emp.setAge(age);
emp.setSalary(salary);
EmployeeDAO dao = (EmployeeDAO)FactoryDAO.getInstanceOf("EmployeeDAO");
dao.addEmp(emp);
response.sendRedirect("showAllEmp.do");
}else if(uri.equals("/deleteEmp")){
int id = Integer.parseInt(request.getParameter("id"));
EmployeeDAO dao = (EmployeeDAO)FactoryDAO.getInstanceOf("EmployeeDAO");
dao.deleteEmp(id);
response.sendRedirect("showAllEmp.do");
}else if(uri.equals("/showSingleEmp")){
int id = Integer.parseInt(request.getParameter("id"));
EmployeeDAO dao = (EmployeeDAO)FactoryDAO.getInstanceOf("EmployeeDAO");
Employee emp = dao.findEmpById(id);
PrintWriter out = response.getWriter();
out.println("<form action='updateEmp.do' style='font-size:30px;charset=utf-8'>");
out.println("ID:<input type='text' name='id' value='" + emp.getId() + "'><br/>");
out.println("姓名:<input type='text' name='name' value='" + emp.getName() + "'><br/>");
out.println("年龄:<input type='text' name='age' value='" + emp.getAge() + "'><br/>");
out.println("薪水:<input type='text' name='salary' value='" + emp.getSalary() + "'><br/>");
out.println("<input type='submit' value='提交'/>");
out.println("</form>");
out.close();
}else if(uri.equals("/updateEmp")){
int id = Integer.parseInt(request.getParameter("id"));
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
Long salary = Long.parseLong(request.getParameter("salary"));
Employee emp = new Employee();
emp.setId(id);
emp.setName(name);
emp.setAge(age);
emp.setSalary(salary);
EmployeeDAO dao = (EmployeeDAO)FactoryDAO.getInstanceOf("EmployeeDAO");
dao.updateEmp(emp);
response.sendRedirect("showAllEmp.do");
}
}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionUtil {
private static String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe";
private static String name = "system";
private static String password = "oracle";
public static Connection openConnection(){
try {
Class.forName("oracle.jdbc.OracleDriver");
Connection conn = DriverManager.getConnection(url, name, password);
return conn;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("未找到相关的数据库驱动类:ConnectionUtil.openConnection()");
return null;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("数据库连接异常:Connection.openConnection()");
return null;
}
}
public static void closeConnection(Connection conn){
try {
if(conn != null && !conn.isClosed()){
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("数据库连接异常:ConnectionUtil.closeConnection()");
}
}
public static void main(String[] args) throws SQLException{
Connection conn = openConnection();
System.out.println(conn);
System.out.println(conn.isClosed());
closeConnection(conn);
System.out.println(conn.isClosed());
}
}
-----------------------------------------------------
一、浏览器是怎么样对接收和发送的数据进行编码的
1.浏览器接受数据:
response.setCharacterEncoding("UTF- 8")的作用是指定对服务器响应进行重新编码的编码。同时,浏览器也是根据这个参数来对其接收到的数据进行重新编码(或者称为解码)。所以在无论你在 JSP中设置response.setCharacterEncoding("UTF-8")或者 response.setCharacterEncoding("GBK"),浏览器均能正确显示中文。
读者可以做个实验,在JSP中设置response.setCharacterEncoding("UTF-8"),在IE中显示该页面时,在IE的菜单中选择"查看(V)"à"编码(D)"中可以查看到是" Unicode(UTF-8)",而在在JSP中设置response.setCharacterEncoding("GBK"),在IE中显示该页面 时,在IE的菜单中选择"查看(V)"à"编码(D)"中可以查看到是"简体中文(GB2312)"。
2.浏览器发送数据:
浏览器在发送数据时,对URL和参数会进行URL编码,对参数中的中文,浏览器也是使response.setCharacterEncoding参数来进行URL编码的。以百度和 GOOGLE为例,如果你在百度中搜索"汉字",百度会将其编码为"%BA%BA%D7%D6"。而在GOOGLE中搜索"汉字",GOOGLE会将其编 码为"%E6%B1%89%E5%AD%97",这是因为百度的response.setCharacterEncoding参数为GBK,而 GOOGLE的的response.setCharacterEncoding参数为UTF-8。
--------------------
二、服务器是在接收和发送数据时,是如何对数据进行编码的
1.服务器发送数据
对于发送数据,服务器按照response.setCharacterEncoding—contentType—pageEncoding的优先顺序,对要发送的数据进行编码。
2.服务器接收数据
对于接收数据,要分三种情况。一种是浏览器直接用URL提交的数据,另外两种是用表单的GET和POST方式提交的数据。
因为各种WEB服务器对这三种方式的处理也不相同,所以我们以Tomcat5.0为例。
①对于表单中POST方式提交的数据
只要在JSP页面上设置了response.setCharacterEncoding或contentType或pageEncoding为"utf-8",在接受数据的JSP/SERVLET中都不会出现中文乱码问题。
②对于URL提交的数据和表单中GET方式提交的数据
在接收数据的JSP/SERVLET中仅仅设置request.setCharacterEncoding参数是不行的
因为在Tomcat5.0中,默认情况下使用ISO-8859-1对URL提交的数据和表单中GET方式提交的数据进行重新编码(解码),要解决该问题:
应该在Tomcat的配置文件server.xml的Connector标签中设置useBodyEncodingForURI或者 URIEncoding属性,其中URIEncoding参数指定对所有GET方式请求(包括URL提交的数据和表单中GET方式提交的数据)进行统一的重新编码(解码)的编码。
其中useBodyEncodingForURI参数表示是否用request.setCharacterEncoding 参数对URL提交的数据和表单中GET方式提交的数据进行重新编码,在默认情况下,该参数为false;
URIEncoding和useBodyEncodingForURI区别是,URIEncoding是对所有GET方式的请求的数据进行统一的重新编码(解码),而useBodyEncodingForURI则是根据响应该请求的页面的request.setCharacterEncoding参数对数据进行的重新编码(解码),不同的页面可以有不同的重新编码(解码)的编码。所以对于URL提交的数据和表单中GET方式提交的数据,可以修改 URIEncoding参数为浏览器编码或者修改useBodyEncodingForURI为true,并且在获得数据的JSP页面中 request.setCharacterEncoding参数设置成浏览器编码。
----------------------
下面总结下,以Tomcat5.0为WEB服务器时,如何防止中文乱码。
1、对于同一个应用,最好统一编码,推荐为UTF-8,当然GBK也可以。
2、正确设置JSP的pageEncoding="UTF-8"
3、在所有的JSP/Servlet中设置contentType="text/html;charset=UTF-8"或response.setCharacterEncoding("UTF-8"),从而间接实现对浏览器编码的设置。
4、对于非表单提交的get或url请求,可以修改Tomcat的默认配置,推荐将useBodyEncodingForURI参数设置为true,也可以将URIEncoding参数设置为 UTF-8(有可能影响其他应用,所以不推荐)。或者用下面的方法,在接收数据时处理:
request.getParameter("userID"),得到userID的值
request.getParameter("userID").trim()将这个值去掉两边的空格
request.getParameter("userID").trim().getBytes("ISO-8859-1"))将这个String用ISO-8859-1编码成一个字节数祖
new String(request.getParameter("userID").trim().getBytes("ISO-8859-1"),"utf-8")将刚才的字节数祖传进string的构造函数按照"utf-8"编码创建一个string对象。
5.使用URLEncoder的方法
传参前用:
//使用指定的编码机制将字符串转换为 application/x-www-form-urlencoded 格式
String username_encoder = URLEncoder.encode(username,"UTF-8");
接参数后显示用:
//使用指定的编码机制对 application/x-www-form-urlencoded 字符串解码
String username_decoder = URLDecoder.decode(request.getParameter("username"),"UTF-8");
-----------------------------------------------------
什么是"gbk"?什么是"utf-8"?
一、字符上区分
GBK包含全部中文字符;
UTF-8则包含全世界所有国家需要用到的字符。
二、编码上区分
GBK是在国家标准GB2312基础上扩容后兼容GB2312的标准(好像还不是国家标准)
UTF-8编码的文字可以在各国各种支持UTF8字符集的浏览器上显示。
例如,如果是UTF8编码,则在外国人的英文IE上也能显示中文,而无需他们下载IE的中文语言支持包。所以,对于英文比较多的论坛 ,使用GBK则每个字符占用2个字节,而使用UTF-8英文却只占一个字节。
三、使用上区分
GBK是中国国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBK大,而且是一般做论坛的DZ这些程序,对应的组件和插件支持上GBK相应开发的比较全面点,再DIY的时候比较方便。
UTF8是国际编码,它的通用性比较好,外国人也可以浏览论坛,而且中文可以直接识别,如果你的论坛要做的比较国际化那就必须用UTF8的。
补充下:UTF8再繁体支持上比GBK有优势滴。
对于DZ论坛来说,很多插件都只支持GBK的,如果需要装较多插件的论坛还是用GBK比较好,而对装较少插件且有特殊用户群的论坛用UTF8比较好。
所以,一般你要是做论坛只是国内的特定圈子里的就用GBK简单点,基本插件都可以安装,但是如果你的站有国外的市场需要就建议UTF8了,
Web中文网站开发中,GBK与UTF-8是使用比较多的两种字符集,但二者是有区别的。总结如下。
1. GBK的文字编码是双字节来表示的,即不论中、英文字符均使用双字节来表示,只不过为区分中文,将其最高位都定成1。
UTF-8编码则是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24位(三个字节)来编码。对于英文字符较多的论坛则用UTF-8节省空间。
2. GBK包含全部中文字符,包括简体和繁体字
UTF-8则包含全世界所有国家需要用到的字符。
3. GBK是在国家标准GB2312基础上扩容后兼容GB2312的标准(好像还不是国家标准)
UTF-8编码的文字可以在各国各种支持UTF8字符集的浏览器上显示。
比如,如果是UTF8编码,则在外国人的英文IE上也能显示中文,而无需他们下载IE的中文语言支持包。 所以,对于英文比较多的论坛 ,使用GBK则每个字符占用2个字节,而使用UTF-8英文却只占一个字节。
请注意:
UTF-8版本虽然具有良好的国际兼容性,但中文需要比GBK/BIG5版本多占用50%的数据库存储空间,因此并非推荐使用,仅供对国际兼容性有特殊要求的用户使用。
简单地说:
对于中文较多的论坛,适宜用GBK编码节省数据库空间。
对于英文较多的论坛,适宜用UTF-8节省数据库空间。