Archive for the ‘Uncategorized’ category

SASS入门

July 26th, 2010

使用SASS写css非常有趣的,它是对CSS3的扩展,增加了嵌套,变量,混合(mixin),选择器继承等功能。SASS通过工具或插件转化成格式化好的css文件。
SASS有两种语法,新的语法叫SCSS(Sassy CSS),是CSS3的超级,兼容CSS3语法,所以CSS3文件可以直接当作SCSS.SCSS格式的SASS后缀名是.scss

$blue: #3bbfce;
$margin: 16px;

.content-navigation {
  border-color: $blue;
  color:
    darken($blue, 9%);
}

.border {
  padding: $margin / 2;
  margin: $margin / 2;
  border-color: $blue;
}

老的语法就叫SASS,灵感来源于Haml,它的目标是简化css的编写。
该格式使用缩进(类似python)分块,不需要写括号和逗号。旧语法的文件名后缀是.sass

$blue: #3bbfce
$margin: 16px

.content-navigation
  border-color: $blue
  color: darken($blue, 9%)

.border
  padding: $margin / 2
  margin: $margin / 2
  border-color: $blue

安装工具

需要Ruby支持,gem install haml
运行命令监听文件或文件夹

sass --watch style.scss:style.css
sass --watch stylesheets/sass:stylesheets/compiled

更多参考http://sass-lang.com/tutorial.html

迁移redmine中文乱码问题

July 23rd, 2010

首先保持原数据库和目标数据库的编码格式都是utf8,导入的时候,先运行set names utf8,
如果新部署了redmine程序,还出现乱码,记得在config/databases.yml上
production的数据库加上encoding:utf8

通过useragent判断客户端

July 1st, 2010
 /**
	 * 传入http请求的UserAgent
	 * 根据它判断是手机还是电脑发送过来的请求
	 * @param userAgent
	 * @return
	 */
	public static boolean choose(String userAgent) {
		if (userAgent.indexOf("Noki") > -1 || // Nokia phones and emulators
		      	userAgent.indexOf("Eric") > -1 || // Ericsson WAP phones and emulators
		      	userAgent.indexOf("WapI") > -1 || // Ericsson WapIDE 2.0
		     	userAgent.indexOf("MC21") > -1 || // Ericsson MC218
		     	userAgent.indexOf("AUR") > -1  || // Ericsson R320
		     	userAgent.indexOf("R380") > -1 || // Ericsson R380
		    	userAgent.indexOf("UP.B") > -1 || // UP.Browser
		     	userAgent.indexOf("WinW") > -1 || // WinWAP browser
		     	userAgent.indexOf("UPG1") > -1 || // UP.SDK 4.0
		     	userAgent.indexOf("upsi") > -1 || //another kind of UP.Browser
		     	userAgent.indexOf("QWAP") > -1 || // unknown QWAPPER browser
		     	userAgent.indexOf("Jigs") > -1 || // unknown JigSaw browser
		     	userAgent.indexOf("Java") > -1 || // unknown Java based browser
		    	userAgent.indexOf("Alca") > -1 || // unknown Alcatel-BE3 browser (UP based)
		     	userAgent.indexOf("MITS") > -1 || // unknown Mitsubishi browser
		     	userAgent.indexOf("MOT-") > -1 || // unknown browser (UP based)
		     	userAgent.indexOf("My S") > -1 ||//  unknown Ericsson devkit browser
		    	userAgent.indexOf("WAPJ") > -1 ||//Virtual WAPJAG www.wapjag.de
		     	userAgent.indexOf("fetc") > -1 ||//fetchpage.cgi Perl script from www.wapcab.de
		     	userAgent.indexOf("ALAV") > -1 || //yet another unknown UP based browser
		    	userAgent.indexOf("Wapa") > -1 || //another unknown browser (Web based "Wapalyzer")
		     	userAgent.indexOf("Oper") > -1) {
			return true;
		} else {
			return false;
		}
	}

Differences between objective-c vs objective-c 2.0

June 28th, 2010

Apple has an overview of Objective-C 2.0 on its Web site, though it’s worth noting that the version of Objective-C 2 on the iPhone doesn’t include garbage collection. Basically, the differences amount to:

  • Garbage collection (on the Mac)
  • for (id object in collection)
  • Properties and dot-syntax
  • Changes to the low-level runtime functions

