??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲欧洲自拍,国产高清亚洲,97精品97http://www.aygfsteel.com/wyz191/category/19203.html走向一条通往JAVA的不归\...zh-cnThu, 22 Mar 2007 10:16:28 GMTThu, 22 Mar 2007 10:16:28 GMT60Java中日期的使用Ҏ(gu)http://www.aygfsteel.com/wyz191/articles/105161.htmljava_蝈蝈java_蝈蝈Wed, 21 Mar 2007 01:57:00 GMThttp://www.aygfsteel.com/wyz191/articles/105161.htmlhttp://www.aygfsteel.com/wyz191/comments/105161.htmlhttp://www.aygfsteel.com/wyz191/articles/105161.html#Feedback0http://www.aygfsteel.com/wyz191/comments/commentRss/105161.htmlhttp://www.aygfsteel.com/wyz191/services/trackbacks/105161.html1、?tng)DateQ具体类java.util.Date (tng)Q?br />2、?tng)Calendar:抽象cjava.text.DateFormat,它派生的一个子cMؓ(f)java.text.SimpleDateFormat (tng)
3、?tng)DateFormat:抽象cjava.util.CalendarQ它z的一个子cMؓ(f)java.util.GregorianCalendar (tng)
Q注Q如果有朋友对具体类和抽象类不了(jin)解,可以参考相关Java资料Q?br />
现在对以上三个类q行如下分析Q?br />
一、对Datecȝ分析 (tng)

Date (tng)cMJDK (tng)1.0开始进化, (tng)当时它只包含?jin)几个简单的处理日期数据的方法。?tng)由于这些方法实用性差Q现在基本上被CalendarcM各方法所代替?jin)。这U改q目的是Z(jin)更好的处理日期数据国际化格式。?tng)Date (tng)cd际上只是一个包裹类, (tng)它包含一个长整型数据, (tng)表示的是从GMT(格林治标准旉)1970q? (tng)1 (tng)月??0:00:00q一M前或者是之后l历的毫U数. (tng)

Z(jin)加深对Datecȝ理解Q列丑֦下一个简单例子来说明Date的用:(x) (tng)
import (tng)java.util.Date; (tng)
public (tng)class (tng)DateTest1 (tng){ (tng)
public (tng)static (tng)void (tng)main(String[] (tng)args) (tng){ (tng)
/** (tng)Get (tng)the (tng)system (tng)Date (tng)**/ (tng)
Date (tng)date (tng)= (tng)new (tng)Date(); (tng)
System.out.println(date.getTime()); (tng)
} (tng)
} (tng)
pȝ输出如下l果Q?br />1001803809710 (tng)

在这个例子中,值得我们注意的是我们使用?jin)Date (tng)构造函数创Z个日期对? (tng)在没有Q何参数的情况下,q个构造函C(x)自动调用System.currentTimeMillis() (tng)Ҏ(gu)来获取当前系l日?。?br />

二、对DateFormatcȝ分析 (tng)

如果我们希望定制日期数据的格? (tng)比如昄的日期格式ؓ(f)Q?006q?6?3日,抽象cjava.util.Calendar和它的子cjava.util.GregorianCalendar能完成这一功能。?br />下面的例子展CZ(jin)如何完成q个工作: (tng)
import (tng)java.util.SimpleDateFormat; (tng)
import (tng)java.util.Date; (tng)
public (tng)class (tng)DateTest2 (tng){ (tng)
public (tng)static (tng)void (tng)main(String[] (tng)args) (tng){ (tng)

SimpleDateFormat (tng)format (tng)= (tng)new (tng)SimpleDateFormat("yyyyqMM月dd?,Locale.US); (tng)
Date (tng)date (tng)= (tng)new (tng)Date(); (tng)
System.out.println(bartDateFormat.format(date)); (tng)
} (tng)
} (tng)

只要通过向SimpleDateFormat (tng)的构造函C递格式字W串" (tng)yyyyqMM月dd?, (tng)我们可以指明自己想要的格式. (tng)其中yyyy是年QMM是月, (tng)dd是日. (tng)字符的个数决定了(jin)日期是如何格式化的,如果格式?yyyyqMM月dd?׃(x)昄 (tng)06q?6?3日;如果?yy-MM-dd"显C?6-06-23。?br />
三、对Calendar (tng)cȝ分析 (tng)

如果惌|、获取、操U一个日期对象的各个特定部分Q比如获得小? (tng)? (tng)分钟、计一个月的某一天说星期几等{。这L(fng)情况需要抽象类java.util.Calendar和它的子cL处理。ؓ(f)?jin)能清楚地说明问题,列D下面的例? (tng)它的功能是计第十个星期五是13? (tng)

import (tng)java.util.GregorianCalendar; (tng)
import (tng)java.util.Date; (tng)
import (tng)java.text.DateFormat; (tng)
public (tng)class (tng)CalendarTest{ (tng)

public (tng)static (tng)void (tng)main(String[] (tng)args) (tng){ (tng)
DateFormat (tng)dateFormat (tng)= (tng)DateFormat.getDateInstance(DateFormat.FULL); (tng)
GregorianCalendar (tng)cal (tng)= (tng)new (tng)GregorianCalendar(); (tng)

/** (tng)Set (tng)the (tng)date (tng)and (tng)time (tng)of (tng)our (tng)calendar (tng)to (tng)the (tng)system&s (tng)date (tng)and (tng)time (tng)**/ (tng)
cal.setTime(new (tng)Date()); (tng)
System.out.println("System (tng)Date: (tng)" (tng)+ (tng)dateFormat.format(cal.getTime())); (tng)

/** (tng)Set (tng)the (tng)day (tng)of (tng)week (tng)to (tng)FRIDAY (tng)**/ (tng)
cal.set(GregorianCalendar.DAY_OF_WEEK, (tng)GregorianCalendar.FRIDAY); (tng)
System.out.println("After (tng)Setting (tng)Day (tng)of (tng)Week (tng)to (tng)Friday: (tng)" (tng)+ (tng)
dateFormat.format(cal.getTime())); (tng)

int (tng)friday13Counter (tng)= (tng)0; (tng)
while (tng)(friday13Counter (tng)<= (tng)10) (tng){ (tng)

/** (tng)Go (tng)to (tng)the (tng)next (tng)Friday (tng)by (tng)adding (tng)7 (tng)days. (tng)**/ (tng)
cal.add(GregorianCalendar.DAY_OF_MONTH, (tng)7); (tng)

/** (tng)I(yng)f (tng)the (tng)day (tng)of (tng)month (tng)is (tng)13 (tng)we (tng)have (tng)another (tng)Friday (tng)the (tng)13th. (tng)**/ (tng)
if (tng)(cal.get(GregorianCalendar.DAY_OF_MONTH) (tng)== (tng)13) (tng){ (tng)
friday13Counter++; (tng)
System.out.println(dateFormat.format(cal.getTime())); (tng)
} (tng)
} (tng)
} (tng)
} (tng)
输出l果? (tng)
System (tng)Date: (tng)Saturday, (tng)September (tng)29, (tng)2005 (tng)


四、ȝ (tng)

在Java通过一下三个类的用,一般可以满_UŞ式的日期使用。实际上QJava中日期用的Ҏ(gu)q有很多Q如果有兴趣的朋友请参考JDK帮助手册。?br />http://www.javaresearch.org/article/55424.htm

java_蝈蝈 2007-03-21 09:57 发表评论
]]>
JDBC2/3.0的特征点?http://www.aygfsteel.com/wyz191/articles/jdbc.htmljava_蝈蝈java_蝈蝈Mon, 05 Feb 2007 06:38:00 GMThttp://www.aygfsteel.com/wyz191/articles/jdbc.htmlhttp://www.aygfsteel.com/wyz191/comments/97998.htmlhttp://www.aygfsteel.com/wyz191/articles/jdbc.html#Feedback0http://www.aygfsteel.com/wyz191/comments/commentRss/97998.htmlhttp://www.aygfsteel.com/wyz191/services/trackbacks/97998.html
Statement (tng)stmt (tng)= (tng)con.createStatement();
ResultSet (tng)rs (tng)= (tng)stmt.executeQuery("SELECT (tng)* (tng)FROM (tng)user (tng)WHERE (tng)username='aa'");
stmt.executeUpdate("UPDATE (tng)user (tng)SET (tng)lastdatetime=now() (tng)where (tng)username='aa'"); (tng)

