Linux下Django部署环境的搭建

目标 搭建起apache部署Django项目的环境,操作系统CentOS 5,软件版本如下: python 2.7 Django 1.5 mod_wsgi 3.3 apache 2.2 Python更新 安装 系统用的是python版本是2.6+,现在需要将python版本更新至2.7+版本了。 下载python2.7的源码包,然后编译安装,命令如下: ./configure --enable-shared make all make install 这边需要注意的是,configure的参数--enable-shared,使用这个参数为python生成动态链接库。如果没有加此参数,编译安装也可以正常完成,不会影响python的使用。但是到安装mod_wsgi会出现错误,错误内容为: /usr/local/lib/python2.7/config/libpython2.7.a: could not read symbols: Bad value collect2ld returned 1 exit status apxs:Error: Command failed with rc=65536 这个错误就是在安装python时候没有./configure --enable-shared 检查版本 完成后一般的路径是 /usr/local/lib/python2.7,可以使用命令检查其版本是否正确 /usr/loacl/bin/python2.7 -V 若是出现错误:python: error while loading shared libraries: libpython2.7.so .1.0: cannot open shared object file: No such file or directory。使用vim新建文件/etc/ld.so.conf.d/python2.7.conf,加入内容:/usr/local/lib。保存退出后运行:ldconfig,再次运行,看是否成功。 建立软链接 用于替换shell下的默认python命令的版本 mv /usr/bin/python /usr/bin/oldpython ln -s /usr/local/bin/python2....

December 11, 2013

Clone使用方法详解

Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别。和C语言一样,当把Java的基本数据类型(如int,char,double等)作为 入口参数传给函数体的时候,传入的参数在函数体内部变成了局部变量,这个局部变量是输入参数的一个拷贝,所有的函数体内部的操作都是针对这个拷贝的操作, 函数执行结束后,这个局部变量也就完成了它的使命,它影响不到作为输入参数的变量。这种方式的参数传递被称为"值传递"。而在Java中用对象的作为入口 参数的传递则缺省为"引用传递",也就是说仅仅传递了对象的一个"引用",这个"引用"的概念同C语言中的指针引用是一样的。当函数体内部对输入变量改变 时,实质上就是在对这个对象的直接操作。 java中的clone: 在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B 任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。在Java语言中,用简单的赋值语句是不能满足这种需 求的。要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单,也是最高效的手段。 Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()。JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点: ** 一是拷贝对象返回的是一个新对象,而不是一个引用。** ** 二是拷贝对象与用 new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。** 有三个值得注意的地方, 一是希望能实现clone功能的CloneClass类实现了Cloneable接口,这个接口属于java.lang包, java.lang包已经被缺省的导入类中,所以不需要写成java.lang.Cloneable。 另一个值得请注意的是重载了clone()方法。最 后在clone()方法中调用了super.clone(),这也意味着无论clone类的继承结构是什么样的,super.clone()直接或间接调 用了java.lang.Object类的clone()方法。下面再详细的解释一下这几点。 应该说第三点是最重要的,仔细观察一下Object类的clone()一个native方法,native方法的效率一般来说都是远高于java中的非 native方法。这也解释了为什么要用Object中clone()方法而不是先new一个类,然后把原始对象中的信息赋到新对象中,虽然这也实现了 clone功能。对于第二点,也要观察Object类中的clone()还是一个protected属性的方法。这也意味着如果要应用clone()方 法,必须继承Object类,在Java中所有的类是缺省继承Object类的,也就不用关心这点了。然后重载clone()方法。还有一点要考虑的是为 了让其它类能调用这个clone类的clone()方法,重载之后要把clone()方法的属性设置为public。那么clone类为什么还要实现Cloneable接口呢? 稍微注意一下,Cloneable接口是不包含任何方法的!其实这个接口仅仅是一个标志,而且 这个标志也仅仅是针对Object类中clone()方法的,如果clone类没有实现Cloneable接口,并调用了Object的clone()方法(也就是调用了super.Clone()方法),那么Object的clone()方法就会抛出 CloneNotSupportedException异常。 什么是影子clone? 调用Object类中clone()方法产生的效果是:先在内存中开辟一块和原始对象一样的空间,然后原样拷贝原始对象中的内容。对基本数据类型,这样的操作是没有问题的,但对非基本类型变量,我们知道它们保存的仅仅是对象的引用,这也导致clone后的非基本类型变量和原始对象中相应的变量指向的是同一个对象。 怎么进行深度clone? 需要两个改变,一是让对象内的非基本类型变量也实现Clone功能(实现Cloneable接 口,重载clone()方法)。二是在对象的Clone方法中加一句o.unCA = (UnCloneA)unCA.clone(); 要知道不是所有的类都能实现深度clone的。例如,如果把上面的CloneB类中的UnCloneA类型变量改成StringBuffer类型,看一下 JDK API中关于StringBuffer的说明,StringBuffer没有重载clone()方法,更为严重的是StringBuffer还是一个 final类,这也是说我们也不能用继承的办法间接实现StringBuffer的clone。 还要知道的是除了基本数据类型能自动实现深度clone以外,String对象,Integer,Double等是一个例外,它clone后的表现好象也实现了深度clone,虽然这只是一个假象,但却大大方便了我们的编程。 Clone中String和StringBuffer的区别,这个区别主要原因来自String和StringBuffer的区别。