Objective-C++ is a compiler mode that allows you to intermingle C++ code with Objective-C code in the same function body.

快速 Python 语言入门教学

June 25th, 2010

为非程序员准备的简洁Python语言教材,欢迎提问,欢迎转帖

计算机语言编程的主要内容就这些:数字,文字,循环,公式,变量

  • 数字: 1, 2, 3, 5.6, 120, 32.4, 3.1415926, -3, -0.123
  • 文字: 你好,我好,你太牛了,很黄很暴力,这类的文字。一般用双引号(“)或者单引号(‘)括起来。术语叫字符串 ,就是一堆字符,串起来。
  • 循环: 循环(loop)就是重复的做一件事。计算机是一个很笨的机器,基本上只会做加,减,乘,除,大于,小于,等于和循环这种简单的工作。编程就是把复杂的问题,拆成简单的单元让它重复。

幸亏有下面讲到的公式,所以很多较复杂的问题已经有了解决方法,我们只是重复的套用别人的解决公式就可以了,不用拆得太细。

Python 语言最大的优势,就是这个语言中包含了大量解决常见问题的公式,你想干的事,基本上都有人帮你干了,你只是需要把他们组织,捆绑起来就可以了。比如下载文件的公式,分析网页内容的公式,压缩文件的公式,处理电子邮件的公式等等。

  • 公式: 就像数学公式 (a+b)2= a2 + 2ab + b2 这种。算的时候带入具体数值,比如:(3+4)2 = 32 + 2*3*4 + 42 = 9+24+16 = 49 。前面的 (a+b)2 就是我们的公式名(当然编程时,我们会用一些比较容易明白的词组做为公式名,比如“和的平方”这种,英语或者拼音都可以),他需要两个参数a,b;后面的 a2 + 2ab + b2 是具体怎么算出来的步骤,这就是我们的公式内容。

在计算机里,公式的术语叫“函数”或者“方法”。我们定义一个函数,就是定义一条公式,用的时候,拿来参数a,b什么的,套一下公式就行了。

为了程序的结构清晰,我们往往会定义很多函数。把复杂的问题分成很多小问题,每个小问题放到一个函数里,然后在解决复杂问题的函数里,使用这些小问题函数解决大问题。更重要的是我们可以大量的使用别人写好的函数来解决自己的问题。

函数的作用是让程序结构清晰,而且可以在不同的地方重复套用。

  • 变量: 就是上面的a,b这种可以代表任何值,可以放进不定值的单词,变量,变量,它代表的量可能会改变。我们用变量来存储我们程序中用到的各种数字,文字,公式。所谓参数,就是定义公式时候用到的变量,就叫参数,换个马甲而已。

换成术语,我们有:

数字 (number) => 数字
字符串 (string) => 文字
循环 (loop) => 循环
函数/方法 (function/method) => 公式
变量 (variable) => 变量

到这里,基本上编程就没什么可学得了。剩下的就是掌握各种编程语言特定的函数和循环的书写格式,再掌握了别人已经写好的函数的用法,组合起来就得了。

最基本的python程序:

print ("世界,你好!")

存到文件 hello.py 里,然后命令行下输入 python hello.py 就可以看到结果了。

这里就用到了函数和字符串,在屏幕上输出一行:世界,你好!

Python 里函数的用法是:函数名(参数1, 参数2)

这里 print 是函数;在屏幕上打印内容,”世界,你好!”是参数,套 print 这个公式用的。

学会怎么用函数了,再学会定义函数的格式,就差不多了。

Python 里注释符号是”#”。就是说,在 # 符号后的那一行文字,都当做解释,不做为程序的命令。

print ("打酱油!") # print ("关我屁事")

只打印出 “打酱油”,剩下的,因为是在 # 后面,所以程序把他们当做注释语言自动忽略了。

def a_b_pingfang(a, b):
    c = a**2 + 2*a*b + b**2
    return c

我们定义一个(a+b)2的函数,def 是英语 define 的缩写,意思是定义函数,定义公式。

第 1 行就是说我们要定义一个函数名叫 a_b_pingfang 的函数,用它的时候,需要两个参 数 a 和 b。尾巴上有个冒号,冒号的意思是说:“下面的一段话就是公式定义了,要注意了”。