q是一个用L(fng)录时Q经常用到的代码Q先是根据用户名aa查找该用L(fng)详细信息Q然后再更新该用L(fng)最后登录时_(d)lastdatetimeQ。这q个里面Q我们用?jin)两个sql语句Q这个是我一直用的方法,但是如果用JDBC2.0l我们提供的便利Q我们只要写一条sql够?jin),其他的都交给jdbcQ看下面的代码:(x) (tng)

Statement (tng)stmt2 (tng)= (tng)con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
ResultSet (tng)rs2 (tng)= (tng)stmt.executeQuery("SELECT (tng)* (tng)FROM (tng)user (tng)WHERE (tng)username='aa'");
rs2.next();
rs2.updateDate("lastdatetime", (tng)new (tng)Date(Calendar.getInstance().getTimeInMillis()));
rs2.updateRow(); (tng)

q里面最主要的特征就是ResultSet.TYPE_FORWARD_ONLY和ResultSet.CONCUR_UPDATABLEQ通过初始化Statement时传不同的参敎ͼ可以对ResultSetq行不用的错作限制。con.createStatement的时候,有三U可以掉用的函数Q?

1、createStatement();
2、createStatement(int (tng)resultSetType, (tng)int (tng)resultSetConcurrency)
3、createStatement(int (tng)resultSetType, (tng)int (tng)resultSetConcurrency, (tng)int (tng)resultSetHoldability) (tng)

其中resultSetType可选值是Q?
 (tng) (tng) (tng)1、ResultSet.TYPE_FORWARD_ONLY (tng) (tng)在ResultSet中只能先前移动游标,
 (tng) (tng) (tng)2、ResultSet.TYPE_SCROLL_INSENSITIVE (tng)在ResultSet中可以随?j)所Ʋ的先前向后Ud游标Q?
 (tng) (tng) (tng)3、ResultSet.TYPE_SCROLL_SENSITIVE (tng)在ResultSet中可以随?j)所Ʋ的先前向后Ud游标Q同时ResultSet的值有所改变的时候,他可以得到改变后的最新的?
其中resultSetConcurrency可选值是Q?
 (tng) (tng) (tng)1、ResultSet.CONCUR_READ_ONLY (tng) (tng)在ResultSet中的数据记录是只ȝQ可以修?
 (tng) (tng) (tng)2、ResultSet.CONCUR_UPDATABLE (tng) (tng)在ResultSet中的数据记录可以L修改Q然后更C(x)数据?
其中resultSetHoldability可选值是Q?
 (tng) (tng) (tng)1、ResultSet.HOLD_CURSORS_OVER_COMMIT (tng)表示修改提交?不关闭ResultSet的游?
 (tng) (tng) (tng)2、ResultSet.CLOSE_CURSORS_AT_COMMIT (tng) (tng)表示修改提交?关闭ResultSet的游标?

对于查询操作W一U初始化Ҏ(gu)createStatement()Q相当于W二U方法的createStatement(ResultSet.TYPE_FORWARD_ONLY, (tng)ResultSet.CONCUR_READ_ONLY)Q第三种Ҏ(gu)的createStatement(ResultSet.TYPE_FORWARD_ONLY, (tng)ResultSet.CONCUR_READ_ONLY, (tng)ResultSet.CLOSE_CURSORS_AT_COMMIT) (tng)

下面写一Ddemo的代码,我把一些特征函数都用出来,但是只是用来查考和说明名灵zL的。?

 (tng)Statement (tng)stmt2 (tng)= (tng)con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
 (tng)ResultSet (tng)rs2 (tng)= (tng)stmt.executeQuery("SELECT (tng)* (tng)FROM (tng)user");
 (tng)rs2.next();
 (tng)rs2.updateDate("lastdatetime", (tng)new (tng)Date(Calendar.getInstance().getTimeInMillis()));
 (tng)rs2.updateRow();
 (tng)rs2.afterLast();
 (tng)while(rs2.previous()){ (tng)/**....*/ (tng)}
 (tng)rs.beforeFirst();
 (tng)while(rs2.next()){ (tng) (tng)/**....*/ (tng)}
 (tng)rs.last();
 (tng)rs.first();
 (tng)rs.absolute(5); (tng)//游标Ud到第5?
 (tng)rs.absolute(-1); (tng) (tng)//游标Ud到最后一?
 (tng)rs.relative(-5); (tng) (tng)//游标向上Ud5?
 (tng)rs.relative(2); (tng) (tng) (tng)//游标向下Ud2?
 (tng)rs.deleteRow(); (tng)//删除当前?
 (tng)rs.last(); (tng) (tng)//游标Ud到最?
 (tng)rs.updateString("summary", (tng)"This (tng)is (tng)..."); (tng)//讄更新的字D?
 (tng)rs.cancelRowUpdates(); (tng) (tng)//取消刚才输入的更?
 (tng)rs.getRow(); (tng)//得到当前行号
 (tng)rs.moveToInsertRow(); (tng) (tng)//游标Ud到要新增的那条记录上
 (tng)rs.updateInt("id", (tng)1);
 (tng)rs.updateString(2, (tng)"my (tng)name");
 (tng)rs.insertRow(); (tng)//插入新记录?