September 5, 2013

Django+apache+mod_wsgi部署

一、安装: 安装Apache、Python、Django、mod_wsgi、项目所需的依赖(数据库驱动、第三方库等) 二、项目设置: 1、把整个项目放到服务器上 2、改变DEBUG配置,修改settings.py文件的DEBUG属性 DEBUG=False 3、数据库连接配置,修改settings.py的数据库连接配置 4、修改允许访问的HOST,修改settings.py的ALLOWED_HOSTS=['*'] 5、添加404和500页面,把页面文件放到template目录下 6、静态文件配置,修改settings.py的STATIC_ROOT的值,此属性的值是部署后静态文件保存的目录。 7、收集静态文件,运行命令:python manage.py collectstatic。django会把STATICFILES_DIRS中配置的目录下的所有文件和文件夹拷贝到STATIC_ROOT配置的目录下。 8、修改与settings.py同目录下的wsgi.py,添加如下代码: import sys sys.path.append("/home/myproject") "/home/myproject"替换成项目的根目录,这段代码的作用是把项目的路径添加到python的环境变量下,使得os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")这句断码可以正确查找到项目的settings.py文件。 三、Apache配置: 修改配置文件httpd.conf 1)、配置Apache加载mod_wsgi LoadModule wsgi_module modules/mod_wsgi.so 2)、配置静态文件映射 Alias URL-path file-path|directory-path 如Alias /static "/home/myproject/static" 3)、apache虚拟主机(VirtualHost)配置 <VirtualHost *:80> DocumentRoot /ytxt/surveyproject ServerName www.feiyuejihua.com WSGIScriptAlias / /ytxt/surveyproject/surveyproject/django.wsgi ErrorLog /ytxt/log/feiyuejihua.log <Directory /> Order deny,allow Allow from all </Directory> <Directory /apache> Allow from all </Directory> </VirtualHost> DocumentRoot:为项目的根路径 ServerName:项目的域名 ErrorLog:为异常日志路径 WSGIScriptAlias:映射一个URL到一个文件系统地址并委派目标文件为WSGI Script 四、启动服务器: 启动:httpd -k start 重启:httpd -k restart 关闭:httpd -k stop 或 httpd -k shutdown

September 2, 2013

Django基础入门

安装: 下载后运行python setup.py install或pip安装 创建项目: 进入准备创建项目的目录下,运行命令: django-admin.py startproject xxx django-admin.py在windows(其他系统也可能因为安装不同而不在环境变量里)下不能直接调用,可以将其放入环境变量中或是去python的安装目录下的Lib\site-packages\django\bin下运行。windows下没有关联文件类型的话,上面的命令前需要加上ptyhon,即 python django-admin.py startproject xxx 创建的项目结构如下: projectname/ |- manage.py |- projectname/ |- __init__.py |- settings.py |- urls.py |- wsgi.py 运行项目: python manage.py runserver 默认端口号是8000,可以指定端口号运行 python manage.py runserver 8080 访问http://127.0.0.1:8000/可以显示django的默认页面 这种运行方式并非部署,只是运行Development Server,只能可靠的处理一次单个请求。在此模式下代码或配置的变动都会立即生效。 创建APP: python manage.py startapp xxx APP结构如下: APPname/ |- __init__.py |- models.py |- tests.py |- views.py 进入项目的settings.py下,把新建的APP加入到INSTALLED\_APPS 中,例如: INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', # Uncomment the next line to enable the admin: # 'django....

August 29, 2013

Java静态代码块(static{})

