BK863

Friday, August 18, 2006

Tomcat整合GWT

本篇介绍如何通过打包为war文件在Tomcat中装载GWT的应用程序。
需要Google Web Toolkit(GWT) 1.1.0

预准备:制作不含javax的gwt-user.jar包
  • 用zip解压gwt-user.jar文件到空目录thisistmp下
  • 在thisistmp目录下执行 jar cvfm gwt-user-good.jar META-INF/MANIFEST.MF -C * .
  • 复制新制作的gwt-user-good.jar到WEB-INF/lib下
所有需要做的就是以下几点(均由ant的build.xml文件完成):
  1. 在www目录下建立tomcat需要的目录结构 (由ant 的createdir任务来完成)
  2. ${appname}-compile编译生成client部分的javascript代码(由gwt-compile任务来完成)
  3. javac编译所有可能需要的server部分的servlet的class文件,并放到www目录的WEB-INF/classes下
  4. 制作不含javax的gwt-user.jar包,置于WEB-INF/lib下,deploy后会被tomcat加载
  5. www目录整个打成war包
  6. deploy到tomcat
下面列出的build.xml和web.xml文件是需要修改的部分,其余部分都以gwt自带的DynaTable为例。
把修改后的这两个文件放到samples/DanaTable下后,就可以执行ant  warfile来生成war文件了。
需要修改的部分在代码中用=====XXXXX来表示。

  • mainclass就是用applicationCreator 创建的时候写的class name;
  • name是应用程序名,即${name}-compile里出现的名字
  • commonlib.home是tomcat的所在目录,需要里面的servlet-api.jar, gwt-user.jar并不需要放在那里,因为前面已经手动重新生成不带javax的gwt-user.jar
  • 如果在windows下,${name}-compile要改为相应的批处理文件名
  • 因为gwt自动生成的tomcat目录是为host-mode创建的,它本身不包含我们要创建的war包需要的web.xml文件,下面会附带根据DynaTable需要的service而修改的web.xml,放置于应用程序目录下后由ant自动拷贝到www/WEB-INF/下



<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="gwtproj" default="warfile">
<property name="mainclass" value="com.google.gwt.sample.dynatable.DynaTable====XXXXX" />
<property name="name" value="DynaTable====XXXXX" />

<property name="tomcat.url" value="http://localhost:8080" />
<property name="tomcat.username" value="admin" />
<property name="tomcat.password" value="admin" />

<property name="src.dir" value="src" />
<property name="web.dir" value="www" />
<property name="build.dir" value="${web.dir}/WEB-INF/classes" />
<property name="commonlib.home" value="/usr/share/tomcat-5.5/====XXXXX" />


<path id="master-classpath">
<fileset dir="${web.dir}/WEB-INF/lib">
<include name="*.jar" />
</fileset>
<fileset dir="${commonlib.home}/common/lib">
<include name="servlet*.jar" />
</fileset>
<pathelement path="${build.dir}" />
</path>

<target name="createdir" description="create nessary directories">
<mkdir dir="${web.dir}/WEB-INF/" />
<mkdir dir="${web.dir}/WEB-INF/lib" />
<mkdir dir="${web.dir}/WEB-INF/classes" />
</target>

<target name="build" depends="createdir,gwt-compile" description="Compile main source tree java files">
<mkdir dir="${build.dir}" />
<javac destdir="${build.dir}" debug="true" deprecation="false" optimize="false" failonerror="true">
<src path="${src.dir}" />
<classpath refid="master-classpath" />
</javac>
</target>

<target name="gwt-compile" description="use gwt's compiler">
<exec executable="./${name}-compile====XXXXX" failonerror="true" />
<copy todir="${web.dir}">
<fileset dir="${web.dir}/${mainclass}/" includes="**/*">
</fileset>
</copy>
<delete dir="${web.dir}/${mainclass}">
</delete>
</target>

<target name="warfile" depends="build" description="create war file">
<copy todir="${web.dir}/WEB-INF/">
<fileset file="web.xml">
</fileset>
</copy>
<war destfile="${name}.war" webxml="${web.dir}/WEB-INF/web.xml">
<fileset dir="${web.dir}">
<include name="**/*.*" />
</fileset>
</war>
</target>
</project>




<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>calendar====XXXXX</servlet-name>
<servlet-class>
com.google.gwt.sample.dynatable.server.SchoolCalendarServiceImpl====XXXXX
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>calendar====XXXXX</servlet-name>
<url-pattern>/calendar====XXXXX</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsf</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>DynaTable.html====XXXXX</welcome-file>
</welcome-file-list>
</web-app>

