Agile
-
有好些日子没有写Blog了,奥运越来越近,工作是越来越忙了,呵呵。
最近主要是在搞公司的工作, 抽空把Scala研究了一下。
用Scala写了一些程序,因为还不熟悉,所以经常要查文档,看资料。
着重研究了一下Scala的Actor用法,在此推荐两篇论文:
Event-Based Programming without Inversion of Control 和 Actors that Unify Threads and Events,
这两个论文都是在Actor 的API中引用的。
Sala的Actor即有Erlang中轻量级Process的优势,又可以直接当作本地线程使用。
我总结了一下,对于Actor的使用,基本上可以根据任务的特点来决定使用哪种了:
1.cpu相关的
对于这种任务,无论是Erlang的Process,还是Scala的Actor都可以支持得很好,Scala的实现是用一个线程池来执行Actor,它可以根据cpu的个数决定线程池中工作线程的个数,同时根据任务的个数,适时的调整这工作线程的个数。
写法在Scala的例子中有很多,类似如下:
loop { react { ........ } }
2.io相关的这种任务主要的工作不在cpu,而在IO操作上,比如读写Socke等,类似这种操作的时候,最好使用Actor的线程特性,也就是在ract的时候,根据参数新创建一个Actor来执行和IO相关的任务,下面的“主Actor”的任务是接收消息,每收到一个消息就启动一个Actor去请求页面的内容,然后再做相关的处理,这也是Actors that Unify Threads and Events 里所主要表达的内容。
loop {react {case url:String =>
actor{
//由个新建的actor执行IO操作,避免阻塞后续的其它的请求
val response = HttpUtil.get(url)
}
}
}
用Scala写并发方面的程序要比Java来得容易,Actor的使用要小心一些,否则不小心就搞出一个“串行”来,呵呵。
说说Struts2吧,
很久没有用过Struts2之类的Web框架了,最近在用Struts2,开始是同事基本上把环境都搭好了,我只需要下载更新后,按步就班地开发就好了。昨天需要我从开始弄一个应用,那就一个背。照猫画虎地把应用弄起来,写action,写jsp,还算顺利。这时发现了一个问题,因为我用的了所谓的"模型驱动"这种参数注入方式,OGNL以前也用过,它可以根据表达来给Action中的对象属性设置由页面中传入的参数。
private Sample sample;
public void setSample(Sample sample){
this.sample = sample;
}
有了上面这段代码,OGNL就能自动地把提交的参数设置到sample这个对象的属性中,比如sample.user.
这就让我产生了一个疑问,如果用户知道我们的Action中的其它setter方法,那会不会受到”攻击“呢。
我试了一下,
private OwnSample ownSample;
public void setOwnSample(OwnSample sample){
this.OwnSample = sample;
}
假设用户知道有这么一个属性可以用,那种他在发送请求的时候会加上一个ownSample.id=XX之类的参数,就会造成OGNL首先会生成一个OwnSample对象,然后设置属性,然后调用 setOwnSample设置给Action中。如果这个参数是使用其它的途径注入,如用Spring,那用户设置的参数会被覆盖掉(在这种情况下也是有害的,因为无谓地多生成了一次对象,还要看创建对象的代价大小,如果是那种比较费时的创建那就惨了),反之用户的参数就会生效了。
虽然是内部使用的程序,我觉得还是能避免这种问题最好,找了一下API,发现可以定义一个acceptableParameterName的方法来过滤一下参数就保险了。
类似的问题还有Struts2在配置文件中定义Action的时候,支持通配符,例如:
<action name="user_*" class="com.UserAction" method="{1}">
这种配置我觉得也是有风险的,如果UserAction里有一个一般用户都不知道的方法,那么如果被猜出来,或者被“离职的职员”恶意访问,问题就大了,除非对这种方法有额外的权限检查。所以如果有这种问题,还是勤快点儿,尽量少用通配符的好,呵呵。
这两个问题是我正经用了两天Struts2之后感觉不太对的地方,写出来,也可能有更好的解决办法,供大家留意一下。
多说一句,现在的各种框架的Demo 或者样例一般是怎么简单怎么来,让人一看就觉得这太简单了,太好用了,省得我老得request.getParameter一个一个的把参数凑整齐再用,这么用多方便。我们还是小心点好,Demo中的例子,不一定在生产环境中靠谱,还需要我们自己推敲一下。:)
-
Tapestry4.0中的session
2006-05-11
Tapestry4之前在Page类中访问HttpSession或HttpRequest是很方便的,这样子就可以了IRequestCycle.getRequestContext().getSession(),昨天看了一下它的源代码,竟然有这样子的注释“
/**
* Returns the {@link RequestContext}. This is provided to ease the upgrade from Tapestry 3.0.
*
* @deprecated To be removed in 4.1.
*/”
在4.1的时候会被删除,虽然我现在用得还是4.0,考虑到以后的升级还是决定不这样做了。
那只好这样子用了
/**注入Request*/
@InjectObject("infrastructure:request")
public abstract WebRequest getRequest();public void login(IRequestCycle cycle) {
this.getRequest().getSession(true).setAttribute("user", getName());
}上面的方法能够在session中保存对象,可想删除怎么办呢? this.getRequest().getSession(true)这样子得到的对象是Tapestry包装的WebSession,当中竟然没有removeAttribute这个方法,郁闷。看看Api中是怎么说的,attribute the new value for the attribute, or null to delete the attribute entirely.
找到答案了,把属性设为null就从session中删除这个对象了。
this.getRequest().getSession(true).setAttribute("user", null);
用了一段时间Tapestry觉得在开发的时候最好看看它的源代码,有些问题文档上没有,看源代码就很明白了。
最近在做新的项目,竟然把以前一想就头大的javascript用了不少,第一次发现原来javascript可以这样写,在写之前看了些Prototype的东西,在写我们自己的项目的一些页面功能时,参照着Prototype的方法来做,竟然也有点面向对象编程的感觉。
刚过完五一,工作起来状态恢复得慢,今天才差不多有些感觉了,继续努力工作,好好学习:)
-
jsp tapestry asp.net 处理大量组件/tag的比较
2006-02-27
最近在工作中遇到一个问题,有一个jsp很大,其中包括了有300多个tag,反应是无法编译(在有的服务器上可以编译,但无法加载),打开生成的java文件,发现在jspService中有超过5000行的代码,其生成的class的code属性的长度超过了65535这个限制,jvm加载的时候认为是无效的class文件,抛出异常。必须给它减肥了,再就是把文件的内容分成两个文件来存放,分别编译,解决问题。
今天突然又想起这个问题了,想看看Tapestry是如何应对这种情况的呢,另外今天开始学习asp.net,也想看看它的反应如何,由于写了一个变态的测试程序,生成所需要的测试文件。
下面是python脚本:
#生成taspstry的测试文件, 生成20000个tagestry 标记
f=open("t.html","w")
s0="""<span jwcid="$content$">"""
s1="""<div><span jwcid="@Insert" value="ognl:msg" raw="true"/></div>"""
s2="</span>"
f.write(s0)
i = 0
while i<20000:
f.write(s1+"\n")
i=i+1
f.write(s2)
f.close()#生成jsp的测试文件, 生成2000个jsp tag标记
f=open("t1.jsp","w")
s0="""<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>"""
s1="""<div><c:out value="test"/></div>"""
f.write(s0)
i = 0
while i<2000:
f.write(s1+"\n")
i=i+1
f.close()#生成asp.net的测试文件, 生成20000个Label组件
s0="""<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
</head>
<body>"""s1 = """<asp:Label ID="Label%d" runat="server" Height="32px" Width="72px"/> """
s2="""</body>
</html>"""f=open("t1.aspx","w")
f.write(s0)
i = 0
while i<20000:
f.write(s1%(i)+"\n")
i=i+1
f.write(s2)
f.close()
-
websphere中的数据库编程一定要注意的一个问题
2005-04-07
在websphere上做数据库的开发,一定要注意数据库获取连接的问题。因为websphere会自动的有一个本地事务处理的规则,如果在应用程序日志中发现有
J2CA0086W
这样的信息,那就一定要检查程序中管理数据库连接的方法地。典型的情况下,这种问题是由于下面的调用方法导致的:
get connection1
use connection1
get connection2
use connection2
close connection 2
close connection 1
就是在已经取得一个连接的情况下,在没有关闭它之前又取得了一个连接,由于websphere的本事务规则会把它们放到shared pool中,会引起连接不够用。导致系统中大量的线程等待连接.
-
pyton小应用 3:分析javacore文件
2005-03-29
前段时间,websphere总是当机,其实也不是当,就是响应特别的慢,几乎没有响应了。实在没有办法只好生成javacore,看一看线程的情况。他们是每隔10分左右生成一个javacore,在websphere中,生成的内容全部在native_stdout.log中,开始看的时候发现有很多线程的调用栈中都有
- locked <0xc2527c58> (a oracle.jdbc.ttc7.TTC7Protocol)
我怀疑可能是这里的问题,用眼看那些日志可真够受的了,也得不到什么有用的信息。就用python写了一个分析程序,把这些locked全找出来,于是就写了下面这个小程序:
# -*- coding: cp936 -*-
import sys
import re
pattern = '[\s*]- locked <0x(.*)>.* \\(a oracle.jdbc.*\\)'
prog = re.compile(pattern)
lockMap = {}
lineMap = {}
if __name__ == "__main__":
if(len(sys.argv)<2):
print '缺少参数'
print sys.argv[1]
print '行数','地址','内容'
dump = open(sys.argv[1],'rb')
line=dump.readline()
ln = 1
lock = 0
crash = 0
while line!='':
#print line
result = prog.match(line)
#print result
if(result != None):
lock = lock +1
objectref = result.group(1)
if lockMap.has_key(objectref):
crash = crash + 1
lockMap[objectref].append(ln)
else:
lockMap[objectref]=[ln]lineMap[ln] = result.group(0)
print str(ln),objectref,result.group(0)
line = dump.readline()
ln = ln+1
print '共有'+str(lock)+'个锁对象出现'lockkeys = lockMap.keys()
print '\n'+str(crash)+'个锁被两个或两个以上的线程取得\n'
print '锁对象\t在log中出现的行数'
for key in lockkeys:
print str(key)
for lc in lockMap[key]:
print '\t'+str(lc)+str(lineMap[lc])
#print lockMap
sys.exit(0)通过对native_stdout.log运行这个程序,得出的结果就是:
......
共有288个锁对象出现
144个锁被两个或两个以上的线程取得
锁对象 在log中出现的行数
c0e6aef0
2562 - locked <0xc0e6aef0> (a oracle.jdbc.ttc7.TTC7Protocol)
5995 - locked <0xc0e6aef0> (a oracle.jdbc.ttc7.TTC7Protocol)
c04e1ae8
2990 - locked <0xc04e1ae8> (a oracle.jdbc.driver.OracleConnection)
6423 - locked <0xc04e1ae8> (a oracle.jdbc.driver.OracleConnection)
c1da32c8
2019 - locked <0xc1da32c8> (a oracle.jdbc.driver.OraclePreparedStatement)
5452 - locked <0xc1da32c8> (a oracle.jdbc.driver.OraclePreparedStatement)..............
由这个结果可以知道,144个锁在线程中被引用,通过结果中显示的行数,locked后面的对象锁始终是被同一个线程持有,比如:
2019 - locked <0xc1da32c8> (a oracle.jdbc.driver.OraclePreparedStatement)
5452 - locked <0xc1da32c8> (a oracle.jdbc.driver.OraclePreparedStatement)这里有一个对象<0xc1da32c8>在同步块里,而在2019和5452这两行上,找到它们的线程号,是同一个,其余的也是一样的结果。这就排除了死锁的可能,也初步排除了程序造成死锁的可能。
而在每个这样的输出中,都有下面的内容:
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Unknown Source)就是由于在读数据的时候线程被阻塞了,导致很多的线程被挂起,在这里是77个线程被挂起了。
我怀疑是oracle的jdbc驱动的问题,于是在网上找资料,果然有相似的问题。于是就按照oracle metalink上所说的,下了一个10g的驱动来用,(忘记说了,我们用的是9.2.0.5那一个驱动),在本地测试了一下,问题没有再现,把服务器上的驱动换掉,现在已经是第3天了,一直没有当机,而且连接也很正常。:)
9.2.0.5的驱动有严重的bug,它可能会导致server当机:(
另外,要避免这个问题发生,还可以通过设置查询超时来避免,不至于把server弄当了。
-
一个好工具
2005-03-18
最近在配置一个websphere,可以刚配置好后就起不来了,检查启动日志,发现ssl的443端口已经被占用了,可一时又找不出是哪个过程占用的端口,同事推荐了一个叫做Fport的程序,拿来一运行,不错,马上找到了占用443的是IIS,关掉IIS,没事了:) -
好用的myEclipse
2004-07-28
今天下载了一个,装上后不能使用,找了半天不知道什么毛病,卸载其他的J2EE开发插件再试,不错,成功了,哈哈.....慢慢研究吧...... -
实践maven
2004-07-12
上周6下了Maven,准备自己实践一下。真是万事开头难。安装比较顺利,设置完环境变量,在命令窗口下敲maven -v,显示了下面的图案,正常。
__ __
| \/ |__ _Apache__ ___
| |\/| / _` \ V / -_) ' \ ~ intelligent projects ~
|_| |_\__,_|\_/\___|_||_| v. 1.0-rc4之后想编译一个项目试试,把一个现有的项目拖过来,照着例子修改project.xml,运行maven jar,一大堆的问号,不知道在说什么,不过在过程中它不断地从http://www.ibiblio.org/maven(这个网站我刚才上还是上不去)上下载jar包,不过总是连接超时,让我百思不得其解,这样来回折腾了10几次,还是一要的问题,就在想它是不是在自动地下载一些需要的jar包呢?后问网友,确认。并给了我几个有效的网站,在build.properties加入:
maven.repo.remote=
http://www.ganet.org/maven/,
http://dist.codehaus.org/,
http://public.planetmirror.com/pub/maven/,
http://mirrors.sunsite.dk/maven/(这里其实是在一行,因为显示不好看,我就把它们分开了)
再试,ok,虽然还有问号,但是已经可以下载jar包了,好不容易把需要的jar包下载完毕,开始编译,正常,生成jar包。
接着试maven site:generate,开始出现更多的问题了,现在几乎所有要用到包都已经下载了,但还是有异常,也不知道是什么异常。查看maven的帮助,有个选项-X,会输出deubg信息,加上一试 maven -X site:generate ,输出了好多的信息,前面的现在用不到,到最后有异常栈出现时,暂停输出,发现是ClassNotFound异常,我想要用到的jar差不多都已经下载了,还会有什么问题呢,我尝试打开其中一个有问题的jar,报告文件错误,看来是下载时文件被破坏了。从%USER_HOME%\.maven\repository中把这个包的所在的目录做掉,这下好了,它开始重新下载文件了,这样反复几次总算生成完毕了。到targe\docs下看,很漂亮,功能很强,就是时间长了点儿:)。
最后尝试maven site:deploy,这次是没办法了,因为它要用ssh来上传文件,而我没有ssh服务器,问朋友,说windows下没有ssh服务器,放弃了:(等有时间在我家的Red Hat上试试吧。
这个过程差不多花了我一天的时间,总体上感觉Maven真是棒极了,除了中文的输出有些问题,我要尝试一下看自己能不能解决掉:)
让我郁闷的是,我把它介绍过一同事,那小子竟然说Maven和Ant差不多,没办法,自己研究吧:)
-
Ejb3
2004-05-08
早上一打开电脑,启动了NewzCrawler,在Gavin的blog上看到了有关EJB3的介绍,http://blog.hibernate.org/cgi-bin/blosxom.cgi/2004/05/07#ejb3,大概的看了一下,和以前的ejb规范相差很大,总之是更易使用了,感觉很像一些JAVA开源社区的产品的集成,像Hibernate,Spring等。 -
Eclipse3M6+Lomboz+Jboss3.2.1开发EJB
2004-02-09
Eclipse3M6+Lomboz+Jboss3.2.1开发EJB。
在Lomboz的server配置中选择好jboss的安装目录,配置好jboss。在Window窗口的show view 中打开Lomboz的J2ee View窗口方便调试。
使用Lomboz的wizard建立j2ee工程,会在目录下生成EJB相关的配置文件,使用wizard生成session bean,直接对业务方法编程。选择此session bean点右键选择"create ejbs",系统自动生成EJBHome,,EJBRemote等类,真是方便。