静态代码块:即在类中的标有static修饰符的代码块,如: static { } 与一般代码块的异同: 相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,一般在代码块中对一些static变量进行赋值。 不同点:静态代码块在非静态代码块之前执行。静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new一次就执行一次。非静态代码块可在普通方法中定义;而静态代码块不行。 与静态方法的区别: 静态代码块在第一次初始化的时候被执行,静态方法在类加载的时候被加载,且必须需要主动调用才会执行。 执行顺序相关: 1、单个类的初始化顺序如下:为静态属性分配内存并赋值->执行静态代码块->为非静态属性分配内存并赋值->执行非静态代码块->构造函数。 2、有继承关系的类的初始化顺序如下:父静属->父静块->子静属->子静块->父非静属->父非静块->父构造->子非静属->子非静块->子构造。 static的一些使用注意事项: 1、静态方法只能调用同类中的其他静态成员(静态方法或是静态变量)。 2、静态方法不能使用this和super。因为静态方法不属于任何实例。 3、静态变量属于整个类,在类的方法中不能定义静态方法。

August 21, 2013

Java源码解读——ArrayList

为了提高自己的Java开发能力,我也向高手、牛人学习,去解读源码。自己底子差了点,不过看个源码还是没问题的。第一站ArrayList。 源码为Java 1.7的源码 ArrayList是一个实现可变长数组,继承AbstractList类,实现所有的List接口,还实现了RandomAccess、Cloneable、Serializable接口。ArrayList不进行同步,除此之外基本和Vector等同。 1、成员变量 private transient Object[] elementData; elementData用于保存数据的数组。 private int size; size为ArrayList内的数据数量,但并不是elementData的长度。 2、构造方法 public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } public ArrayList() { this(10); } public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } 第一个是根据指定长度建立List,第二个是根据默认长度建立List,第三个根据传入Collection子类实例创建List。通过第三个实例看到Collection子类都会实现toArray()方法,可以看出至少很多Collection子类依赖于数组来实现(还没看过其他的集合实现,这只是我的妄言而已)。 3、add方法 public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } 该方法在数组最后添加一个元素。ensureCapacityInternal方法提供了ArrayList的自增长实现,以确保elementData有足够的长度来容纳新进入的元素(后面介绍自增长的实现)。...

August 14, 2013

编写可读代码的艺术-代码应当易于理解

虽说我编程也有五年了,不过很多细节的东西还是不够注意。关于别人是否能读懂自己所写的代码,这个问题的确很少在平常的开发中想过,即使有过这个念头,最多的也就是考虑下代码的结构清晰,这有助于减少BUG,方便阅读。至于其他相关的就比较少解除了,或是完全没有概念。之前学习过变量和函数的命名,不过实际中很少考虑,命名很是随意。读这书是希望提高下自己的代码质量,当然个人认为代码的可读、整洁、优美是代码质量的一部分。 可读性基本定理 定理:代码的写法应当是别人理解它所需的时间最小化 找一个同事,测试下他读自己代码并理解它所需要的时间,这个“理解代码时间”就是最小化的理论度量。并且这个“理解”有很高的标准,真的完全理解所看的代码的话,就能改动它、找出缺陷并明白它是如何与代码的其他部分交互的。 总是越小越好吗 从代码数量上来看,越少的代码,阅读和理解的速度就应该越快,但这不是必然,少的代码并不总是更好,如: assert((!(bucket = FindBucket(key))) || !bucket->IsOccupied()); 相比 bucket = FindBucket(key); if (bucket != NULL) assert(!bucket->IsOccupied()); 前者理解起来比后者两行代码所花的时间更多。 有时候一条适合的注释可以让阅读着更快地理解代码,尽管增加了长度。 理解代码所需的时间是否与其他目标有冲突 这里说的其他目标包括优化、架构、测试等。不过答案是否定的,这些根本不会相互影响。更多的介绍会在后面章节提到。 最难的部分 是的,最难的部分是让养成一个在编码时考虑如何让他人更容易理解你的代码的习惯。这不光需要时间去适应,而且需要一定的毅力。开发过程中各种情况都会让你放弃这种想法,比如进度、他人代码的质量等。 如果你是个新手,说真的,这书值得去看。在日常的工作中,去理解他人代码或是他人来阅读你的代码的情景时常有。甚至自己也会忘记自己所写代码的含义,一周或一个月后再去看自己的代码,都觉得那么陌生。项目的维护时间远多余开发,当后期需要再次开发或修改BUG的时候,那些好的、易于理解的代码将大大节省时间。所以编写可读代码不经方便他人,还能提高自身的工作效率。

