log4j.properties文g内容Q?/p>
按如下语句执行:
java DumpMethods java.util.Stack
它的l果输出为:
public java.lang.Object java.util.Stack.push(java.lang.Object)
public synchronized java.lang.Object java.util.Stack.pop()
public synchronized java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized int java.util.Stack.search(java.lang.Object)
q样列Zjava.util.Stack cȝ各方法名以及它们的限制符和返回类型?/p>
q个E序使用 Class.forName 载入指定的类Q然后调?getDeclaredMethods 来获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描q某个类中单个方法的一个类?/p>
2.开始?Reflection
用于 reflection 的类Q如 MethodQ可以在 java.lang.relfect 包中扑ֈ。用这些类的时候必要遵@三个步骤Q第一步是获得你想操作的类?java.lang.Class 对象。在q行中的 Java E序中,?java.lang.Class cL描述cd接口{?/p>
下面是获得一?Class 对象的方法之一Q?br />
Class c = Class.forName("java.lang.String");
q条语句得到一?String cȝcd象。还有另一U方法,如下面的语句Q?br />
Class c = int.class; 或?nbsp; Class c = Integer.TYPE;
它们可获得基本类型的cM息。其中后一U方法中讉K的是基本cd的封装类 (?Integer) 中预先定义好?TYPE 字段?br />
W二步是调用诸如 getDeclaredMethods 的方法,以取得该cM定义的所有方法的列表?br />
一旦取得这个信息,可以进行第三步了——?reflection API 来操作这些信息,如下面这D代码:
Class c = Class.forName("java.lang.String");
Method m[] = c.getDeclaredMethods();
System.out.println(m[0].toString());
它将以文本方式打印出 String 中定义的W一个方法的原型?br />
在下面的例子中,q三个步骤将Z?reflection 处理Ҏ应用E序提供例证?/p>
模拟 instanceof 操作W?br />
得到cM息之后,通常下一个步骤就是解军_?Class 对象的一些基本的问题。例如,Class.isInstance Ҏ可以用于模拟 instanceof 操作W:
class A {
}
public class instance1 {
public static void main(String args[]) {
try {
Class cls = Class.forName("A");
boolean b1 = cls.isInstance(new Integer(37));
System.out.println(b1);
boolean b2 = cls.isInstance(new A());
System.out.println(b2);
} catch (Throwable e) {
System.err.println(e);
}
}
}
在这个例子中创徏了一?A cȝ Class 对象Q然后检查一些对象是否是 A 的实例。Integer(37) 不是Q但 new A() 是?/p>
3.扑ևcȝҎ
扑և一个类中定义了些什么方法,q是一个非常有价g非常基础?reflection 用法。下面的代码实Cq一用法Q?br />
import java.lang.reflect.*;
public class method1 {
private int f1(Object p, int x) throws NullPointerException {
if (p == null)
throw new NullPointerException();
return x;
}
public static void main(String args[]) {
try {
Class cls = Class.forName("method1");
Method methlist[] = cls.getDeclaredMethods();
for (int i = 0; i < methlist.length; i++) {
Method m = methlist[i];
System.out.println("name = " + m.getName());
System.out.println("decl class = " + m.getDeclaringClass());
Class pvec[] = m.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param #" + j + " " + pvec[j]);
Class evec[] = m.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println("exc #" + j + " " + evec[j]);
System.out.println("return type = " + m.getReturnType());
System.out.println("-----");
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
q个E序首先取得 method1 cȝ描述Q然后调?getDeclaredMethods 来获取一pd?Method 对象Q它们分别描qC定义在类中的每一个方法,包括 public Ҏ、protected Ҏ、package Ҏ?private Ҏ{。如果你在程序中使用 getMethods 来代?getDeclaredMethodsQ你q能获得l承来的各个Ҏ的信息?br />
取得?Method 对象列表之后Q要昄q些Ҏ的参数类型、异常类型和q回值类型等׃难了。这些类型是基本cdq是cȝ型,都可以由描述cȝ对象按顺序给出?br />
输出的结果如下:
name = f1
decl class = class method1
param #0 class java.lang.Object
param #1 int
exc #0 class java.lang.NullPointerException
return type = int
-----
name = main
decl class = class method1
param #0 class [Ljava.lang.String;
return type = void
-----
4.获取构造器信息
获取cL造器的用法与上述获取Ҏ的用法类|如:
import java.lang.reflect.*;
public class constructor1 {
public constructor1() {
}
protected constructor1(int i, double d) {
}
public static void main(String args[]) {
try {
Class cls = Class.forName("constructor1");
Constructor ctorlist[] = cls.getDeclaredConstructors();
for (int i = 0; i < ctorlist.length; i++) {
Constructor ct = ctorlist[i];
System.out.println("name = " + ct.getName());
System.out.println("decl class = " + ct.getDeclaringClass());
Class pvec[] = ct.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param #" + j + " " + pvec[j]);
Class evec[] = ct.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println("exc #" + j + " " + evec[j]);
System.out.println("-----");
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
q个例子中没能获得返回类型的相关信息Q那是因为构造器没有q回cd?br />
q个E序q行的结果是Q?br />
name = constructor1
decl class = class constructor1
-----
name = constructor1
decl class = class constructor1
param #0 int
param #1 double
-----
5.获取cȝ字段(?
扑և一个类中定义了哪些数据字段也是可能的,下面的代码就在干q个事情Q?br />
import java.lang.reflect.*;
public class field1 {
private double d;
public static final int i = 37;
String s = "testing";
public static void main(String args[]) {
try {
Class cls = Class.forName("field1");
Field fieldlist[] = cls.getDeclaredFields();
for (int i = 0; i < fieldlist.length; i++) {
Field fld = fieldlist[i];
System.out.println("name = " + fld.getName());
System.out.println("decl class = " + fld.getDeclaringClass());
System.out.println("type = " + fld.getType());
int mod = fld.getModifiers();
System.out.println("modifiers = " + Modifier.toString(mod));
System.out.println("-----");
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
q个例子和前面那个例子非常相伹{例中用了一个新东西 ModifierQ它也是一?reflection c,用来描述字段成员的修饰语Q如“private int”。这些修饰语自n由整数描qͼ而且使用 Modifier.toString 来返回以“官方”序排列的字W串描述 (?#8220;static”?#8220;final”之前)。这个程序的输出是:
name = d
decl class = class field1
type = double
modifiers = private
-----
name = i
decl class = class field1
type = int
modifiers = public static final
-----
name = s
decl class = class field1
type = class java.lang.String
modifiers =
-----
和获取方法的情况一下,获取字段的时候也可以只取得在当前cMx了的字段信息 (getDeclaredFields)Q或者也可以取得父类中定义的字段 (getFields) ?/p>
6.ҎҎ的名U来执行Ҏ
文本到这里,所丄例子无一例外都与如何获取cȝ信息有关。我们也可以?reflection 来做一些其它的事情Q比如执行一个指定了名称的方法。下面的CZ演示了这一操作Q?br />
import java.lang.reflect.*;
public class method2 {
public int add(int a, int b) {
return a + b;
}
public static void main(String args[]) {
try {
Class cls = Class.forName("method2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod("add", partypes);
method2 methobj = new method2();
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = meth.invoke(methobj, arglist);
Integer retval = (Integer) retobj;
System.out.println(retval.intValue());
} catch (Throwable e) {
System.err.println(e);
}
}
}
假如一个程序在执行的某处的时候才知道需要执行某个方法,q个Ҏ的名U是在程序的q行q程中指定的 (例如QJavaBean 开发环境中׃做这L?Q那么上面的E序演示了如何做到?/p>
上例中,getMethod 用于查找一个具有两个整型参C名ؓ add 的方法。找到该Ҏq创Z相应?Method 对象之后Q在正确的对象实例中执行它。执行该Ҏ的时候,需要提供一个参数列表,q在上例中是分别包装了整?37 ?47 的两?Integer 对象。执行方法的q回的同h一?Integer 对象Q它装了返回?84?/p>
7.创徏新的对象
对于构造器Q则不能像执行方法那栯行,因ؓ执行一个构造器意味着创徏了一个新的对?(准确的说Q创Z个对象的q程包括分配内存和构造对?。所以,与上例最怼的例子如下:
import java.lang.reflect.*;
public class constructor2 {
public constructor2() {
}
public constructor2(int a, int b) {
System.out.println("a = " + a + " b = " + b);
}
public static void main(String args[]) {
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct = cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
} catch (Throwable e) {
System.err.println(e);
}
}
}
Ҏ指定的参数类型找到相应的构造函数ƈ执行它,以创Z个新的对象实例。用这U方法可以在E序q行时动态地创徏对象Q而不是在~译的时候创建对象,q一炚w常有价倹{?/p>
8.改变字段(?的?br />
reflection 的还有一个用处就是改变对象数据字D늚倹{reflection 可以从正在运行的E序中根据名U找到对象的字段q改变它Q下面的例子可以说明q一点:
import java.lang.reflect.*;
public class field2 {
public double d;
public static void main(String args[]) {
try {
Class cls = Class.forName("field2");
Field fld = cls.getField("d");
field2 f2obj = new field2();
System.out.println("d = " + f2obj.d);
fld.setDouble(f2obj, 12.34);
System.out.println("d = " + f2obj.d);
} catch (Throwable e) {
System.err.println(e);
}
}
}
q个例子中,字段 d 的D变ؓ?12.34?br />
9.使用数组
本文介绍?reflection 的最后一U用法是创徏的操作数l。数l在 Java 语言中是一U特D的cȝ型,一个数l的引用可以赋给 Object 引用。观察下面的例子看看数组是怎么工作的:
import java.lang.reflect.*;
public class array1 {
public static void main(String args[]) {
try {
Class cls = Class.forName("java.lang.String");
Object arr = Array.newInstance(cls, 10);
Array.set(arr, 5, "this is a test");
String s = (String) Array.get(arr, 5);
System.out.println(s);
} catch (Throwable e) {
System.err.println(e);
}
}
}
例中创徏?10 个单位长度的 String 数组QؓW?5 个位|的字符串赋了|最后将q个字符串从数组中取得ƈ打印了出来?br />
下面q段代码提供了一个更复杂的例子:
import java.lang.reflect.*;
public class array2 {
public static void main(String args[]) {
int dims[] = new int[]{5, 10, 15};
Object arr = Array.newInstance(Integer.TYPE, dims);
Object arrobj = Array.get(arr, 3);
Class cls = arrobj.getClass().getComponentType();
System.out.println(cls);
arrobj = Array.get(arrobj, 5);
Array.setInt(arrobj, 10, 37);
int arrcast[][][] = (int[][][]) arr;
System.out.println(arrcast[3][5][10]);
}
}
例中创徏了一?5 x 10 x 15 的整型数l,qؓ处于 [3][5][10] 的元素赋了gؓ 37。注意,多维数组实际上就是数l的数组Q例如,W一?Array.get 之后Qarrobj 是一?10 x 15 的数l。进而取得其中的一个元素,即长度ؓ 15 的数l,q?Array.setInt 为它的第 10 个元素赋倹{?br />
注意创徏数组时的cd是动态的Q在~译时ƈ不知道其cd?/p>
|
|
说明 | q算W?/strong> | 说明 |
+ |
?/p> |
> ?gt | 大于 |
- |
?/p> |
<= ?le | 于{于 |
* |
?/p> |
>= ?ge | 大于{于 |
/ ?div |
?/p> |
&& ?and | 逻辑?/td> |
% ?mod |
模(求余Q?/p> |
|| ?or | 逻辑?/td> |
== ?= |
{于 |
! ?not | 逻辑?/td> |
!= ?!= |
不等?/p> |
empty | 查是否ؓI?/td> |
< ?lt |
于 |
a ? b : c | 条gq算W?/td> |
|
q算l果 | EL 关系q算表达?/strong> | q算l果 |
${1} | 1 | ${1 < 2} | true |
${1 + 2} | 3 | ${1 lt 2} | true |
${1.2 + 2.3} | 3.5 | ${1 > (4/2)} | false |
${-4 - 2} | -6 | ${4.0 >= 3} | true |
${21 * 2} | 42 | ${4.0 ge 3} | true |
${10%4} | 2 | ${100.0 eq 100} | true |
${10 mod 4} | 2 | ${(10*10) != 100} | false |
${(1==2) ? 3 : 4} | 4 | ${(10*10) ne 100} | false |
|
内容 |
applicationScope |
应用E序范围内的scoped变量l成的集?/p> |
cookie |
所有cookiel成的集?/p> |
header |
HTTPh头部Q字W串 |
headerValues |
HTTPh头部Q字W串集合 |
initParam |
全部应用E序参数名组成的集合 |
pageContext |
当前面的javax.servlet.jsp.PageContext对象 |
pageScope |
面范围内所有对象的集合 |
param |
所有请求参数字W串l成的集?/p> |
paramValues |
所有作为字W串集合的请求参?/p> |
requestScope |
所有请求范围的对象的集?/p> |
sessionScope |
所有会话范围的对象的集?/p> |
eg: ${empty(requestScope.backpath)?'admin_TcAction.do?method=findFinish':requestScope.backpath}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"
<hibernate-mapping package="hbm">
<class name="EmylinkUpcode" table="emylink_upcode">
<id
name="id" type="integer" column="plink_code"
>
<generator class="org.hibernate.id.IncrementGenerator"/>
</id>
<property
name="account"
column="account"
type="string"
not-null="true"
length="20"
/>
<property
name="plinkName"
column="plink_name"
type="string"
not-null="true"
length="50"
/>
<property
name="plinkExplain"
column="plink_explain"
type="string"
not-null="false"
length="100"
/>
<property
name="typeCode"
column="type_code"
type="string"
not-null="false"
length="8"
/>
<set name="emylinkUlinks" inverse="true" lazy="true" cascade="all">
<key column="plink_code"/>
<one-to-many class="EmylinkUlink"/>
</set>
</class>
</hibernate-mapping>
* 延迟加蝲
如果lazy=true(延迟加蝲), 加蝲EmylinkUpcode?hibernate不会立即加蝲EmylinkUlink,只有?Iterator<EmylinkUlink> it = ul.iterator();)执行?hibernate才加载EmylinkUlink实例; 如果在加载前关闭session,则报异常LazyInitializationException ; 可以使用Hibernate.initialize(Object o)强制及联加蝲
*J2SE5.0的泛?
emylinkUlinks集合中只能存放EmylinkUlink对象Q从集合中获取对象无需再类型{?br />
struts+spring+hibernate关于hibernate中lazy="true"的问题。web.xml中用
它的原理是Q打开面的时候打开sessionQ一直到面装蝲完毕才关闭sessionQ这样就解决了lazy="true"时session is closed的问题?br />
关于OpenSessionInViewFilter 延迟加蝲失效问题 http://www.javaeye.com/topic/15057
OpenSessionInView的效率问?nbsp; http://www.javaeye.com/topic/17501
一 CVS服务?/a>的安装:
1。查看你的操作系l上是否安装了CVSQ?br />
#> rpm -qa|grep cvs
如果没有安装你可以在Redhat W?张光盘上扑ֈ
2。徏立cvs用户l:
#> groupadd cvs
3。徏立cvsl的cvsroot用户和所属的目录Q?
#> useradd -g cvs -G cvs –d /cvsroot cvsroot
4。ؓcvsroot用户d密码Q?
#> passwd cvsroot
5。改?/cvsroot/ 的目录属性:
#> chmod –R 770 /cvsroot
6。改变用L陆n份:
#> su cvsroot
7。开始创建单个项目:
#> cd /cvsroot
#> mkdir project1
#>mkdir project2
8。开始徏立仓库:
#> cvs –d /cvsroot/project1 init
#> cvs –d /cvsroot/project2 init
#> chmod –R 770 ./project1/ ./project2/
9。徏立CVS服务启动文gQ我们用xinetd方式Q?
#> [Crtl]+[d] 切换到root用户w䆾
#> cd /etc/xinetd.d
#> vi cvspserver
注:׃xinetd的server_args长度限制,当你惌行很多的单个仓库的时?可以q么做:
#> vi cvspserver
~写cvs.run脚本
#> vi /cvsroot/cvs.run
#>chmod +x /cvsroot/cvs.run
10。加入cvs服务Q?
#>vi /etc/services
cvspserver 2401/tcp #pserver cvs service
cvspserver 2401/udp #pserver cvs service
11。启动cvs服务Q?
#> /etc/init.d/xinetd restart
12。检查cvspserver服务是否已经启动Q?
#> netstat -l |grep cvspserver
应该有如下结果:
tcp 0 0 *:cvspserver *:* LISTEN
二。CVS服务的用L理:
上面我们已经建立了project1和project2两个CVS仓库Q下面我们分别给两个仓库建立cvs用户?
13。创建可以登陆cvs服务?/a>的用户名和密码:
#> su cvsroot
#> vi /cvsroot/project1/CVSROOT/passwd
trotter:*****:cvsroot
mimi:*****:cvsroot
#>vi /cvsroot/project2/CVSROOT/passwd
trotter:*****:cvsroot
gary:*****:cvsroot
q两个文件的意思是有trotterQmimiQgary三个cvs用户Qmimi拥有project1的用权限,gary拥有project2的用权限,trotter拥有project1和project2的用权限。登陆后的权限是cvsroot权限?br /> 注意Q这里的cvs用户和系l用h不同的?
14?****为密码,׃下文件生成:
#> vi /cvsroot/passwd.pl
#>chmod a+x /cvsroot/passwd.pl
15。如果你想生成一个密码是“123456”Q则Q?
#> /cvsroot/passwd.pl “123456”
回R卛_得到加密密码,用其替换passwd文g中的*****
16。OkQcvs现在已经全部安装完成了,如果你想让一个用h有project1的权限,你就?cvsroot/project1/CVSROOT/passwd中给他加入一个用P如果你想让一个用户同时具有project1和project2的权限,你就l?cvsroot/project1/CVSROOT/passwd?cvsroot/project2/CVSROOT/passwd里给他加一个用户名和密码相同的用户卛_。最后,我们试用一下:
#> cvs -d :pserver:trotter@192.168.1.200:/cvsroot/project1 login
敲入命o回R后提C入trotter的密?你按照自p|的密码输入,如果没有什么错误信息出现就是成功了
一个cron表达式有臛_6个(也可?个)有空格分隔的旉元素?br />
按顺序依ơؓ
1.U(0~59Q?
2.分钟Q?~59Q?
3.时Q?~23Q?
4.天(月)Q?~31Q但是你需要考虑你月的天敎ͼ
5.月(0~11Q?
6.天(星期Q(1~7 1=SUN ?SUNQMONQTUEQWEDQTHUQFRIQSATQ?
7.q䆾Q?970Q?099Q?/span>
其中每个元素可以是一个??),一个连l区?9-12),一个间隔时?8-18/4)(/表示每隔4时),一个列?1,3,5),通配W?br /> ׃"月䆾中的日期"?星期中的日期"q两个元素互斥的,必须要对其中一个设|?.
0 0 10,14,16 * * ? 每天上午10点,下午2点,4?br /> 0 0/30 9-17 * * ??? 朝九晚五工作旉内每半小?br /> 0 0 12 ? * WED 表示每个星期三中?2?
有些子表辑ּ能包含一些范围或列表
例如Q子表达式(天(星期Q)可以?“MON-FRI”Q?#8220;MONQWEDQFRI”Q?#8220;MON-WED,SAT”
“*”字符代表所有可能的?
因此Q?#8220;*”在子表达式(月)里表C每个月的含义,“*”在子表达式(天(星期Q)表示星期的每一?
“/”字符用来指定数值的增量
例如Q在子表辑ּQ分钟)里的“0/15”表示从第0分钟开始,?5分钟 ;
在子表达式(分钟Q里?#8220;3/20”表示从第3分钟开始,?0分钟Q它?#8220;3Q?3Q?3”Q的含义一?
“Q?#8221;字符仅被用于天(月)和天Q星期)两个子表辑ּQ表CZ指定?
?个子表达式其中之一被指定了g后,Z避免冲突Q需要将另一个子表达式的D?#8220;Q?#8221;
“L” 字符仅被用于天(月)和天Q星期)两个子表辑ּQ它是单?#8220;last”的羃?
但是它在两个子表辑ּ里的含义是不同的?
在天Q月Q子表达式中Q?#8220;L”表示一个月的最后一?,
在天Q星期)自表辑ּ中,“L”表示一个星期的最后一天,也就是SAT
如果?#8220;L”前有具体的内容,它就h其他的含义了
例如Q?#8220;6L”表示q个月的倒数W6天,“QRQL”表示q个月的最后一个星期五
注意Q在使用“L”参数Ӟ不要指定列表或范_因ؓq会D问题