计算机编程里,* 代表乘法,/代表除法,** 代表乘方, b**2 就是 b 的二次方。

注意: Python 是用 缩进空格 来表示段落的,冒号(:)来表示段落开始。

第 2 行先缩进4个空格,说明下面缩进4格的,都是同一段落,用来具体计算上面定义的公式的。把 a 2+2*a*b+b 2 的计算结果,放到c里。

c类似于a,b,都是表示一个变量,它可以用来存放数字,文字,甚至函数。这里它存放的是用a,b计算后得到的结果。因为不是在函数名里,所以术语叫做“变量”,用在函数名里,就叫参数了。

“变量”就是用一个单词来代表一个可以变化的量的。单词里可以有字母,数字和下加线(_),数字不能打头。

第 3 行,把存在c里的结果,传回给函数的使用者。

return 命令的意思,就是立即结束函数的执行,把return后面的值传给调用者,可以传回多个值。

现在可以使用这个公式了,我们把套公式叫调用函数

ping2 = a_b_pingfang(2, 3)

ping2 里存放了 a_b_pingfang(2, 3)得到的结果,也就是上面 return c 这句,把 c 的内容,传给了外面的ping2。

把结果打印出来:

print(ping2)

全部程序就是:

def a_b_pingfang(a, b):
    c = a**2 + 2*a*b + b**2
    return c
ping2 = a_b_pingfang(2, 3)
print(ping2)

存到 test2.py ,跑 python test2.py 就可以看到输出 25。

当然还有循环,怎么让程序重复的做事?我们有 while(当…), for(对于…) 命令来进行循环控制。

a = 0
while a < 100:
   a = a + 1
   print a

这个循环说,当 a < 100 的时候,把 a 增加 1,再把它打印出来,然后重复。当 a 等于100了,条件不符合了,就结束了。

我们有 <, >, ==, <=, >=, != 来判断大于,小于,等于,小于等于,大于等于,不等于。

还有 and(并且), or(或者), not(不是) 来进行逻辑运算,所谓逻辑运算,就是测试多个不同判断之间的关系的:

(a == 1) and (b != 2) 来测试这两个判断是否同时成立:a 等于 1 并且 b 不等于 2。 (a == 1) or (b != 2) 来测试这两个判断里是否有至少一个成立:a 等于 1 或者 b 不等于 2。 not a == 1 来测试这个判断是否是错的。错的就是对的,对的就是错的,颠倒黑白:不是 a 等于 1,那就是 a 不等于 1 了,好像有点脱裤子放屁。其实在别的更复杂的判断组合里更有用些。

我们还有 break(中断) 来打断循环,和 continue(继续) 来立刻回到循环开始,也可以用 if(如果) 命令来进行判断:

a = 0
while True:
    a = a + 1
    if a >= 100:
        break
    print a

这里 True(正确) 表示永远正确,相对的是 False(错误) 表示永远错误。这一段是说一直执行,因为 while 的条件总是正确,就是说“当符合总是正确的条件的时候,不断重复”,当然是永远正确,永远重复了。下面在 if 处判断如果a大于等于100,如果是,那么执行 if 下的段落,这里我们打断了循环。如果条件不符,就跳过 if 下面的小段落,该干嘛干嘛,具体到这里就是打印 a 然后继续执行循环。

for 循环是利用下面介绍的的列表数据结构对列表进行循环。

下面具体说到python特异功能,它有几个特殊的存储数据的格式。

  • 列表: list
  • 元组: tuple
  • 字典: dict (dictionary)
  • 集合: set

列表:把很多变量存进一个列表里,叫列的意思,就因为他像列车一样,一节一节车厢,每厢放一个变量。格式为 b, c, 1, 3, 5, ‘葡萄’, ‘葡萄皮儿’,可以看到,方括号里,可以放具体的数字,文字,也可以放变量,用逗号分隔。

这些内容是在固定位置上,可以通过他们的位置,来提取:

alist = [1, 3, 5, '很傻', '葡萄', '葡萄皮儿', a, var1]
print (alist[0]) # 打印 1
print (alist[3]) # 打印 "很傻"