August 9, 2013

霸王别姬-人生一场戏

中午闲着没事看了下陈凯歌导言的《霸王别姬》,先不说其他的,吐槽下英文名——《Farewell My Concubine》,意思是“告别我的情妇”,让我怎么和“霸王别姬”这四个字联系起来。怪不得中国的文学作品老拿不到国际的什么奖。 程蝶衣 幼年的他是不是找女娃来演的啊,那个秀气啊。幼年的他一脸漠然像,感觉他对自己人生没有任何的想法,听天由命。当他逃出戏班子,在剧院看了那出霸王别姬后,似乎他才确认了他人生的目标。 他的人生就是一段戏,入戏的时候实在他说出“我本是女娇娥,又不是男儿郎”,出戏是在电影最后,说出了“我本是男儿郎,又不是女娇娥”。期间他就一直沉浸在他自己的戏里面。按段小楼的说法是他简直是入魔了。幼年的蝶衣柔弱、胆小,而后来的他却显得坚毅、勇敢,特别是找日本人救小楼。再加上对小楼的那份情,这不正是霸王别姬中虞姬应有的吗。应了袁四爷那句话“虞姬是真虞姬”。 蝶衣最后选择了自杀,在他说出了“我本是男儿郎,又不是女娇娥”后。相信在他说出这句话后他已经出戏了,而这场戏,一演就是大半辈子。回首往事,再看已经不存在了的霸王,以及将来要承受的现实,像虞姬那样自刎是他唯一的选择了,他的自刎也为他如戏的一生画上了圆满的句号。 电影中蝶衣对他母亲的感情描述的地方很少,我记得只有三处:烧掉他母亲给的衣服;写信给母亲然后烧掉;在戒毒的时候喊着娘。他心里对他母亲是又爱又恨,烧掉他母亲给他的衣服,这是因为他母亲风尘女子的身份,是他无法抬头面对他人。而烧掉给他母亲的信,他完全就当母亲已经不在人世了,电影没有介绍他去寻找他母亲,或是根本就没打算寻找,也许是还恨着母亲抛弃他吧。而写信说明还是思念母亲。在他最艰难时刻含着“娘”,那些对话是在他小时候对他母亲说的,他还依然保留这小时候和母亲在一起的记忆。这里也说明了蝶衣记忆力为什么这么好了,他怕失去,所以一直记着。在开始的时候蝶衣能清楚的说出不唱戏的时间和两人没见面的时间。 段小楼 电影开始那个说话没底气的人很难与后面那个脾气差、耿直、冲动的段小楼对着上,直到看完电影,看着他的一点的一点的改变,才能理解。 不管他是真霸王还是假霸王,按他幼年和出名那会的性格,他的英雄救美,他对日本人的无视,还真与楚霸王几分相似。也许这也是蝶衣一直把他当心中的楚霸王的原因之一吧。 他的人生从菊仙的出现才发生了改变。一个女人能成就一方霸主,也能毁掉一个英雄啊!小楼没有发现蝶衣对他的爱,因为他不知道蝶衣一直在戏里,或是他一直就没入戏,也真实袁四爷那句“虞姬是真虞姬,霸王是假霸王”,不是他演的不够好,而是他本来就没有入戏。所以说菊仙并不是什么第三者,也不能去怪蝶衣的恋情的畸形。身为虞姬的蝶衣自然爱着那个英雄楚霸王,而作为男人的小楼和菊仙在一起也是情理所在。 他的改变也那一代人的改变,从年轻气盛的小伙子,直到成为一个世俗的老人,经历了抗日战争、解放、文革的人,能不改变吗。菊仙对多只算催化剂,不管如何,最后他还是变成那样子的。 菊仙 一个风尘女子,有勇有谋,善于判断形势,也是她加速了小楼的改变。也是他为蝶衣和小楼间带来了冲突。不过她只是一个代表,即使没有菊仙,也会有其他人替补上她的位置,小楼是个男人,终究会结婚生子,他和蝶衣之间的问题总是会出现的。有了菊仙这样的女子,让故事变的更不一般。 菊仙一直担心小楼和蝶衣在一起会出事,反对小楼和蝶衣一起唱戏,她内心的不安出自当初她对誓言的背弃。当她求蝶衣救小楼的时候承诺今后离开小楼,结果她食言了。再加上她为自己赎身时候老鸨说的那番话,也许就能明白她最后自杀的原因了。当小楼说出和她划清界限后,小楼是无奈的,但是在菊仙心里,她会觉得小楼还是介意了她以前的身份。 只是不明白菊仙最后为什么救那把剑。这把剑本来是类似小楼和蝶衣间的定情信物,对于她来说,没有多少价值。 最后 这里面没有三角恋,一个在戏里,一个在戏外;一个在古代,一个在现实。蝶衣对小楼也只是虞姬对霸王的感情,而小楼和菊仙是一对平凡夫妻的感情。 这里面也有因果报应,菊仙、张公公、袁四爷、小四,他们都得到应有的报应。话说蝶衣和小楼估计都把小四当自己的孩子一样看待吧。可惜了这娃,只能说是那个时代的错。 我喜欢戏班子师傅教导徒弟那几话:第一句,人得自各儿成全自各儿。第二句,自古人生一世,需有一技之长,我辈既务斯业,便当专心用功,以后名扬四海,根据全在年轻。是啊,我的一技之长是什么——编程。只能专心用功,以后希望名扬四海。

