原文地址:http://dev2dev.bea.com.cn/techdoc/200311546.html
由于近来论坛中经常碰到中文问题的咨询,所以在下在百忙之中赶出这篇文章,希望能给大家一点指引.如有纰漏,请及时指正!
Web应用中的中文问题
1. 静态页面中文信息不能正确显示
浏览器端看到中文不能正确显示,首先应该检查浏览器是否支持中文,浏览器的编码是否设置正确.为保证静态页面中文信息正确显示可以在HTML <HEAD> 部分增加:
<meta http-equiv="Content-Type" content="text/html" charset="GBK">
2. JSP里的中文提示信息不能正确显示
JSP里的中文提示信息不能正常显示,最直接的原因是WebLogic的默认字符集不是中文字符集(Weblogic8.1里是setlocal,Weblogic7.0sp3,sp4为UTF-8),因此可以在JSP页面中设置字符集,加入如下脚本:
<%@ page contentType="text/html; charset=GBK" %>
这种做法需要对每个JSP页面进行设置,下面的做法针对所有的jsp页面进行设置,比较通用.
3. JSP文件中的提示信息不能正确编译
JSP文件中的提示信息正确编译,可以在weblogic.xml里设置如下脚本,同时也可以解决上面说的第二个问题:
<jsp-descriptor>
<jsp-param>
<param-name>compileCommand</param-name>
<param-value>javac</param-value>
</jsp-param>
<jsp-param>
<param-name>compilerSupportsEncoding</param-name>
<param-value>true</param-value>
</jsp-param>
<jsp-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</jsp-param>
</jsp-descriptor>
4. JSP文件之间不能正确传递中文数据
JSP文件之间不能正确传递中文数据,可以有两种方法解决.
其一:在web.xml里加上如下脚本:
<context-param>
<param-name>weblogic.httpd.inputCharset./*</param-name>
<param-value>GBK</param-value>
</context-param>
其二:在weblogic.xml里加上如下脚本:
<charset-params>
<input-charset>
<resource-path>/*</resource-path>
<java-charset-name>GBK</java-charset-name>
</input-charset>
</charset-params>
当然这种问题也可以自己用java.net.URLEncoder和java.net.URLDecoder来处理中文.
以上都没有涉及到数据库操作,所以当出现乱码时,逐一分析,
必能找到问题所在.另外可能还需要修改WebLogic应用服务器所在操作系统的字符集,确保支持中文.
文件名和目录中的中文问题
如果你的文件名或者目录是中文怎么办呢?上面提到的方法不能解决你的问题了.这时需要使用java.net.URLEncoder编码.举个例子,在test.jsp里,你需要提供一个超链接到 ./测试/测试.jsp,你可以这么写:
<p><a href="<%=java.net.URLEncoder.encode("./测试/测试.jsp")%>">go</p>
JDBC中的中文问题
如果以上的方法还不能解决你的乱码问题,那么可能是JDBC操作中的失误.这里以Oracle9I为例来说明jdbc中的中文问题.首先查询数据库:
select * from v$nls_parameters where parameter='NLS_CHARACTERSET';
得到数据库的字符集,如果ZHS16GBK,则JDBC的操作不需要转码;如果是us7ascii,则需要转码或者作相关配置.下面以使用不同的数据库驱动程序为例来介绍.
1. 使用Thin Driver
如果使用Thin Driver,那么需要在查询数据库的时候将字符集由ISO转换为GBK,写入数据库的时候将字符集由GBK转换为ISO.
举个例子:
插入一条记录:
Connection conn=null;
PreparedStatement pstmt = null;
try {
String strSql="insert into tabA(A,B) values('1111','王超')";
conn=ds.getConnection();
strSql = new String(strSql.getBytes("GBK"), "ISO-8859-1");
pstmt = conn.prepareStatement(strSql);
pstmt.executeUpdate();
}
catch (Exception e) {
//logger.error(e, e);
}
finally {
disconn(conn, pstmt);
}
查询一条记录:
Connection conn=null;
PreparedStatement pstmt = null;
ResultSet rs=null;
try {
String strSql="select B from tabA where A='1111'";
conn=ds.getConnection();
strSql = new String(strSql.getBytes("GBK"), "ISO-8859-1");
pstmt = conn.prepareStatement(strSql);
rs=pstmt.executeQuery();
String strB;
if (rs.next()){
strB=new String(rs.getString(1) .getBytes("ISO-8859-1"), "GBK");
}
catch (Exception e) {
//logger.error(e, e);
}
finally {
disconn(conn, pstmt, rs);
}
这里建议你在属性文件里设置oracle字符集,根据字符集判断
是否转码,以增加应用的移植性.
2.使用OCI Driver
直接使用WebLogic提供的driver,在配置连接池时设置Properties属性:
weblogic.codeset=GBK,如下图所示:
当你采用了上面的两个方法还不能解决你的乱码时,你检查一下是否仅仅是孤僻字不能正常显示呢?这种情况你需要使用oracle的字符集包: nls_charset12.zip,将该包加入到WebLogic classpath中.
加密中的中文问题
对于不含中文信息的加密和解码,我想有很多算法可以实现.但由于中文为两个字符,普通的加密算法在一次加密一次解密之后无法复原.采用BASE64对中文信息进行编码后再加密可以轻松解决这个问题.当然解密之后同样需要用BASE64解码.示例如下:
String pw="中文";
System.out.println(pw);
pw=new sun.misc.BASE64Encoder().encode(pw.getBytes());
System.out.println(pw);
//加密
String pw1=encode(pw);
System.out.println(pw1);
//解密
String pw2=decode(pw1);
System.out.println(pw2);
byte[] bt=new sun.misc.BASE64Decoder().decodeBuffer(pw2);
pw2=new String(bt);
System.out.println(pw2);
下面给出一个完整的使用kaiser算法加密的源代码:
package test;
/**
* 加密类
*/
import java.lang.Math;
public class SecurityTest {
interface Constants{
public static final int INT_PRIM_NUMBER = 95;
public static final int INT_RETURN_LOOP = 94;
}
/**
* SysBean constructor comment.
*/
public SecurityTest() {
super();
}
/**
* 解密方法
* @author zhg
* 创建日期 (2002-12-15 10:17:08)
* @param strCode 需解密的字符串
* @return 解密后的字符串
* @version 1.0
*/
public static String decode(String strCode) {
String strOriginal;
int intRnd;
String strRnd;
int intStrLen;
String strDecodeMe = "";
if (strCode.equals(""))
return strDecodeMe;
intStrLen = strCode.length() - 1;
strRnd = strCode.substring(intStrLen / 2, intStrLen / 2 + 1);
intRnd = strRnd.hashCode() - new SecurityTest().startChar();
strCode =
strCode.substring(0, intStrLen / 2)
+ strCode.substring(intStrLen / 2 + 1, intStrLen + 1);
strOriginal =
new SecurityTest().loopCode(
strCode,
Constants.INT_RETURN_LOOP - intRnd);
strDecodeMe = strOriginal;
return strDecodeMe;
}
/**
* 加密方法.随机取得加密的循环次数,使得每次加密所得的秘文会有所不同
* @author zhg
* 创建日期 (2002-12-15 10:17:08)
* @param strOriginal 需加密的字符串
* @return 加密后的字符串
* @version 1.0
*/
public static String encode(String strOriginal) {
String strCode;
int intRnd;
char rnd;
int intStrLen;
String strCodeMe = "";
if (strOriginal.equals(""))
return strCodeMe;
//2 到 93 之间的随即数,即同一原文可能获得93种不同的秘文
intRnd = (int) (Math.random() * (Constants.INT_RETURN_LOOP - 2) + 2);
strCode = new SecurityTest().loopCode(strOriginal, intRnd);
//对随机数作偏移加密
rnd = (char) (intRnd + new SecurityTest().startChar());
intStrLen = strCode.length();
strCodeMe =
strCode.substring(0, intStrLen / 2)
+ rnd
+ strCode.substring(intStrLen / 2, intStrLen);
if (strCodeMe.indexOf("'") >= 0)
return encode(strOriginal);
else
return strCodeMe;
}
//基础的凯撒算法,并对于每一位增加了偏移
private String kaiserCode(String strOriginal) {
int intChar;
String strCode;
int i;
int intStrLen;
int intTmp;
intStrLen = strOriginal.length();
strCode = "";
for (i = 0; i < intStrLen; i++) {
intChar = strOriginal.substring(i, i + 1).hashCode();
intTmp = intChar - this.startChar();
intTmp =
(intTmp * Constants.INT_PRIM_NUMBER + i + 1) % this.maxChar()
+ this.startChar();
strCode = strCode + (char) (intTmp);
}
return strCode;
}
//循环调用凯撒算法一定次数后,可以取得原文
private String loopCode(String strOriginal, int intLoopCount) {
String strCode;
int i;
strCode = strOriginal;
for (i = 0; i < intLoopCount; i++)
strCode = this.kaiserCode(strCode);
return strCode;
}
public static void main(String[] args) throws Exception {
String pw = "中文";
System.out.println(pw);
pw = new sun.misc.BASE64Encoder().encode(pw.getBytes());
System.out.println(pw);
//加密
String pw1 = encode(pw);
System.out.println(pw1);
//解密
String pw2 = decode(pw1);
System.out.println(pw2);
byte[] bt = new sun.misc.BASE64Decoder().decodeBuffer(pw2);
pw2 = new String(bt);
System.out.println(pw2);
}
private int maxChar() {
String str1 = "~";
String str2 = "!";
return str1.hashCode() - str2.hashCode() + 1;
}
private int startChar() {
String str1 = "!";
return str1.hashCode();
}
}
总结
本文列举了WebLogic中经常碰到的一些中文问题的解决方法.希望读者能够灵活运用.需要提醒的是GBK字符集比GB2312的字库大,有些不常用字在GB2312里是没有的.所以请尽量使用GBK字符集.
由于近来论坛中经常碰到中文问题的咨询,所以在下在百忙之中赶出这篇文章,希望能给大家一点指引.如有纰漏,请及时指正!
Web应用中的中文问题
1. 静态页面中文信息不能正确显示
浏览器端看到中文不能正确显示,首先应该检查浏览器是否支持中文,浏览器的编码是否设置正确.为保证静态页面中文信息正确显示可以在HTML <HEAD> 部分增加:
<meta http-equiv="Content-Type" content="text/html" charset="GBK">
2. JSP里的中文提示信息不能正确显示
JSP里的中文提示信息不能正常显示,最直接的原因是WebLogic的默认字符集不是中文字符集(Weblogic8.1里是setlocal,Weblogic7.0sp3,sp4为UTF-8),因此可以在JSP页面中设置字符集,加入如下脚本:
<%@ page contentType="text/html; charset=GBK" %>
这种做法需要对每个JSP页面进行设置,下面的做法针对所有的jsp页面进行设置,比较通用.
3. JSP文件中的提示信息不能正确编译
JSP文件中的提示信息正确编译,可以在weblogic.xml里设置如下脚本,同时也可以解决上面说的第二个问题:
<jsp-descriptor>
<jsp-param>
<param-name>compileCommand</param-name>
<param-value>javac</param-value>
</jsp-param>
<jsp-param>
<param-name>compilerSupportsEncoding</param-name>
<param-value>true</param-value>
</jsp-param>
<jsp-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</jsp-param>
</jsp-descriptor>
4. JSP文件之间不能正确传递中文数据
JSP文件之间不能正确传递中文数据,可以有两种方法解决.
其一:在web.xml里加上如下脚本:
<context-param>
<param-name>weblogic.httpd.inputCharset./*</param-name>
<param-value>GBK</param-value>
</context-param>
其二:在weblogic.xml里加上如下脚本:
<charset-params>
<input-charset>
<resource-path>/*</resource-path>
<java-charset-name>GBK</java-charset-name>
</input-charset>
</charset-params>
当然这种问题也可以自己用java.net.URLEncoder和java.net.URLDecoder来处理中文.
以上都没有涉及到数据库操作,所以当出现乱码时,逐一分析,
必能找到问题所在.另外可能还需要修改WebLogic应用服务器所在操作系统的字符集,确保支持中文.
文件名和目录中的中文问题
如果你的文件名或者目录是中文怎么办呢?上面提到的方法不能解决你的问题了.这时需要使用java.net.URLEncoder编码.举个例子,在test.jsp里,你需要提供一个超链接到 ./测试/测试.jsp,你可以这么写:
<p><a href="<%=java.net.URLEncoder.encode("./测试/测试.jsp")%>">go</p>
JDBC中的中文问题
如果以上的方法还不能解决你的乱码问题,那么可能是JDBC操作中的失误.这里以Oracle9I为例来说明jdbc中的中文问题.首先查询数据库:
select * from v$nls_parameters where parameter='NLS_CHARACTERSET';
得到数据库的字符集,如果ZHS16GBK,则JDBC的操作不需要转码;如果是us7ascii,则需要转码或者作相关配置.下面以使用不同的数据库驱动程序为例来介绍.
1. 使用Thin Driver
如果使用Thin Driver,那么需要在查询数据库的时候将字符集由ISO转换为GBK,写入数据库的时候将字符集由GBK转换为ISO.
举个例子:
插入一条记录:
Connection conn=null;
PreparedStatement pstmt = null;
try {
String strSql="insert into tabA(A,B) values('1111','王超')";
conn=ds.getConnection();
strSql = new String(strSql.getBytes("GBK"), "ISO-8859-1");
pstmt = conn.prepareStatement(strSql);
pstmt.executeUpdate();
}
catch (Exception e) {
//logger.error(e, e);
}
finally {
disconn(conn, pstmt);
}
查询一条记录:
Connection conn=null;
PreparedStatement pstmt = null;
ResultSet rs=null;
try {
String strSql="select B from tabA where A='1111'";
conn=ds.getConnection();
strSql = new String(strSql.getBytes("GBK"), "ISO-8859-1");
pstmt = conn.prepareStatement(strSql);
rs=pstmt.executeQuery();
String strB;
if (rs.next()){
strB=new String(rs.getString(1) .getBytes("ISO-8859-1"), "GBK");
}
catch (Exception e) {
//logger.error(e, e);
}
finally {
disconn(conn, pstmt, rs);
}
这里建议你在属性文件里设置oracle字符集,根据字符集判断
是否转码,以增加应用的移植性.
2.使用OCI Driver
直接使用WebLogic提供的driver,在配置连接池时设置Properties属性:
weblogic.codeset=GBK,如下图所示:
当你采用了上面的两个方法还不能解决你的乱码时,你检查一下是否仅仅是孤僻字不能正常显示呢?这种情况你需要使用oracle的字符集包: nls_charset12.zip,将该包加入到WebLogic classpath中.
加密中的中文问题
对于不含中文信息的加密和解码,我想有很多算法可以实现.但由于中文为两个字符,普通的加密算法在一次加密一次解密之后无法复原.采用BASE64对中文信息进行编码后再加密可以轻松解决这个问题.当然解密之后同样需要用BASE64解码.示例如下:
String pw="中文";
System.out.println(pw);
pw=new sun.misc.BASE64Encoder().encode(pw.getBytes());
System.out.println(pw);
//加密
String pw1=encode(pw);
System.out.println(pw1);
//解密
String pw2=decode(pw1);
System.out.println(pw2);
byte[] bt=new sun.misc.BASE64Decoder().decodeBuffer(pw2);
pw2=new String(bt);
System.out.println(pw2);
下面给出一个完整的使用kaiser算法加密的源代码:
package test;
/**
* 加密类
*/
import java.lang.Math;
public class SecurityTest {
interface Constants{
public static final int INT_PRIM_NUMBER = 95;
public static final int INT_RETURN_LOOP = 94;
}
/**
* SysBean constructor comment.
*/
public SecurityTest() {
super();
}
/**
* 解密方法
* @author zhg
* 创建日期 (2002-12-15 10:17:08)
* @param strCode 需解密的字符串
* @return 解密后的字符串
* @version 1.0
*/
public static String decode(String strCode) {
String strOriginal;
int intRnd;
String strRnd;
int intStrLen;
String strDecodeMe = "";
if (strCode.equals(""))
return strDecodeMe;
intStrLen = strCode.length() - 1;
strRnd = strCode.substring(intStrLen / 2, intStrLen / 2 + 1);
intRnd = strRnd.hashCode() - new SecurityTest().startChar();
strCode =
strCode.substring(0, intStrLen / 2)
+ strCode.substring(intStrLen / 2 + 1, intStrLen + 1);
strOriginal =
new SecurityTest().loopCode(
strCode,
Constants.INT_RETURN_LOOP - intRnd);
strDecodeMe = strOriginal;
return strDecodeMe;
}
/**
* 加密方法.随机取得加密的循环次数,使得每次加密所得的秘文会有所不同
* @author zhg
* 创建日期 (2002-12-15 10:17:08)
* @param strOriginal 需加密的字符串
* @return 加密后的字符串
* @version 1.0
*/
public static String encode(String strOriginal) {
String strCode;
int intRnd;
char rnd;
int intStrLen;
String strCodeMe = "";
if (strOriginal.equals(""))
return strCodeMe;
//2 到 93 之间的随即数,即同一原文可能获得93种不同的秘文
intRnd = (int) (Math.random() * (Constants.INT_RETURN_LOOP - 2) + 2);
strCode = new SecurityTest().loopCode(strOriginal, intRnd);
//对随机数作偏移加密
rnd = (char) (intRnd + new SecurityTest().startChar());
intStrLen = strCode.length();
strCodeMe =
strCode.substring(0, intStrLen / 2)
+ rnd
+ strCode.substring(intStrLen / 2, intStrLen);
if (strCodeMe.indexOf("'") >= 0)
return encode(strOriginal);
else
return strCodeMe;
}
//基础的凯撒算法,并对于每一位增加了偏移
private String kaiserCode(String strOriginal) {
int intChar;
String strCode;
int i;
int intStrLen;
int intTmp;
intStrLen = strOriginal.length();
strCode = "";
for (i = 0; i < intStrLen; i++) {
intChar = strOriginal.substring(i, i + 1).hashCode();
intTmp = intChar - this.startChar();
intTmp =
(intTmp * Constants.INT_PRIM_NUMBER + i + 1) % this.maxChar()
+ this.startChar();
strCode = strCode + (char) (intTmp);
}
return strCode;
}
//循环调用凯撒算法一定次数后,可以取得原文
private String loopCode(String strOriginal, int intLoopCount) {
String strCode;
int i;
strCode = strOriginal;
for (i = 0; i < intLoopCount; i++)
strCode = this.kaiserCode(strCode);
return strCode;
}
public static void main(String[] args) throws Exception {
String pw = "中文";
System.out.println(pw);
pw = new sun.misc.BASE64Encoder().encode(pw.getBytes());
System.out.println(pw);
//加密
String pw1 = encode(pw);
System.out.println(pw1);
//解密
String pw2 = decode(pw1);
System.out.println(pw2);
byte[] bt = new sun.misc.BASE64Decoder().decodeBuffer(pw2);
pw2 = new String(bt);
System.out.println(pw2);
}
private int maxChar() {
String str1 = "~";
String str2 = "!";
return str1.hashCode() - str2.hashCode() + 1;
}
private int startChar() {
String str1 = "!";
return str1.hashCode();
}
}
总结
本文列举了WebLogic中经常碰到的一些中文问题的解决方法.希望读者能够灵活运用.需要提醒的是GBK字符集比GB2312的字库大,有些不常用字在GB2312里是没有的.所以请尽量使用GBK字符集.
发表评论
-
ant 编译,内存溢出
2010-12-21 19:43 4409当使用Ant编译大量的Java源文件时,会出现java.lan ... -
Tomcat线程池apr和threadPool
2010-10-15 11:47 2775Tomcat是使用最广的Java We ... -
displaytag外部翻页和排序
2009-05-28 22:07 0显然,displaytag标签在进行排序和分页时,默认行为是针 ... -
友好的错误提示页面,我们可以自定义错误页面:
2008-11-13 13:19 5243转载,原地址:http://xuxiangpan888.ite ... -
MSAgent 详细解说(下)
2007-04-22 01:14 1720七、我的菜单 右键点击 ... -
MSAgent 详细解说(上)
2007-04-22 00:46 3313转:http://www.blueidea.com/tech/ ... -
网页内嵌播放器
2007-04-18 12:42 9423原址:http://caoxiaoyong.spaces ... -
中文文件下载失败的前因后果
2007-04-17 09:36 1722问题如下:客户的论坛 ... -
jar命令的简单应用
2007-04-17 09:24 2506环境假设: 1、假设你在硬盘的某个目录下需要创佳jar/war ... -
转:JBoss技术支持文档
2007-03-26 13:09 2121文章来源:http://java.ccidnet.com/ar ... -
转载-在JBoss中配置多个数据库和数据源
2007-03-13 10:02 2209JBoss是一款非常强大的J2EE应用程序服务器,但是这种强 ... -
安全:编写自己的登录与访问控制模块
2007-03-05 17:04 1578http://java.ccidnet.com/art/375 ...
相关推荐
### WebLogic 8.1 性能调优详解 #### 一、WebLogic 8.1简介 WebLogic Server 是一款高性能的企业级应用服务器,由BEA Systems开发,后被Oracle收购并继续维护和发展。WebLogic 8.1 版本在企业应用部署和服务方面...
问题可能源于WebLogic 8.1所使用的Servlet API版本较低,不支持`setCharacterEncoding`方法。Servlet 2.4及更高版本才正式引入了这个方法,而WebLogic 8.1可能仅支持Servlet 2.3或更低版本。 标签中的"WEBLOGIC8"指...
- **实现方法**:在 Weblogic Portal 8.1 中实现分页显示,可以通过编写自定义 Portlet 来实现。具体而言,可以使用 Java 分页框架(如 JPA)来分页查询数据,然后在前端页面中显示结果。 #### 第三方插件集成 **1...
3. **使用weblogic的类路径问题**:确保DWR库文件正确添加到了WebLogic服务器的类路径中。 4. **没有cookies的情况下使用DWR**:提供替代方案,比如使用URL重写来绕过对cookies的依赖。 **10.2 JavaScript高级应用*...
- **Java Reporting Component安装**:对于不同的开发环境,如Borland JBuilder 10、BEA Weblogic Workshop 8.1 SP2等,提供了详细的安装指导。 #### 快速开始 - **示例数据**:提供了一个名为Xtreme.mdb的示例...
### DWR中文文档知识点概述 #### 一、DWR入门 **1.1 简介** DWR(Direct Web Remoting)是一种简化Ajax应用程序开发的技术。它通过提供一种简单的方式来调用服务器端的Java方法,从而使得客户端的JavaScript代码...
解决中文乱码问题,确保请求数据的正确处理。 **11.4 创建登录验证的过滤器** 实现登录验证功能,确保只有经过身份验证的用户才能访问某些资源。 **11.4 串联过滤器** 将多个过滤器串联起来,实现更复杂的功能...
9.9. 公共问题的解决方案 9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 ...
#### 第11章 过滤器解决中文乱码及登录验证 ##### 11.1 Servlet过滤器简介 - Servlet过滤器是在请求到达目标资源之前或响应离开目标资源之后进行拦截的组件。 ##### 11.2 创建Servlet过滤器 - 实现`javax.servlet....
9.9. 常见问题的解决方法 9.9.1. 对一个特定的 DataSource 使用了错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 ...
9.9. 公共问题的解决方案 9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1....
9.9. 公共问题的解决方案 9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1....
9.9. 常见问题的解决方法 9.9.1. 对一个特定的 DataSource 使用了错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 ...