Mysql与JSP网页中文乱码问题的解决方案
自从以前学习JSP开始,中文乱码问题就一直不断,苦不堪言。这次在项目开始之前,我们要解决的第一个问题就是把mysql的中文乱码问题搞定。经过多天的努力,终于成功的解决了中文乱码问题,特写在这里,以备后用。
5 U: z' d; |8 d+ R6 }. {9 }
9 d7 a/ ~6 G5 e7 F- I! v软件及环境:Windows XP(2000), j2sdk1.4.2, Tomcat 5.0.25, mysql 4.1, EMS Mysql Manager 2(方便建表,版本2.8.5.1),驱动为mysql-connector-java-3.1.4-beta-bin.jar。
3 R$ v J" q( [- J. c8 \, k- R) D
: f0 a8 ~8 K8 ^, R- ]目标:在该环境下,实现中文的正常显示,读取与插入数据库。
: ~7 j- |% b+ H/ J% F4 f, z4 Y0 k: D4 k6 s' r9 C
注:我只在此环境下测试通过,别的系统及不同版本未测试
0 S) ?- X- M) q+ V5 ]* h( B! \# |, |
# x+ Y# H: C2 r6 p1 v$ ~要点:统一字符集(JSP页面编码,mysql建库时字符集选择,连接数据库URL,request设定等) - O( ~3 m* G5 m: A/ i) U0 i
9 s' T& D, ^1 @) ]- \% w* K下面我以GBK为例讲解。如果要使用utf-8,只要在相应的GBK处换成utf-8即可
% z! F, U. ? r+ [! V+ @5 ]# _+ x
% ^" P+ v' }( K: n/ w- E--------------------------- 步骤1 以GBK字符集建库建表 -------------------------------------
$ K2 L$ z( J# c4 H
7 V" ?% d0 C( _5 {我使用EMS来建mysql的数据库及表,因为它是图形界面,方便操作(就像SQL SERVER 2000中的企业管理器一样)。 ! P/ C, e \5 R2 I2 b
4 C7 W' s" w0 P6 C
建库时,从EMS菜单中选create Database...新建一个数据库,CharacterSet选gbk_bin(另一个gbk_chinese_ci不知道与这个有什么区别,我找资料也没有找到。如果你知道,请告诉我,我补充在这里)。不要把工具栏上有一个加号和数据库模样的图标当成新建数据库了,那个新注册一个已经存在的数据库。
4 e$ i4 X6 \! }( U后面建表时,也要选择同样的字符集。 , W1 j1 O9 q7 e# ]1 R8 O9 p
/ B8 G+ u! [+ k7 P. e$ [9 g, p
建好后,此时不要用EMS向里面插入数据,否则你看到的中文依然是乱码。 9 P# e! N* L T ~; r/ x
# [! m( C) v9 L7 K--------------------------- 步骤2 连接数据库的URL后加些参数 ------------------------------- 4 u* o( Y7 D3 M* @6 J2 c$ s3 ^7 o
' {3 {2 p/ H5 n6 v. A
假设我新建的数据库是testdb,那么我连接数据库的url应该为:
1 L0 `' B5 b& e7 m' N8 V4 Y* |0 u5 n* y0 ?
jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=gbk ; Z& c! d' p. W7 Y0 p
+ ]8 O% v+ L6 M7 Y1 m此时要注意:如果我是把这个url写在JAVA代码中,就直接这样写。但如果是在xml配置文件中(如struts-config.xml,web.xml等),要把其中的&改为&才行,否则会出错。也就是:
- H8 x1 @) a$ z8 N. G% a2 x( I
7 d0 Z5 \, Y/ d3 t0 ojdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=gbk ! x: E" b2 ?$ y0 N4 M4 \9 T4 e: p
' t( U6 ~/ ]8 x! p5 C% n--------------------------- 步骤3 每个JSP页面都要声明该中文字符集 ----------------------------
( Z* G& C! N( @6 [+ ]
: O5 I8 E$ M9 |在每个JSP页面的最上面都加上一句 ' A; _: Z/ T& |6 X E
' v* k7 _: D P* A" J6 {<%@ page language="java" contentType="text/html;charset=GBK" %> ' {0 d3 A6 n5 g3 r# G& D6 [ z
/ g3 s: o& a6 g这样才能保证JSP页面中的中文显示正常
# R1 g8 Z3 g0 |
8 A- ` N: V% H7 R4 ~: a' Y% p--------------------------- 步骤4 加一个传递参数时设定request字符集的filter类 -----------------------
0 M% w) ~. ^ b" i
+ f/ q/ t& R$ a1 t6 }3 n5 x因为网络中字符在传递的时候,都是统一以iso-8859-1的编码传递,所以我们必须对request重新设定字符集,才能正常显示中文。如果采用filter类来实现,我们不用在每次取中文参数时都要重新设定。 3 V' ~5 ~+ _( M7 Q/ ]* k, `5 |/ v
* k! D$ U+ L6 y! v8 c3 lfilter类的内容:
3 j& J2 X/ S( H3 i
$ v+ i- k+ D+ p, W6 b' m2 R, f, r/*
2 G$ M1 s5 o2 {& v! X4 `7 H- b: ^* ==================================================================== 2 L! L I/ J$ S$ X6 f
* 1 m. V- j% O& P% }
* JavaWebStudio 开源项目 , q+ k5 x. Y. \" W/ e/ P9 u0 {
* 9 ^5 `& m5 F) ?( o; y% U: k
* Struts_db v0.1
+ J4 }, v% P4 l/ o: i( M8 k*
2 e+ q. C8 x; e6 U0 X9 s* ====================================================================
- W/ Q9 w p' C0 T7 ?- u*/ # Z; A* e% u! A5 \8 F' k
package com.strutsLogin.util;
' [1 D4 T7 Q8 E, F3 K' G7 r$ g' |/ n e; X
import java.io.IOException; 5 w: R9 @2 e' r6 v% P( C$ Q7 A+ X
8 r- h4 y" y& ~: ]4 a) G
import javax.servlet.Filter;
, q0 v8 N1 F9 g! _import javax.servlet.FilterChain;
, y) V7 U" c# Qimport javax.servlet.FilterConfig;
; h$ h |/ i# z$ i# t: D9 A3 ]import javax.servlet.ServletException;
. e/ b' f# v9 S' yimport javax.servlet.ServletRequest; : A' H4 t6 v/ {1 ?, m0 y
import javax.servlet.ServletResponse; + `1 }) K) Q5 S
. h* L" U, s/ ?' q' U
/** $ A4 {& b, @0 r: N
* 中文过滤器 * U6 @, M2 p k$ `! y: ~
*/
6 U7 @3 E1 t, d5 o; \. ppublic class SetCharacterEncodingFilter implements Filter {
3 J0 }3 b5 h4 ?2 h# X# E, @! J+ p1 i: ~4 P; `) ^
// ----------------------------------------------------- Instance Variables
* ?+ |4 | Y, r+ r4 q7 f
7 z9 f6 l {6 B/** ; M" k0 e9 F5 G' k$ ?6 G
* The default character encoding to set for requests that pass through 0 e# y: c: X* ^& B
* this filter. ' g8 h2 m, @! A
*/ 4 s" P7 \/ j3 c! ~' C. m& H
protected String encoding = null; ; _0 D4 z+ W% M9 u
' n( w$ d- q3 I' F t4 D! R a6 l/** 8 ^- E! u5 n# H, U$ k
* The filter configuration object we are associated with. If this value
9 b" V# C; x9 f& B* is null, this filter instance is not currently configured. 8 j, A4 u3 i8 F
*/
6 w/ c& W/ n# B3 f# ]' cprotected FilterConfig filterConfig = null; 5 a7 Y, x& m' X2 L
# h" B0 T7 o7 A1 ]
/**
2 W5 @" y- @+ {* J6 Q" Q8 V* Should a character encoding specified by the client be ignored?
. O! G! f- T8 U1 u8 N( Z/ t" e& P*/
I) F7 g; K+ T1 ^$ b* D% e5 Qprotected boolean ignore = true;
3 i/ J4 A: j' q& ?' M
3 B* }. V1 o3 B! y$ }// --------------------------------------------------------- Public Methods 3 D3 V$ K) T- {3 C5 M6 J1 ]* D3 n
; x+ D" N: b) W) B/ W( O/** ' y" }2 X! c( j" p; F
* Take this filter out of service. 0 m$ {9 [: d: ?: L7 C; Z
*/ ) J2 y& a% x9 w: ^; N$ w
public void destroy() { / [; }; o" ]1 I) O
8 H1 t4 _* `& d7 Q3 a- ~
this.encoding = null; l1 ^( a) `. G% r! O& l; \- A
this.filterConfig = null;
: q/ H+ V, Y, V/ {
2 ?' d7 a" ^1 \+ J) B" ~& i}
- ^/ A5 F9 V2 B( ~" H p: a
/ s0 I: P# `( o6 a4 G/**
- G" B( g& I9 a( [) W& F* Select and set (if specified) the character encoding to be used to
/ Y/ t4 E5 o& z" P# J8 G* interpret request parameters for this request. $ J* b, n' Q) r5 T8 ?
* - m3 o; G4 t; t' C+ }
* @param request The servlet request we are processing 1 D# T7 `( K; b0 ?/ z, J. x+ |
* @param result The servlet response we are creating
& L3 L, ^ F, U( v$ q/ m* @param chain The filter chain we are processing
1 C# n x2 p; H/ B' T* d, f*
7 f* m6 ?, }5 P% h; b8 g+ T% _* @exception IOException if an input/output error occurs
) S/ P' f3 W; Q- j$ F e5 ]. l$ p. k3 }* @exception ServletException if a servlet error occurs - ~6 W- A* @7 W+ t* [
*/
2 M1 _3 `( T2 Z1 ^' Jpublic void doFilter(ServletRequest request, ServletResponse response,
1 q/ k" F; I( @8 JFilterChain chain)
9 |( P! i6 ~" K2 ]+ r4 k- P- xthrows IOException, ServletException {
# H* ~6 c, ~5 _8 \& e. y/ T1 V, m7 \- h5 r/ j, m- _, T V
// Conditionally select and set the character encoding to be used
) A/ Y, l- r s9 x: t4 a# O3 M. W4 ]if (ignore || (request.getCharacterEncoding() == null)) {
0 n. h8 E/ @# ^* o1 |9 @5 W# h; lString encoding = selectEncoding(request);
% A& O) j b$ o/ Nif (encoding != null) . C* P' Y- c: K a; s# }; J) q, b
request.setCharacterEncoding(encoding); 5 ~& ?( T' w7 Z4 y1 m- D* ]
} " b5 [1 f. ~& v, v1 L1 D/ p7 O/ X; \
6 ^! H5 l \% l2 m
// Pass control on to the next filter
/ d, f/ F) X4 b: qchain.doFilter(request, response);
9 E4 Z# f* o- u; e" }+ M" |0 m" s ^# O8 G
}
. g4 n2 s1 N) `* k, `- ^2 I$ G' V% ]- _$ h1 ]6 w; v7 d, N& {
/** : P% T- o8 W8 I
* Place this filter into service.
3 Z& H0 ~8 \% M5 q5 q& @*
/ i' e; L5 t: ^& l# D/ P& D* @param filterConfig The filter configuration object
1 x0 V# e# t$ K3 d# N! p( N9 b*/ 3 c" G) U5 e d: }6 O
public void init(FilterConfig filterConfig) throws ServletException { / `7 _( B3 i ?" z- z9 L5 K2 b; {
6 P' c% O5 g+ x& x( d7 L1 |. w
this.filterConfig = filterConfig;
7 B' n/ Q0 K) L" S, Sthis.encoding = filterConfig.getInitParameter("encoding");
+ }& R/ U' x* hString value = filterConfig.getInitParameter("ignore"); 0 }' m: R* T7 Y/ D' x
if (value == null) " j2 R: V0 e0 i9 Q4 Z, [' T; P- d
this.ignore = true; % N! C1 j4 D- E8 e) {2 _8 K
else if (value.equalsIgnoreCase("true"))
8 c' o) A/ G% Q- L }this.ignore = true; 1 {; x% }. Z# V
else if (value.equalsIgnoreCase("yes"))
" ?8 C; N- {4 j) `) w4 d' Qthis.ignore = true; 1 I) J6 G" g2 @( M0 ?2 U
else 2 n) `+ {% Y$ ~$ q7 L
this.ignore = false;
a; s$ q) I/ g% L
" t) D9 V# @4 u5 G& t} ( \! B! a9 S( b; z# ~
3 R6 z' [. \- I4 W7 W# W// ------------------------------------------------------ Protected Methods : q! R+ U8 ~" J7 I' q2 x+ \
( X' \/ H* R; G3 C* L/ U/**
; d/ H9 }! `% q0 T% ^% @* Select an appropriate character encoding to be used, based on the ! ~9 \8 f1 `5 W! N: \* z6 x
* characteristics of the current request and/or filter initialization ! c: h# o: a6 C: e+ u; z% u/ g1 i( s
* parameters. If no character encoding should be set, return
0 I$ G5 ^3 U5 G7 e) p' N* <code>null</code>. i% E, J( o0 a+ f! k Q
* <p>
7 v: }0 ]5 d' k$ N1 Y* The default implementation unconditionally returns the value configured
5 ]7 ^. v3 p7 }1 x4 E6 D* by the <strong>encoding</strong> initialization parameter for this
0 @* ^7 Z: k; S6 n+ c* filter.
1 k* O% H& {# w! r3 Q h' K8 q* 5 x1 _2 @- P4 n5 n6 Y
* @param request The servlet request we are processing $ @4 M4 w# b+ I! S
*/ . l! s a( q) A- I
protected String selectEncoding(ServletRequest request) { ; f+ p9 w5 G! Q7 L: H3 k' E
- Q$ n1 F* g3 g, V j: _
return (this.encoding); " n' i+ W: e) m4 S' g
/ ]/ F: D2 F+ Z/ ]$ ?4 s( ?9 T
}
2 R, C- N# c* o: o; Q- A9 M% p$ u! ~5 D! w
}//EOC
8 \* }5 U! y" G) Y1 M& J7 u0 c1 m8 ]( k% m k
# E) t% V; a) d! n; |4 {该代码来自于[url]www.javawebstudio.com[/url],特此感谢! ! s" U$ f& L4 g; N1 t8 m0 y+ g
: b* @9 E5 K4 S. G
然后我们在web.xml中加一些配置,就可以了,配置如下: + q1 P5 ^, J2 H* c
* B2 n# @; x* U$ ]! H2 Y
<filter> + M! J0 N# T0 u) c5 ^2 b: p1 \7 v" k
<filter-name>Set Character Encoding</filter-name>
8 i- u8 D5 h# D# I* w<filter-class>javawebstudio.struts_db.SetCharacterEncodingFilter</filter-class> # w; F& ^* c" ?6 h2 U7 t. u! P
<init-param>
. a8 u; K; w0 R4 f) H- G& `<param-name>encoding</param-name>
1 ~. R# t1 H! G0 Y( y<param-value>GBK</param-value> ! J, H- t9 c. a2 y; y/ }. q3 Z# c0 T
</init-param>
2 L, v+ f$ w( o7 W0 K/ D4 o" q<init-param> G7 Z5 _5 }5 V( S
<param-name>ignore</param-name>
$ A2 L, T: c0 F/ _9 l<param-value>true</param-value> # j6 z" a( j3 |1 \0 F/ \$ T. \! L
</init-param> " e2 ?- G( L! {! t3 _9 m6 O
</filter> ~7 U1 {( N' b4 [* J
2 e5 Y6 C& H' z
<filter-mapping>
8 s9 }0 V* j( m; ^" N# [4 E<filter-name>Set Character Encoding</filter-name>
6 }; i( F% J0 ?. @, u<servlet-name>action</servlet-name> ; {& A& ^0 `/ {1 I' J, {
</filter-mapping> 7 A5 t/ M$ y7 |9 Z8 U0 z4 e% n
: Z* ]5 e4 u6 V9 Z! r# `& H
放在web.xml的合适位置。一般在最后,<jsp-config>标签之前(如果有的话)
; {: W8 n7 @$ M2 Q0 V6 [9 y( E9 r* F1 D i" f) @( y; g
经过以上步骤,JSP和mysql的中文显示及插入就都正常了。在STRUTS中也正常。
) ^5 [: ?" L7 v+ O& ` V \
( n1 O7 N. `* }# m, J但是,此时如果你用EMS或mysql的命令行控制台来看表中的数据,却发现它们都是????。这是怎么回事呢? z2 }# D# D8 l8 n- I% }
9 r* {* W( E' T/ b) E不用担心,只要我们运行下面的这几行命令,就能看到正常的中文了! ; Q, Y/ q4 B, ]$ c D4 D( X
" N5 e4 X+ K$ H" o3 {: v8 Z$ H
SET character_set_client = gbk;
# W( e2 ^9 P2 h, LSET character_set_connection = gbk; # _+ s# s0 F2 | H9 Q& L$ G
SET character_set_database = gbk; 4 z! _3 l; Y* n& Q/ G. Z& _3 _
SET character_set_results = gbk;
3 p3 Y# C& H& e5 S- {SET character_set_server = gbk;
- z m; b/ V: N
* ~" S" W3 t6 \3 c/ aSET collation_connection = gbk_bin; 2 J4 Y5 ?) K- p; V& L
SET collation_database = gbk_bin; : B6 e: |$ ?- H/ u i
SET collation_server = gbk_bin;
& d) c( b; W% e/ T, g0 t: C5 V5 V; _2 O" ~- D
如果你用的是mysql的命令行,则直接输入就好。
8 ~6 a5 [; N( p- S+ q8 G. _( l2 W" g1 K- _$ N
如果是EMS,则在工具栏中有一个Show SQL Editor按钮,点一下,把上面的命令输入,再按一个"execute"的按钮,就行了!
+ T& x% d; z+ X( O3 w! g
! m. T! z q2 C1 {7 ?& @# f+ v而且在这种情况下,你可以甚至可以用中文名来建数据库,表名和字段名!!!! " K3 l# V1 h$ Y: \9 l
6 q" i9 U; A; ~---------------------------------------------------------------------------------------------------- 2 L2 }& ^0 i5 S
$ c: d) l+ w$ I+ ^, D6 X- \
但是有一点要特别注意! 9 N# l7 T, E" P/ z$ O5 z
+ N( {7 D$ y$ }: s像GBK,UTF-8这样的名字,在mysql与JAVA中有不同的规定,写的时候要格外注意,否则会出错。 ' t5 g2 K" R3 ?; F3 f1 ^8 G
( o% a; G& f8 c# P e比如GBK,在JAVA中要写成GBK,但在mysql中要写成gbk(连接数据库的URL) ( |% O9 c8 d( \/ S
- L- o c7 d% ?9 R. w8 e8 p% U
比如UTF-8,在JAVA中要写成UTF-8,但在Mysql中要写成utf8
7 R- Z$ l0 _/ u1 V! L% T" U* r9 x4 Y. i2 u: ^
其它的字集符也有类似的区别