Wednesday, August 16, 2006

什么是Thread Safe?

Thread-safety(线程安全)是指代码被多个线程同时执行的时候仍然正常工作。尤其是要满足当多个线程都需要访问同一共享数据空间的时候,只有一个线程能被满足。

多线程执行的时候是处在一个共享地址空间,每个线程都可以访问其他线程的内存空间。为了使程序符合预定的执行的逻辑顺序,提出了线程安全的概念,符合线程安全标准的代码可以更好地得到控制、预测,不至于陷入后期Bug调试而无从下手的尴尬境地。

在实际中要判定一段代码是线程安全的会比较困难,而往往采用相反的策略:如何会导致线程不安全?下面列出了常见的一部分。
  1. 访问了全局变量或使用了堆(尤其没有自动回收的时候)。
  2. 分配/释放全局限制的资源,比如文件,子进程。
  3. 通过指针等类似的间接访问方式。
另一方面,有时也可以保证一段代码(或函数)是线程安全的,如果它:
  1. 仅仅使用栈中的局部变量
  2. 仅访问输入的参数(实际就是在栈中)
  3. 仅调用满足上面两条的代码(或函数)
这种代码属于叫“pure” function,封闭加工的方式工作。再多这样的自闭线程都是安全的。

判定是困难的,但可以在局部范围内完全肯定(或否定)一个命题。强弱的区别。



Python notes(2)

assignments




a,b,c=x

Here the x , the RHS(Righthand side) should be
iterable with exactly 3 items!



augmented assignment the only differencs is that
the LHS object may be modified if it has
coresponding in-place method as __iadd__ for (+).



numeric conversion



implicit : from int, long, float, to complex.
explicit : give (int(), long(), float(), complex() )
a non-complex argument. Also can from a string.


int('435',25) #=> 2580



Arithmetic



