我想做一个查询,在jsp页面上输入了一个学生的名字,提交后由一个servlet(dealstudent.java)去处理,其中又要调用另一个student_info.java用来返回学生的姓名,就是在这个程序
中String name=request.getparamet("name")得到的是乱码,所以在数据库里面也查不到任何数据,请问该如何解决啊?谢谢

解决方案 »

  1.   

    [转贴]Java/J2EE中文问题终极解决之道 
    现在有很多人都碰到过乱码问题,不停的发贴问,那么究竟有没有一种完全的解决方案呢?看看banq这位中国一流的java程序员是怎么说的。Java/J2EE中文问题终极解决之道 
    板桥里人 http://www.jdon.com 2005/06/29  Java中文问题一直困扰着很多初学者,如果了解了Java系统的中文问题原理,我们就可以对中文问题能够采取根本的解决之道。  最古老的解决方案是使用String的字节码转换,这种方案问题是不方便,我们需要破坏对象封装性,进行字节码转换。  还有一种方式是对J2EE容器进行编码设置,如果J2EE应用系统脱离该容器,则会发生乱码,而且指定容器配置不符合J2EE应用和容器分离的原则。  在Java内部运算中,涉及到的所有字符串都会被转化为UTF-8编码来进行运算。那么,在被Java转化之前,字符串是什么样的字符集? Java总是根据操作系统的默认编码字符集来决定字符串的初始编码,而且Java系统的输入和输出的都是采取操作系统的默认编码。  因此,如果能统一Java系统的输入、输出和操作系统3者的编码字符集合,将能够使Java系统正确处理和显示汉字。这是处理Java系统汉字的一个原则,但是在实际项目中,能够正确抓住和控制住Java系统的输入和输出部分是比较难的。J2EE中,由于涉及到外部浏览器和数据库等,所以中文问题乱码显得非常突出。  J2EE应用程序是运行在J2EE容器中。在这个系统中,输入途径有很多种:一种是通过页面表单打包成请求(request)发往服务器的;第二种是通过数据库读入;还有第3种输入比较复杂,JSP在第一次运行时总是被编译成Servlet,JSP中常常包含中文字符,那么编译使用javac时,Java将根据默认的操作系统编码作为初始编码。除非特别指定,如在Jbuilder/eclipse中可以指定默认的字符集。  输出途径也有几种:第一种是JSP页面的输出。由于JSP页面已经被编译成Servlet,那么在输出时,也将根据操作系统的默认编码来选择输出编码,除非指定输出编码方式;还有输出途径是数据库,将字符串输出到数据库。  由此看来,一个J2EE系统的输入输出是非常复杂,而且是动态变化的,而Java是跨平台运行的,在实际编译和运行中,都可能涉及到不同的操作系统,如果任由Java自由根据操作系统来决定输入输出的编码字符集,这将不可控制地出现乱码。  正是由于Java的跨平台特性,使得字符集问题必须由具体系统来统一解决,所以在一个Java应用系统中,解决中文乱码的根本办法是明确指定整个应用系统统一字符集。  指定统一字符集时,到底是指定ISO8859_1 、GBK还是UTF-8呢?   (1)如统一指定为ISO8859_1,因为目前大多数软件都是西方人编制的,他们默认的字符集就是ISO8859_1,包括操作系统Linux和数据库MySQL等。这样,如果指定Jive统一编码为ISO8859_1,那么就有下面3个环节必须把握:  开发和编译代码时指定字符集为ISO8859_1。  运行操作系统的默认编码必须是ISO8859_1,如Linux。  在JSP头部声明:<%@ page contentType="text/html;charset=ISO8859_1" %>。  (2)如果统一指定为GBK中文字符集,上述3个环节同样需要做到,不同的是只能运行在默认编码为GBK的操作系统,如中文Windows。  统一编码为ISO8859_1和GBK虽然带来编制代码的方便,但是各自只能在相应的操作系统上运行。但是也破坏了Java跨平台运行的优越性,只在一定范围内行得通。例如,为了使得GBK编码在linux上运行,设置Linux编码为GBK。  那么有没有一种除了应用系统以外不需要进行任何附加设置的中文编码根本解决方案呢?  将Java/J2EE系统的统一编码定义为UTF-8。UTF-8编码是一种兼容所有语言的编码方式,惟一比较麻烦的就是要找到应用系统的所有出入口,然后使用UTF-8去“结扎”它。  一个J2EE应用系统需要做下列几步工作:开发和编译代码时指定字符集为UTF-8。JBuilder和Eclipse都可以在项目属性中设置。 
    使用过滤器,如果所有请求都经过一个Servlet控制分配器,那么使用Servlet的filter执行语句,将所有来自浏览器的请求(request)转换为UTF-8,因为浏览器发过来的请求包根据浏览器所在的操作系统编码,可能是各种形式编码。关键一句:
    request.setCharacterEncoding("UTF-8")。
    网上有此filter的源码,Jdon框架源码中com.jdon.util.SetCharacterEncodingFilter
    需要配置web.xml 激活该Filter。 
    在JSP头部声明:<%@ page contentType="text/html;charset= UTF-8" %>。 
    在Jsp的html代码中,声明UTF-8:
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    设定数据库连接方式是UTF-8。例如连接MYSQL时配置URL如下:
    jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8
    一般数据库都可以通过管理设置设定UTF-8 
    其他和外界交互时能够设定编码时就设定UTF-8,例如读取文件,操作XML等。 
         笔者以前在Jsp/Servlet时就采取这个原则,后来使用Struts、Tapestry、EJB、Hibernate、Jdon等框架时,从未被乱码困扰过,可以说适合各种架构。希望本方案供更多初学者分享,减少Java/J2EE的第一个拦路虎,也避免因为采取一些临时解决方案,导致中文问题一直出现在新的技术架构中。
      

  2.   

    JAVA字符编码 
     
    一、概要
    在JAVA应用程序特别是基于WEB的程序中,经常遇到字符的编码问题。为了防止出现乱码,首先需要了解JAVA是如何处理字符的,这样就可以有目的地在输入/输出环节中增加必要的转码。其次,由于各种服务器有不同的处理方式,还需要多做试验,确保使用中不出现乱码。
    二、基本概念
    2.1 JAVA中字符的表达
    JAVA 中有char、byte、String这几个概念。char 指的是一个UNICODE字符,为16位的整数。byte 是字节,字符串在网络传输或存储前需要转换为byte数组。在从网络接收或从存储设备读取后需要将byte数组转换成String。String是字符串,可以看成是由char组成的数组。String 和 char 为内存形式,byte是网络传输或存储的序列化形式。
    举例:

    String ying = “英”;
    char ying = ying.charAt(0);
    String yingHex = Integer.toHexString(ying);
    82 F1 
    byte yingGBBytes = ying.getBytes(“GBK”);
    GB编码的字节数值
    D3 A2 
    2.2 编码方式的简介
    String序列化成byte数组或反序列化时需要选择正确的编码方式。如果编码方式不正确,就会得到一些0x3F的值。常用的字符编码方式有ISO8859_1、GB2312、GBK、UTF-8/UTF-16/UTF-32。
    ISO8859_1用来编码拉丁文,它由单字节(0-255)组成。
    GB2312、GBK用来编码简体中文,它有单字节和双字节混合组成。最高位为1的字节和下一个字节构成一个汉字,最高位为0的字节是ASCII码。
    UTF-8/UTF-16/UTF-32是国际标准UNICODE的编码方式。 用得最多的是UTF-8,主要是因为它在对拉丁文编码时节约空间。
    UNICODE值 UTF-8编码
    U-00000000 - U-0000007F: 0xxxxxxx
    U-00000080 - U-000007FF: 110xxxxx 10xxxxxx 
    U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx 
    U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 
    U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 
    U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 
    三、J2SE中相关的函数
    String str =”英”;
    //取得GB2312编码的字节
    byte[] bytesGB2312 = str.getBytes(“GB2312”); 
    //取得平台缺省编码的字节(solaris为ISO8859_1,windows为GB2312)
    byte[] bytesDefault = str.getBytes();
    //用指定的编码将字节转换成字符串
    String newStrGB = new String(bytesGB2312, “GB2312”);//用平台缺省的编码将字节转换成字符串(solaris为ISO8859_1,windows为GB2312)
    String newStrDefault = new String(bytesDefault);
    //用指定的编码从字节流里面读取字符
    InputStream in = xxx;
    InputStreamReader reader = InputStreamReader( in, “GB2312”);
    char aChar = reader.read();
    四、JSP、数据库的编码
    4.1 JSP中的编码
    (1) 静态声明:
    CHARSET有两个作用:
    JSP文件的编码方式:在读取JSP文件、生成JAVA类时,源JSP文件中汉字的编码
    JSP输出流的编码方式:在执行JSP时,往response流里面写入数据的编码方式
    (2) 动态改变:在往response流里面写数据前可以调用response.setContentType(),设定正确的编码类型。
    (3) 在TOMCAT中,由Request.getParameter() 得到的参数,编码方式都是ISO8859_1。所以如果在浏览器输入框内输入一个汉字“英”,在服务器端就得到一个ISO8859_1编码的(0x00,0xD3,0x00,0xA2)。所以通常在接收参数时转码:
    String wrongStr = response.getParameter(“name”);
    String correctStr = new String(wrongStr.getBytes(“ISO8859_1”),”GB2312”);
    在最新的SERVLET规范里面,也可以在获取参数之前执行如下代码:
    request.setCharacterEncoding(“GB2312”);
    4.2 数据库的编码
    (1) 数据库使用UTF-16
    如果String中是UNICODE字符,写入读出时不需要转码
    (2) 数据库使用ISO8859_1
    如果String中是UNICODE字符,写入读出时需要转码
    写入:String newStr = new String(oldStr.getByte(“GB2312”), “ISO8859_1”);
    读出:String newStr = new String(oldStr.getByte(“ISO8859_1”),”GB2312”);
    五、源文件的编码
    5.1 资源文件
    资源文件的编码方式和编辑平台相关。在WINDOWS平台下编写的资源文件,以GB2312方式编码。在编译时需要转码,以确保在各个平台上的正确性:
    native2ascii –encoding GB2312 source.properties
    这样从资源文件中读出的就是正确的UNICODE字符串。
    5.2 源文件
    源文件的编码方式和编辑平台相关。在WINDOWS平台下开发的源文件,以GB2312方式编码。在编译的时候,需要指定源文件的编码方式:
    javac –encoding GB2312
    JAVA编译后生成的字节文件的编码为UTF-8。①最新版TOMCAT4.1.18支持request.setCharacterEncoding(String enc)
    ②资源文件转码成company.name=\u82f1\u65af\u514b
    ③如果数据库使用utf-16则不需要这部分转码
    ④页面上应有
    转码ⅰ:
    String s = new String
    (request.getParameter(“name”).getBytes(“ISO8859_1”),”GB2312”);
    转码ⅱ:
    String s = new String(name.getBytes(“GB2312”),”ISO8859_1”);
    转码ⅲ:
    String s = new String(name.getBytes(“ISO8859_1”),” GB2312”);  =========================================================JAVA内部究竟是用的什么字符编码呢?这个问题我也找了很久,后来在THINK IN JAVA 3rd的12章里看到一个例子出现了UTF-16BE,难道是它? 
         byte[] utf_16be = name.getBytes("utf-16be");     printbyte(utf_16be);结果出来了:58 02  length = 2
    哈哈,I got it!不多不少两个字节,内容也一样。果然是它。同时我在里面也看到,UNICODE的编码还有一个LE,这里的BE,LE我想应该是bigendian和littleendian吧。 ==========================================================import java.io.*;
         public class TestCodeIO {
               public static void main(String[] args) throws Exception{
                     InputStreamReader isr = new InputStreamReader(System.in,"iso8859-1");
                           //Create an InputStreamReader that uses the given charset decoder
                     BufferedReader br = new BufferedReader (isr);
                     String strLine = br.readLine();
                     br.close();
                     isr.close();
                     System.out.println(strLine);
                     System.out.println(new String (strLine.getBytes(),"iso8859-1"));//错误改法
                           //Encodes this String (strLine) into a sequence of bytes using the platform's 
                           //default charset(gb2312) then constructs a new String by decoding the 
                          //specified array of bytes using the specified charset (iso8859-1)
                          //because this String (strLine) uses the charset decoder "iso8859-1",so it can
                          //only be encoded by "iso8859-1",cann't be encoded by the platform's default
                          //charset "gb2312",so this line is wrong.
                    System.out.println(new String (strLine.getBytes("iso8859-1")));//正确改法
                         //Encodes this String (strLine) into a sequence of bytes using the named 
                         //charset (iso8859-1),then constructs a new String by decoding the 
                         //specified array of bytes using the platform's default charset (gb2312).
                         //This line is right.
           } 
    }上面的英文注释已经说得很清楚了,这里我还是解释一下吧:首先是错误的改法  System.out.println(new String (strLine.getBytes(),"iso8859-1"));
    这句代码是将strLine中的字符串用系统默认的编码方式(这里是gb2312)
    转换为字节序列,然后用指定的编码方式(这里是iso8859-1)构造一个新的
    String对象,并打印到屏幕上。
    错误在哪里呢?请注意这一段代码  
    InputStreamReader isr = new InputStreamReader(System.in,"iso8859-1");
    BufferedReader br = new BufferedReader (isr);
    String strLine = br.readLine();
    这里strLine存储的内容是用指定的编码方式(iso8859-1)存储的,而转换成字节码
    的时候(这句代码strLine.getBytes())却使用了系统默认的gb2312编码,所以当然就
    输出乱码了!然后用gb2312编码的字节序列构建新的String对象的时候又使用了
    iso8859-1编码,所以输出的乱码和System.out.println(strLine)有所不同。至于正确的改法就不用详细说明了吧,首先将strLine用iso8859-1编码方式转换成字节
    序列,然后用系统默认的编码方式(gb2312)构建新的String对象,然后打印输出。
     
      

  3.   

    提交的时候都是以UTF-8提交的
      

  4.   

    我按congliu君的方法,全部改成UTF-8,结果连原来的汉字都变成了乱码了,这究竟是怎么回事啊,
      

  5.   

    如果只是用JSP和Servlet的话将字符集改成“UTF-8”来解决中文问题不是很好,一般情况下用UTF-8的话需要用native2ascii命令进行转码,这个是用在Struts中解决国际化问题比较好你可以在Servlet中的doGet或者是doPost(看你的JSP表单用的是什么传送方式)加上request.setCharacterEncoding("GBK");
    在JSP中要这样写<%@ page contentType="text/html; charset=GBK" %>
    这个方法其实不是特别好,有时也会出现乱码,比如空格什么的,但是比较简单,也适合你做的程序的套路