JDBC2.0提供的还有一个功能就是数据库的批量操作:(x) (tng)

 (tng) (tng)con.setAutoCommit(false);
 (tng) (tng)Statement (tng)stmt3 (tng)= (tng)con.createStatement();
 (tng) (tng)stmt3.addBatch("insert (tng).....");
 (tng) (tng)stmt3.addBatch("insert (tng).....");
 (tng) (tng)int[] (tng)rows (tng)= (tng)stmt3.executeBatch();
 (tng) (tng)con.commit(); (tng)

但是有一点要注意Qstmt3.executeBatch()他不?x)自动给你回滚数据操作,当你?条update语句的时候,如果W三条发生错误,那么无法自动回滚前两条update语句的媄(jing)响,所以一定要自己手工q行事务理。?

在?zhn)的事务中使用?tng)Savepoint (tng)
JDBC3.0中最令h兴奋的附加特点就是?tng)Savepoint (tng)?jin)。有时候需要的是对事务多一点的控制Q而不是在当前的事务中单地Ҏ(gu)一个改变进行回滚。在JDBC3.0下,(zhn)就可以通过 (tng)Savepoint (tng)获得q种控制。Savepoint (tng)接口允许(zhn)将事务分割为各个逻辑断点Q以控制有多事务需要回滚。看下面的代码:(x) (tng)

conn.setAutoCommit(false); (tng)
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); (tng)
Statement (tng)stmt (tng)= (tng)conn.createStatement(); (tng)
int (tng)rows (tng)= (tng)stmt.executeUpdate( (tng)"INSERT (tng)I(yng)NTO (tng)authors (tng)(first_name, (tng)last_name) (tng)valueS(′Lewis? (tng)′Carroll?"); (tng)
Savepoint (tng)svpt (tng)= (tng)conn.setSavepoint("NewAuthor"); (tng)
try{
 (tng)rows (tng)= (tng)stmt.executeUpdate( (tng)"UPDATE (tng)authors (tng)set (tng)type (tng)= (tng)′fiction′?tng)WHERE (tng)last_name (tng)= (tng)′Carroll?); (tng)
}catch(Exception (tng)e){
 (tng)conn.rollback(svpt);
 (tng)rows (tng)= (tng)stmt.executeUpdate( (tng)" (tng)update (tng).......... (tng)other (tng)sql (tng)");
}
conn.commit(); (tng)

上面代码昄Q当UPDATE (tng)authorsp|的时候,pȝ事务回滚UPDATE (tng)authors的sql的媄(jing)响,而INSERT (tng)I(yng)NTO (tng)authors的sql仍然有效 (tng)


(g)索自动生的关键字?/b> (tng)
Z(jin)解决对获取自动生的或自动增加的关键字的值的需求,JDBC (tng)3.0现在获取这U值变得很L。要定M所产生的关键字的|只要单地在语句的 (tng)execute() (tng)Ҏ(gu)中指定一个可选的标记QStatement.RETURN_GENERATED_KEYS和Statement.NO_GENERATED_KEYS。在执行q条语句后,所产生的关键字的值就?x)通过从?tng)Statement (tng)的实例方法?tng)getGeneratedKeys() (tng)来检索?tng)ResultSet (tng)而获得。ResultSet (tng)包含?jin)每个所产生的关键字的列。看下面代码Q?

Statement (tng)stmt (tng)= (tng)conn.createStatement(); (tng)
stmt.executeUpdate("INSERT (tng)I(yng)NTO (tng)authors (tng)(first_name, (tng)last_name) (tng)valueS (tng)(′George? (tng)′Orwell?", (tng)Statement.RETURN_GENERATED_KEYS); (tng)
ResultSet (tng)rs (tng)= (tng)stmt.getGeneratedKeys(); (tng)
if (tng)( (tng)rs.next() (tng)) (tng){ (tng)
 (tng)int (tng)key (tng)= (tng)rs.getInt(); (tng)
}

http://www.netskycn.com/article/articleId2913.html

java_蝈蝈 2007-02-05 14:38 发表评论
]]>
基本的类装入异常 http://www.aygfsteel.com/wyz191/articles/97908.htmljava_蝈蝈java_蝈蝈Mon, 05 Feb 2007 00:29:00 GMThttp://www.aygfsteel.com/wyz191/articles/97908.htmlhttp://www.aygfsteel.com/wyz191/comments/97908.htmlhttp://www.aygfsteel.com/wyz191/articles/97908.html#Feedback0http://www.aygfsteel.com/wyz191/comments/commentRss/97908.htmlhttp://www.aygfsteel.com/wyz191/services/trackbacks/97908.html (tng) (tng) (tng) 下面的几U异常是比较常见的:(x)
ClassNotFoundException
 (tng) (tng) (tng) ClassNotFoundException 是最常见的类装入异常cd。它发生在装入阶Dc(din)Java 规范?ClassNotFoundException 的描q是q样的:(x)
 (tng) (tng) (tng) 当应用程序试N过cȝ字符串名Uͼ使用以下三种Ҏ(gu)装入c,但却找不到指定名U的cd义时抛出该异常?br /> (tng) (tng) (tng) * c?Class 中的 forName() Ҏ(gu)?br /> (tng) (tng) (tng) * c?ClassLoader 中的 findSystemClass() Ҏ(gu)?br /> (tng) (tng) (tng) * c?ClassLoader 中的 loadClass() Ҏ(gu)?br /> (tng) (tng) (tng) 所以,如果昑ּ地装入类的尝试失败,那么抛?ClassNotFoundException?br /> (tng) (tng) (tng) q些异常修复h通常比较单。可以用 (tng) verbose 选项(g)查类路径Q确保用的c\径设|正。如果类路径讄正确Q但是仍然看到这个错误,那么是需要的cdc\径中不存在。要修复q个问题Q可以把cȝ动到c\径中指定的目录或 JAR 文g中,或者把cL在的位置d到类路径中?br />