August 9, 2013

设计模式学习-组合模式(Composite)

意图: 将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 结构: 参与者 Component(Graphic) 为组合中的对象声明接口。 在适当的情况下,实现所有类共有接口的缺省行为。 (可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。 Leaf(Rectangle、Line、Text等) 在组合中表示叶节点对象,叶节点没有子节点。 在组合中定义图元对象的行为。 Composite(Picture) 定义有子部件的那些部件的行为。 存储子部件。 在Component接口中实现与子部件有关的操作。 Client 通过Component接口操纵组合部件的对象。 代码示例: Component public interface Component { public void operation(); public void add(Component item); void remove(Component item); public Component getChild(int i); } Composite public class Composite implements Component { private List<Component> children = new ArrayList<Component>(); @Override public void operation() { for (Component child : children) { child.operation(); } } @Override public void add(Component item) { this....

August 8, 2013

原型工厂模式

顾名思义就是原型模式和工厂模式的结合。在GOF的书里面,抽象工厂那节中对这个有描述,不过内容很少,所以看的时候也没注意到。 说个实际的问题:系统需要向用户发送短信,但是根据场景的不同,发送的短信格式也不同,比如重置密码和发送临时验证码的短信格式就有区别,而之前的开发人员使用了策略模式,每个内容都有一个类,现在也不方便去改动这些。但是随需求的增加,发送的场景在不断增加,策略+工厂方法模式的情况下需要去增加更多的if-else,导致扩展困难,也使得调用时候不直观。 本人自认为自己小脑瓜没有能力想出好办法,只好去翻下书籍,无意中看到了抽象工厂内介绍原型工厂的内容,想着可以借鉴。如果依靠一定规范的传入参数,通过if-else来判断需要使用的算法闲代码忒长,那么不为什么不直接传入算法呢。当然传入算法的类的话太费资源,但是传个Class或Class Name不适问题。 参数就是用枚举,这比String参数好,原因是String可以传入任何字符串,而枚举只能是枚举内的指定值,枚举代码如下: public enum MessageBuilderEnum { RESET_PASSWORD_SMS(ResetPwSmsMsgSendServiceImpl.class), RESET_PASSWORD_EMAIL(ResetPwMailMsgSendServiceImpl.class), SMS_FEE(SmsFeeMsgSendServiceImpl.class), TEMP_CODE_SMS(TempCodeSmsMsgSendServiceImpl.class), UNIVERSAL_SMS(BoundMsgSendServiceImpl.class); private Class<?> builderClass; MessageBuilderEnum(Class<?> builderClass) { this.builderClass = builderClass; } public Class<?> getBuidlerClass() { return builderClass; } } 再看下功能实现的代码 private static ConcurrentHashMap<String, AbstractMsgSendServiceImpl> messageBuilder = new ConcurrentHashMap<String, AbstractMsgSendServiceImpl>(); public MessageSendServiceImpl() { for (MessageBuilderEnum builderClass : MessageBuilderEnum.values()) { try { messageBuilder.put(builderClass.getBuidlerClass() .getSimpleName(), (AbstractMsgSendServiceImpl) builderClass .getBuidlerClass().newInstance()); } catch (InstantiationException e) { logger.error(e.getMessage(), e); } catch (IllegalAccessException e) { logger....

July 31, 2013