在python里,次序是从0开始数的,开始是0,然后是1,2,3,4,5,所以上面的列表 alist的第一个内容,可以用alist[0]来提取,第二个用alist[1]来提取。就像年龄一样,一生下来是零岁,一年以后才是一岁,不是中国传统那样,生下来就一岁,那是虚岁。蟒蛇语言它只认准确的东西,不玩儿虚的。

print (alist[4]) # 打印 '葡萄'

这里,我们可以介绍用 for 循环来访问这个列表里的所有内容:

for me in alist:
    print (me)

上面这一段,打印所有alist里的内容。

这个循环是,对于列表 alist ,从 0 位置开始,访问它的每一个位置,把这个位置上的值, 放到 me 里,然后针对不同的 me 值,重复执行下面段落的内容。

in 表示 me 在 alist 里,也可以用来判断:

  if "葡萄" in alist:
     print "葡萄在alist里!"

列表的内容是可以改变的,我们可以把第4个位置设为”很天真”:

alist[3] = alist[3] + ' 很天真'
print (alist[3]) # 打印 '很傻 很天真'

下面说道的元组的内容就不能改变了。

元组:元组就是列表,但是他的内容是不能改变的,用圆括号()来表示。 他的内容只能一开始就设定。但是,元组和列表之间是可以用函数互相转变的,转成列表就可以改变内容,转回元组就不能改了。

元组是用圆括号来表示,所以叫元组嘛。

atuple = (2, 3, "老子")
alist = list(atuple) # 变成 [2, 3, "老子"]
alist[0] = 0
tuple2 = tuple(alist) # 变回 (0, 3, "老子")

在 python 里,字符串也是一种特殊的元组,也就是内容不可变的字符列表。

txt = 'abcdefg'
print(txt[1]) # 打印 b

字典:字典就像一般的字典,一个字,一个解释,再一个字,再一个解释。用大括号表示:

adict = {1: "我是解释",
  2: "我是解释2",
  "我是3": 3,
  "我是4": 4
  }

前面的字叫钥匙(key)或者索引,后面的解释,叫”值”。索引不能重复,必须是唯一的。

我们可以看到,前面的字,和后面的解释可以是数字,文字,还可以是函数或者元组。但是前面的字,不能是列表,因为列表内容是可变的,可变的东西都不能做索引。

我们用索引来提取,设定或者增加值,而不是用位置:

adict[1] # "我是解释"
adict["我是3"] # 3
adict[1] = 2 # 设定新的值
adict["新索引"] = "没头脑和不高兴" # 增加一个新索引和值

集合: 集合就是数学上用的集合,把一堆东西放到一起,类似列表,不同的地方是内容不重复,而且也没有次序。

aset = set([1, 2, 3, 2, 4, 6]) # 去掉重复内容,所以是 1,2,3,4,6

可以看出,建立一个集合的方式,是使用set()函数,函数的参数可以是列表,或者元祖,反正是一串儿的都可以。

集合的用处是利用他内容不可重复的特性,来去掉重复的内容。至于其他的合集,交集也是这个特性的延伸。

集合也是可以变成列表的,利用 list() 函数。

alist = list(aset) # 内容 [1,2,3,4,6]

Python 里包涵了很多别人写好的函数、方法让我们直接利用。譬如写网络程序的函数,数 学计算的函数,分析电邮文件的函数,加密的函数。我们要做的就是套公式

这些函数分门别类的放到叫“模块”的东西里。一个模块里,包括很多功能相类的函数。而具体实现上,一个模块,就是一个python的程序文件。

如果模块还需要细分更多层,那么每层就是一个文件目录。里面有很多做为模块的python文件。

要使用模块,我们用“进口”这个命令: import

import time
now = time.clock()
print (now)

这里,我们先进口 time 模块,然后使用 time 模块里的函数 clock() ,得到当前时间,打印出来。

用个英文句点表示模块time里的clock函数: 模块名.函数名

在 python 里,我们会用到很多别人写的模块,能自己少写点儿源码,尽量少写,懒不是?

其实编程来说,类并不是必须的,但是因为很多python提供的模块,里面的函数都是包在类里面的,所以我们需要介绍一下类。

面向对象编程,是现在比较流行的编程方式,是个人都得用“面像对象”的思路来编程,来显得自己跟得上形式。其实面对对象并不是必须的,光棍并不可耻。

类就是种类的意思。