NoClassDefFoundError
 (tng) (tng) (tng) NoClassDefFoundError 是类装入器在装入阶段抛出的另一个常见异常。JVM 规范?NoClassDefFoundError 的定义如下:(x)
 (tng) (tng) (tng) 如果 Java 虚拟机或 ClassLoader 实例试图装入cd义(作ؓ(f)正常的方法调用的一部分Q或者作Z?new 表达式创建新实例的一部分Q,但却没有扑ֈcd义时抛出该异常?br /> (tng) (tng) (tng) 当目前执行的cdl编译,但是找不到它的定义时Q会(x)存在 searched-for cd义?
 (tng) (tng) (tng) 实际上,q意味着 NoClassDefFoundError 的抛出,是不成功的隐式类装入的结果?br /> (tng) (tng) (tng) 单说来,是引用的类在类路径中没有找到?br />ClassCastException
 (tng) (tng) (tng) c装入器能够抛出的另一个异常是 ClassCastException。它是在cd比较中发C兼容cd的时候抛出的。JVM 规范指定 ClassCastException 是:(x)
 (tng) (tng) (tng) 该异常的抛出Q表明代码企图把对象的类型{换成一个子c,而该对象q不是这个子cȝ实例?
UnsatisfiedLinkError
 (tng) (tng) (tng) 在把本地Ҏ(gu)调用链接到对应的本机定义Ӟc装入器扮演着重要角色。如果程序试图装入一个不存在或者放错的本机库时Q在链接阶段的解析过E会(x)发生 UnsatisfiedLinkError。JVM 规范指定 UnsatisfiedLinkError 是:(x)
 (tng) (tng) (tng) 对于声明?native 的方法,如果 Java 虚拟机找不到和它对应的本a定义Q就?x)抛(gu)异常?
 (tng) (tng) (tng) 当调用本机方法时Q类装入器会(x)试装入定义?jin)该?gu)的本机库。如果找不到q个库,׃(x)抛出q个错误?br /> (tng) (tng) (tng) 本机库的装入p?System.loadLibrary() Ҏ(gu)的类的类装入器启?Q根据用的c装入器Q会(x)搜烦(ch)不同的位|:(x)
 (tng) (tng) (tng) * 对于?bootstrap c装入器装入的类Q搜?sun.boot.library.path?br /> (tng) (tng) (tng) * 对于由扩展类装入器装入的c,先搜?java.ext.dirsQ然后是 sun.boot.library.pathQ然后是 java.library.path?br /> (tng) (tng) (tng) * 对于ql类装入器装入的c,搜烦(ch) sun.boot.library.pathQ然后是 java.library.path?br />ClassCircularityError
 (tng) (tng) (tng) JVM 规范指定 ClassCircularityError 的抛出条件是Q?br /> (tng) (tng) (tng) cL接口׃是自q类或超接口而不能被装入?
 (tng) (tng) (tng) q个错误是在链接阶段的解析过E中抛出的。这个错误有点奇怪,因ؓ(f) Java ~译器不允许发生q种循环情况。但是,如果独立地编译类Q然后再把它们放在一P可能发生这个错误?br />ClassFormatError
JVM 规范指出Q抛?ClassFormatError 的条件是Q?br /> (tng) (tng) (tng) 负责指定所h的编译类或接口的二进制数据Ş式有误?
 (tng) (tng) (tng) q个异常是在c装入的链接阶段的校验过E中抛出。如果字节码发生?jin)更改,例如ȝ本号或次版本号发生?jin)更改Q那么二q制数据的Ş式就?x)有误。例如,如果对字节码故意做了(jin)更改Q或者在通过|络传送类文g时现Z(jin)错误Q那么就可能发生q个异常?br /> (tng) (tng) (tng) 修复q个问题的惟一Ҏ(gu)是获得字节码的正确副本Q可能需要重新进行编译?br />ExceptionInInitializerError
Ҏ(gu) JVM 规范Q抛?ExceptionInInitializer 的情冉|Q?br /> (tng) (tng) (tng) * 如果初始化器H然完成Q抛Z些异?EQ而且 E 的类不是 Error 或者它的某个子c,那么׃(x)创徏 ExceptionInInitializerError cȝ一个新实例Qƈ?E 作ؓ(f)参数Q用q个实例代替 E?br /> (tng) (tng) (tng) * 如果 Java 虚拟囑ֈ建类 ExceptionInInitializerError 的新实例Q但是因为出?Out-Of-Memory-Error 而无法创建新实例Q那么就抛出 OutOfMemoryError 对象作ؓ(f)代替?br />http://www.aygfsteel.com/zyl/archive/2007/02/04/97881.html

java_蝈蝈 2007-02-05 08:29 发表评论
]]>
又谈q问题解决[转]http://www.aygfsteel.com/wyz191/articles/95671.htmljava_蝈蝈java_蝈蝈Wed, 24 Jan 2007 02:00:00 GMThttp://www.aygfsteel.com/wyz191/articles/95671.htmlhttp://www.aygfsteel.com/wyz191/comments/95671.htmlhttp://www.aygfsteel.com/wyz191/articles/95671.html#Feedback0http://www.aygfsteel.com/wyz191/comments/commentRss/95671.htmlhttp://www.aygfsteel.com/wyz191/services/trackbacks/95671.html有h_(d)q问题?sh)直跟中国的程序员特别有缘Q真是再同意不过?jin),不管是StrutsQJSFQJSPQ还是MySQLQTomcatQ全都或多或有q的问题?br />一般的做法有用FilterQ?

 (tng)< filter >
 (tng) (tng) (tng) (tng) < filter-name > Set Character Encoding </ filter-name >
 (tng) (tng) (tng) (tng) < filter-class > org.springframework.web.filter.CharacterEncodingFilter </ filter-class >
 (tng) (tng) (tng) (tng) < init-param >
 (tng) (tng) (tng) (tng) (tng) (tng) < param-name > encoding </ param-name >
 (tng) (tng) (tng) (tng) (tng) (tng) < param-value > GBK </ param-value >
 (tng) (tng) (tng) (tng) </ init-param >
 (tng) (tng) (tng) (tng) < init-param >
 (tng) (tng) (tng) (tng) (tng) (tng) < param-name > ignore </ param-name >
 (tng) (tng) (tng) (tng) (tng) (tng) < param-value > true </ param-value >
 (tng) (tng) (tng) (tng) </ init-param >
 (tng) (tng) </ filter >
 (tng) (tng) < filter-mapping >
 (tng) (tng) (tng) (tng) < filter-name > Set Character Encoding </ filter-name >
 (tng) (tng) (tng) (tng) < url-pattern > *.do </ url-pattern >
 (tng) (tng) </ filter-mapping >
 (tng) (tng) < filter-mapping >
 (tng) (tng) (tng) (tng) < filter-name > Set Character Encoding </ filter-name >
 (tng) (tng) (tng) (tng) < url-pattern > *.jsp </ url-pattern >
 (tng) (tng) </ filter-mapping >
 (tng) (tng) < filter-mapping >
 (tng) (tng) (tng) (tng) < filter-name > Set Character Encoding </ filter-name >
 (tng) (tng) (tng) (tng) < url-pattern > *.html </ url-pattern >
 (tng) (tng) </ filter-mapping >
 (tng) (tng) < filter-mapping >
 (tng) (tng) (tng) (tng) < filter-name > Set Character Encoding </ filter-name >
 (tng) (tng) (tng) (tng) < url-pattern > *.htm </ url-pattern >
 (tng) (tng) </ filter-mapping >