-Qold command line switch make (/ and // ) equal.
-Qnew make / a true division or specify


from _ _future_ _ import division

in module file head.



1.*a/b to avoid making any assumption on the types of a and b




divmod(x,y) #=> return (quotient, remainder) pair



Sequence < Container < Iterable



Sequence has built-in function: len(cntnr) ,
min(itrbl), max(itrbl) , and sum(itrbl)


# repetition , concatenation
(3,)*3 #=> (3,3,3)
[24,23,]*-3 #=> []
(42,) + () + (0,) #=> (42, 0)

# membership test
3 in [3,4,5] and '22' in "get22in" #=> True

# indexing
S[-L,-L+1,...-1] = S[0,1,...L-1] #Using an index >=L or <-L raises an exception

# slicing
S[i:j(:l)] #=> all S[n] where i<=n<j
#=> i(=0, omit or <=-L)
#=> j(=L, omit or >=L)
#=> S[n] = S[L+n] if n<0
#=> l, the step, this is called extended mode

# list slicing modifying
S[i:i]=[1,2,3] #=> insert 1,2,3 before 'ith'
S[::2]=[1,2,..n] #=> should have same numbers as in this extended mode

List Methods:

















MethodDescription
L.count(x)num of occurence of object 'x'
L.index(x)first index of 'x', or Exception
L.append(x)
L.extend(iterable)
L.insert(i,x)
L.remove(x)
L.pop([i])
L.reverse()
as is








Sorting!




L.sort([f]) #=> sort L ascending, as
#=> def cmp2ndword(a, b): return cmp(a.split( )[1], b.split( )[1])
#=> L.sort(cmp2ndword)
L.sort(cmp=cmp, key=None, reverse=False) #=> function: cmp(a,b) , key(x), reverse=True/False
#=> sorting works as cmp(key(x),key(y))

Note : Passing compare function is much slower than the following two methods
as (called decorate-sort-undecorate DSU)

A = [ (s.split( )[1], s) for s in L ]
A.sort( )
L[:] = [ t[1] for t in A ]

# or Use operator pass key= to sort (use cmp as few as possible)
import operator L.sort(key=operator.itemgetter(1))





Sets



Basic set operation :












NonmutatingMutating
copy()
difference(S2) ('-' )
intersection(S2)('&' )
issubset(S2)
issuperset(S2)
symmetric_difference(S2)('^' )
union(S2)('|' )
add(x)
clear()
discard(x) (no warning)
pop()( kick one out)
remove(x) (error not found)


pop() is useful when want to save memory during a 'consuming' process



Dictionaries



Basic set operation :












NonmutatingMutating
copy()
has_key(k) (as 'k in D')
items() (list item a pair)
keys()
values()
iteritems(),iterkeys(),itervalues()
get(k[,x]) (D[k] or x if not k found)
clear()
update(D1) (D1 update to D)
popitem()
setdefault(k[,x]), pop(k[,x])


popitem() is same useful as pop() in a set.



setdefault(k[,x]) same as get(k) but if not found auto-set it. pop(k[,x]) works oppositely which also does unbinding.



D[k] and pop(k) may raise exception, D.get(k[,x]) and pop(k,x) return x or None if not found.
update() semantics same as dict() :


dict([(1,2)])
dict(x=1)
dict({'z':1} ,x=42, y=2, z=7)



String formating



as C's printf, Python string offers output format as below:



































































CharacterOutputformat
d,idecimal integer
uunsigned integer
o,x,Xunsigned octal, hexadecimal, Hexadecimal
e,Eexponential form
f,Fdecimal form
g,Gauto exponential/fixed point
csingle character
rrepr
sstr
%%
Modifier CharacterEffects
%(name)use values from a dict
%#use alternate form to convert
%0zero-padded
%-left-justified
%spaceone space padded to a positive number
%+ with (+/-) signs
%*.*take width.precision from values like "%. f" % (5,3,2.1) which is as same as "%5.3f" % 2.1 => "2.100"


%s will be auto-replaced with str(value) which is very useful as below:

one = "x:"+str(x)+" y:"+str(y) # same as below
another = "x:%s y:%s" %(x,y)

Another formatter is string.Template which could be subclassed to provide
customization(See Template strings).



Examples:


>>> from string import Template
>>> s = Template('$who likes $what') # construction
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
>>> d = dict(who='tim')
>>> Template('Give $who $100').substitute(d) # $100 is not valid placeholder
Traceback (most recent call last):
[...]
ValueError: Invalid placeholder in string: line 1, col 10
>>> Template('$who likes $what').substitute(d)
Traceback (most recent call last):
[...]
KeyError: 'what'
>>> Template('$who likes $what').safe_substitute(d)
'tim likes $what'



looping



It's possible to extract multi values from an item during only one looping.
The item should be iterable and has exactly as many items as there are in the
target list.


for key, value in d.items( ):
if not key or not value: # keep only true keys and values
del d[key]

Note: Must not use d.iteritems() which del d[key] will raise a
runtime error : "dictionary changed size during iteration".
The iterable should not be modified (items in it could be).



xrange(n) and range(n) : xrange() will consume less memory but a little slower during
iterating. range() could be used wherever xrange() could but not vice versa.



else in Loop : If loop terminates via break, return or exception,
the else excutes.



pass : do nothing in a looping body which should never be empty.

难道奇迹发生了?

在看到这篇访问blogspot更简洁的方法的时候激动了一把,不过更大的激动来自于后面。
当然用http://www.pkblogs.com/googleblog/是可以访问的,但当我点next blog后,地址栏显示的是原来的地址,再试了几个blogspot后都畅通无阻!

此时此刻: 浙江电信,2006.8.11  09:30左右,记录一下
虽然我怀疑是暂时性的解封,比如GFW正在重启,呵呵,应该没那么烂吧?

这个比较搞,骗你没商量

怎么使你上班看网页的时候,让老板看起来觉得你在努力工作(在处理word 2003应该算吧)?
去这里http://www.workfriendly.net/看看,输入一个网址,比如http://slashdot.org/
自动弹出一个word风格的界面,注意,只是word风格的界面!自己不要把它当word来用哦,嘿嘿
值得注意的是地址栏旁边的Boss key ,这个似乎太明显了。。。所有的图片当然没咯

脑子有点晕

为什么Pi可以这么算?想不出来。。。

lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
while s != lasts:
lasts = s
n, na = n+na, na+8
d, da = d+da, da+32
t = (t * n) / d
s += t

Pi = 3 + 3 (1/24+ (1+8)/(24+32) + (1+8*2)/(24+32*2)+ ... ) ?

O'Reilly 分析的网站开发语言走势

看图说话:

php作为网站开发的老大,终于收到了挑战。是什么促生了javascript的跳跃式发展?毫无疑问,这与google带来的GWT(Google Web Toolkit)是分不开的。他使得写像Google地图Gmail等AJAX程序变得如此轻松。说白了,web 2.0最主要的特色就是动态的内容。而在没有GWT的时候,纵使javascript如此之强大,要掌握并发挥出它的特色功用并拓展为整体框架已是困难重重,更别说是在后期的不同浏览器,不同的平台的上花费的调试时间。GWT作为一个翻译器,把一般化的整体框架设计问题转化为java语言方式的设计实现问题,然后经它翻译后变为各个平台浏览器通用的javascript并于后台服务器沟通。不能不说这怎么会不是一项令人疯狂的技术。是GWT成就了javascript.

2005年末还有一个重要的杀手, 铁轨上的红宝石( Ruby on Rails, 这个翻译不错吧,嘿嘿) 。很难想象,历史竟然在同一时刻,在不同地方惊人地重复着。Rails成就了Ruby,一个古老而神秘的东方语言,1993年出自一个日本人之手。Ruby本身给我的感觉就像真的ruby,华丽,神秘,但忍不住会觉得做作的感觉。感觉归感觉,理性的动物不该只顾及感觉。Ruby语言确实是精炼的语言,但有的时候甚至觉得简陋(一个重要原因当然是我还不太熟悉)。而且他简陋的文档又将大大提高他的门槛(其实文档还是有的,只是大陆把ruby-doc封锁了,估计是跟某个XX网站沾到了,真不知是哪辈子做的孽,遭罪的却是我们)。这里还有个奇怪的问题,你能想象一个日本人写的语言,竟然不支持自己的本土语言吗? Ruby里所有的字符都是按单字节ASCII处理!没有任何utf8支持(至少在Ruby 1.8) 我猜测Matz本人( Ruby作者: Yukihiro Matsumoto)会很鄙视C#的这种代码:


public class 猪头
{
public void 去死吧()
{
Console.WriteLine("这样也可以-_-b");
}
}
回过头来说Rails, 它用Ruby把网站开发中MVC彻底分离, 无需任何配置文件,内部控制所有网站的逻辑,同时提供完整的数据库访问操作. 你能想象一行代码 scaffold: 把所有的CRUD基本操作全部实现吗? 这就是Rails带来的令人诧异而富有吸引力的tutorial给我的印象。当然这仅仅是tutorial,离真正的成品还远着,不过这足以使Ruby让人眼球了一把。

python是真正的程序员的语言,但或许它不适合作这种开发,或许,呵呵,它在等待着 "python on a Elephant" 中的大象。想起小新的“大象大象鼻子怎么那么长”,嘿嘿。


python notes(1)

Comment



(#) not inside ("") begins a comment



miscellaneous



empty physical line to terminate a multiline statement



(\) join two adjacent physical line into a single logical line.
but, if an open parenthesis ( (,[,{ ) has not been closed,
python automatically joins them.



continuation line do not need to be indented but only the logical line begins with.



_ in interactive : last expression



identifier nomenclature




[A-Z]\w* : class names
^_ : private identifier
^__ : strongly private identifier
^__\w+__$ : language-defined special name
_ in interactive : last expression



numeric data type



\d*(l|L)$ : explicitly denote a long integer, ('l') is not recommended!! 长得太像1了!



sys.maxint(as 0111) : lagest positive plain integer



-sys.maxint-1(as 1000=1111(-1)-0111) : most negative plain integer



z.imag : this bizar name(maybe wanna to keep 4 characters long as 'real') means
the image part of a complex literal.



关于浮点,这篇文章不得不提:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
at http://docs.sun.com/source/806-3568/ncg_goldberg.html
有空去翻译一遍。



Sequences



Sequences 有strings,tuples,lists。strings下面有单独介绍。
分别用tuple(an iterable ),list(an iterable )来构造。
Python 中的iterable是sequence概念的推广,all sequences are iterables.



tuple series of expressions (the items of the tuple) separated by commas (,).
外面的括号不是必须的,但要表示一个tuple传给函数做变量则需要括号,否则逗号会被
解释为函数参数列表分隔用。当然,要表示空tuple就少不了;要表示一个项的tuple,
还需要在最后右括号前加逗号。如下:


need_tuple((3,4,5)) # 一个tuple做一个参数
need_3args(3,4,5) # 3个int作3个参数
(),tuple() # 空tuple
(3,) # 一个项的tuple
(3) # 3 , an int



list 与tuple不同,需要外面的([和] )。
比较有特色的是List comprehension 。实际就是用for loop把
一个个满足条件的target, append到生成的list里面。
比如:


# 生成一个不为0的list
result1 = [x+1 for x in some_sequence if x!=0]
# 还可以多嵌套,
[x+y for x in alist for y in another]
# 这与下面的双循环等价
result6 = []
for x in alist:
for y in another:
result6.append(x+y)



Sets



set and frozenset which are found in module 'sets'
use the following codes to auto select for either Python 2.3 or Python 2.4:


try:
set except NameError:
from sets import Set as set, ImmutableSet as frozenset
# create a set
set
set('rrrrr') #->set(['r'])

Items in sets is Hashable , frozenset it self is Hashable, but not set.
So no set(except frozenset) can belong to set(include frozenset).


Dictionaries



As sets, keys in a dict should be hashable , value could be any type.
dict itself is mutable, not hashable.


# only last key matters
{'x':1, 'x':2} #=> {'x':2}
dict() #=> empty dict
dict([(1,2)]) #=> from an itarable of **pairs**
dict(x=1) #=> what the fucking is this??!! a {'x':1} ?? I hate it!
#and the following eccentric mixture! gives {'y': 2, 'x': 42, 'z': 7}
dict({'z':1} ,x=42, y=2, z=7)

#this is useful
dict.fromkeys('iloveu',8) #=> {'e': 8, 'i': 8, 'l': 8, 'o': 8, 'u': 8, 'v': 8}



boolean



Any nonzero number or nonempty container(string, tuple, list, set, or dictionary)
are True .



0 (of any numeric type), None, and empty containers are false.


i = 1
i += True # i = 2





String !



一般的quoting可以使用( '或" ),但python比较特色的triple-quoting( """或'''
二者的区别就在于一般的quoting里不能有 换行 quote符号本身 ,相同点是:都不能有
没被反斜杠的反斜杠(原因当然是因为反斜杠比较反斜杠,或者叫比较转义,另类的意思)



开头加r或R的则上面的连反斜杠的问题都解决了,缺点当然就是你输入不了\DDD或\xXX,因为\已经
变成平民了,不再具有任何特权。不过想连接多行(single-quoting),行末尾的\还是少不了的,
但不是起原来反斜杠的作用了,而是表示“这里换行前面有一个我其实不想要,但不得不要的\ "



Unicode String
如果代码里有中文,那么只有把中文放在u"" 这unicode string里,而且还要在文件开头 指定编码,
就像:


# -*- coding: cp936 -*-

unicode string除了有相同的反斜杠类:行尾的\, \\, \', \", \a(Bell), \b(Backspace),
\f(form feed, 不知道干吗的),\n, \r(Carriage return, 著名的^M), \t, \v, \DDD, \xXX,
\other(不变,但没有\),还多了个\uXXXX指明一个unicode字符,而且还有一个\N{name },
name
http://www.unicode.org/charts/
里找。(比如\N{Copyright Sign})






All about character/encoding/utf-8



use other character set ONLY in string literals and comments
add following at the start of source file


# -*- coding: utf-8 -*-

windows live!evil swodniw

windows live 空间终于改版了,终于改得更慢了。
而且地址也要多打一个字了(msn->live,虽然用msn还是能访问)。
30秒后居然才刚能看到顶上硕大无比的广告条。我顶!你个广告条!~

但更令人惊讶的是竟然还是有如此众多的用户。。。
最近开始发到这里的唯一原因是用了 Performancing(应该还有别的工具可以完成这个功能),不用打开这巨space无比的space就能直接发表,大大提高发贴的速度和激情! Just publish it!

如果你有多个blog 空间需要你去照顾,那么恭喜你, Performancing又可以助你一臂之力。
  • 添加多个blogs易如反掌;
  • 同时还可以自动获取分类,并提供发表分类的选择;
  • 更新或删除旧的文章;
  • 暂存草稿,修改后随时发表。
心动了就赶紧行动。
介绍链接地址:http://performancing.com/

下载地址:https://addons.mozilla.org/addon.php?id=1730

超酷的小男孩

下载地址:ftp://mainfei:mainfei123456@218.30.67.86:2221/film40713001.wmv
声音很赞~!



Google Talk的新功能

正式下载地址上没有该连接,补下载地址:
http://desktop.google.com/download/googletalk/googletalk-setup-testing.exe

File Transfers


文件传输的功能,如果可以通过google的服务器中转那自然可以方便教育网与公众网,但估计不太现实,还是通过邮件吧。
比较需要的功能是:不用登陆到网页就能发邮件的gtalk附加界面。

Voicemail

语音留言。相当有用的功能! 收到邮件的人可以直接在gmail里播放留言。 绝对胜过枯燥的文字。

Music Status

略。(爱用就用)我不用这些播放器。
目前仅支持:

test ag

re