Agile
-
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()
-
最近的总结
2006-01-24
又是一个多月没有写日志了,总是在瞎忙,今天就把最近的情况总结一下。
1.Linux
取得Shell运行时所在的目录
功能:主要取得了当前运行脚本的绝对目录和参数,这个脚本是晚上帮朋友写的,以前也想写一个类似的脚本,一直没有动手,效果还不错。
#! /bin/sh
name=$0
args=$*
name=`echo $name|sed 's/^\.\{1,2\}\/\{1,\}//'`
if [ ! $(echo $name | grep '^/' - ) ]; then
if [ `pwd` == '/' ]; then
name=/$name
else
name=`pwd`/$name
fi
fi
script=`/bin/ls -l $name | awk '{ print $NF; }'`
while test -h "$script"
do
script=`/bin/ls -l $script | awk '{ print $NF; }'`
done
bindir=`dirname $script`
echo "BaseDir:$bindir Args:$args"在两台机子之间拷贝文件
cat <file0> | ssh <host> "cat > /destfilepath"
这个脚本需要在两台机子之间配置ssh,有可能需要输入密码,很是方便。
2.Tagpstry
换了新的工作,对一些j2ee的框架接触的少了许多,最近在用tapestry(tacos)+spring+hibernate做一个东西,另外用了jdk5.0,用了其中的泛型和annotation的功能,最喜欢String.fromat这个功能了,强。
有时用tapestry进行一些特殊功能的实现,不是太灵活,特别是在基于tacos时,例如当提交form的时候,想要为用户提供一个确认的窗口,直接使用tacos的时候,是很难办到的,我找了它的好些component也没有找到类似的功能,用了一个比较别扭的办法:
<form jwcid="pageForm">
<div>
<label>
<span key="title">标题:</span> </label>
<input name="title" type="text" size="60" value="ognl:document.pageTitle" jwcid="title@TextField"/>
</div>
<div>
<a jwcid="@tacos:AjaxDirectLink" name="dp" id="dp" listener="ognl:listeners.deletePageData" parameters="ognl:{pageDataId}" updateComponents="ognl:{'auditResult'}"/><!--在这个a tag中触发jwcid dp的click事件-->
<a href="javaScript:var ok = window.confirm('confirm?');if(ok){did.style.display='none';document.all.dp.click()}"><span key="deletePageData">删除此记录</span></a>
</div>
</form>使用Tapestry最大的感触是刚开始的时候有些不大适应,用的习惯后就对它强大的功能很是佩服,而且在DW中设计页面正如它所声明的一样,基本上不影响整体页面的效果。
3.Java
说起来实在是不好意思,最近才明白了String.replace和String.replaceAll之间的区别,前者不使用正则表达式,而后者使用正则表达式来执行替换操作。
Jrockit是一个很强大的jvm,利用它提供的工具,可以动态的监视jvm中内存使用的状态,从Bea的文档上知道了Jrockit5.0有内存泄漏检测的工具,令人郁闷的是一直也没有成功的使用这个功能,不知道是否是由于License的限制。Jrockit的性能通过调整jvm的参数可以有很大的提升,公司有一台服务器,双CPU,把Jrockit的垃圾收集改为parallele,同时把-Xmx设为1000M,系统的响应速度得到了很大的提升,呵呵。
Hibernate删除的时候,可以通过它来删除Object,但如果对象的个数多于一个,还是用sql来删除的好,不要猜测数据的多少,因为我们不好预测到所有可能发生的情况,在sql server使用Hibernate的delete方法的时候,按照hibernate的做法,它会先找到所有要删除的对象,之后才删除,我在测试一个程序的时候,发现sql server的后台进程阻塞了好几个,全是由于事先认为数据量不大,使用Hibernate删除不会有太多的影响,就懒得用jdbc来直接删除,其实通过spring的JdbcTemplate非常方便。
4.Python
前些日子用Python写了个程序,先在windows上写,后传到Linux上运行,发现总是不对,在网上搜索了一下,有高人说可能是由于windows和Linux之间换行符的不同赞成的,可以用dos2unix命令解决,不过这个命令不是在所有的Linux发行版上都有的。
5.其它
最近GCT考试结果出来了,还好被录取了,又要上学了,呵呵。今天上午把亲爱的GF送上火车了,心里的一块石头总算落下来了,不过又要给自己找火票了,晚上有同学打过电话来说,回大同的票已经没有了,郁闷,该怎么回家呢?明天再说吧。
-
Python TcpTunnel
2005-09-01
昨天工作中突然要用到Apache Soap中的一个叫做TcpTunnel工具,找了半天才找到,用得时候还是比较好的,就是感觉有时需要保存下来,很不方便,一大堆的输出全在文本框里了,晚上要加班,等频道那边填数据的空隙,就用Python写了一个简单的实现,还是比较好用地:)我把每次请求和响应顺序地写到对应的文件里,什么Cookie啊,JESSIONID啊,全能得到,呵呵:)
下面就是代码:
# -*- coding: cp936 -*-
import socket
import thread
import threading
"""
类似于apache soap TcuTunnle工具的Python实现
"""
class TcpTunnel(object):
def __init__(self,host,port,destHost,destPort):
self.host = host
self.port = port
self.destHost = destHost
self.destPort = destPort
def run(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((self.host,self.port))
s.settimeout(1)
s.listen(1)
i = 0
while True:
try:
conn,addr = s.accept()
rq_o = open(requestOut+"."+str(i),'w')
rp_o = open(responseOut+"."+str(i),'w')
dest = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
dest.connect((self.destHost,self.destPort))
request = Request(conn,dest,rq_o)
response = Response(conn,dest,rp_o)
request.start()
response.start()
print 'Connected by', addr
i = i+1
except socket.timeout,msg:
passclass Request(threading.Thread):
def __init__(self,local,remote,rq_o):
threading.Thread.__init__(self)
self.local = local
self.remote = remote
self.rq_o = rq_odef run (self):
while True:
try:
data = self.local.recv(1024)
if not data:
self.remote.shutdown(socket.SHUT_WR)
break
self.rq_o.write(data)
self.remote.send(data)
except socket.error, msg:
self.remote.shutdown(socket.SHUT_WR)
break
self.local.shutdown(socket.SHUT_RD)
self.rq_o.close()class Response(threading.Thread):
def __init__(self,local,remote,rp_o):
threading.Thread.__init__(self)
self.local = local
self.remote = remote
self.rp_o=rp_odef run (self):
while True:
try:
data = self.remote.recv(1024)
if not data:
self.local.shutdown(socket.SHUT_WR)
break
self.rp_o.write(data)
self.local.send(data)
except socket.error, msg:
self.local.shutdown(socket.SHUT_WR)
break
self.remote.shutdown(socket.SHUT_RD)
self.rp_o.close()
requestOut = "request.out"
responseOut = "response.out"tcp = TcpTunnel("localhost",8080,"www.google.com",80)
tcp.run()BTW:最近心情很不好,可以说是非常地糟,刚才在写这个程序的时候发现自己竟然可以不再想那些烦恼,好像已经完全地忘掉它们了, 随意地实现自己的想法,这时我终于认识到了,我是程序员了已经:)
事情终究要解决的,终究是要有结果的,可是用什么方式结束是个未知数,我希望有好的结果,老天保佑。
-
用PYTHON从HTML中提取数据
2005-06-10
最近刚换了工作,提起换工作,我都不好意思了,二年换了四家,惭愧,这回要认真的体会一家公司了。
前段时间做测试,需要大量的身份证号和姓名,一时手头上又没有那么多,用GOOGLE搜了一下,还真找到一个网页,上面有不少信息,可是不方便提取出来,我想了一个简单的办法,先把这个文件保存下来,再写一个PYTHON小程序,用正则表达式从HTML文件里抽取出想要的数据,调用的时候把输出重定义向到一个文件中,就取到了里面想要的数据。下面是这个小程序,比起JAVA来,代码少了很多。
# -*- coding: cp936 -*-
import sys
import os
import re
import timefilepattern ="""姓名:(.*)身份证:(.*)"""
filep = re.compile(filepattern)
if __name__ == "__main__":
if(len(sys.argv)<2):
print '缺少参数'
sys.exit(0)dump = open(sys.argv[1],'r')
data = dump.read()
result = filep.findall(data)
if(result!=None):for group in result:
name = group[0].strip(' ')
cid = group[1].strip(' ')
if (len(name)>0 and len(cid)>0 and (len(cid)==18 or len(cid)==15)):
print cid+"/"+name+"\r\n",
dump.close()
sys.exit(0) -
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弄当了。
-
python小应用 2
2005-03-22
python小应用可以帮助我们解决一些不大容易的问题。
今天收到了一个邮件,不知道为什么,在gmail里有的邮件总是乱码,点击original message,看到了base64的编码,是gbk,而手边又没有适合的工具来转换编码,用pythong很方便就可以了:)
打开python shell,输入
import base64
msg = base64.decodestring("""base64的编码拷到这里""")
print msg
就可以看到邮件的文本内容了。
由于base64的编码长度一般比较长,所以用"""和"""来括起来这些内容是个不错的选择:)
-
python小应用 1: 修改MP3
2005-03-19
上周买了一个MP3播放器,挺好的。昨天下了一些Queen的MP3,拷贝到了MP3里面,在路上一听,才发现格式错误。回到家里到电脑上放,可以的啊。仔细的检查了一下文件,发现这次下的MP3里都有一张Queen专缉的图片,这就导致了我的MP3无法播放这些MP3了。
今天到公司,正好上网找了一下MP3的格式,顺便用python写了一个程序,修改MP3,把那些信息都删除,MP3就可以正常播放了,程序见下面:
# -*- coding: cp936 -*-
"""
将MP3文件中的ID3V2.3部分去掉,以便在MP3机上播放
用法:mp3lcear [源mp3目录] [生成的mp3目录]
"""
import sys
import os
import string
import shutil
import struct
import thread
import threading
import timemp3suffix = 'mp3'
class Process(threading.Thread):
"""
简单地在运行的过程中显示进度
"""
def __init__(self,msg,sleepTime):
threading.Thread.__init__(self)
self.msg = msg
self.running = True
self.sleepTime = sleepTime
def setPause(self,pause):
self.pause = pause
def setRunning(self,running):
self.running = running
def run (self):
while(self.running):
self.pause.wait()
print self.msg,
time.sleep(self.sleepTime)def usage(code, msg=''):
"""
程序的使用方法
"""
print >> sys.stderr, __doc__
if msg:
print >> sys.stderr, msg
sys.exit(code)
def checkDir(argDir,create=False):
"""
检查目录是否存在,如果create为Ture,则新建一个目录
"""
tempDir = None
if(not os.path.isdir(argDir)):
currentDir = os.path.abspath(os.curdir)
tempDir = os.path.join(currentDir,argDir)
if(not os.path.isdir(tempDir) and create):
os.mkdir(tempDir)
else:
usage(1,"目录"+argDir+"不存在")
else:
tempDir = os.path.abspath(argDir)
return tempDirdef clearMp3(srcFile,destFile):
"""
修改mp3文件,并将其创建到destFile所指定的地址
"""
global process
srcfp = None
filesize = os.path.getsize(srcFile)
try:
srcfp = open(srcFile,'rb')
head = srcfp.read(3)
if(head=='ID3'):
srcfp.seek(3,1)
size = srcfp.read(4)
if(not len(size)==4):
print srcFile+'文件格式错误'
else:
size0 = struct.unpack('b',size[0])[0]
size1 = struct.unpack('b',size[1])[0]
size2 = struct.unpack('b',size[2])[0]
size3 = struct.unpack('b',size[3])[0]
headSize =(((size0&0x7f)<<21) | ((size1&0x7f)<<14) | ((size2&0x7f)<<7) | (size3&0x7f))
filesize = filesize - headSize
destfp = None
try:
dataLen = 0
destfp = open(destFile,'wb')
srcfp.seek(headSize,1)
data=srcfp.read(1024)
while (data!= ''):
destfp.write(data)
data=srcfp.read(1024)
except Exception,e:
print '创建文件'+destFile+'错误',e
try:
if (destfp != None):
destfp.close
except Exception,de:
print de
else:
print srcFile+'不需要修改 拷贝',
try:
shutil.copyfile(srcFile,destFile)
except Exception, ce:
print ce
except Exception,oe:
print '修改中出错',oe
try:
if (srcfp != None):
srcfp.close()
except Exception,se:
print deif __name__ == "__main__":
if(len(sys.argv)<3):
usage(1)
global processsourceDir = checkDir(sys.argv[1])
destDir = checkDir(sys.argv[2],True)print 'Mp3源目录',sourceDir
print 'Mp3目的目录',destDir
process = Process('...',1)
pause = threading.Event()
process.setPause(pause)process.start()
for filename in os.listdir(sourceDir):
srcPath = os.path.join(sourceDir, filename)
destPath = os.path.join(destDir, filename)
if os.path.isfile(srcPath):
print '开始处理 '+filename,
tempfilename = filename.lower()
if(not tempfilename.endswith(mp3suffix)):
print filename+'不是一个mp3文件\n'
else:
pause.set()
clearMp3(srcPath,destPath)
pause.clear()
print '结束 \n'
pause.set()
process.running = False
sys.exit(0)用这个程序修改后的MP3比原来要小一些了,因为一张图片被删除了,起到了给MP3"瘦身"的作用。在那些mp3中,每个都有一张400多K的图片,10几个MP3,就相当一个普通MP3文件的大小了。python写一些小工具很是方便:)
刚才才知道师姐是今天走,我还以为是明天晚上的车。回想一下,从认识到现在,都快三年了也,我,她和她老公经常在一起玩,现在要走了,还不知道什么时候才能再见
,不过以后经常被她宰的机会也少了许多,正所谓那什么,哈。。。
。祝她一路顺风,一路平安^_^ -
jython测试网络程序
2004-06-24
刚用jython测试了一下今天的程序,新的程序使用NIO,用jython交互式的运行方式,可以很方便地测试这种程序,可以手动连接到服务器上,然后向它发数据,像一个功能更加强大的Telnet,同时呢,可以观察服务器的反应,输入特定的数据,看其效果,更容易debug和查看程序的逻辑,比较不好地是它需要我们手动地连接,如果测试量较大很不方便,在今后几天想一想有没有更好的方法:) -
让我无奈的Jython
2004-06-15
Jython,一听这名字我就下决心要学习它,与Java的集成可以说是做到了完美,你几乎不用学Jython的函数库或它的类库,会使Java的类库就可以了。但是与CPython相比,它的严谨性会差一点,上午写了一个py,在文件里调用了一个方法"".jion("a"),在用jython调用没有报错,但是我感觉结果不对,于是在CPython的运行这个文件,它马上检查出了这个错误,这是Jython特有的吗? -
Jython2.1在Jdk1.5中的问题(2)
2004-06-15
昨天回家试了一下运行jython,发生它的报错是org.python.core.PyObject类的格式错误,只好重新编译一下,还好,它可以单独编译。重新打包jython.jar用jdk1.5试运行,正常。现在在Red Hat Linux中使用Jython,还不错,它的命令窗口还以是透明的,这样就能随时看到我桌面上设的陈慧琳了。惟一感觉不好的是一旦进入Jython的交互环境,方向键就变得很难用了,惟一能用的就是退格键,一敲方向键,打出的不知是什么字符,感觉好像还是Unicode字符:)太郁闷了。