的,有用


 (tng)<% request.setCharacterEncoding( " GBK " ); %>
的,q有?/p>


 (tng)<% @ page contentType = " text/html; charset=GBK " (tng) pageEncoding = " GBK " %>

<meta http-equiv="content-type" content="text/html; charset=GBK">

?q可以用


 (tng)<% (tng) String name (tng) = (tng) (tng) new (tng) String(request.getParameter( " name " ).getBytes( " 8859_1 " ), (tng) " GB2312 " ); (tng) %>

昨天在做项目的q程中,发现用URL传request参数的时候,在第二个面上得Cؕ码的问题。把上面几种Ҏ(gu)都试?jin)一下还是不行。仔l追t了(jin)一下,发现在页面的源代码上中文是正常的Q一直到URLq是中文正常Q可是在后台的Action里面log出来成?jin)ؕ码?jin)Q于是猜x在request装的过E中把中文变成ؕ码了(jin)Q以致于后台直接是取到的ؕ码。在后台Action中Set入中文,面上正常显C,说明Struts的中文已l不存在问题。剩下的Q应该就只有doGet和doPostҎ(gu)的问题(sh)(jin)。找?jin)一下tomcat的配|文Ӟ发现只要在server.xml中:(x)


 (tng) (tng) (tng) (tng) (tng) <!-- (tng) Define a non-SSL HTTP/1.1 Connector on port 8080 (tng) -->
 (tng) (tng) (tng) (tng) < Connector (tng) port ="8080" (tng) maxHttpHeaderSize ="8192"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) maxThreads ="150" (tng) minSpareThreads ="25" (tng) maxSpareThreads ="75"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) enableLookups ="false" (tng) redirectPort ="8443" (tng) acceptCount ="100"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) connectionTimeout ="20000" (tng) disableUploadTimeout ="true" />
 (tng) (tng) (tng) (tng) <!-- (tng) Note : To disable connection timeouts, set connectionTimeout value
 (tng) (tng) (tng) (tng) to 0 (tng) -->
改ؓ(f)


 (tng) (tng) (tng) (tng) (tng) <!-- (tng) Define a non-SSL HTTP/1.1 Connector on port 8080 (tng) -->
 (tng) (tng) (tng) (tng) < Connector (tng) port ="8080" (tng) maxHttpHeaderSize ="8192"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) maxThreads ="150" (tng) minSpareThreads ="25" (tng) maxSpareThreads ="75"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) enableLookups ="false" (tng) redirectPort ="8443" (tng) acceptCount ="100"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) connectionTimeout ="20000" (tng) disableUploadTimeout ="true" (tng) URIEncoding ="GBK"/>
 (tng) (tng) (tng) (tng) <!-- (tng) Note : To disable connection timeouts, set connectionTimeout value
 (tng) (tng) (tng) (tng) to 0 (tng) -->
是加上URIEncoding="GBK"׃事大吉了(jin)?br />
再加上一条:(x)

<session-factory>
  <property name="hibernate.connection.url">jdbc:jtds:sqlserver://192.168.0.3:1433;DatabaseName=HomeConsume;charset=GBK</property>
  <property name="hibernate.cglib.use_reflection_optimizer">true</property>
  <property name="hibernate.connection.password">sju</property>
  <property name="hibernate.connection.username">sa</property>
  <property name="hibernate.connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
  <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
  <mapping resource="net/magicyang/homeconsume/pojo/Test.hbm.xml" />
  <mapping resource="net/magicyang/homeconsume/pojo/Consumeinfo.hbm.xml" />
  <mapping resource="net/magicyang/homeconsume/pojo/Consumetype.hbm.xml" />
  </session-factory>
xQ应该再困难的ؕ码问题都解决?jin)吧。就是要在页面上、数据库中、request里、doGet、doPostҎ(gu)里面都是中文Q看你还有什么地方躲Q?



java_蝈蝈 2007-01-24 10:00 发表评论
]]>
Java抽象cd接口的区别[转蝲]http://www.aygfsteel.com/wyz191/articles/95209.htmljava_蝈蝈java_蝈蝈Mon, 22 Jan 2007 00:53:00 GMThttp://www.aygfsteel.com/wyz191/articles/95209.htmlhttp://www.aygfsteel.com/wyz191/comments/95209.htmlhttp://www.aygfsteel.com/wyz191/articles/95209.html#Feedback0http://www.aygfsteel.com/wyz191/comments/commentRss/95209.htmlhttp://www.aygfsteel.com/wyz191/services/trackbacks/95209.html abstract (tng)class和interface是Java语言中对于抽象类定义q行支持的两U机Ӟ正是׃q两U机制的存在Q才赋予?jin)Java强大的面向对象能力。abstract (tng)class和interface之间在对于抽象类定义的支持方面具有很大的怼性,甚至可以怺替换Q因此很多开发者在q行抽象cd义时对于abstract (tng)class和interface的选择昑־比较随意。其实,两者之间还是有很大的区别的Q对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意囄理解是否正确、合理。本文将对它们之间的区别q行一番剖析,试图l开发者提供一个在二者之间进行选择的依据。?tng)?br />
理解抽象c?tng)?br />
abstract (tng)class和interface在Java语言中都是用来进行抽象类Q本文中的抽象类q从abstract (tng)class译而来Q它表示的是一个抽象体Q而abstract (tng)class为Java语言中用于定义抽象类的一U方法,误者注意区分)(j)定义的,那么什么是抽象c,使用抽象c能为我们带来什么好处呢Q?tng)?br />
在面向对象的概念中,我们知道所有的对象都是通过cL描绘的,但是反过来却不是q样。ƈ不是所有的c都是用来描l对象的Q如果一个类中没有包含够的信息来描l(sh)个具体的对象Q这L(fng)cd是抽象类。抽象类往往用来表征我们在对问题领域q行分析、设计中得出的抽象概念,是对一pd看上M同,但是本质上相同的具体概念的抽象。比如:(x)如果我们q行一个图形编辑Y件的开发,׃(x)发现问题领域存在着圆、三角Şq样一些具体概念,它们是不同的Q但是它们又都属于Ş状这样一个概念,形状q个概念在问题领域是不存在的Q它?yu)是一个抽象概c(din)正是因为抽象的概念在问题领域没有对应的具体概念Q所以用以表征抽象概늚抽象cL不能够实例化的。?tng)?br />
在面向对象领域,抽象cM要用来进行类型隐藏。我们可以构造出一个固定的一l行为的抽象描述Q但是这l行为却能够有Q意个可能的具体实现方式。这个抽象描q就是抽象类Q而这一lQ意个可能的具体实现则表现为所有可能的zcR模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允怿改的Q同Ӟ通过从这个抽象体zQ也可扩展此模块的行为功能。熟(zhn)OCP的读者一定知道,Z(jin)能够实现面向对象设计的一个最核心(j)的原则OCP(Open-Closed (tng)Principle)Q抽象类是其中的关键所在。?tng)?br />