基本上面对对象就是把同类的函数,变量打包放到一个包袱里,这个包袱就叫“类”。挺土气是吧?其实面对对象也并不就一定时髦,也可以俗不可耐,就看你包袱打的怎么样了。

这个“类”一般上是以具体的东西为模板,譬如物种:人类,猫类;物品:家俱类,电器类。他里面打包的函数,基本上是针对这个类进行操作的,譬如人说话,人吃饭,人的鼻子人的嘴,猫逮耗子,家居磨损。

使用类的时候,我们先具体化他,把种类变成个体。人类变成某人,猫类变成某猫,家俱变成某件家俱。这个具体化的类,就是所谓的“对象(object)”。然后我们就可以使用这个具体人,猫,家居的函数,针对具体的人,物进行操作了,所谓操作对象。

class RenLei:
    def __init__(self, mingzi):  # self 是一个固定参数名,代表这个对象自己。
        self.mingzi = mingzi     # 把名字存到对象自己的 mingzi 变量上。
    def shui2(self):             # 谁函数
        return self.mingzi

上面的例子,一开始就要求给这个对象一个名字。

在类的定义里,每一个函数,他的第一个参数,都是规定死的,必须是self。self代表这个对象自己。在对象内部,这个对像本身的变量,函数,都是通过这个self来存取的。

在调用类里的函数时,不用提供 self 这个参数,程序自动提供 self,让我们使用它其他的函数,变量。我们只要提供其他参数即可。

__init__() 这个函数是一个特殊的函数,他代表从类具体化到对象的时候,需要套用的公式。

通过类建立对象的时候,程序会自动调用 __init__()函数。所以它叫做初始化函数。建立对象的时候,有什么一开始的要求,都可以通过它来指定,比如要求“脚不大好头发没有麻子”。

当然如果没有初始要求,也可以不定义这个函数,那么程序就不会自动调用它了。

# 建立对象,提供的函数对应__init__() 函数,self 这个参数程序会自动提供,不用我们提供。
xiaozhang1 = RenLei("小张")  
mingzi = xiaozhang1.shui2()  # 使用“对象名.函数名()”的格式来调用类里的函数。
print mingzi <-- "小张"

Python 里的字符串,列表,元组,字典,它们本身都是面对对象的类,所以带有很多函数可以对自己进行操作,譬如:

a = "脚不大好 头发没有 麻子".split()

split是字符串这个类的函数,他可以把字符串在给定位置分割,当我们不给他参数的时候,会在所有空白位置分割,然后返回一个列表,里面是被割裂的字符串。

结果,a 的内容是 ["脚不大好", "头发没有", "麻子"],这是一个有3个元素的列表。

对于字符串,列表,字典之类的操作,请熟读说明手册对他们的说明,python编程,主要就靠字符串,列表和字典了。

重中之重: 大量的使用 list 这个列表方式来存储、操作数据。一字长蛇阵是蟒蛇的绝招,多用没错。

写一个 Python 程序,我们一般的步骤是:

  1. 进口所有会用到到模块 import
  2. 定义我们自己的类和函数。对于每个函数里要用到的函数,被调用的函数一般放在调用函数的前面定义。这样我们读程序的时候,如果从上到下,就知道调用的函数,在前面是怎么定义的,有什么功能,需要什么参数,返回什么值。
  3. 在文件的最下面,调用上面定义的函数和类,开始工作。
  4. 命令行的选项是通过 sys.argv 这个列表得到的。
  5. 尽量使用python提供的内建函数和模块里的函数,所以我们对Python的模块说明手册要很熟悉。

Python 运行,是从文件的上面往下走的,看到一条命令执行一条命令,一直到最后一行。当我们定义函数和类的时候,他们只是定义,而没有执行,所以Python 看到他们,先存起来,直到看到定义外的具体命令,才真正的执行。如果这个命令调用上面的函数,那么就把存起来的函数执行一下。

完整例子: 把一个两列的文件input.txt,分割成两个文件col1.txt, col2.txt,一个文件一列。 input.txt 内容:

a1 啊阿
ai1 挨埃哀
ao2 熬鳌翱獒

程序内容:

def split_file(filename): # 把文件分成两列
    col1 = [] # 存储第一列
    col2 = []
    fd = open(filename) # open 函数用来打开文件,返回一个文件对象
    text = fd.read() # fd.read 读入文件fd 的内容。
    lines = text.splitlines() # 把读入的内容分行
    for line in lines: # 循环每一行
        part = line.split(None, 1) # 分割一行。
        col1.append(part[0]) # 把分割的第一部分放到col1后面。
        col2.append(part[1])

    return col1, col2 # 返回 col1, col2

def write_list(filename, alist): # 把文字列表内容写入文件
    fd = open(filename, 'w') # 打开输出文件col1.txt,'w'指定使用写入模式。
    for line in alist:
         fd.write(line + '\n')

def main(): # 主函数,程序进入点,习惯性叫他 main()
    filename = 'input.txt'            # 把输入文件名 input.txt 放进一个变量
    col1, col2 = split_file(filename) # 调用分割函数,结果存入 col1, col2
    write_list('col1.txt', col1)      # 调用写入函数
    write_list('col2.txt', col2)

main() # 唯一的函数外命令,程序开始执行,调用上面的 main() 函数数。

这里,输入的文件名是写死的 input.txt ,我们可以使用模块 optparse 来通过命令行读取用户提供的文件,会更灵活些,那些就是你研究过 optparse 以后的事了。

更多的功能,函数,请参考python的官方教学和手册。

先熟悉:

  • 内建函数
  • 内建数据类型 (字符串,数字,列表,字典,文件对象)
  • sys 模块
  • re 模块
  • os 模块
  • optparse 模块

熟悉这些,基本上编程没问题了。

深入 Python是一本经典的参考书,虽然没有涵盖所有python模块的内容,但是对初学者基本够用。而且它是一个自由文件,说俗了就是合法免费的,又有中文翻译版,难得。

也可以参考 Python 绝对简明手册这个中文说明。

如果需要网络编程,还要熟悉网络相关的模块,urllib2,socket,xml.etree.elementtree。

如果想要图形界面,建议使用pygtk或者pyqt图形界面函数库,这时候,也需要熟悉面对对象编程的概念。

对于英文不好的人,建议买一本有Python函数模块介绍的中文书,作为参考书,在编程的时候,边编边翻书。

Python 的中文意思是巨蟒,大蟒蛇。但是这个语言的具体出处是一个叫Monty Python的英 国电视剧。

来源:http://code.google.com/p/hashao/wiki/ChinesePythonTutor

SMO的16条规则(转发)

June 25th, 2010

SMO的16条规则:
1. Increase Your Linkability(增加链接能力)
作者认为链接能力的多少还是却取决于内容,而且内容还必须是独一无二的(unique)、有用的(useful)和吸引人的(compelling)。不过一些策略还是要考虑的,比如可以逐步地发表内容(像连载小说一样),从而吸引links(注意力),traffic(流量)和subscribers(订阅者),然后再完成内容的整合包装。
2. Make Tagging and Bookmarking Easy(让加入标签和书签的操作更容易)
Easy Tagging and Bookmarking的作用很大,读者分享内容不会那么麻烦,从而提升了内容分享的几率,不过前提还是在于内容。同样promotion(推广)也仅是辅助。
3. Reward Inbound Links (回报导入连接)
当别人链接到你的网站上,你是否应该予以“回报”呢?当然各有各的看法,方法也是各有不同。
4. Help Your Content Travel(内容传播)
社会化媒体中内容传播的渠道有很多,分享方式也会很多。而传统的influencer观念在此已不再适用,内容传播的深度取决于需求。
5. Encourage the Mashup鼓励混合
社会化网络时代,内容混合将是不可避免的事,内容分享和内容混合所带来的利益最终将回馈于内容初创者。而免费音乐则是典型代表。
6. Be a User Resource, Even if it Doesn’t Help You(用户资源库)
社会化网络时代,要有”give value to get value” perspective。不要害怕把用户引向竞争对手那里去,要懂得帮助用户,这样才真正算是没有丢掉用户。
7. Reward Helpful and Valuable Users(回报那些乐于助人的用户和有价值的用户)
乐于助人的用户和有价值的用户将是你的宝贵资源,如何回报他们是一个值得思考的问题。
8. Participate(参与)
不参与怎可能懂得社会化媒体。参与才是让内容发生涟漪效应的关键所在。
9. Know How to Target Your Audience(懂得如何确定你的目标受众)
这点不用多说了。融入Audience所在的community并让他们感觉到connection。
10. Create Content(创造内容)
要创造客户需要的内容,并且要坚持不懈地做下去。
11. Be Real(要真实)
社会化媒体营销效果固然好,不过如果处理不好跟客户的关系,其反面冲击力也会是巨大的。远至戴尔地狱门、沃尔玛假博客门,近至KFC“秒杀门”,去学会跟你的客户交流吧!REAL是交流中必备的要素。
12. Don’t Forget Your Roots, Be Humble(做人不要忘本,要谦逊!)
社会化媒体成功得益于无私的奉献和互相帮助,当你成功时,记得犒劳手下,做人也是如此!
13. Don’t Be Afraid to Try New Things, Stay Fres(不要害怕尝试新事物,要保持新鲜感)
社会化媒体一直处于变化之后,紧跟趋势,及时掌握新事物。
14. Develop a SMO Strategy(制定SMO Strategy)
SMO战略的制定首要要有一个明确的goals和strategy,而不能仅仅是停留在tactics。成功不在于工具,而在于思想。
15. Choose Your SMO Tactics Wisely(选择明智的SMO策略)
不要盲目跟风,一路照搬。工具都一样,思想要不一样。
16. Make SMO part of your process and best practices(将SMO融入你的工作环节和最佳做法)
将SMO融入公司的DP/PR/DESIGN等等的每一个阶段。

