??xml version="1.0" encoding="utf-8" standalone="yes"?> 1Q获得类型类 可以看到Q对象a是A的一个实例,A某一个类Q在if语句中用a.getClass()q回的结果正是A的类型类Q在Java中表CZ个特定类型的cdcd以用“cd.class”的方式获得,因ؓ(f)a.getClass()获得是A的类型类Q也是A.classQ因此上面的代码执行的结果就是打印出“equal”。特别注意的是,cdcL一一对应的,父类的类型类和子cȝcdcL不同的,因此Q假设A是B的子c,那么如下的代码将得到“unequal”的输出:(x) 因此Q如果你知道一个实例,那么你可以通过实例?#8220;getClass()”Ҏ(gu)获得该对象的cdc,如果你知道一个类型,那么你可以?#8220;.class”的方法获得该cd的类型类?br />
除了(jin)q些以外Q利用类型类q可以反该cd中的所有属性和Ҏ(gu)。在Java中所有的属性信息都用Field表示Q所有的Ҏ(gu)信息都用Method表示Q这辆各c都是java.lang.reflect包中的类。在Class中提供了(jin)4个相关的Ҏ(gu)获得cd的属性:(x) 对于Ҏ(gu)也有cM的函数即Q?br />
getMethods():Method[] 4Q创建实?br />
利用Class对象可以创徏一个类型的实例。如果一个类型拥有无参数的构造函敎ͼ那么可以单地调用Class.newInstance()Ҏ(gu)创徏一个实例。如果该cd没有无参数的构造函敎ͼ或者你希望是用某个有参数的构造函敎ͼ那么可以首先使用getConstructors()、getConstructor(Class[] parameterTypes)和getDeclaredConstructors()、getDeclaredConstructor(Class[] parameterTypes)获得构造函敎ͼq两个方法的q回值都使Constructorcd。特别注意的是,构造函C能(h)承,因此你调用getConstructor也只能返回这个类型中定义的所有公有构造函数?br />
以下内容来自http://hi.baidu.com/suofang/blog/item/a58bdd5829d5e583800a1812.htmlQ其中的囄可到q个地址查看Q? l过q次安装Q发C载正的E序完成了(jin)工作?0%Q因为很多安装都是完全自动的Q而配|又非常的简单。本文的所有下载都是针?span style="color: rgb(255,0,0)">Subversion1.4.2Q不要搞错阿Q下面是要下载的E序Q?/p>
PythonQ?http://www.python.org/ftp/python/2.4.4/python-2.4.4.msi Python是必ȝq行环境QTrac自然要下载,Clearsilver是Trac需要的面昄框架QPysqlite是访问sqlite数据库的E序包,而svn-python是访问Subversion的程序包?/p>
首先安装PythonQ然后其他几个安装程序能够自动识别Python的安装,从而只需要按照默认安装即可?/p>
我的Python安装?#8220;D:\Python24”Q我们在D盘创Z(jin)一个目录tracQ作为trac环境存放的目录,然后?#8220;D:\Python24\Scripts”下运行(“>”后的为实际输入的内容Q后面相同)(j)Q?/p>
D:\Python24\Scripts>..\python.exe trac-admin d:\trac initenv 然后提示输入Project的名字,我们输入自己喜欢的名字,q里我输入tractestQ回车;然后询问使用何种数据库,Z(jin)教程的简单,q里使用默认的sqlite数据库,直接回R卛_Q数据库?x)存攑֜环境存放的目录;然后会(x)询问版本库的类型,默认卛_Q然后会(x)询问版本库的路径Q在q个例子里我输入的是“d:\svnroot\project2”Q这个目录里是我的一个版本库Q然后提CZ用何U模版,回R默认卛_。最后回车,如果没有问题Qtrac配置环境?yu)徏立v来了(jin)Q现在启动服务器卛_Q运行:(x) D:\Python24\Scripts>..\python.exe tracd --port 8000 d:\trac 然后在浏览器打开“http://localhost:8000/trac” Q如果看到有内容Q应该就是安装成功了(jin)Q恭喜! default_charset = UTF-8 则在版本库中的文本文件如果是UTF-8~码的,则其中的中文字显C非常正常,当然如果是GBKQ其实就是ISO88591Q的文gQ显C的中文是ؕ码。要惛_全解册个问题,不是单纯Trac能解决的Q需要考虑更全面的方式解决?/p>
大家如果q有什么其他需求,可以l箋(hu)探烦(ch)。其实Trac的安装过Eƈ不复杂,只是因ؓ(f)同时要描q多U可能,所以让人摸不着头脑。在本文介绍的基上,你还可以有很多选择Q例如用MySQL数据库(要安装MySQL和MySQL的Python库)(j)Q或者用ApacheQ需要安装Apache和对应的Python集成工具Q?/p>
作? beansoft@126.com 2007.01.03 下蝲本文源码: ajaxform_gbk.zip 6KB 更新: 试通过: Resin 3.0.18, Tomcat 5.0.30, 5.5.20; 览? IE 6/Firefox 2.0. 有朋友提?当AJAX遭遇GBK的尴?/a> 里说?AJAX 使用 GBK ~码? 表单提交出Cؕ? 如前文所q? 只要全部采用 UTF-8 ~码, 是没有Q何问题的. 那么都用 GBK ? 首先要讲的是我们的文章还是一L(fng)原则: 可能少的改动原来的代码来解决中文ؕ码问? 所以本文的CZ没有用过滤器{方? 那么使用 GBK ~码到底有没有ؕ码问题呢? W一个关键点是 AJAX 的表单提交代码必L的按照 HTTP 规范实现, 卌保持原来?GET/POST 方式不变, 也要保持里面的内容和览器提交的内容一怸? 以下内容摘自我编写的内部培训教材: ----------------- 引用开?----------------- 首先必须要介l一?HTTP 协议?GET, POST 的工作方? 当用户在Web览器地址栏中输入一个带有http://前缀的URLq按下Enter?或者在Web面中某个以http://开头的链接上单击鼠标,HTTP事务处理的第一个阶D?-建立q接阶段开始了(jin).HTTP的默认端口是80. h消息的顶端是h?用于指定Ҏ(gu),URL和HTTP协议的版?h行的最后是回R换行.Ҏ(gu)有GET,POST,HEAD,PUT,DELETE{? 应答消息的第一行ؓ(f)状态行,其中包括?jin)HTTP版本?状态码和对状态码q行短解释的消息;状态行的最后是回R换行.状态码?位数字组??c? 例如:415,表示不支持改媒体cd;503,表示服务器不能访?最常见的是200,表示成功.常见的报头有:Last_Modified(最后修Ҏ(gu)?,Content_Type(消息内容的MIMEcd),Content_Length(内容长度){? 那么 GET ?POST 有什么区? 区别是一个在 URL h里面附带?jin)表单参数和? 一个是?HTTP h的消息实体中. 用下面的例子可以很容易的看到同样的数据通过GET和POST来发送的区别, 发送的数据?username=张三 : GET 方式, 览器键?http://localhost?username=张三 POST 方式: 比较一下上面的两段文字, (zhn)会(x)发现 GET 方式把表单内Ҏ(gu)在前面的h头中, ?POST 则把q些内容攑֜h的主体中? 同时 POST 中把h?Content-Type 头设|ؓ(f) application/x-www-form-urlencoded. 而发送的正文都是一L(fng), 可以q样来构造一个表单提交正? encodeURIComponent(arg1)=encodeURIComponent(value1)&encodeURIComponent(arg2)=encodeURIComponent(value2)&..... ? encodeURIComponent q回一个包含了(jin) charstring 内容的新?String 对象QUnicode 格式Q, 所有空根{标炏V重音符号以?qing)其他?ASCII 字符都用 %xx ~码代替Q其?xx {于表示该字W的十六q制数?例如Q空D回的?"%20" ?字符的值大?255 的用 %uxxxx 格式存储。参?JavaScript ?encodeURIComponent() Ҏ(gu). 下面pZ下如何在 JavaScript 中执行一?GET 或?POST h. 如果(zhn)用q?Java, 那么(zhn)可能熟(zhn)下列的?java.net.URLConnection c进?POST 操作的代?参?Java Tip 34: POSTing via Java ): 以上的代码向 somepage 发送了(jin)一?POST h, 数据?name = Buford Early, email = buford@known-space.com. POST 方式 x(chng)希望你已l能够理解如何用 JavaScript 中的 XMLHttpRequest 对象来执?GET/POST 操作, 剩下的工作就是?zhn)如何来构造这些提交的参数? 最后我l出一个将现有?form 提交代码修改为异步的 AJAX 提交的代?注意目前作者还?sh)知道如何?file 上传表单域也能异步上传文?. 首先L(fng)两个 JavaScript 函数: 函数 ajaxSubmitForm 表单要提交的内容进行封? 然后调用 ajaxSubmit 函数来执行真正的异步提交, 表单提交后所q回的结果则昄在给定的 DIV 容器中或者没有指定参数时?DOM 对象动态生成一?DIV 容器来显C结果ƈd到页面末? q样, 对原来的表单只需要改动一个地方就可以原来的表单提交改ؓ(f)异步模式, 卛_ form 标签里加? onSubmit="ajaxSubmitForm(this);return false;" 卛_, return false 保表单不会(x)被浏览器同步提交. 完整的例子请?a >q里. ----------------- 引用l束 ----------------- OK, 希望x(chng)为止(zhn)已l理解了(jin)如何?AJAX 来正的执行 GET/POST. 如果q个问题(zhn)解决了(jin), 可是说后台的q问题和你直接通过表单提交几乎没有区别? q个Ҏ(gu)的具体封装已l在附g?ajax_common.js 中了(jin). x(chng)也该贴出来我们的 GBK ~码的客L(fng)面的内容了(jin): <html> <head> </head> <body> 提交方式: GET<br> <div id="loading" style="display:none; position:absolute; <div id="resultDiv" style="border:1px solid orange; background-color: #FFFFCC; cursor:pointer;" title="Click to hide" onClick="this.style.display='none';"> </html> 那么W二个关键点是服务器端的表单数据读取了(jin).q个问题跟具体的服务器有很大关系. 对于 Resin 服务器来? 问题很少, 基本上不论是 POST ?GET, Zؕ码的概率都比较小. 但是 Tomcat ׃敢恭l了(jin), q大概也是开源品和商业产品的区? ~Z前后一致性和兼容? 因ؓ(f)开源的不需要提供技术支? Tomcat ?GET/POST 的编码处理方式不同的版本都不一? 像 Eclipse/Netbeans 新版本从来不需要兼容老版本的插g API 一? Hibernate/Struts/Spring 也是一? 所以学 Java 的很? 当然, q就是免?开源的代h(hun). 跑题?sh)? 因此我们的服务器端代码大部分都是?Tomcat 的ؕ码问题的解决(POST的没有问? 主要?GET Ҏ(gu)?. <%@ page contentType="text/html; charset=gbk" pageEncoding="gbk"%> request.setCharacterEncoding("utf-8"); <%! /** try { /** <head> <% Form submit method:<%=request.getMethod()%><br/> while (e.hasMoreElements()) { if(isTomcat && request.getMethod().equalsIgnoreCase("GET")) { // l前台返回一个可以执行的脚本 </body> booleanisTomcat=application.getServerInfo().toLowerCase().indexOf("tomcat") !=-1; q一句主要针?Tomcat q行处理, 如果?GET Ҏ(gu)的话, 需要将表单参数?ISO8859-1 转换?UTF-8 (注意不是 GBK, 貌似 Tomcat 很喜?UTF-8?). 其它的地方和原来?UTF-8 版本的没有区? 当然如果(zhn)的站点应该用过滤器来更方便的解册个问? 结: 其它的一些资料可以参考Blogjava上的一原创文? [原创](mi)struts,ajaxq解决Ҏ(gu) Ƣ迎发表和更好的观点. 谢谢! 重申本文无意代替(zhn)的 AJAX 框架, 不过在你抓狂的时候可以考虑看看他们表单提交的代? Ҏ(gu)? The method parameter can have a value of "GET", "POST", or "PUT" (use "GET" when requesting data and use "POST" when sending data (especially if the length of the data is greater than 512 bytes. The URL parameter may be either a relative or complete URL. The async parameter specifies whether the request should be handled asynchronously or not. true means that script processing carries on after the send() method, without waiting for a response. false means that the script waits for a response before continuing script processing 0 = uninitialized
我们知道在Java中一切都是对象,我们一般所使用的对象都直接或间接(h)承自ObjectcRObjectcM包含一个方法名叫getClassQ利用这个方法就可以获得一个实例的cdcR类型类指的是代表一个类型的c,因ؓ(f)一切皆是对象,cd也不例外Q在Java使用cdcL表示一个类型。所有的cdc都是Classcȝ实例。例如,有如下一D代码:(x)
A a = new A();
if(a.getClass()==A.class)
System.out.println("equal");
else System.out.println("unequal");
A a = new A();
if(a.getClass()==B.class)
System.out.println("equal");
else System.out.println("unequal");
2Q获得类型的信息
在获得类型类之后Q你可以调用其中的一些方法获得类型的信息?jin),主要的方法有Q?br />
getName():StringQ获得该cd的全U名U?br />
getSuperClass():ClassQ获得该cd的直接父c,如果该类型没有直接父c,那么q回null?br />
getInterfaces():Class[]Q获得该cd实现的所有接口?br />
isArray():booleanQ判断该cd是否是数l?br />
isEnum():booleanQ判断该cd是否是枚丄型?br />
isInterface():booleanQ判断该cd是否是接口?br />
isPrimitive():booleanQ判断该cd是否是基本类型,x(chng)否是intQbooleanQdouble{等?br />
isAssignableFrom(Class cls):booleanQ判断这个类型是否是cdcls的父Q祖先)(j)cLӞ先Q接口?br />
getComponentType():ClassQ如果该cd是一个数l,那么q回该数l的lgcd?br />
此外q可以进行类型{换这cȝ操作Q主要方法有Q?br />
asSubclass(Class clazz):ClassQ将q个cd转换至clazzQ如果可以{换,那么Lq回clazzq个引用Q否则抛出异常?br />
cast(Object obj):ObjectQ将obj强制转换个类型类代表的类型,不能转换的话抛出异常?/span>
getField(String name):Field
getFields():Field[]
getDeclaredField(String name):Field
getDeclaredFields():Field[]
其中getField用于q回一个指定名U的属性,但是q个属性必L公有的,q个属性可以在父类中定义。如果是U有属性或者是保护属性,那么都会(x)抛出异常提示找不到这个属性。getFields则是q回cd中的所有公有属性,所有的U有属性和保护属性都找不到。getDeclaredField获得在这个类型的声明中定义的指定名称的属性,q个属性必L在这个类型的声明中定义,但可以ɿU有和保护的。getDeclaredFields获得在这个类型的声明中定义的所有属性,包括U有和保护的属性都?x)被q回Q但是所有父cȝ属性都不会(x)被返回。D个例子,先考虑下面两个cȝ声明Q?br />
class A extends B {
public int a1;
private int a2;
}
class B {
public int b1;
private int b2;
}
如果利用A的类型类调用getFieldsQ那么会(x)q回a1和b1两个属性,如果调用getField("a2")则会(x)报错Q如果调用getDeclaredFields则会(x)q回a1和a2Q如果调用getDeclaredField("b1")则会(x)报错?/span>
getMethod(String name, Class ... parameterTypes):Method
getDeclaredMethods():Method[]
getDeclaredMethod(Strubg name, Class ...parameterTypes):Method
不定长参?..是JDK5.0以后新加入的语法。这几个Ҏ(gu)的用法和上面的类|只是在获得特定方法时Q除?jin)要告知?gu)的名字,q需要告知方法的参数Q如果没有参敎ͼ那么可以传递nullQ或者空数组Q但是最好的Ҏ(gu)是什么都不写Q编译器?x)自行解决不定长参数问题?br />
如果要获得所有的属性(Ҏ(gu)Q,包括公有和私有的Q那么就必须利用getDeclareFieldsQgetDeclareMethodsQ方法,然后再利用getSuperClass的方法获得父c,然后递归下去?br />
3Q属性和Ҏ(gu)
所有的属性都使用Field表示Q所有的Ҏ(gu)都用Method表示。利用Field和Method可以获得属性和Ҏ(gu)的信息,甚至执行是获取、修改属性值和调用Ҏ(gu)?br />
对于属性,主要有以下方法可以用:(x)
getType():ClassQ获得该属性的cd?br />
getName():StringQ获得属性名U?br />
isAccessible():booleanQ判断该属性是否是可以讉K的,通常U有和保护的cd都是不可以访问的?br />
get(Object obj):ObjectQ获得实例obj的属性|如果该实例的cd中不包含q个属性,那么׃(x)报错?br />
set(Object obj, Object value)Q设|该实例的属性?br />
setAccessible(boolean flag)Q设|该属性是否可以访问,如果你调用get和setҎ(gu)Q那么有可能?x)引发访问权限的错误Q这个时候你可以调用setAccessibleҎ(gu)使得该属性可以访问。例如下面的代码Q?br />
A a = new A();
Field f = A.class.getDeclaredField("a2");
f.setAccessibe(true);
System.out.println(f.get(a));
f.set(a,12);
System.out.println(f.get(a));
如果Ud中间的f.setAccessibe(true);那么代码?x)报错,反之输? 12?br />
对于属性而言Q如果该属性的cd是基本类型,那么q可以用一些便L(fng)set和get操作Q例如getIntQsetInt什么的Q你可以Ҏ(gu)自己的需要调用相应的Ҏ(gu)?br />
对于Ҏ(gu)Q可以有以下的方法:(x)
getName():StringQ获得方法的名字?br />
getReturnType():ClassQ获得方法的q回值类型?br />
getParameterTypes():Class[]Q获得方法的参数cd?br />
isAccessible():booleanQ判断该Ҏ(gu)是否是可以访问的?br />
setAccessible(boolean flag)Q设|该Ҏ(gu)是否可以讉K?br />
invoke(Object obj, Object... args):ObjectQ调用实例obj的相应方法,其参数由argsl定Q如果没有参数那么可以什么都不写?br />
getExceptionTypes():Class[]Q获得该Ҏ(gu)可能抛出的异常类cd?br />
q几个方法的含义和用法都和Field的类|q里不再赘述?/span>
Constructor的用方法和Method的类|它也存在getParameterTypes()Ҏ(gu)和getExceptionTypes()Ҏ(gu)Q不同的是,它用newInstance(Object... args)来调用一个构造函敎ͼ注意newInstance不需要实例对象,因ؓ(f)q个时候你q没创徏出来q个实例呢?/span>
]]>
connect by prior start with l常?x)被用到一个表中存在递归关系的时候。比如我们经怼(x)一个比较复杂的目录?wi)存储到一个表中。或者将一些部门存储到一个表中,而这些部门互相有隶属关系。这个时候你׃(x)用到connect by prior start with?
典型的用方法就是:(x)
select * from table connect by prior cur_id=parent_id start with cur_id=???
例如Q?
a b
1 0
2 1
3 1
4 2
5 3
如果x(chng)找a=2?qing)其下面的所有数据,则:(x)
select * from table connect by prior a=b start with a=2
a b
2 1
4 2
q些只是基础Q皮毛。其实只要你灉|的构造查询语句。可以得出意想不到的l果。比如生成树(wi)每一个\径?
但是q些记录l成的树(wi)必须正常才可以。如果有互ؓ(f)父子的情况,׃(x)出现循环错误Q?
CZQ?
'800')this.width='800';if(this.height>'600')this.height='600';" border=0>
'800')this.width='800';if(this.height>'600')this.height='600';" border=0>
--子取?
select * from tb_cus_area_cde a
CONNECT BY PRIOR a.c_snr_area=a.c_area_cde START WITH a.c_area_cde='1040101'
--父取?
select * from tb_cus_area_cde a
CONNECT BY PRIOR a.c_area_cde=a.c_snr_area START WITH a.c_snr_area is null
*************************自己ȝ q是看CSDN吧,赛_(ki)L不好?a target="_blank">http://writeblog.csdn.net/PostList.aspx*********************************
create table TVideoSort
(
FsysId NVARCHAR2(32 char) not null,
FSortName NVARCHAR2(32 char),
FSortTopId NVARCHAR2(32 char),
FSortAddress number,
FSortIsList char(1),
constraint PK_TVIDEOSORT primary key (FsysId)
);
数据如下Q?/font>
--子查Ӟ通过子节点向根节点追?/font>.Q?/font>
查询〔特下边〕的父节?/font>
select FsysId,FSortName,FSortTopId,FSortAddress,FSortIsList from TVideoSort
start with FsysId='3703E5CD81E48D6BE040007F01001254'--fsysid
connect by prior FSortTopId=FsysId
order by FsortAddress
――父查子Q通过根节炚w历子节点.Q?/font>
查询〔特下边〕的子节点:(x)l果
select FsysId,FSortName,FSortTopId,FSortAddress,FSortIsList
from TVideoSort start with FsysId='3703E5CD81E48D6BE040007F01001254' --fsysid
connect by prior FsysId=FSortTopId order by FsortAddress
查询〔特长练?fn)〕的子节点:(x)l果
select FsysId,FSortName,FSortTopId,FSortAddress,FSortIsList
from TVideoSort start with FsysId='36AE4D68EC7D364CE040007F01000CA5'
connect by prior FsysId=FSortTopId order by FsortAddress
特别注意Q两个查询只?/font>FsysId=FSortTopId不同而已Q即子查父则?/font>FSortTopId做ؓ(f)主表攑։面,父查子则?/font>FsysId攑։面作主表
]]>1Q下载程?/h3>
TracQ?http://ftp.edgewall.com/pub/trac/trac-0.10.2.win32.exe
ClearsilverQ?http://www.clearsilver.net/downloads/win32/clearsilver-0.9.14.win32-py2.4.exe
PysqliteQ?http://initd.org/pub/software/pysqlite/releases/2.3/2.3.2/pysqlite-2.3.2.win32-py2.4.exe
svn-pythonQ?http://subversion.tigris.org/downloads/svn-python-1.4.2.win32-py2.4.exe
2, 安装E序3Q配|Trac
ȝ
我要和你重逢在借钱的\?br />
手头来紧,只能回想
有钱的日?像在天堂
呕也,呕也,呕也..
谁在呼唤,工资快涨
昂贵的猪肉像白云在飘?br />
东边借钱,西边q帐
一摞摞的钞?送到银行
在工资没涨的沧桑?br />
致富的\在何?br />
再紧紧裤?来碗面汤
呕也,呕也,呕也
呕也,呕也,呕也
]]>
自八八年崛vQ至?ji)六q鼎盛,从零二年功成Q到如今而名颓:(x)凡二十年Q水益深Q火益热Q薪益低Qd益损Q信益失。而当局者放于利而行Q民声民怨,|若|闻Q不同之aQ恍若未见。规令滋彎ͼ败纪qQ虚a教化Q狗屁文章;口号漫天Q奇事滋长:(x)有hw被完美累,有h名因Z彰。二十年兴衰事,L掩卷长叹Q?br />
臛_L××Q行伍出w,刚愎自用Q质胜于文;乃翁天下马上得,驱驰自依行军{;军h重功ȝ死,拼死争得盛世来:(x)时至一?ji)?ji)八,聚得利润大把Q衣轻裘Q乘宝马Q多而均Q富且安Q军有胦(ch)Q士皆来Q军有赏Q士争往(xin)Q军?j)大振,累死无怨;使近者?zhn)Q远者归Q门庭若?jng),显赫一时?br />
也信盛衰人间道,不堪反复太匆匆?br />
盛时不长Q盛事不再;成由萧何Q不知谁败?颜渊弃世Q名垂青Ԍȝ早夭Q功振千古;_֍叛国Q名颓n辱;王莽盗器Q老而不歅R可怜当初不国殇Q老来p涂留短长:(x)玩刀弄笔Q不知所以,信口虚谈Q不知所aQ岗薪不配,前后不一Q寡而不均,贫且不安Q军已来Q削其胦(ch)Q军已往(xin)Q减其赏Q耕牛夜犁无宿草,仓鼠昼寝有余_;使近者怨,q者惧Q侯门一入深似vQ鸡肋埋w难出来?br />
若乃产品飘洲洋Q固守陈陋主张;技术稍逊一{,可以w体相抗Q阔别半个世U,重回朝鲜战场。烈士地下有知,必定黯然伤Q?#8220;我昔弃n沙场Q只为儿久女长;早知子孙q战Q隐w市(jng)井熙攘?#8221;呜呼Q月子弯弯照?ji)州Q几人欢乐几人愁Q几人春安||帐Q几人拼死谋ELQ几宴论行赏Q几人?zhn)歌掩惆怅:(x)“莫叹军|军要却敌,城高功亦高,?dng)命何惜?#8221;
至于胡君新宇Q生不逢地Q煤矿淘金,D精竭力Q薪未v兮已寿终Q棺已盖兮未正寝。念其生前催人泪Q观其n后寒人心(j)。呜|一杯清酒诗一,胡君昨日列神仙;玉帝若问人间事,׃能命换钱!
念及(qing)胡家严慈Q白发送子Qh能换钱,钱难赎命Q列q堂,一屋?zhn)怆,陈钱桌上Q满堂凄凉;夜深人静(rn)Q?zhn)来填膺,半夜三更Q泣不成壎ͼ泪眼相对Q端坐待明,千秋万岁Qؓ(f)哀难胜Q枯指十扣,人逐时瘦,万岁千秋Q致L休?br />
再看上下领导Q开?x)辟谣,依恃丰厚之赔偿,姿态得意而洋z,Ƣ聚于一堂,Ȁ情而开Ԍ(x)仁义华ؓ(f)Q出手百万,胡家不赔Q华为没赚,外界谣传Q要有主见,艰苦奋斗作风Q不p某存D隐玎ͼ呜呼Q我见此事已Ҏ(gu)Q又L语重唧唧Q始信锦衣裹兽Q终知狼能着皮Q同是天涯落hQ长歌此时哭兄弟Q同时天地父母生Q同根相煎何太急!
酸楚酸辛三百天,易岗易薪一周年Q一q三癑օ十日Q都在岗薪匹配中Q员工至今未被泽Q领导月月有l效Q行政供奉厚黑学Q华?sh)I漫拖字诀Q负p天下Q德信民心(j)。于是乎Q贱买应届学生,自谓源远长Q庙妖气笼|,偏爱外来和尚Q年q坝上插新秧Qؓ(f)他h做嫁衣裳Q^原满目离苗Q移植他处好成长Q子胥旋卛_吴国Q马童不日随刘邦Q大厦将們֯栋梁Q栋梁都在别家忙Q寡Z力回天?不死以待时亡?br />
?qing)夫每到q末Q聚?x)奇多,千里逢迎Q白丁满座;有附应R雅之土hQ多自诩高雅之文Ԍ马戏开q,_墨dQ莫W^怸知书Q嘴上吐出黄金屋Q洋z洒z上千篇Q两个黄鹂鸣脆柳Q洒z洋z数万言Q一行白鹭上青天Q可怜中华文化上下五千年Q千万a不堪看,篇抗战Q句句亮剑,与会(x)者成百上千,宁无一个有新意Q宁无一人有pQ清明祭坟,新春q远Q溯只C七年Q子孙如此多娇,死虞舜Q气折唐?br />
故公怹道,曎ͼ(x)骗hQ自骗,把h骗,员工之铭Q是Q欺人,自欺Q被人欺Q弄智失信,玩h丧dQ无德富贵,不知其可Q万疑,惭言雷锋Q千夫所指,愧对诚信Q冷眼旁观,效走傅军Q热?j)企|再v一P春江水暖Q老鸭先知Q大?wi)未倒,猢狲先散Q大旗衰落,q在眼前Q祸赯墙,为期不远?br />
至于W者,拼命?zhun)钱Q养家糊口,q光Q感知遇恩,低调收尾贵发一aQ恨Zh甚,大\不^l需人铲Q敢竭鄙城,针砭所见,曲突徙薪Qؓ(f)时不晚,焦头烂额Q盛世可接;q途知q,q能中兴Q亡补牢,可华ؓ(f)Q?/span>
]]>
栈的优势是,存取速度比堆要快Q仅ơ于寄存器,栈数据可以共享。但~点是,存在栈中的数据大与生存期必L定的,~Z灉|性。栈中主要存放一些基本类型的变量Q?int, short, long, byte, float, double, boolean, charQ和对象句柄?
栈有一个很重要的特D性,是存在栈中的数据可以共享。假设我们同时定义:(x)
int a = 3;
int b = 3Q?
~译器先处理int a = 3Q首先它?x)在栈中创徏一个变量ؓ(f)a的引用,然后查找栈中是否?q个|如果没找刎ͼ将3存放q来Q然后将a指向3。接着处理int b = 3Q在创徏完b的引用变量后Q因为在栈中已经?q个|便将b直接指向3。这P出C(jin)a与b同时均指?的情c(din)?
q时Q如果再令a=4Q那么编译器?x)重新搜索栈中是否?|如果没有Q则?存放q来Qƈ令a指向4Q如果已l有?jin),则直接将a指向q个地址。因此a值的改变?sh)?x)影响到b的倹{?
要注意这U数据的׃n与两个对象的引用同时指向一个对象的q种׃n是不同的Q因U情况a的修改ƈ不会(x)影响到b, 它是q译器完成的,它有利于节省I间。而一个对象引用变量修改了(jin)q个对象的内部状态,?x)?jing)响到另一个对象引用变量?
String是一个特D的包装cL据。可以用Q?
String str = new String("abc");
String str = "abc";
两种的Ş式来创徏Q第一U是用new()来新建对象的Q它?x)在存放于堆中。每调用一ơ就?x)创Z个新的对象。而第二种是先在栈中创Z个对Stringcȝ对象引用变量strQ然后查找栈中有没有存放"abc"Q如果没有,则将"abc"存放q栈Qƈ令str指向”abc”Q如果已l有”abc” 则直接o(h)str指向“abc”?
比较c里面的数值是否相{时Q用equals()Ҏ(gu)Q当试两个包装cȝ引用是否指向同一个对象时Q用==Q下面用例子说明上面的理论?
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一个对象的?
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的方式是生成不同的对象。每一ơ生成一个?
因此用第二种方式创徏多个”abc”字符?在内存(sh)其实只存在一个对象而已. q种写法有利与节省内存空? 同时它可以在一定程度上提高E序的运行速度Q因为JVM?x)自动根据栈中数据的实际情况来决定是否有必要创徏新对象。而对于String str = new String("abc")Q的代码Q则一概在堆中创徏新对象,而不其字符串值是否相{,是否有必要创建新对象Q从而加重了(jin)E序的负担?
另一斚w, 要注? 我们在用诸如String str = "abc"Q的格式定义cLQL惛_然地认ؓ(f)Q创Z(jin)Stringcȝ对象str。担?j)陷阱!对象可能q没有被创徏Q而可能只是指向一个先前已l创建的对象。只有通过new()Ҏ(gu)才能保证每次都创Z个新的对象?
׃Stringcȝimmutable性质Q当String变量需要经常变换其值时Q应该考虑使用StringBufferc,以提高程序效率?
]]>
2007-01-03
修复?AJAXFormer 中第二个参数 resultDiv 处理不当的问?
增加?jin)从服务器端q回脚本q加以执行的功能;
增加?jin)表单提交后|络出错的错误显C功?
q些新功能都已经攑֜CZ面中了(jin).
随着q接的徏?HTTPp入了(jin)客户向服务器发送请求的阶段.客户向服务器发送的h是一个有特定格式的ASCII消息,其语法规则ؓ(f):
6KB
< Method > < URL > < HTTP Version > <\n>
{ <Header>:<Value> <\n>}*
<\n>
{ Entity Body }
在请求行之后是若q个报头(Header)?每个报头行都是由一个报头和一个取值构成的二元?报头和取g间以":"分隔;报头行的最后是回R换行. 常见的报头有Accept(指定MIME媒体cd),Accept_Charset(响应消息的编码方?,Accept_Encoding(响应消息的字W集),User_Agent(用户的浏览器信息){?
在请求消息的报头行之后是一个回车换?表明h消息的报头部分结?在这个\n之后是请求消息的消息实体(Entity Body).
Web服务器在收到客户hq作出处理之?要向客户发送应{消?与请求消息一?应答消息的语法规则ؓ(f):
< HTTP Version> <Status Code> [<Message>]<\n>
{ <Header>:<Value> <\n> } *
<\n>
{ Entity Body }
在报头行之后也是一个回车换?用以表示应答消息的报头部分的l束,以及(qing)应答消息实体的开?
下面是一个应{消息的例子:
HTTP/1.0 200 OK
Date: Moday,07-Apr-97 21:13:02 GMT
Server:NCSA/1.1
MIME_Version:1.0
Content_Type:text/html
Last_Modified:Thu Dec 5 09:28:01 1996
Coentent_Length:3107
<HTML><HEAD><TITLE>...</HTML>
GET /?username=%E5%BC%A0%E4%B8%89 HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: localhost
Connection: Keep-Alive
POST / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: localhost
Content-Length: 28
Connection: Keep-Alive
username=%E5%BC%A0%E4%B8%89
URL url;
URLConnection urlConn;
DataOutputStream printout;
// URL of CGI-Bin or jsp, asp script.
url = new URL ("somepage");
// URL connection channel.
urlConn = url.openConnection();
// ......
// No caching, we want the real thing.
urlConn.setUseCaches (false);
// Specify the content type.
urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// Send POST output.
printout = new DataOutputStream (urlConn.getOutputStream ());
String content = "name=" + URLEncoder.encode ("Buford Early") + "&email=" + URLEncoder.encode ("buford@known-space.com");
printout.writeBytes (content);
printout.flush ();
printout.close ();
用JavaScript 来执?POST/GET h是同L(fng)原理, 下面的代码展CZ(jin)分别?XMLHttpRequest 对象?somepage ?GET ?POST 两种方式发送和上例相同的数据的具体q程:
GET 方式
var postContent =
"name=" + encodeURIComponent("Buford Early") + "&email=" + encodeURIComponent("buford@known-space.com");
xmlhttp.open("GET", "somepage" + "?" + postContent, true);
xmlhttp.send(null);
var postContent =
"name=" + encodeURIComponent("Buford Early") + "&email=" + encodeURIComponent("buford@known-space.com");
xmlhttp.open("POST", "somepage", true);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send(postContent);
// form - the form to submit
// resultDivId - the division of which to display result text in, in null, then
// create an element and add it to the end of the body
function ajaxSubmitForm(form, resultDivId) {
var elements = form.elements;// Enumeration the form elements
var element;
var i;
var postContent = "";// Form contents need to submit
for(i=0;i<elements.length;++i) {
var element=elements[i];
if(element.type=="text" || element.type=="textarea" || element.type=="hidden") {
postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(element.value) + "&";
}
else if(element.type=="select-one"||element.type=="select-multiple") {
var options=element.options,j,item;
for(j=0;j<options.length;++j){
item=options[j];
if(item.selected) {
postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(item.value) + "&";
}
}
} else if(element.type=="checkbox"||element.type=="radio") {
if(element.checked) {
postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(element.value) + "&";
}
} else if(element.type=="file") {
if(element.value != "") {
postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(element.value) + "&";
}
} else {
postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(element.value) + "&";
}
}
alert(postContent);
ajaxSubmit(form.action, form.method, postContent);
}
// url - the url to do submit
// method - "get" or "post"
// postContent - the string with values to be submited
// resultDivId - the division of which to display result text in, in null, then
// create an element and add it to the end of the body
function ajaxSubmit(url, method, postContent, resultDivId)
{
var loadingDiv = document.getElementById('loading');
// call in new thread to allow ui to update
window.setTimeout(function () {
loadingDiv.innerText = "Loading....";
loadingDiv.style.display = "";
}, 1);
// code for Mozilla, etc.
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
// code for IE
else if (window.ActiveXObject)
{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if(xmlhttp) {
xmlhttp.onreadystatechange = function() {
// if xmlhttp shows "loaded"
if (xmlhttp.readyState==4)
{
if(resultDivId) {
document.getElementByID(resultDivId).innerHTML = xmlhttp.responseText;
} else {
var result = document.createElement("DIV");
result.style.border="1px solid #363636";
result.innerHTML = xmlhttp.responseText;
document.body.appendChild(result);
}
loadingDiv.innerHTML =
"Submit finnished!";
}
};
if(method.toLowerCase() == "get") {
xmlhttp.open("GET", url + "?" + postContent, true);
xmlhttp.send(null);
} else if(method.toLowerCase() == "post") {
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send(postContent);
}
} else {
loadingDiv.innerHTML =
"Can't create XMLHttpRequest object, please check your web browser.";
}
}
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>AJAX Form Submit Test</title>
<script src='ajax_common.js'></script>
本页面的~码是中?<br/>
<meta http-equiv="Content-Type" content="text/html; charset=gbk"><br/>
<b>试q的服务?</b><br/>
Resin 3.0.18<br/>
Tomcat 5.5.20<br/>
Tomcat 5.0.30<br/>
<h3>AJAX Form Submit Test</h3>
Fill the form and then click submit<br>
提交方式: POST<br>
<form method="POST" id="form1" name="form1"
action="form_action.jsp"
onSubmit="former.ajaxSubmitForm();return false;">
<p><input type="hidden" name="hidden1" value="hiddenValue">
text:<input type="text" name="textf&1" size="20" value="text文本&1">
checkbox:<input type="checkbox" name="checkbox1" value="ON" checked>
radio:<input type="radio" value="V1" checked name="radio1">
select:<select size="1" name="select1">
<option selected value="option1">D1</option>
</select>
<br>
<br>
<input type="submit" name="B1" value="submit">
<input type="reset" name="B2" value="reset">
</p>
</form>
<form method="GET" id="form2" name="form2"
action="form_action.jsp"
onSubmit="former2.ajaxSubmitForm();return false;">
<p><input type="hidden" name="hidden1" value="hiddenValue">
text:<input type="text" name="text文本&2" size="20" value="text文本&2">
checkbox:<input type="checkbox" name="checkbox1" value="ON" checked>
radio:<input type="radio" value="V1" checked name="radio1">
select:<select size="1" name="select1">
<option selected value="option1">D1</option>
</select>
<br>
<br>
<input type="submit" name="B1" value="submit">
<input type="reset" name="B2" value="reset">
</p>
</form>
border:1px solid orange; height:20px; width:600; left: 93px; top: 112px;
background-color: #FFFFCC; cursor:pointer;" title="Click to hide" onClick="this.style.display='none';"></div>
Form 1 的提交结果将?x)显C在q里.
</div>
<script type="text/javascript">
var former = new AjaxFormer($('form1'), 'resultDiv');
var former2 = new AjaxFormer($('form2'));
</script>
</body>
<html>
<%
//Send some headers to keep the user's browser from caching the response.
response.addHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT" );
response.addHeader("Last-Modified", new java.util.Date().toGMTString());
response.addHeader("Cache-Control", "no-cache, must-revalidate" );
response.addHeader("Pragma", "no-cache" );
// This will emulate a network delay, for 2 sec.
//Thread.currentThread().sleep(2000);
%>
* 转换字符串的内码.
*
* @param input
* 输入的字W串
* @param sourceEncoding
* 源字W集名称
* @param targetEncoding
* 目标字符集名U?br>* @return 转换l果, 如果有错误发? 则返回原来的?br>*/
public static String changeEncoding(String input, String sourceEncoding,
String targetEncoding) {
if (input == null || input.equals("")) {
return input;
}
byte[] bytes = input.getBytes(sourceEncoding);
return new String(bytes, targetEncoding);
} catch (Exception ex) {
}
return input;
}
* 一个类g JavaScript ?escape 函数的功? 保q可以正确传输.
*/
public static String escape(String src) {
int i;
char j;
StringBuffer tmp = new StringBuffer();
tmp.ensureCapacity(src.length() * 6);
for (i = 0; i < src.length(); i++) {
j = src.charAt(i);
if (Character.isDigit(j) || Character.isLowerCase(j)
|| Character.isUpperCase(j))
tmp.append(j);
else if (j < 256) {
tmp.append("%");
if (j < 16)
tmp.append("0");
tmp.append(Integer.toString(j, 16));
} else {
tmp.append("%u");
tmp.append(Integer.toString(j, 16));
}
}
return tmp.toString();
}
%>
<title>Test form action page</title>
</head>
<body>
q是 GBK ~码版本的后台表单提交页?<br/>
boolean isTomcat = application.getServerInfo().toLowerCase().indexOf("tomcat") != -1;
%>
The form content u send is:<br/>
<%
java.util.Enumeration e = request.getParameterNames();
String name = (String)e.nextElement();
String value = request.getParameter(name);
name = changeEncoding(name, "ISO8859-1", "UTF-8");
value = changeEncoding(value, "ISO8859-1", "UTF-8");
}
out.println("<b>" + name + "</b> = " + value + "<br/>");
}
//response.addHeader("response_script", changeEncoding("alert('提交完成');", "ISO8859-1", "UTF-8"));
response.addHeader("response_script", escape("alert('提交完成');"));
%>
</html>
1. 使用一致的字符集很重要, 要么全是 GBK, 要么全是 UTF-8, 如果有条? 全部用 UTF-8, 那样工作量是最的;
2. ?AJAX 提交的时候一定要按照 HTTP 的规范来, 做到和浏览器量兼容, 其?POST 的时候不要再往(xin) URL 地址里加参数? 你那hq规! 后果是有的服务器会(x)不搭理你传递的q些参数! q是如我所? 参数提交之前要用 encodeURIComponent() 来{? q也是ؓ(f)?jin)符合浏览器的?fn)惯做?
3. 后台如果d参数有ؕ? 尽量多?ISO8859-1, GBK, UTF-8 中间多{换几ơ试? 可以试试偶写的那?changeEncoding() Ҏ(gu), 把几个{换后的表单值都列出? 一定有一个是正确? L可以解决问题? q个本来不应该是偶们的Q? 但是写服务器的h是老美, 其?Tomcat 作? 只熟(zhn)?ISO8859-1.
4. 鉴于 TOMCAT d POST 参数的时候很出问题, 因此AJAX提交表单的时候多?POST Ҏ(gu), 量不用 GET.
q行截屏:
本h译?XMLHttpRequest 对象介绍:The XMLHttpRequest Object Reference XMLHttpRequest 对象参?/h2>
Methods Ҏ(gu)
Method Ҏ(gu)
Description 描述
abort()
Cancels the current request
取消当前h
getAllResponseHeaders()
Returns the complete set of http headers as a string
完整的 HTTP 头部做ؓ(f)一个字W串q回
getResponseHeader("headername")
Returns the value of the specified http header
q回l定?HTTP 头的?/td>
open("method","URL",async,"uname","pswd")
Specifies the method, URL, and other optional attributes of a request
指定表单提交Ҏ(gu), URL, 以及(qing)h的可选属?br>
method 参数可以?GET", "POST" 或?"PUT" q些g之一(使用"GET"来请求数? 特别? 当发送的数据长度大于512字节时?"POST").
URL 参数可以为相对的和完整的 URL.
async 参数指定h是否为异步方式处? true 意味着调用 send() Ҏ(gu)后脚本(h)l向下执? 不需要等待响? false 意味着脚本等待响应之后才能(h)l执?/p>
send(content)
Sends the request
发送请?/td>
setRequestHeader("label","value")
Adds a label/value pair to the http header to be sent
在要发送的 HTTP 头中d 标签/取?/td>
Properties 属?/h3>
Property 属?/th>
Description 描述
onreadystatechange
An event handler for an event that fires at every state change
每次状态改变时除非的事件处理器
readyState
Returns the state of the object:
1 = loading
2 = loaded
3 = interactive
4 = complete
q回对象的状?br>
0 = 未初始化
1 = 载入?br>2 = 已蝲?br>3 = 交互
4 = 完成
responseText
Returns the response as a string
响应做为字W串q回
responseXML
Returns the response as XML. This property returns an XML document object, which can be examined and parsed using W3C DOM node tree methods and properties
响应做为XMLq回. q个属性返回一?XML 文档对象, 可以?W3C ?DOM 节点?wi)方法和属性进行检索分?/td>
status
Returns the status as a number (e.g. 404 for "Not Found" or 200 for "OK")
状态做为数字返?例如 404 ?Not Found" 或?200 ?"OK")
statusText
Returns the status as a string (e.g. "Not Found" or "OK")
状态做为字W串q回(例如 "Not Found" 或?"OK")
]]>
package donne.study;public abstract class HelloWorldBean implements javax.ejb.SessionBean {(tng) (tng) (tng) /**
(tng) (tng) (tng) (tng) * @ejb.interface-method view-type="remote"
(tng) (tng) (tng) (tng) */
(tng) (tng) (tng) public String getHelloWorld(String sMessage) {(tng) (tng) (tng) (tng) (tng) (tng) (tng) return "Hello World! "+sMessage;
(tng) (tng) (tng) }}
package donne.study;/**
(tng)* Remote interface for HelloWorld.
(tng)* @generated
(tng)* @lomboz generated
(tng)*/
public interface HelloWorld
(tng) (tng) extends javax.ejb.EJBObject
{(tng) (tng) public java.lang.String getHelloWorld( java.lang.String sMessage )
(tng) (tng) (tng) (tng) (tng) throws java.rmi.RemoteException;}
package donne.study;/**
(tng)* Home interface for HelloWorld.
(tng)* @generated
(tng)* @lomboz generated
(tng)*/
public interface HelloWorldHome
(tng) (tng) extends javax.ejb.EJBHome
{
(tng) (tng) public static final String COMP_NAME="java:comp/env/ejb/HelloWorld";
(tng) (tng) public static final String JNDI_NAME="HelloWorld";(tng) (tng) public donne.study.HelloWorld create()
(tng) (tng) (tng) (tng) (tng) throws javax.ejb.CreateException,java.rmi.RemoteException;}
package donne.study;import java.util.Hashtable;import javax.naming.InitialContext;
import javax.naming.NamingException;(tng)public class HelloWorldClient {(tng) (tng) (tng) private donne.study.HelloWorldHome getHome() throws NamingException {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) return (donne.study.HelloWorldHome) getContext().lookup(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) donne.study.HelloWorldHome.JNDI_NAME);
(tng) (tng) (tng) }(tng) (tng) (tng) private InitialContext getContext() throws NamingException {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) Hashtable props = new Hashtable();(tng) (tng) (tng) (tng) (tng) (tng) (tng) props.put(InitialContext.INITIAL_CONTEXT_FACTORY,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) "org.jnp.interfaces.NamingContextFactory");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) props.put(InitialContext.PROVIDER_URL, "jnp://192.168.0.1:1099");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) InitialContext initialContext = new InitialContext(props);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) return initialContext;
(tng) (tng) (tng) }(tng)(tng) (tng) (tng) public String getEJBString() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) try {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) donne.study.HelloWorld myBean = getHome().create();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) return myBean.getHelloWorld("From Tomcat Jsp");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) } catch (Exception e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) return e.getMessage();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) }
(tng) (tng) (tng) }
}
<%@ page contentType="text/html; charset=GBK"%>
<%@ page import = "donne.study.HelloWorldClient" %>
<HTML>
<BODY>
<%
(tng)HelloWorldClient helloID=new HelloWorldClient();
(tng)out.print(helloID.getEJBString());
%></BODY>
</HTML>
几天前,在Don Box的博客上Q我设法回答一个问?Spring比EJB单吗Q?.现在,q个问题像是有些多余?jin),因?f)Spring和EJB的目标ƈ不完全一_(d)但也总EJB和Spring两者所共有之处来回{,是可以的。Ted Neward在他的博客上Ҏ(gu)的回复进行了(jin)评论,我现在去回应一下他的观炏V?/p>
Ted评论:Spring是一个比EJB单多?jin)的框架Q因为Spring更多是用ZPOJO(PlainObject Old Object)的方案,但对?一些情?下,它ƈ不简?而是更复杂?/p>
Rod:好的,?一些情??地球是扁q的对吧。在我的l验中,如果实现业务逻辑所需要的java Object过3个的时候,认ؓ(f)用POJO(通常有一个接?Ҏ(gu)更复杂的人很:(x)l我印象深刻的是Q那些否定POJOҎ(gu)的那些hQ真正尝试两U方案ƈ做出Ҏ(gu)的h为零。可能他们有自己的观点,但我q不知道?也许直接的事务和q程Ҏ(gu)更另人愉(zhn)?)我真的非常希望看到能真正证明ZPOJO的方案更复杂更难用的评论?/p>
Rod:Z么Spring比EJB单易?我不能给你一个独立的主观臆断Q我可以告诉你的是,我是借鉴EJBQƈq用我多q的l验来设计Spring的,我也很乐于去比较.从一开始,Spring(或者其他的IOC加Services框架)框架是和你的业务代码隔ȝQ没有藕合的.q个区别是很有重大意义的。Q何Object可以被事务化而不需要陷入EJB的丛林中。这对于代码的重用也是有意义的。实际上Q在你自q业务对象中,很少有框架的侵入Q换句话_(d)你会(x)有更多的自由去运用面向对象的分析设计?/p>
Ted:哦,我已l说q了(jin)Q企业pȝ通常不是来练?fn)OO(面向对象),因ؓ(f)那么做有一U让我们陷入ȝ(ch)的危险趋?---q也是Z么h们在|络计算的趋势下Q用CORBA,DCOM和RMI来解决问题的原因。你应该考虑一下,把collection|于服务器端Qiterator攑֜客户端的意义Q然后你明?....
Rod:Ted,我提到的"更多自由M用OO",q不是说所有地斚w用OO,当然Q分布式对象是很需要的。但重要的是Q不要把"企业应用"?分布式应?混ؓ(f)一? 应用E序的内部结构应该尽可能的面向对?然后提供一个高层的接口对远E调用暴Ԍ理想状态下Q仅仅这个接口才可以攑ּ面向对象.(基本上像SDO--服务数据对象Service Data Objectsq样的解x(chng)案在q部分是很庞大的).所以在分布式对象徏模中Q在应用内部引入优秀的应用程序接?虽然破坏OO)是没有争议的。Spring和其他的IOC(inverse of control控制反{)容器Q不?x)在OO斚w讄障碍,而EJB没做到Q它大范围内C赖了(jin)EJB的接口和框架?/p>
在我对于Spring的XML配置要比EJB复杂的部|描q文件简单易配置的评论后----Ted写到:公正地说,Rod--JSR 175 在简化部|描q配|?包括你的Spring的XML配置)斚w的所做的工作是有意义?而不是所?,在java5之前Q部|描q文件是一个必ȝQ很gh的事情吗Q不q的是,事实表明Q考虑到所有的可能性,q已l是最佳的解决Ҏ(gu)?jin)?所有h都记得EJB1.0ӞZ对象的描q符)?/p>
Rod:没错,JSR-175?x)在DD(Data Define数据定义)斚wq一步改?已经有所改善Q虽然注释被一再过度?不过那是另一个话题(sh)(jin)).不错QDDs(数据定义文g)是必要的Q虽然很J琐Q这是java借用C#中属性集/注释的想法而来?但问题是,现在的EJB部v描述让h惊骇地冗长,差不多全在XML?而且一个标准的ejb-jar.xml部v描述文gq不够,通常需要两个。相反,Spring的配|文件短精(zhn),而且不需要额外的引用。当?dng)EJB3.0不在q里讨论Q因为我惌论的是现在用EJB的方?直到2006或者JSR-220完成的时??/p>
(tng) (tng) (tng) 在Don的博客上Q我对他拿Springq行的测试表达了(jin)我的敬:
(tng) (tng) Rod:因ؓ(f)你的代码不是严重依赖于容器的Q所以可以方便的q行单元试Q比如用JUnit。这样一来,和过Ml的J2EE容器内测试方案比hQ提高(sh)(jin)巨大的效率。你也可以在Spring容器上做集成试Q而不需要一个重量的J2EE应用服务?---不像其他应用服务器,Spring容器可以很快启动?/p>
Don:我仅仅是说尽量少的依赖于容器QEJBq不是一个完全失败的技术,用OpenEJB容器效率q不?x)很低的Q至从我的试来证明?/p>
Rod:我ƈ不确定像OpenEJBq种轻量U的EJB容器?x)是一个另人满意的解决Ҏ(gu).我没有遇到有人用q它Q我自己也没用过。真正的EJB试LJ杂的,通常需要五分钟一个编?试循环?/p>
Rod:比较一下Spring的Pet Store例子和EJBҎ(gu)的,可以发?在Spring的例子中Q很有冗余的代码,也就是说什么都不做的代?..
比如Service接口,JNDI服务查询操作{等.在我接触的项目中,用一个Spring+Hibernate的合框Ӟ臛_能拿去EJBҎ(gu)?0%---20%的代?对于目的提交和后期l护是有重大意义?
Don:我来说说我的观点,单ƈ不永q是好的Q不q的是,它仅仅代表简单,没有JNDIQ就{于说牺牲了(jin)理人员在不重启服务器的情况下,寚w|进行调整的需要。这可能对于一些客L(fng)应用来说不是太重要,但对于一?4*7的应用来讲就是个大问题(sh)(jin)?/p>
Rod:当然Q我说的用Springl结你代码中?服务接口QJNDI查找",q不是说真的不用JNDI,比如_(d)你还是希望调用EJB,Spring可以l你创徏一个代理,装?jin)JNDI查找啊?/p>
在Pet Store的例子中Q我力L一个简单的架构--既然我们来讨论Pet Store,关键的就是,Spring和其他轻量的框架技术,l了(jin)你一个简易框架的选择。如果是传统的J2EE,你想创徏一个Pet Store,你最好是用Perl或?Net,或者抛弃J2EE的高U特性,只选择Servlet和JSP,所以有一个你自己的简易架构是必要的?/p>
没有JNDIQ就{于说牺牲了(jin)理人员在不重启服务器的情况下,寚w|进行调整的需?,嗯,有多需要用JNDI重新配置应用的需?更好的解x(chng)案是JMX,但应用服务器q不?jin)解你想做什么有意义的配|,同时Spring 1.2已经加入?jin)对JMX的支?q将方便开发者去操作应用对象和配|。比如说Q改变(sh)个JNDI的环境变量是我们很少要做的事?开发者通常?x)很准确地配|这些信息,来避免修改的痛苦?我同意,q可能是个不好的假设Q但实通常是这L(fng))Q你如果想通过JNDI来改变某个|你已l知道何时来扑ֈ?{等?/p>
Don:误住,EJB提供双机事务的支持,而Spring没有Q这一点让我不安,Spring失去?jin)它的亮炏V?/p>
Rod:Spring不会(x)做或者很做双机事务,不知道怎么q定Spring失去它的亮点?Spring的事务层抽象是在事物{略的基上的一层,一个方案就是JTA,在这U方案下Q双Z务来自于应用服务器底层的支持Q而不是Spring.实际?JTA事物{略是我们最早就重视q实现的功能。我明白Q在一个无JTA支持的简单容器下Q丢弃一个落后的local和global事务~程模型是很有意义的.