从语法定义层面看abstract (tng)class和interface (tng) (tng)

在语法层面,Java语言对于abstract (tng)class和interfacel出?jin)不同的定义方式Q下面以定义一个名为Demo的抽象类Z来说明这U不同。?tng)?br />
使用abstract (tng)class的方式定义Demo抽象cȝ方式如下Q?tng)?br />
abstract (tng)class (tng)Demo (tng)?jng) (tng)?br /> (tng)abstract (tng)void (tng)method1(); (tng) (tng)
 (tng)abstract (tng)void (tng)method2(); (tng) (tng)
 (tng)…?tng)?br />}?tng)?br />
使用interface的方式定义Demo抽象cȝ方式如下Q?tng)?br />
interface (tng)Demo (tng){ (tng) (tng)
 (tng)void (tng)method1(); (tng) (tng)
 (tng)void (tng)method2(); (tng) (tng)
 (tng)…?tng)?br />} (tng) (tng)

在abstract (tng)class方式中,Demo可以有自q数据成员Q也可以有非abstarct的成员方法,而在interface方式的实CQDemo只能够有?rn)态的不能被修改的数据成员Q也是必须是static (tng)final的,不过在interface中一般不定义数据成员Q,所有的成员Ҏ(gu)都是abstract的。从某种意义上说Qinterface是一U特DŞ式的abstract (tng)class。?tng)?br />
 (tng) (tng) (tng) (tng) (tng) (tng)从编E的角度来看Qabstract (tng)class和interface都可以用来实?design (tng)by (tng)contract"的思想。但是在具体的用上面还是有一些区别的。?tng)?br />
首先Qabstract (tng)class在Java语言中表C的是一U承关p,一个类只能使用一ơ承关pR但是,一个类却可以实现多个interface。也许,q是Java语言的设计者在考虑Java对于多重l承的支持方面的一U折?sh)考虑吧。?tng)?br />
其次Q在abstract (tng)class的定义中Q我们可以赋予方法的默认行ؓ(f)。但是在interface的定义中Q方法却不能拥有默认行ؓ(f)Qؓ(f)?jin)绕q这个限Ӟ必须使用委托Q但是这?x) (tng)增加一些复杂性,有时?x)造成很大的麻?ch)。?tng)?br />
在抽象类中不能定义默认行存在另一个比较严重的问题Q那是可能?x)造成l护上的ȝ(ch)。因为如果后来想修改cȝ界面Q一般通过abstract (tng)class或者interface来表C)(j)以适应新的情况Q比如,d新的Ҏ(gu)或者给已用的方法中d新的参数Q时Q就?x)非常的ȝ?ch)Q可能要p很多的时_(d)对于zcd多的情况Q尤为如此)(j)。但是如果界面是通过abstract (tng)class来实现的Q那么可能就只需要修改定义在abstract (tng)class中的默认行ؓ(f)可以了(jin)。?tng)?br />
同样Q如果不能在抽象cM定义默认行ؓ(f)Q就?x)导致同L(fng)Ҏ(gu)实现出现在该抽象cȝ每一个派生类中,q反?one (tng)ruleQone (tng)place"原则Q造成代码重复Q同样不利于以后的维护。因此,在abstract (tng)class和interface间进行选择时要非常的小?j)。?tng)?br />

从设计理念层面看abstract (tng)class和interface (tng) (tng)

上面主要从语法定义和~程的角度论qC(jin)abstract (tng)class和interface的区别,q些层面的区别是比较低层ơ的、非本质的。本节从另一个层面:(x)abstract (tng)class和interface所反映出的设计理念Q来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概늚本质所在。?tng)?br />
前面已经提到q,abstarct (tng)class在Java语言中体C(jin)一U承关p,要想使得l承关系合理Q父cdzcM间必d?is (tng)a"关系Q即父类和派生类在概忉|质上应该是相同的Q参考文献?〕中有关?is (tng)a"关系的大幅深入的论qͼ有兴的读者可以参考)(j)。对于interface (tng)来说则不?dng)q不要求interface的实现者和interface定义在概忉|质上是一致的Q仅仅是实现?jin)interface定义的契U而已。ؓ(f)?jin)便于理解Q下面将通过一个简单的实例q行说明。?tng)?br />
考虑q样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Doorh执行两个动作open和closeQ此时我们可以通过abstract (tng)class或者interface来定义一个表C抽象概念的类型,定义方式分别如下所C:(x) (tng) (tng)

使用abstract (tng)class方式定义DoorQ?tng)?br />
abstract (tng)class (tng)Door (tng){ (tng) (tng)
 (tng)abstract (tng)void (tng)open(); (tng) (tng)
 (tng)abstract (tng)void (tng)close()Q?tng)?br />} (tng) (tng)

 (tng) (tng) (tng)
使用interface方式定义DoorQ?tng)?br />

interface (tng)Door (tng){ (tng) (tng)
 (tng)void (tng)open(); (tng) (tng)
 (tng)void (tng)close(); (tng) (tng)
} (tng) (tng)

 (tng) (tng) (tng)
其他具体的Doorcd可以extends使用abstract (tng)class方式定义的Door或者implements使用interface方式定义的Door。看h好像使用abstract (tng)class和interface没有大的区别。?tng)?br />
如果现在要求Doorq要h报警的功能。我们该如何设计针对该例子的cȝ构呢Q在本例中,主要是ؓ(f)?jin)展Cabstract (tng)class和interface反映在设计理念上的区别,其他斚w无关的问题都做了(jin)化或者忽略)(j)Q下面将|列出可能的解决Ҏ(gu)Qƈ从设计理念层面对q些不同的方案进行分析。?tng)?br />
解决Ҏ(gu)一Q?tng)?br />
单的在Door的定义中增加一个alarmҎ(gu)Q如下:(x) (tng) (tng)

abstract (tng)class (tng)Door (tng){ (tng) (tng)
 (tng)abstract (tng)void (tng)open(); (tng) (tng)
 (tng)abstract (tng)void (tng)close()Q?tng)?br /> (tng)abstract (tng)void (tng)alarm(); (tng) (tng)
} (tng) (tng)

 (tng) (tng) (tng)