处理utf8编码

June 21st, 2010

textmate的作者的这篇文章很好的解释了使用utf8的理由,尤其对于网页开发,更应该是用utf8

http://blog.macromates.com/2005/handling-encodings-utf-8/

在macos上安装oracle sqlplus客户端

May 26th, 2010

在mac os 10.6.3上安装通过。
准备工作
1. 从oracle官网上下载oracle客户端和sqlplus包,这两个是必须的,根据自己的系统选择32位或64位
- the Oracle Client ‘Instant Package – Basic’
- the Oracle Client ‘Instant Package – SqlPlus‘
2. 下载自动安装脚本
有作者为简化安装和配置步骤,写了两个脚本,
MacSqlPlus.sh
将sqlplus安装在/opt/oracle/instantclient_10_2目录中,同时设置了TNS_ADMIN和DYLD_LIBRARY_PATH两个环境变量
这个脚本需要做一个改动,因为第二个脚本生成的tnsname.ora文件存放在/opt/oracle/tns目录下,

#这行
echo "TNS_ADMIN=/opt/oracle/instantclient_10_2/tns" >> ~/.profile
#改成
echo "TNS_ADMIN=/opt/oracle/tns" >> ~/.profile

TNSconnectMac.sh
配置生成tnsname.ora文件

3. 安装
根据脚本的要求,需要将下载的两个安装和两个脚本文件都包复制到/var/root目录下,并且使用root用户登入,你可能需要设置root的密码才能使用root帐号登入,

source ~/.profile

原文:http://www.danilovizzarro.it/2008/07/how-to-install-sqlplus-and-the-oracle-client-v102-on-a-mac-os-x-leopard-1054/

tocmat6 security policy problem when using spring

May 18th, 2010

many people have encoutered this problem,

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.util.Log4jConfigListener
java.security.AccessControlException: access denied

as tomcat has improve its security policy, you have to change it

add the following line into your policy file.(the default dir in ubuntu tomcat is /var/lib/tomcat6/conf/policy.d, )

grant codeBase "file:/var/lib/tomcat6/webapps/yourapp/WEB-INF/classes/-" {
  permission java.security.AllPermission;
};
grant codeBase "file:/var/lib/tomcat6/webapps/yourapp/WEB-INF/lib/-" {
  permission java.security.AllPermission;
};

使用memcache实现锁功能

May 14th, 2010

使用PHP的Memcache模块,
获得锁

function acquireLock($key, $maxTTL = 5)
{
  $lockKey = 'lock-' . $key;
  $cache = new Memcache();
  $tries = 0;
  for ( $tries = 0; $tries < 5; $tries++)
  {
     if($cache->add($lockKey, $maxTTL)
           return true;
      sleep(1);
  }
}

释放锁

function releaseLock($key)
{
  $lockKey = 'lock-' . $key;
  $cache = new Memcache();
  $cache->delete($lockkey);
}