编了个简单的jsp,结果jsp向SqlServer2008传中文出现乱码问题,找了半天发现以下几个错误,总结一下。
通常情况下遇到乱码问题,解决的思路都是保证数据库+程序+页面编码三码一致。
我遇到的问题如下:
1.表单使用Post方式提交后接收到的乱码问题
这个乱码是tomcat的内部编码格式iso8859-1在捣乱,也就是说post提交时,如果没有设置提交的编码格式,则会以iso8859-1方式进行提交,
接受的jsp却以utf-8的方式接受。导致乱码。既然这样的原因,下面有几种解决方式,并比较。
A、接受参数时进行编码转换
String str = new String(request.getParameter("something").getBytes("ISO-8859-1"),"utf-8");
这样的话,每一个参数都必须这样进行转码。很麻烦。但确实可以拿到汉字。
B、在请求页面上开始处,执行请求的编码代码
request.setCharacterEncoding("UTF-8");
把提交内容的字符集设为UTF-8。这样的话,接受此参数的页面就不必在转码了。
直接使用String str = request.getParameter("something");即可得到汉字参数。但每页都需要执行这句话。
这个方法也就对post提交的有效果,对于get提交和上传文件时的enctype="multipart/form-data"是无效的。
**如果要调用request.setCharacterEncoding进行编码设置,一定要在任何参数被访问之前调用。**
类StudentSer extends HttpServlet改后代码:
...
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
Student student = new Student();
student.setSname(request.getParameter("sname"));
student.setSpass(request.getParameter("spass"));
StudentImpl studentImpl = new StudentImpl();
studentImpl.saveStudent(student);
}
...
C、为了避免每页都要写request.setCharacterEncoding("UTF-8"),建议使用过滤器filter对所有jsp
创建 EnCodeFilter.java
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class EnCodeFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filter) throws IOException, ServletException {
//System.out.println("----doFilter-EnCodeFilter----");
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//如果有下一个过滤器则跳转到下一个过滤器,否则跳转到目标页面
filter.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
同时在web.xml中添加
<filter>
<filter-name>enCodeFilterfilter-name>
<filter-class>filter.EnCodeFilterfilter-class>
filter>
<filter-mapping>
<filter-name>enCodeFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
2.表单使用Get方式提交后接收到的乱码问题
方一:打开tomcat下conf文件夹下server.xml添加URIEncoding="utf-8"
即
方二:
摘选自http://blog.csdn.net/xiao_jun_0820/article/details/7220464
在jsp中对中文进行了编码的时候用的是UTF-8的编码方式,而在servlet中调用request.getParameter();
方法的时候使用服务器指定的编码格式自动解码一次,
所以前台编码一次后台解码一次而解码和编码的方式不用所以造成了乱码的出现。
这就类似于以下代码:
String name=java.net.URLEncoder.encode("测试", "UTF-8");
System.out.println(name);
System.out.println(java.net.URLDecoder.decode(name, "ISO-8859-1"));
编码后的是%E6%B5%8B%E8%AF%95;
而用ISO-8859-1解码后的是???è?;
但是如果调用的是
System.out.println(java.net.URLDecoder.decode(name, "UTF-8"));
则结果是打印“测试”;
在servlet中调用java.net.URLDecoder.decode(request.getParameter("name"), "UTF-8")方法和调用java.net.URLDecoder.decode(request.getQueryString(), "UTF-8")所得到的结果是不一样的,就是由于在request.getParameter("name")之前会自动做一次解码的工作,而且是默认的ISO-8859-1。
所以,在使用java.net.URLEncoder.encode()和java.net.URLDecoder.decode(),的时候需要在前端页面中使用两次java.net.URLDecoder.decode()方法。
使用两次编码的过程相当于如下代码:
String name=java.net.URLEncoder.encode("测试", "UTF-8");
System.out.println(name);
name=java.net.URLEncoder.encode(name,"UTF-8");
System.out.println(name);
name=java.net.URLDecoder.decode(name, "UTF-8");
System.out.println(name);
System.out.println(java.net.URLDecoder.decode(name, "UTF-8"));
输出为:
%E6%B5%8B%E8%AF%95
%25E6%25B5%258B%25E8%25AF%2595
%E6%B5%8B%E8%AF%95
测试
第一次编码后将汉字编码为%和字母数字的格式,而第二次编码的时候是对%字母数字进行编码,虽然解码的时候使用的是ISO-8859-1,
但是对于%和字母数字而言用ISO-8859-1和UTF-8解码出来的是一样的,此时就回到了汉字被编码过一次的字符串了,
当再次进行解码的时候使用UTF-8就回将它转会汉字
<%
String name=java.net.URLEncoder.encode(java.net.URLEncoder.encode(students.get(i).getSname(),"UTF-8"),"UTF-8");
%>
"/hello/updateStudent.jsp?sid=<%=students.get(i).getSid()%>&sname=<%=name%>&spass=<%=students.get(i).getSpass()%>&slikes=<%=students.get(i).getSlikes()%>">更新
<%
String sname =java.net.URLDecoder.decode(request.getParameter("sname"),"UTF-8");
%>
姓名:<input type="text" name="sname" value="<%=sname%>"/>
3.数据库中name的数据类型用了varchar
摘选自http://m.blog.csdn.net/blog/u012575083/13769111)
改成 nvarchar 就好了,简单来说,varchar是一个字节一个字节的存储,而 nvarchar 是两个字节,而汉字是两个字节,所以就会出现乱码。下面在仔细说一说各数据类型的区别。
sql server数据类型char和nchar,varchar和nvarchar,text和ntext的区别:
1)varchar和nvarchar的区别:
varchar(n)
长度为 n 个字节的可变长度且非 Unicode 的字符数据。n 必须是一个介于 1 和 8,000之间的数值。存储大小为输入数据的字节的实际长度,而不是 n 个字节(如varchar(6),当字段为qqq时,数据库实际占用空间为3个字节,而不是6个字节,但只允许存储6个字节,一般中文占两个字节)。
nvarchar(n)
包含 n 个字符的可变长度 Unicode 字符数据。n 的值必须介于 1 与 4,000 之间。字节的存储大小是所输入字符个数的两倍。
两字段分别有字段值:我和coffee
那么varchar字段占2×2+6=10个字节的存储空间,而nvarchar字段占8×2=16个字节的存储空间。
如字段值只是英文可选择varchar,而字段值存在较多的双字节(中文、韩文等)字符时用nvarchar
2)SQL Server中,varchar和nvarchar如何选择?
varchar在SQL Server中是采用单字节来存储数据的,nvarchar是使用Unico来存储数据的.中文字符存储到SQL Server中会保存为两个字节(一般采用Unico编码),英文字符保存到数据库中,如果字段的类型为varchar,则只会占用一个字节,
而如果字段的类型为nvarchar,则会占用两个字节.
正常情况下,我们使用varchar也可以存储中文字符,但是如果遇到操作系统是英文操 作系统并且对中文字体的支持不全面时, 在SQL Server存储中文字符为varchar就会出现乱码(显示为??).而且正常情况下,主机都会支持中文的环境,所以如果使用varchar来存储数据,
在开发阶段是发现不了的.多数情况下,在布署的时候也不会有问题.
但是!如果布署的主机是英文操作系统,并且不支持中文环境,那问题就出来了.所有的varchar字段在存储中文的时候都会变成乱码(显示为??).
而且一般情况下你不会知道这是因为你采用了错误的数据类型来存储所造成的,你会试着去装中文字体,试着去设置操作系统的语言环境...
这些都不能解决问题,唯一能解决问题的是把数据库字段的类型个性为nvarchar(或者nchar).对项目管理比较熟悉的朋友应该都知道,
到布署阶段再来修改数据库是一个很恐怖的事情.
使用nvarchar的另一个非常好处就是在判断字符串的时候可以不需要考虑中英文两种字符的差别.
当然,使用nvarchar存储英文字符会增大一倍的存储空间.但是在存储代价已经很低廉的情况下,优先考虑兼容性会给你带来更多好处的.
所以在Design的时候应该尽量使用nvarchar来存储数据.只有在你确保该字段不会保存中文的时候,才采用varchar来存储.
1、CHAR。CHAR存储定长数据很方便,CHAR字段上的索引效率级高,比如定义char(10),那么不论你存储的数据是否达到了10个字节,
都要占去10个字节的空间。
2、VARCHAR。存储变长数据,但存储效率没有CHAR高。如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,
把它定义为VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。为什么“+1”呢?这一个字节用于保存实际使用了多大的长度。
从空间上考虑,用varchar合适;从效率上考虑,用char合适,关键是根据实际情况找到权衡点。
3、TEXT。text存储可变长度的非Unicode数据,最大长度为2^31-1(2,147,483,647)个字符。
和char、varchar比较起来,nchar、nvarchar则最多存储4000个字符,不论是英文还是汉字;而char、varchar最多能存储8000个英文,4000个汉字。可以看出使用nchar、nvarchar数据类型时不用担心输入的字符是英文还是汉字,较为方便,但在存储英文时数量上有些损失。
**所以一般来说,如果含有中文字符,用nchar/nvarchar,如果纯英文和数字,用char/varchar**
更多jsp乱码问题解决见:http://blog.chinaunix.net/uid-20624711-id-1911411.html
未完待续。。。。