或者?tng)?br />
interface (tng)Door (tng){ (tng) (tng)
 (tng)void (tng)open(); (tng) (tng)
 (tng)void (tng)close(); (tng) (tng)
 (tng)void (tng)alarm(); (tng) (tng)
} (tng) (tng)

 (tng) (tng) (tng)
那么h报警功能的AlarmDoor的定义方式如下:(x) (tng) (tng)

class (tng)AlarmDoor (tng)extends (tng)Door (tng){ (tng) (tng)
 (tng)void (tng)open() (tng){ (tng)…?tng)} (tng) (tng)
 (tng)void (tng)close() (tng){ (tng)…?tng)} (tng) (tng)
 (tng)void (tng)alarm() (tng){ (tng)…?tng)} (tng) (tng)
} (tng) (tng)

 (tng) (tng) (tng)
或者?tng)?br />
class (tng)AlarmDoor (tng)implements (tng)Door (tng)?jng) (tng)?br /> (tng)void (tng)open() (tng){ (tng)…?tng)} (tng) (tng)
 (tng)void (tng)close() (tng){ (tng)…?tng)} (tng) (tng)
 (tng)void (tng)alarm() (tng){ (tng)…?tng)} (tng) (tng)
}?tng)?br />
q种Ҏ(gu)q反?jin)面向对象设计中的一个核?j)原则ISPQInterface (tng)Segregation (tng)PricipleQ,在Door的定义中把Door概念本n固有的行为方法和另外一个概?报警?的行为方法؜在了(jin)一赗这样引L(fng)一个问题是那些仅仅依赖于Doorq个概念的模块会(x)因ؓ(f)"报警?q个概念的改变(比如Q修改alarmҎ(gu)的参敎ͼ(j)而改变,反之依然。?tng)?br />
解决Ҏ(gu)二:(x) (tng) (tng)

既然open、close和alarm属于两个不同的概念,Ҏ(gu)ISP原则应该把它们分别定义在代表q两个概늚抽象cM。定义方式有Q这两个概念都用abstract (tng)class方式定义Q两个概念都使用interface方式定义Q一个概念用abstract (tng)class方式定义Q另一个概念用interface方式定义。?tng)?br />
昄Q由于Java语言不支持多重承,所以两个概念都使用abstract (tng)class方式定义是不可行的。后面两U方式都是可行的Q但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意囄反映是否正确、合理。我们一一来分析、说明。?tng)?br />
如果两个概念都用interface方式来定义,那么反映出两个问题Q?、我们可能没有理解清楚问题领域,AlarmDoor在概忉|质上到底是Doorq是报警器?2、如果我们对于问题领域的理解没有问题Q比如:(x)我们通过对于问题领域的分析发现AlarmDoor在概忉|质上和Door是一致的Q那么我们在实现时就没有能够正确的揭C我们的设计意图Q因为在q两个概늚定义上(均用interface方式定义Q反映不Zq含义。?tng)?br />
如果我们对于问题领域的理解是QAlarmDoor在概忉|质上是DoorQ同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢Q前面已l说q,abstract (tng)class在Java语言中表CZU承关p,而承关pd本质上是"is (tng)a"关系。所以对于Doorq个概念Q我们应该用abstarct (tng)class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行ؓ(f)Q所以报警概念可以通过interface方式定义。如下所C:(x) (tng) (tng)

abstract (tng)class (tng)Door (tng){ (tng) (tng)
 (tng)abstract (tng)void (tng)open(); (tng) (tng)
 (tng)abstract (tng)void (tng)close()Q?tng)?br />} (tng) (tng)
interface (tng)Alarm (tng){ (tng) (tng)
 (tng)void (tng)alarm(); (tng) (tng)
} (tng) (tng)
class (tng)AlarmDoor (tng)extends (tng)Door (tng)implements (tng)Alarm (tng){ (tng) (tng)
 (tng)void (tng)open() (tng){ (tng)…?tng)} (tng) (tng)
 (tng)void (tng)close() (tng){ (tng)…?tng)} (tng) (tng)
 (tng) (tng) (tng) (tng)void (tng)alarm() (tng){ (tng)…?tng)} (tng) (tng)
} (tng) (tng)

 (tng) (tng) (tng)
q种实现方式基本上能够明的反映出我们对于问题领域的理解Q正的揭示我们的设计意图。其实abstract (tng)class表示的是"is (tng)a"关系Qinterface表示的是"like (tng)a"关系Q大家在选择时可以作Z个依据,当然q是建立在对问题领域的理解上的,比如Q如果我们认为AlarmDoor在概忉|质上是报警器Q同时又hDoor的功能,那么上述的定义方式就要反q来?jin)?/font>


java_蝈蝈 2007-01-22 08:53 发表评论
]]>
多反向代理[Squid]下获取客L(fng)真实IP地址 http://www.aygfsteel.com/wyz191/articles/93624.htmljava_蝈蝈java_蝈蝈Sat, 13 Jan 2007 10:03:00 GMThttp://www.aygfsteel.com/wyz191/articles/93624.htmlhttp://www.aygfsteel.com/wyz191/comments/93624.htmlhttp://www.aygfsteel.com/wyz191/articles/93624.html#Feedback0http://www.aygfsteel.com/wyz191/comments/commentRss/93624.htmlhttp://www.aygfsteel.com/wyz191/services/trackbacks/93624.html在很多应用下都可能有需要将用户的真实IP记录下来Q这时就要获得用L(fng)真实IP地址Q在JSP里,获取客户端的IP地址的方法是Q?strong>request.getRemoteAddr()Q这U方法在大部分情况下都是有效的。但是在通过?jin)Apache,Squid{反向代理Y件就不能获取到客L(fng)的真实IP地址?jin)?br />
  q段旉在做IPl计的程序设计,׃服务器作?jin)集,使用了(jin)反向代理YӞ?/font> http://192.168.1.110:2046/ 的URL反向代理?/font> http://www.xxx.com/ 的URLӞ?strong>request.getRemoteAddr()Ҏ(gu)获取的IP地址是:(x)127.0.0.1 或 192.168.1.110Q而ƈ不是客户端的真实QP。这是什么原因呢Q?br />
  q是反向代理的原因。经q代理以后,׃在客L(fng)和服务之间增加了(jin)中间层,因此服务器无法直接拿到客L(fng)的IPQ服务器端应用也无法直接通过转发h的地址q回l客L(fng)。但是在转发h的HTTP头信息中Q增加了(jin)XQFORWARDEDQFOR信息。用以跟t原有的客户端IP地址和原来客L(fng)h的服务器地址。当我们讉K
