平台:Lucene 2.1.0,JRE 1.4,Oracle 10g,IBM Web Sphere。
数据表:Article。字段:ID(自动增长),Title(String),Content(String)。共有550000条记录。
对Article建立索引:
1import org.apache.lucene.analysis.*;
2import org.apache.lucene.analysis.cn.*;
3import org.apache.lucene.document.*;
4import org.apache.lucene.index.*;
5import java.sql.*;
6import oracle.jdbc.pool.*;
7
8public class Index {
9 private String url="jdbc:oracle:thin:@//192.168.0.l:1521/Test";
10 private String user="terry";
11 private String password="dev";
12 private Connection con=null;
13 private Statement st=null;
14 private ResultSet rs=null;
15 private String indexUrl="E:\\ArticleIndex";
16
17 private ResultSet getResult() throws Exception{
18 OracleDataSource ods=new OracleDataSource();
19
20 ods.setURL(this.url);
21 ods.setUser(this.user);
22 ods.setPassword(this.password);
23
24 this.con=ods.getConnection();
25 this.st=this.con.createStatement();
26 this.rs=this.st.executeQuery("SELECT * FROM Article");
27
28 return this.rs;
29 }
30
31 public void createIndex() throws Exception{
32 ResultSet rs=this.getResult();
33
34 Analyzer chineseAnalyzer=new ChineseAnalyzer();
35 IndexWriter indexWriter=new IndexWriter(this.indexUrl,chineseAnalyzer,true);
36 indexWriter.setMergeFactor(100);
37 indexWriter.setMaxBufferedDocs(100);
38
39 java.util.Date startDate=new java.util.Date();
40
41 System.out.println("开始索引时间:"+startDate);
42
43 executeIndex(rs,indexWriter);
44
45 indexWriter.optimize();
46
47 indexWriter.close();
48
49 java.util.Date endDate=new java.util.Date();
50
51 System.out.println("索引结束时间:"+endDate);
52 System.out.println("共花费:"+(endDate.getTime()-startDate.getTime())+"ms");
53 }
54
55 private void executeIndex(ResultSet rs,IndexWriter indexWriter) throws Exception{
56 int i=0;
57
58 while(rs.next()){
59 int id=rs.getInt("ID");
60 String title=rs.getString("TITLE");
61 String info=rs.getString("CONTENT");
62
63 Document doc=new Document();
64
65 Field idField=new Field("ID",Integer.toString(id),Field.Store.YES,Field.Index.NO,Field.TermVector.NO);
66 Field titleField=new Field("Title",title,Field.Store.YES,Field.Index.TOKENIZED,Field.TermVector.YES);
67 Field infoField=new Field("Content",title,Field.Store.YES,Field.Index.TOKENIZED,Field.TermVector.YES);
68
69 doc.add(idField);
70 doc.add(titleField);
71 doc.add(infoField);
72
73 indexWriter.addDocument(doc);
74
75 i++;
76 }
77
78 this.close();
79
80 System.out.println("共处理记录:"+i);
81 }
82
83 private void close() throws Exception{
84 this.rs.close();
85 this.st.close();
86 this.con.close();
87 }
88}
查找:
1import java.io.*;
2import org.apache.lucene.analysis.cn.*;
3import org.apache.lucene.search.*;
4import org.apache.lucene.store.*;
5import org.apache.lucene.document.*;
6import org.apache.lucene.queryParser.QueryParser;
7
8import java.util.*;
9
10public class Search {
11
12 private static final String indexUrl="E:\\ArticleIndex";
13
14 public static void main(String[] args) throws Exception {
15/**/ /*建立索引代码,查找时注释*/
16 //Index index=new Index();
17
18 //index.createIndex();
19
20
21
22
23 File indexDir=new File(indexUrl);
24 FSDirectory fdir=FSDirectory.getDirectory(indexDir);
25
26 IndexSearcher searcher=new IndexSearcher(fdir);
27
28//对中文建立解析(必须)
29 QueryParser parser=new QueryParser("Title",new ChineseAnalyzer());
30 Query query=parser.parse("李湘");
31
32 Date startDate=new Date();
33 System.out.println("检索开始时间:"+startDate);
34
35 Hits result=searcher.search(query);
36
37 for(int i=0;i<result.length();i++){
38 Document doc=result.doc(i);
39
40 System.out.println("内容:"+doc.get("Content"));
41 }
42
43 Date endDate=new Date();
44
45 System.out.println("共有记录:"+result.length());
46 System.out.println("共花费:"+(endDate.getTime()-startDate.getTime()));
47 }
48
49}
经测试,建立索引文件大概花了11分钟。一般情况下,和用SQL执行LIKE查询差不多。
当然,这只是我的粗略测试。最近一阶段,我会对Lucene进行代码深入研究。
posted @
2007-08-16 10:57 jacksontoto 阅读(243) |
评论 (0) |
编辑 收藏
摘要: 搜索流程中的第二步就是构建一个Query。下面就来介绍Query及其构建。 当用户输入一个关键字,搜索引擎接收到后,并不是立刻就将它放入后台开始进行关键字的检索,而应当首先对这个关键字进行一定的分析和处理,使之成为一种后台可以理解的形式,只有这样,才能提高检索的效率,同时检索出更加有效的结果。那么,在Lucene中,这种处理,其实就是构建一个Query对象。 就Query对象本身言,它只是Luce...
阅读全文
posted @
2007-08-16 10:56 jacksontoto 阅读(687) |
评论 (0) |
编辑 收藏
[ 2007-7-27 16:28:00 | By: 叶寻飞 ]
初学JSP时,写了一些工具函数因为不太会用JAVA下的正则表达式也只能这么写啦!
发出来让大家批评批评提点意见!有几个函数不算是自己写的希望爱挑剌的朋友嘴
下留情!我是新手我怕谁,脸皮不行的人水平也上不去呀.嘻嘻..
package mxzc.web.strctrl;
public class StringCtrl
{/********************************************
public synchronized String HTMLcode(String TXTcode) 功能:文本替换
public synchronized String Unhtmlcode(String str) 功能:(不完全)反文本
替换
public synchronized String Unhtmlcodea(String str) 功能:反文本替换
public synchronized boolean emailcheck (String email) 功能:检查一个字
符串是否符合E-Mail
public synchronized boolean isemailstr(String email) 功能:检查一个字
符串是否符合E-Mail
public synchronized boolean isqqstr(String qq) 功能:检查一个字符串是
否符合QQ
public synchronized boolean isnumstr(String num) 功能:检查一个字符串
是否为一数字串
public synchronized String userstrlow(String user) 功能:替换用户名中
不合法的部分
public synchronized boolean userstrchk(String user) 功能:检查字符串是
否符合用户名法则
public synchronized boolean istelstr(String tel) 功能:检查字符串是否
为TEL
public synchronized boolean urlcheck(String url) 功能:检查字符串是否
为URL
public synchronized String isotogbk(String iso) 功能:ISO9006-1码转换
为GBK
public synchronized String gbktoiso(String gbk) 功能:GBK码转换为
ISO9006-1
public synchronized String dostrcut(String oldstr,int length) 功能:按
汉字长换行(英文按半个字长)
public synchronized String inttodateshow(int datenum) 功能:将1900年至
时间的秒数换为日期字符串
public synchronized String nowdateshow() 功能:显示当前日期
public synchronized java.util.Date inttodate(int datenum) 功能:将秒数
转换为日期
public synchronized int datetoint() 功能:将时间换为从1900年至今的秒
数
public synchronized int datetoint(java.util.Date d) 功能:将时间换为从
1900年至时间的秒数
public synchronized String overlengthcut(String str,int length) 功能:
截取前几个字符,单位为汉字字长
public synchronized String replace(String str,String suba,String subb)
功能:字符串替换
*********************************************/
private static final String isostr="ISO8859-1";
private static final String gbkstr="GBK";
public StringCtrl()
{
}
public synchronized boolean emailcheck (String email)
{
if(email==null)return false;
if(email.length()<6)return false;
if(email.indexOf("@")<2)return false;
if(email.indexOf(".")<4)return false;
if(email.endsWith(".")||email.endsWith("@"))return false;
if(email.lastIndexOf("@")>email.lastIndexOf(".")-1)return false;
if(email.lastIndexOf("@")!=email.indexOf("@"))return false;
String[] lowstr={"\@#","\"","\n","&","\t","\r","<",">","/","\\","#"};
for(int i=0;i<lowstr.length;i++)if(email.indexOf("lowstr")>0)return
false;
return true;
}
public synchronized boolean isemailstr(String email)
{
if(email==null)return false;
if(email.indexOf("@")==-1||email.indexOf(".")==-1||email.length()<6)
return false;
return true;
}
public synchronized boolean isqqstr(String qq)
{
if(qq==null)return false;
if(qq.length()>12)return false;
if(qq.length()<5)return false;
for(int i=0;i<qq.length();i++)
if(!(((int)qq.charAt(i))<=57&&((int)qq.charAt(i))>=48))return false;
return true;
}
public synchronized boolean isnumstr(String num)
{
if(num==null)return false;
if(num.length()<1)return false;
for(int i=0;i<num.length();i++)
if(!(((int)num.charAt(i))<=57&&((int)num.charAt(i))>=48))return false;
return true;
}
public synchronized String userstrlow(String user)
{
String newuserstr=user.trim();
char[] lowstr=
{@#\@#@#,@#\"@#,@#\n@#,@#&@#,@#\t@#,@#\r@#,@#<@#,@#>@#,@#/@#,@#\\@#,@##
@#};
for(int i=0;i<lowstr.length;i++)
newuserstr=newuserstr.replace(lowstr[i],@#+@#);
return newuserstr;
}
public synchronized boolean userstrchk(String user)
{
String newuserstr=user.trim();
char[] lowstr=
{@#\@#@#,@#\"@#,@#\n@#,@#&@#,@#\t@#,@#\r@#,@#<@#,@#>@#,@#/@#,@#\\@#,@##
@#,@#~@#,@#`@#,@#!@#,@#@@#,@#$@#,@#%@#,@#^@#,@#*@#,@#(@#,@#)@#,@#-
@#,@#_@#,@#+@#,@#=@#,@#|@#,@#?@#,@#,@#,@#;@#,@#.@#};
for(int i=0;i<lowstr.length;i++)
newuserstr=newuserstr.replace(lowstr[i],@#+@#);
return (user.equals(newuserstr))?true:false;
}
public synchronized boolean istelstr(String tel)
{
if(tel==null)return false;
if(tel.length()<1)return false;
if(tel.length()>32)return false;
for(int i=0;i<tel.length();i++)
if(!(((int)tel.charAt(i))<=57&&((int)tel.charAt(i))>=48))if(tel.charAt
(i)!=@#-@#)return false;
return true;
}
public synchronized boolean urlcheck(String url)
{
if(url==null)return false;
if(url.length()<10)return false;
String urls=url.toLowerCase();
if(!urls.startsWith("http://"))return false;
if(url.indexOf("<")>0||url.indexOf(">")>0)return false;
return true;
}
public synchronized String isotogbk(String iso)throws Exception
{
if(iso!=null)return (new String(iso.getBytes(isostr),gbkstr));
if(iso.length()<1)return "";
return null;
}
public synchronized String gbktoiso(String gbk)throws Exception
{
if(gbk!=null)return (new String(gbk.getBytes(gbkstr),isostr));
if(gbk.length()<1)return "";
return null;
}
public synchronized String HTMLcode(String TXTcode)
{
String newstr="";
if(TXTcode==null)return "";
newstr=TXTcode;
newstr=replace(newstr,"&","&");
newstr=replace(newstr,"\"",""");
newstr=replace(newstr," "," ");
newstr=replace(newstr,"<","<");
newstr=replace(newstr,">",">");
newstr=replace(newstr,"\@#","'");
return newstr;
}
public synchronized String Unhtmlcode(String str)
{
String newstr="";
if(str==null)return "";
if(str.length()<1)return "";
newstr=str;
newstr=replace(newstr,"&","&");
//newstr=replace(newstr,""","\"");
newstr=replace(newstr," "," ");
newstr=replace(newstr,""","\"");
//newstr=replace(newstr,"<","<");
//newstr=replace(newstr,">",">");
newstr=replace(newstr,"'","\@#");
return newstr;
}
public synchronized String Unhtmlcodea(String str)
{
String newstr="";
if(str==null)return "";
if(str.length()<1)return "";
newstr=str;
newstr=replace(newstr,"&","&");
newstr=replace(newstr,""","\"");
newstr=replace(newstr," "," ");
newstr=replace(newstr,"<","<");
newstr=replace(newstr,">",">");
newstr=replace(newstr,"'","\@#");
return newstr;
}
public synchronized String dostrcut(String oldstr,int length)
{
int i=0;
int j=0;
int k=0;
String newstr="";
if(oldstr==null)return "";
if(length<=0)return "";
for(i=0;i<oldstr.length();i++)
{
if(oldstr.charAt(i)==@#\n@#)j=0;
else if(((int)(oldstr.charAt(i)))>255)j+=2;
else j++;
if((j/2)>=length)
{
newstr=newstr.concat(oldstr.substring(k,i)+"\n");
k=i;
j=0;
}
}
newstr=newstr.concat(oldstr.substring(k)+"\n");
return newstr;
}
public synchronized String inttodateshow(int datenum)
{
int year=0;
int month=0;
int day=0;
int hour=0;
int minute=0;
int second=0;
String datestr="";
java.util.Date d;
d=new java.util.Date((long)(datenum)*1000);
java.util.Calendar ds=java.util.Calendar.getInstance();
ds.setTime(d);
year=ds.get(java.util.Calendar.YEAR);
month=ds.get(java.util.Calendar.MONTH);
day=ds.get(java.util.Calendar.DATE);
hour=ds.get(java.util.Calendar.HOUR_OF_DAY);
minute=ds.get(java.util.Calendar.MINUTE);
second=ds.get(java.util.Calendar.SECOND);
datestr=Integer.toString(year)+"/"+Integer.toString(1+month)
+"/"+Integer.toString(day);
return datestr;
}
public synchronized String nowdateshow()
{
int year=0;
int month=0;
int day=0;
int hour=0;
int minute=0;
int second=0;
String datestr="";
java.util.Calendar ds=java.util.Calendar.getInstance();
year=ds.get(java.util.Calendar.YEAR);
month=ds.get(java.util.Calendar.MONTH);
day=ds.get(java.util.Calendar.DATE);
hour=ds.get(java.util.Calendar.HOUR_OF_DAY);
minute=ds.get(java.util.Calendar.MINUTE);
second=ds.get(java.util.Calendar.SECOND);
datestr=Integer.toString(year)+"/"+Integer.toString(1+month)
+"/"+Integer.toString(day);
return datestr;
}
public synchronized java.util.Date inttodate(int datenum)
{
int year=0;
int month=0;
int day=0;
String datestr="";
java.util.Date d;
d=new java.util.Date((long)(datenum)*1000);
return d;
}
public synchronized int datetoint()
{
java.util.Date d=null;
long ds=0;
d=new java.util.Date();
ds=d.getTime();
return (int)(ds/1000);
}
public synchronized int datetoint(java.util.Date d)
{
long ds=0;
ds=d.getTime();
return (int)(ds/1000);
}
public synchronized String overlengthcut(String str,int length)
{
int i=0;
int j=0;
if(str==null)return "";
if(length<0)return "";
if(str.length()<=length)return str;
for(i=0;i<str.length();i++)
{
if(((int)(str.charAt(i)))>255)j+=2;
else j++;
if((j/2)>=length)
{
return str.substring(0,i);
}
}
return str;
}
public synchronized String replace(String str,String suba,String subb)
{
String newstr="";
int start=0;
int offset=0;
int subalength=0;
int strlength=0;
if(str==null||suba==null||subb==null)return str;
if(suba.equals(subb))return str;
if(str.length()<suba.length()||str.length()<subb.length())return str;
if(str.length()>0&&suba.length()>0&&subb.length()>0)
{
subalength=suba.length();
strlength=str.length();
while(true)
{
if(str.indexOf(suba)<0)break;
if(offset>strlength)break;
start=str.indexOf(suba,offset);
if(start<offset)break;
newstr=newstr.concat(str.substring(offset,start));
newstr=newstr.concat(subb);
offset=start+subalength;
}
newstr=newstr.concat(str.substring(offset));
return newstr;
}
else
{
return str;
}
}
}
posted @
2007-08-03 15:07 jacksontoto 阅读(184) |
评论 (0) |
编辑 收藏
在Java编程中,中文字体编码难倒了不少程序员,如果抓住了影响Java中文显示的几个关键因素,问题将迎刃而解。
Java是目前最流行的面向对象的编程语言之一,Java支持UTF-8、ISO-8
859-1、GBK等各种字体编码,可笔者发现Java中字体编码的问题仍难倒了不少程序员,网上虽然也有不少关于在Java中如何正确显示中文的文章,但都不够全面,笔者特意总结如下。
影响Java中字体编码正确显示的有几个因素: 1)数据库的连接方式; 2)网页中使用的字体编码; 3)数据库里存放数据的字体编码; 4)Java的缺省字体编码。如果在编程中遇到不能正确显示中文时,要先弄清楚以上几项所使用的字体编码,再分析找出原因,即可解决问题。
众所周知,JSP是Java的一种,和网页有关,而网页也有自己的中文编码系统,所以JSP处理中文要比纯Java的类文件更为麻烦。本文的测试数据库是MySQL3.2,数据库连接驱动是用org.gjt.mm.mysql.Driver,这里主要讨论UTF-8和GBK的显示( GB2312是GBK的一个子集,Java中可以使用GBK来代替GB系列)。我们先来研究JSP中字体编码问题, 下面第一到第六点是针对JSP的(因为从数据库里读出中文数据与写入中文数据有所区别,咱们分别说明,前三点是从读取数据库到显示在网页,后三点是从网页输入数据到存入数据库),第七到第九点针对纯Java的类文件。 以下rs表示ResultSet的一个实例,是执行Select语句之后产生的数据集。
一、数据库连接方式使用UTF-8
在连接数据库的驱动后面加上这句参数useUnicode=true&characterEncoding=
UTF-8,例如jdbc:mysql://localhost/DBVF?autoReconnect=true&useUnicode=
true&characterEncoding=UTF-8,从数据库里读出中文显示在使用GBK的JSP的网页里,如果数据库里存放的字体编码是UTF-8,在JSP中使用 str=new String(rs.getBytes(1),"UTF-8")或者str=rs.getString(1),可以正确显示中文。如果数据库里存放的是GBK数据,那么JSP中也要使用str=new String(rs.getBytes(1),"GBK")来显示正确的中文。值得注意的是如果页面使用UTF-8,数据库里存放的是UTF-8,也可以用str=new String(rs.getBytes(1),"GBK")正确显示中文。如果网页是UTF-8,而数据库里存放的是GBK,无法直接显示中文,需要2步转换, str=new String(rs.getBytes(1),"GBK"); 再str=new String(str.getBytes("UTF-8"),"GBK"),才可以正确显示中文。
二、数据库连接方式使用GBK
在连接数据库的驱动后面加上这句参数useUnicode=true&characterEncoding=
GBK,例如jdbc:mysql://localhost/DBVF?autoReconnect=true&UseUnicode=true&
characterEncoding=GBK,从数据库里读出中文,显示在使用GBK的JSP的网页里,如果数据库里存放的字体编码是UTF-8,在JSP中一定要使用 str=new String(rs.getBytes(1),"UTF-8"),才正确显示中文。如果数据库里存放的是GBK数据,那么JSP中也要使用str=new String(rs.getBytes(1),"GBK") 或者直接使用str=rs.getString(1),即可显示正确的中文。 如果网页是UTF-8,而数据库里存放的是GBK,只能用str=new String(rs.getString(1).getBytes("UTF-8"),"GBK")的方法来显示中文; 如果网页是UTF-8,而数据库里存放的是UTF-8,可用str=new String(rs.getBytes(1),"GBK") 或者rs.getString(1)方法来显示中文。
三、使用缺省数据库连接方式
连接数据库的驱动后面没有这句参数useUnicode=&characterEncoding=,例如jdbc:mysql://localhost/DBVF?autoReconnect=true,没有参数useUnicode=true&characterEncoding,表示使用默认的ISO-8895-1编码。
1. 从数据库里读出中文,显示在GBK的网页里。如果数据库里存放的字体编码是UTF-8,在JSP网页中一定要使用语句 str=new String(rs.getBytes(1),"UTF-8") 或者str= new String(rs.getString(1).getBytes("ISO-8859-1"),"UTF-8"),才可正确显示中文。如果数据库里存放的是GBK数据,那么JSP中也要使用str=new String(rs.getBytes(1),"GBK")或str=new String(rs.getString(1).getBytes("ISO-8859-1"),"GBK") 显示正确的中文。
2. 如果网页是UTF-8,不能直接正确显示GBK,需要2步转换,str=new String(rs.getBytes(1),"GBK"),再str=new String(str.getBytes("UTF-8"),"GBK") 才可以正确显示中文。如果数据库里存的是UTF-8,直接用str=new String(rs.getBytes(1),"GBK")或者str=new String(rs.getString(1).getBytes("ISO-8859-1"),"GBK")就可以显示中文了。
以上是读取数据库里中文正确显示在网页上,下面三点是如何正确存入数据库。
四、数据库连接方式使用UTF-8编码
JSP中要把网页输入的中文存入数据库,通常有一个提交(Submit)的过程,是用str=request.getParameter("username"),然后执行update或者insert语句来存入数据库。如何赋值给str很重要,而且这里中文输入与网页所使用的字体编码有关。
1、 网页使用UTF-8,使用str= new String(request.getParameter("username").getBytes("ISO-8859-1"),"UTF-8")或者str= new String(request.getParameter("username").getBytes(),"UTF-8"),都可以使得存到数据库里的数据是UTF-8编码。
2. 网页使用GBK,使用str= new String(request.getParameter("username").getBytes(),"GBK"),那么存入数据库的是UTF-8编码。
3. 值得注意的是使用UTF-8的数据库连接方式不能存得GBK。
五、数据库连接方式使用GBK编码
1. 输入使用GBK网页,存到数据库里是GBK的方法: str= new String(request.getParameter("username").getBytes("ISO-8859-1"),"GBK") 或者str= new String(request.getParameter("username").getBytes(),"GBK")。
2. 网页使用GBK,想存入UTF-8到数据库里,要分2步: 先str=new String(request.getParameter("username").getBytes(),"GBK"),再str=new String(str.getBytes("UTF-8"),"GBK")即可。
3. 网页使用UTF-8,而且使用str= new String(request.getParameter("username").getBytes("ISO-8859-1"),"GBK") 或者str= new String(request.getParameter("username").getBytes(),"UTF-8"),那么存到数据库里的数据是UTF-8编码。
4. 网页使用UTF-8,而且使用str= new String(request.getParameter("username").getBytes("ISO-8859-1"),"UTF-8"),那么存到数据库里的数据是GBK编码。
六、数据库连接方式使用缺省,即不使用参数useUnicode和characterEncoding
1. 网页使用GBK,如果使用str= request.getParameter("username")或者str= new String(request.getParameter("username").getBytes()),那么在数据库里的数据是GBK码。网页使用UTF-8 和使用str= request.getParameter("username"),则存入数据库是UTF-8编码。
2. 如果使用str= new String(request.getParameter("username").getBytes("ISO-8859-1")),那么根据网页提供的字体编码而存到数据库里,比如是UTF-8的网页,那么存到数据库中就是UTF-8编码,如果使用GBK网页,那么存到数据库里的字就是GBK编码。
3. 如果使用str= new String(request.getParameter("username").getBytes("UTF-8"),"UTF-8")这一种组合能存到正确的数据外,其他存到数据库里的数据则都是乱码或者错误码。在这个UTF-8组合的特例中,网页使用的是GBK,则存放到数据库里就是GBK,网页使用UTF-8,那么存到数据库里的就是UTF-8。
4. 网页是GBK的要存得UTF-8,一定需要2步: company=new String(request.getParameter("company").getBytes(),"GBK")和company=new String(company.getBytes("UTF-8"))。
5. 网页是UTF-8的,不能存得GBK在数据库里,一句话,改变数据库连接方式不能存得GBK码。
以上所有的都是基于JSP网页和数据库交换数据,下面讨论一下纯JAVA编程下的字体编码转换。
七、数据库连接方式使用UTF-8编码
1. 数据库里的中文是UTF-8,可以转换为GBK,但不能把GBK存入数据库。
2. 数据库是GBK,如果转换为UTF-8,使用content=new String(rs.getBytes(2),"GBK")直接将content存入数据库就可为UTF-8。
八、数据库连接方式使用GBK编码
1. 数据库里的中文是UTF-8,如果转换为GBK,使用content= new String(rs.getString(2).getBytes(),"UTF-8"),再直接使用update或者insert语句插入到数据库,即存得GBK。如果使用content= new String(rs.getString(2).getBytes(),"GBK")或者content= new String(rs.getString(2).getBytes()),再存入数据库即存得还是UTF-8编码。
2. 数据库里的中文是GBK,如果转换为UTF-8,使用content= new String(rs.getString(2).getBytes("UTF-8"))或者content= new String(rs.getString(2).getBytes("UTF-8"),"GBK"),再直接使用update或者insert语句插入到数据库,即存得UTF-8。
3. 如果某个String是GBK,要转换为UTF-8,也是使用content= new String(GBKstr.getBytes("UTF-8"))或者content= new String(GBKstr.getBytes("UTF-8"),"GBK"); 如果某个String是UTF-8,要转换为GBK,应该使用new String(UTFstr.getBytes("GBK"),"UTF-8")。
九、数据库连接方式使用缺省,即不跟参数
1. str2=new String(GBKstr.getBytes("UTF-8"),"ISO-8859-1"),可以将数据库里的GBK编码转换为UTF-8。
2. 读取UTF-8然后存入UTF-8,则用str1=new String(UTFstr.getBytes(),"ISO-8859-1")或者str1=new String(UTFstr.getBytes("GBK"),"ISO-8859-1")。
3. 不能实现数据库里的UTF-8转换为GBK。
如果采用UTF-8的数据库连接方式或者缺省数据连接方式,那么无法将UTF-8转为GBK;而GBK的数据库连接方式可以实现UTF-8和GBK的相互转换。建议大家采用GBK的数据连接方式。
posted @
2007-08-01 09:01 jacksontoto 阅读(208) |
评论 (0) |
编辑 收藏
第三步:对动态输出内容编码
每一个ISO-8859-1字符集中的字符都可以编码为一个数值,完整的对应关系请见下面的几个表:
数 值
编码表示法
含 义
表现形式
�-
-
Unused
-
-
HorizontalTab
space
-
Linefeed
space
-
-
Unused
-
-
Space
space
!
-
Exclamationmark
!
"
"
Quotationmark
"
#
-
Numbersign
#
$
-
Dollarsign
$
%
-
Percentsign
%
&
&
Ampersand
&
'
-
Apostrophe
'
(
-
Leftparenthesis
(
)
-
Rightparenthesis
)
*
-
Asterisk
*
+
-
Plussign
+
,
-
Comma
,
-
-
Hyphen
-
.
-
Period(fullstop)
.
/
-
Solidus(slash)
/
0-9
-
Digits(0-9)
0-9
:
-
Colon
:
;
-
Semi-colon
;
<
<
Lessthan
<
=
-
Equalssign
=
>
>
Greaterthan
>
?
-
Questionmark
?
@
-
Commercialat
@
A-Z
-
UppercaseA-Z
A-Z
[
-
Leftsquarebracket
[
\
-
Reversesolidus(backslash)
\
]
-
Rightsquarebracket
]
^
-
Caret
^
_
-
Horizontalbar
_
`
-
Acuteaccent
`
a-z
-
Lowercasea-z
a-z
{
-
Leftcurlybrace
{
|
-
Verticalbar
|
}
-
Rightcurlybrace
}
~
-
Tilde
~
-Ÿ
-
Unused
-
Non-breakingspace
¡
¡
Invertedexclamation
¡
¢
¢
Centsign
¢
£
£
Poundsterlingsign
£
¤
¤
Generalcurrencysign
¤
¥
¥
Yensign
¥
&brVBar;
¦
Brokenverticalbar
¦
§
§
Sectionsign
§
¨
¨
UMLaut(dierisis)
¨
©
©
Copyright
©
ª
ª
Feminineordinal
ª
«
«
Leftanglequote,guillemotleft
«
¬
¬
Notsign
¬
Softhyphen
®
®
ReGISteredtrademark
®
¯
¯
Macronaccent
¯
°
°
Degreesign
°
±
±
Plusorminus
±
²
²
Superscripttwo
²
³
³
Superscriptthree
³
´
´
Acuteaccent
´
µ
µ
Microsign
µ
¶
¶
Paragraphsign
¶
·
·
Middledot
·
¸
¸
Cedilla
¸
¹
¹
Superscriptone
¹
º
º
Masculineordinal
º
»
»
Rightanglequote,guillemotright
»
¼
¼
Fraction(onequarter)
¼
½
½
Fraction(onehalf)
½
¾
¾
Fraction(threequarters)
¾
¿
¿
Invertedquestionmark
¿
À
À
CapitalA,graveaccent
À
Á
Á
CapitalA,acuteaccent
Á
Â
Â
CapitalA,circumflexaccent
Â
Ã
Ã
CapitalA,tilde
Ã
Ä
Ä
CapitalA,umlaut(dierisis)
Ä
Å
Å
CapitalA,ring
Å
Æ
Æ
CapitalAEdipthong(ligature)
Æ
Ç
Ç
CapitalC,cedilla
Ç
È
È
CapitalE,graveaccent
È
É
É
CapitaE,acuteaccent
É
Ê
Ê
CapitalE,circumflexaccent
Ê
&EUML;
Ë
CapitalE,umlaut(dierisis)
Ë
Ì
Ì
CapitalI,graveaccent
Ì
Í
Í
CapitalI,acuteaccent
Í
Î
Î
CapitalI,circumflexaccent
Î
Ï
Ï
CapitalI,umlaut(dierisis)
Ï
Ð
Ð
CapitalEth,Icelandic
Ð
Ñ
Ñ
CapitalN,tilde
Ñ
Ò
Ò
CapitalO,graveaccent
Ò
Ó
Ó
CapitalO,acuteaccent
Ó
Ô
Ô
CapitalO,circumflexaccent
Ô
Õ
Õ
CapitalO,tilde
Õ
Ö
Ö
CapitalO,umlaut(dierisis)
Ö
×
×
Multiplysign
×
Ø
Ø
CapitalO,slash
Ø
Ù
Ù
CapitalU,graveaccent
Ù
Ú
Ú
CapitalU,acuteaccent
Ú
Û
Û
CapitalU,circumflexaccent
Û
Ü
Ü
CapitalU,umlaut(dierisis)
Ü
Ý
Ý
CapitalY,acuteaccent
Ý
Þ
Þ
CapitalThorn,Icelandic
Þ
ß
ß
Smallsharps,German(szligature)
ß
à
à
Smalla,graveaccent
à
á
á
Smalla,acuteaccent
á
â
â
Smalla,circumflexaccent
â
ã
ã
Smalla,tilde
ã
&aUML;
ä
Smalla,umlaut(dierisis)
ä
å
å
Smalla,ring
å
æ
æ
Smallaedipthong(ligature)
æ
ç
ç
Smallc,cedilla
ç
è
è
Smalle,graveaccent
è
é
é
Smalle,acuteaccent
é
ê
ê
Smalle,circumflexaccent
ê
ë
ë
Smalle,umlaut(dierisis)
ë
ì
ì
Smalli,graveaccent
ì
í
í
Smalli,acuteaccent
í
î
î
Smalli,circumflexaccent
î
ï
ï
Smalli,umlaut(dierisis)
ï
ð
ð
Smalleth,Icelandic
ð
ñ
ñ
Smalln,tilde
ñ
ò
ò
Smallo,graveaccent
òò
ó
ó
Smallo,acuteaccent
ó
ô
ô
Smallo,circumflexaccent
ô
õ
õ
Smallo,tilde
õ
ö
ö
Smallo,umlaut(dierisis)
ö
÷
÷
Divisionsign
÷
ø
ø
Smallo,slash
ø
ù
ù
Smallu,graveaccent
ù
ú
ú
Smallu,acuteaccent
ú
û
û
Smallu,circumflexaccent
û
ü
ü
Smallu,umlaut(dierisis)
ü
ý
ý
Smally,acuteaccent
ý
þ
þ
Smallthorn,Icelandic
þ
ÿ
ÿ
Smally,umlaut(dierisis)
ÿ
根据上表,我们来看2个应用实例:
© 2000 Some Co., Inc.:用©表示版权标识信息。
© 2000 Some Co., Inc.:用©同样标识版权标识信息。
对不被信任的数据进行编码要优于过滤不被信任的数据。在客户端浏览器需要显示一些特殊字符的情况下,这种处理方式会恢复特殊字符的庐山真面目。当然,对所有不被信任的数据进行编码,是个相当耗费资源的工作。根据需要,Web开发者可以在编码和过滤2种方法中进行权衡,选择一种或者混合使用。
该文章转载自1024k:http://www.1024k.cn/web/2007/200701/15407.html
posted @
2007-07-18 18:50 jacksontoto 阅读(207) |
评论 (0) |
编辑 收藏
第二步:鉴别特殊的字符
什么是特殊字符?HTML定义如下:特殊字符就是那些能够影响页面显示效果的字符。依据上下文的不同,特殊字符也会有所不同。下面我们来分类看看:
● 在块级别元素所包含的内容中应考虑的特殊字符有:
<:引入一个标记
&:引入一个字符实体
>:结束一个标记
● 在属性值中应考虑的特殊字符有:
":在以双引号包裹属性值的情况下,"标记了属性值的结尾。
':在以单引号包裹属性值的情况下,'标记了属性值的结尾。
空白字符:在属性值没有被任何引号包裹的情况下,空白字符标记了属性值的结尾,比如空格、tab。
&:当需要在属性值中引入字符实体时,就需要使用&。
● 搜索引擎系统会在搜索结果页面中包含一个再次运行搜索的链接,这个链接中会包含编码过的搜索查询字符串。这种情况下应考虑的特殊字符有:
空格、tab以及换行符:它们标记了URL的结尾。
&:它标记一个字符实体,或者一个独立的CGI参数。
非ASCII字符:就是ISO-8859-1编码中ASCII码大于128的字符,它们不允许在URL中使用。
%:无论服务器对由escape编码的HTTP参数如何解码,都必须过滤出字符%。
● 在 之间的内容中应考虑的特殊字符有:分号,圆括号,大括号以及换行符。
● 在服务器端脚本中应考虑的特殊字符有:!
● 其他情况下应考虑的特殊字符有:=。但注意,现有的攻击事件还没有利用过这个字符,但作为一个全面考虑,这里还是列出来。
另外,我们还要重视一种情况:其他附加字符也可能包含在特殊字符列表中。总之,Web开发者必须对应用程序的输入内容进行检查,以确定哪些字符会影响程序的执行。
该文章转载自1024k:http://www.1024k.cn/web/2007/200701/15408.html
posted @
2007-07-18 18:49 jacksontoto 阅读(207) |
评论 (0) |
编辑 收藏
在各种Internet攻击行为中,通过Web方式侵入系统造成信息泄漏、数据丢失的事件非常普遍。例如,攻击者在页面表单中输入恶意内容,绕过输入检查,攻击系统。为此,Web开发者应采取有效的措施从信息采集的入口处堵截恶意内容的进入。本文将对这方面的问题进行分析,并提供几种应对方法。
问题分析
Web页面包含文本和HTML标记,它们由服务器建立,被客户端解释。HTML标记一般被服务器特殊对待。例如,“<”一般指示一个HTML标记的开始,“<P>”可以影响页面的显示格式,<Script>可以将脚本代码引入浏览器而执行。
对于静态页面,服务器可以完全控制它在客户端如何解释。但是对于动态页面,服务器就不可能完全控制它在客户端的解释行为了。这样就产生了问题:如果动态页面中包含了不可信的内容,那么无论是服务器端还是客户端,就不能保证是否会发生安全问题。
现在,几乎所有的商用Web服务器就会建立动态页面。最典型的一个例子就是我们经常要使用的搜索引擎,它接受用户的查询内容后,搜索数据库,然后将动态内容写入一个页面模板,最后显示给用户包含搜索结果的页面。这种情况下,检查动态内容是否包含了特殊字符就非常重要,例如“<”。如果包含了特殊字符,用户端的浏览器就可能将之误解为HTML标记或者引入执行程序,而不是当做文本信息显示出来。危险也就产生于此!如果不对动态页面进行特殊字符的检查,那么攻击者就有可能在交互页面的输入表单中写入些特殊字符串,从而导致输出页面执行非法行为。这种例子很多,比如我们编写一个留言簿,却不对输入内容进行特殊字符的校验,那么攻击者就有可能填写特殊字符,最终导致留言簿页面的非正常工作,例如填写一段恶意代码:死循环JavaScript脚本、重复打开窗口的JavaScript脚本。
应对措施分析
通常,不被信任的内容主要来自以下几个方面:URL参数,表单输入元素,Cookies和数据库查询。要减轻这些方面可能导致的攻击,建议采取如下的步骤:
1、为每个由服务器产生的Web页面明确地设置字符集编码
2、鉴别特殊的字符
3、对动态输出内容编码
4、过滤动态输出内容中的特殊字符
5、检查cookies 值
以下详细分析这5个步骤。
第一步:明确地设置字符集编码
字符集编码就是页面的字符编码体系,在浏览器中可以通过“查看/编码”来转换:
很多Web页面都省略了字符集编码设置,也就是说在页面源代码头部HTTP一节中没有定义charset参数。早期的HTML版本中,如果没有定义charset参数,字符集编码就默认为ISO-8859-1。但实际上,许多浏览器都有各自的默认字符集编码。因此,HTML版本4规定,如果没有指定charset参数,任何可能的字符集编码都可以使用,这就依赖于用户的浏览器种类了。
如果Web服务器不能指定使用哪个字符集编码,那么它就不能区分出特殊字符。没有指定字符集编码的Web页面之所以可以在大多数时间中工作良好,这是因为在大多数的字符集编码类别中,同一字符对应一个小于128的字节值。对于大于128的特殊字符,例如“<”,将采用16位字符编码方案处理。一些浏览器能够识别并执行这种编码方案,但同时,攻击者也可能据此使用恶意脚本,使防范难度加大,因为服务器可能完全不能了解哪个字节代表哪个特殊字符。例如,字符集UTF-7为“<”和“>”提供了可选编码,几种流行的浏览器一般将它们看做标记的起始和结束字符。为了不造成服务器和客户端的字符编码的不一致,Web服务器应该明确设置字符集,以确认插入的数据是否为特殊字符编码的后续字节。比如,下面的代码强行设置了页面使用ISO-8859-1字符集编码:
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<TITLE>HTML SAMPLE</TITLE>
</HEAD>
<BODY>
<P>This is a sample HTML page
</BODY>
</HTML>
该文章转载自1024k:http://www.1024k.cn/web/2007/200701/15409.html
posted @
2007-07-18 18:49 jacksontoto 阅读(225) |
评论 (0) |
编辑 收藏
本来以为上一次的配置就搞定了,结果本地测试好好的,到了服务器上调试就完蛋了,本地只测试了一个ASP站和一个JSP站,而实际情况是多个asp站和jsp站,又试了两次还是不行,终于在第三次尝试后搞定了,写下来做个纪念。
第一次尝试使用:
<VirtualHost *:80>
ServerAdmin feifei0658@sina.com
ServerName www.5hope.com
DcumentRoot "G:\5hope
DirectoryIndex index.html index.htm index.asp
ProxyPass / http://www.5hope.com:88/
ProxyPassReverse / www.5hope.com:88/
</VirtualHost>
<VirtualHost *:80>
ServerAdmin feifei0658@sina.com
ServerName www.shundabanjia.com
DocumentRoot "G:\wuyubing\www"
DirectoryIndex index.html index.htm index.asp
ProxyPass / http://www.shundabanjia.com:88/
ProxyPassReverse / http://www.shundabanjia.com:88/
</VirtualHost>
本以为这样设置多站点就搞定了,结果发现只识别第一个站点,访问别的站点都是这个站的内容,折腾了一上午,没成功。
第二次尝试使用:
<VirtualHost *:80>
#添加了这个属性**********
ProxyPreserveHost On
ServerAdmin feifei0658@sina.com
ServerName www.shundabanjia.com
DocumentRoot "G:\wuyubing\www"
DirectoryIndex index.html index.htm index.asp
ProxyPass / http://www.shundabanjia.com:88/
ProxyPassReverse / http://www.shundabanjia.com:88/
</VirtualHost>
LoadModule jk_module modules/mod_jk.so
JkWorkersFile "D:\tomcat5.0.28\conf\workers.properties"
<VirtualHost *:80>
ServerAdmin feifei0658@sina.com
ServerName www.openria.cn
DirectoryIndex index.html index.htm index.jsp
JkMount /* ajp13
JkAutoAlias "D:\tomcat-5.0.28\Webapps\ria"
<Directory "D:\tomcat-5.0.28\webapps\ria">
Options Indexes FollowSymLinks
allow from all
</Directory>
</VirtualHost>
这回经过查官方资料,发现了一个属性,叫ProxyPreserveHost On,试了一下,是可以用实现多个虚拟的asp站点了,但是和我的tomcat站点定义冲突,访问不了jsp站,又不行,只好再找。
第三次尝试使用:
NameVirtualHost *:80
<VirtualHost *:80>
ProxyPreserveHost On
ServerAdmin feifei0658@sina.com
ServerName www.shundabanjia.com
DocumentRoot "G:\wuyubing\www"
DirectoryIndex index.html index.htm index.asp
ProxyPass / http://www.shundabanjia.com:88/
ProxyPassReverse / http://www.shundabanjia.com:88/
</VirtualHost>
LoadModule jk_module modules/mod_jk.so
JkWorkersFile "D:\tomcat5.0.28\conf\workers.properties"
<VirtualHost *:80>
ServerAdmin feifei0658@sina.com
ServerName www.openria.cn
DirectoryIndex index.html index.htm index.jsp
JkMount /* ajp13
JkAutoAlias "D:\tomcat-5.0.28\webapps\ria"
<Directory "D:\tomcat-5.0.28\webapps\ria">
Options Indexes FollowSymLinks
allow from all
</Directory>
</VirtualHost>
经过反复看文档,这回终于搞定了,原来是没有吧"Use name-based virtual hosting."打开,去掉NameVirtualHost *:80前面的#号就可以了,真是晕啊。
总算成功了,看来有问题还需要看官方资料,网友的资料还是不完整啊,通过自己的努力,发现新的线索:
ProxyPreserveHost On
NameVirtualHost *:80
这也是自己的收获啊,希望这些经历能帮助需要他的人。
再次庆祝一下,自己的网站终于要开通了,欢迎访问:www.openria.cn
该文章转载自1024k:http://www.1024k.cn/web/2007/200701/15431.html
posted @
2007-07-18 18:46 jacksontoto 阅读(361) |
评论 (0) |
编辑 收藏