http://www.xxx.com/index.jsp/ Ӟ其实q不是我们浏览器真正讉KC(jin)服务器上的index.jsp文gQ而是先由代理服务器去讉K http://192.168.1.110:2046/index.jsp Q代理服务器再将讉K到的l果q回l我们的览器,因ؓ(f)是代理服务器去访问index.jsp的,所以index.jsp中通过request.getRemoteAddr()的方法获取的IP实际上是代理服务器的地址Qƈ不是客户端的IP地址?br />
  于是可得?gu)得客L(fng)真实IP地址的方法一Q?br />
1  (tng) public  (tng)String (tng)getIpAddr(HttpServletRequest (tng)request) (tng) {
2  (tng) (tng) (tng) (tng) (tng) (tng)String (tng)ip (tng) =  (tng)request.getHeader( " x-forwarded-for "
);
3  (tng) (tng) (tng) (tng) (tng) (tng) if (ip (tng) ==  (tng) null  (tng) ||  (tng)ip.length() (tng) ==  (tng) 0 ) (tng)
{
4  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ip (tng) =
 (tng)request.getRemoteAddr();
5  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

6  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) return  (tng)ip;
7  (tng) (tng) (tng) (tng)}

  可是当我讉K http://www.xxx.com/index.jsp/ Ӟq回的IP地址始终是unknownQ也q不是如上所C的127.0.0.1 或 192.168.1.110?jin),而我讉K http://192.168.1.110:2046/index.jsp Ӟ则能q回客户端的真实IP地址Q写?jin)个?gu)去验证?br />
  
 (tng)1 <% @ (tng)page (tng)import = " java.util.* "  (tng) %>
 (tng)2 < table (tng) border =1 (tng) cellspacing =0 (tng) cellpadding =0 (tng) align =center >  (tng)
 (tng)3 < tr >
 (tng)
 (tng)4 < th > Name </ th >
 (tng)
 (tng)5 < th > Value </ th >
 (tng)
 (tng)6 </ tr >
 (tng)
 (tng)7 <%
 (tng)
 (tng)8
Enumeration (tng)enumNames; (tng)
 (tng)9 String
 (tng)strName,strValue; (tng)
10

11 enumNames (tng) =
 (tng)request.getHeaderNames(); (tng)
12 while
(enumNames.hasMoreElements()){ (tng)
13  (tng) (tng) (tng) (tng)strName (tng) =  (tng)( String
)enumNames.nextElement(); (tng)
14  (tng) (tng) (tng) (tng)strValue (tng) =
 (tng)request.getHeader(strName); (tng)
15  (tng) (tng) (tng) (tng)
%>  (tng)
16  (tng) (tng) (tng) (tng) < tr >
 (tng)
17  (tng) (tng) (tng) (tng) < td > <% = strName %> </ td >
 (tng)
18  (tng) (tng) (tng) (tng) < td > <% = strValue %> </ td >
 (tng)
19  (tng) (tng) (tng) (tng) </ tr >
 (tng)
20  (tng) (tng) (tng) (tng) <%
 (tng)
21
} (tng)
22
%>
23 < tr >
24 </ table >
25


  出来的结果:(x)X-Forwarded-For: unknown 。X-Forwarded-For实存在Q但其值却为unknownQl找原因。上|搜?jin)搜Q原因出在了(jin)Squid上?br />
squid.conf 的配制文件 forwarded_for w认是为onQ如?forwarded_for 设成?off  则:(x)

X-Forwarded-For: unknown

一查,发现forwarded_for 设Z(jin)offQ原因找C(jin)Q把forwarded_for 设Z(jin)onQ重启后Q访?/font> http://www.xxx.com/index.jsp/  获得的IP是客L(fng)的真实IP?br />
  于是可得?gu)得客L(fng)真实IP地址的方法二Q?br />
 (tng)1  (tng) (tng) (tng) (tng) public  (tng)String (tng)getIpAddr(HttpServletRequest (tng)request) (tng) {
 (tng)2  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String (tng)ip (tng) =  (tng)request.getHeader( " x-forwarded-for "
);
 (tng)3  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) if (ip (tng) ==  (tng) null  (tng) ||  (tng)ip.length() (tng) ==  (tng) 0  (tng) ||  (tng) " unknown " .equalsIgnoreCase(ip)) (tng)
{
 (tng)4  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ip (tng) =  (tng)request.getHeader( " Proxy-Client-IP "
);
 (tng)5  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng)6  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) if (ip (tng) ==  (tng) null  (tng) ||  (tng)ip.length() (tng) ==  (tng) 0  (tng) ||  (tng) " unknown " .equalsIgnoreCase(ip)) (tng) {
 (tng)7  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ip (tng) =  (tng)request.getHeader( " WL-Proxy-Client-IP "
);
 (tng)8  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng)9  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) if (ip (tng) ==  (tng) null  (tng) ||  (tng)ip.length() (tng) ==  (tng) 0  (tng) ||  (tng) " unknown " .equalsIgnoreCase(ip)) (tng) {
10  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ip (tng) =
 (tng)request.getRemoteAddr();
11  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

12  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) return  (tng)ip;
13  (tng) (tng) (tng) (tng)}

14



  可是Q如果通过?jin)多U反向代理的话,X-Forwarded-For的值ƈ不止一个,而是一Ԍp|I竟哪个才是真正的用L(fng)的真实IP呢?

  {案是取X-Forwarded-For中第一个非unknown的有效IP字符丌Ӏ?br />
  如:(x)
  X-Forwarded-ForQ?92.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100
  用户真实IP为:(x) 192.168.1.110



java_蝈蝈 2007-01-13 18:03 发表评论
]]>
JFreeChart在JSP中的应用实例 [转]http://www.aygfsteel.com/wyz191/articles/jfreechart.htmljava_蝈蝈java_蝈蝈Sat, 13 Jan 2007 09:48:00 GMThttp://www.aygfsteel.com/wyz191/articles/jfreechart.htmlhttp://www.aygfsteel.com/wyz191/comments/93623.htmlhttp://www.aygfsteel.com/wyz191/articles/jfreechart.html#Feedback0http://www.aygfsteel.com/wyz191/comments/commentRss/93623.htmlhttp://www.aygfsteel.com/wyz191/services/trackbacks/93623.html阅读全文

java_蝈蝈 2007-01-13 17:48 发表评论
]]>
վ֩ģ壺 ʻ| | | IJ| | | | | Ĭ| ݸ| | | | | | | ǭ| | | | ۷| ³ƶ| | | | | | | ʳ| | | | ͼ| ɽ| | | | ɽ| °Ͷ| | |