密码保护:ghs.google.com付费及免费方案(密码:111111)
博客重构完毕(Reconstruct Blog)
花了2个月时间,终于把博客从micolog完全转到自己的构架上来
放弃micolog的原因很多,但不可否认micolog是一款在GAE上出色的Blog.但也因为GAE因为GWF作怪,活跃度不是很高.导致micolog的发展一直不是很快
考虑到micolog自身因设计时候造成代码的冗余以及体积的庞大,自己就重造了一会轮子. ╮(╯▽╰)╭ 上天原谅我吧.
博客重构后,重点考虑到了性能问题,因此在次方面进行了优化,网速正常情况下
访问http://i-studio.appspot.com只需要2s
访问http://www.fengsage.com 由于反向代理的关系,一般在5s-10s内打开
原http://fengsageblog.appspot.com 访问都会自动跳转到相应的http://i-studio.appspot.com页面上来
目前运行已经一周,尚运行稳定.
————————Exercise English—————————–
Take me two months, I reconstruct my blog on GoogleAppEngine.
Micolog is very good blog on GoogleAppEngine. everyone can download the srouce from http://code.google.com/p/micolog/
But i also have some reason give up it.
1. The blog develop very slow. the author long time update. i think the GWF is important reason that it also closed the connection when chinese person visted GAE.
2. The blog code not beautiful. ok, because author using python. me too. i like the code more simple and beautifule.
╮(╯▽╰)╭
I take long time optimizing the connection spped when chinese person visited it.
if visted http://i-studio.appspot.com only need 2s
if vised http://www.fengsage.com may be need 5-10s
older person can connection the old url. all request will auto skip the new url http://i-studio.appspot.com
以后有机会,写博文都加一篇英文的~ 练习练习鸟语~
总结2010
从QQ空间上挪下来,方便归纳
2010总的来说是一个收获的一年,得到了很多,也许也失去了些东西,有得有失谁能说得清呢!
学习某位同学的格式,我也分几部分总结总结:
1、学习
好吧,早已经毕业了,应该不谈这个,但最为一名软件从业人员这方面还是很重要的.分下面几个内容:
a) 软件技术. 这一年技术水平(理论水平)提高的很快,考虑问题的角度也越来越抽象,不在局限于一行行的代码,逐渐看穿软件开发的一些迷雾.
b) English. 这一年也是用这玩意最多的一年,老总说的对,English只是一门工具,用多了就熟练了. 一年后的今天阅读English文档不在费力(仅局限于计算机文档)
2、生活
独身在外也没什么好谈的, 暂时还是没有脱离光棍的我,周末除了爬山就是宅在家里了. 幸运的是经常组织原SLT团队的”叔叔””阿姨”们周末去爬山,不至于太无聊. 当然希望未来和MM去爬山,而不是和一群”叔叔””阿姨”们. (“叔叔””阿姨们”想骂就骂吧)
3、工作
今年大部分时间都在鸿程度过. 有幸出国了一趟,见识了点世面. 现在回到公司,缺少一种人气.想念SLT团队的”叔叔””阿姨”们
4、情感 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ (已经加密)
5、成长
完全是凑数,就4点不吉利,5点比较好. 曾对一位MM说过,过去的我混混沌沌的,大学毕后的我才是真的我吧. 回想从小学到高中的阶段,真感觉就在昨天一般,那时候所思所想现在想来真的好好笑. 一句话总结,我终于是我了,我找到了我.
————–2011展望部分待续……
使用Google Captcha作网站的验证码(Python)
CAPTCHA 是Completely Automated Public Turing test to tell Computers and Humans Apart的缩写,够长吧!中文意思是:"全自动区分电脑与人类的图灵测试" 简单来说就是用于区分人类和电脑的验证码图片.
感谢伟大的Google提供了其实现和相应的API. 相关文档大家可自行参考:
http://www.google.com/recaptcha
最近公司的一个项目要使用验证码防止恶意脚本批量注册或遍历破解密码. 传统的解决方式很多,比如IP记录,验证码…但最常见的还是验证码功能,但现在验证码也是有很多弱点的,很容易被破解. 敢兴趣的朋友可以参看相关文章(http://www.xklog.org/article/internet/python-verify-code-recognize-discuz.html) 其实最主要想使用Google Captacha的原因是想省力气,懒得写太复杂的算法. 囧~呵呵
Google Captacha有相应的python实现,但是我感觉默认库可定制性太差,所以只部分采用.
开始之前我先来说下Google Captacha的原理.
传统的验证码是网站先随即生成一个字符,然后保存字符串到session或数据库中.然后把这个字符串生成图片,输出到页面上去.
Google Captacha构架如下图:
步骤看上去比较多,其实对网站开发者来说重点是3步.即图上的1、3、4. 下面稍微解释下
第一步是用户从Google服务器上得到一个验证码图片
没错,是用户获取。对开发人员来说就是在页面加一个ajax调用,当用户加载页面的同时,加载一个Google Capatcha图片即可.
第二步是当用户把含验证码信息表单提到后台,也是web应用最常见的步骤.
第三步是网站后台把用户得到的验证码传递给Google Capatcha服务器验证用户输入的是否正确.
这里就是重点所在,Google服务器如何知道当前验证码输入是否和第一步用户请求到的图片一致,就需要一样东西,即一个随机码. 此外要确定是哪一个网站用户申请的图片和哪一个网站验证图片,需要另外一样东西,即私钥/公钥.
上面简单介绍了下原理,对开发人员来说读代码比看文章管用的多.下面直接开始
一、注册网站私/公钥.https://www.google.com/recaptcha/admin/create
Public Key:
6LcmCL8S*****JH2rJ5l9mgj9xIq63wM0Qeliafm
Private Key:
6LcmCL8S******DFxZh7GY-nWdklo9zWJpQ9Y0yY4
二、编写用户页面,公钥是用户向Google服务器请求一个Capatcha图片. 此步骤需要用户公钥
由于国内加载GoogleCapatcha图片比较慢,我用了异步请求.大致代码如下
HTML
分享一个Python数字分页工具
有点造轮子的嫌疑,感觉Django自带的分页工具不是很好用,部分重写了下
Python代码
class Pagination(): ''' Pagination tools ''' count = 0 page_size = 10 current_page = 1 page_gap = 5 page_count = 0 def __init__(self,object_list,page_size,current_page = 1,page_gap=5): u'''Simple Pagination tools object_list: The queue or list objects page_size: Page size current_page: Current Page page_gap: The gap of current page, inlcude left gap and right gap. the same value is this. ''' self.object_list = object_list self.count = self._get_count() self.page_size = page_size self.current_page = current_page self.page_gap = page_gap if not self.count % page_size: self.page_count = self.count / page_size else: self.page_count = self.count / page_size + 1 def _get_count(self): "Returns the total number of objects, across all pages." try: self.count = self.object_list.count() except (AttributeError, TypeError): self.count = len(self.object_list) return self.count def page_objects(self): bottom = (self.current_page-1)*self.page_size top = bottom + self.page_size if top >= self.count: top = self.count return self.object_list[bottom:top] def has_pre(self): if self.current_page > 1: return True return False def has_next(self): if self.current_page < self.page_count: return True return False def has_first(self): if self.current_page == 1: return False return True def has_last(self): if self.current_page == self.page_count: return False return True def page_limit(self): return self.page_size * (self.current_page - 1) def page_left_list(self): if self.current_page > self.page_gap: return range(self.page_count+1)[self.current_page-self.page_gap:self.current_page] return range(self.page_count+1)[1:self.current_page] def page_right_list(self): if self.current_page + self.page_gap <= self.page_count: return range(self.page_count+1)[self.current_page+1:self.current_page+self.page_gap+1] return range(self.page_count+1)[self.current_page+1:] def page_list(self): return range(self.page_count+1)[1:] def page_html_format(self): html = '<div id="pagination">' if self.has_first(): html += '<a href="?page=1">First</a>n' html += ''.join(['<a href="?page=%s">%s</a>n'%(n,n) for n in self.page_left_list()]) html += '<a class="a1">%s</a>n'%self.current_page html += ''.join(['<a href="?page=%s">%s</a>n'%(n,n) for n in self.page_right_list()]) if self.has_last(): html += '<a href="?page=%s">Last</a>n'%self.page_count html += '</div>' return html
使用方法很简单
... PAGE_SIZE=10 try: pagination = Pagination(results,PAGE_SIZE,current_page=int(request.GET.get('page', 1)),page_gap=10) except InvalidPage: raise Http404 context = { 'query': sTerm, 'object_list': pagination.page_objects(), 'pagination': pagination, } return render_to_response('search/search.html',RequestContext(request,context)) ...
模板使用
{{ pagination.page_html_format }}
效果如下(自己定义CSS)
Apache Servicemix 教程 – EIP基础
有段时间没写这系列文章了,今天“心血来潮”写上一篇.
EIP即Enterprise Information Portal. 是ESB领域一个比较重要的概念,事实上不单单是ESB, EIP可以用在很多地方,相对于BPEL更加底层. 关于EIP有一款非常著名的开源产品,也是apache顶级项目之一 Apache Camel http://camel.apache.org/ 这里Servicemix对Camel也有专门的JBI封装,并且Servicemix也很推荐使用Apache Camel作为其EIP.
EIP的范畴太大(我水平也有限),我们这里只讲在Servicemix里的EIP. 推荐一部EIP经典之作,《Enterprise Integration Patterns 》构架师必备宝典之一. 涵盖了EIP所有的设计模型.Apache Camel就是几乎对这本书所讲到的模型都做了实现.堪称经典中的经典.
本章作为基础,不想扯到Apache Camel上去,只对servicemix自带的eip进行讲解.熟悉以后可以轻松过渡到Apache Camel中去.
开始之前,请确认了解XML相关知识,如Xquery、Xpath、命名空间等. 不了解朋友请先在W3C网站上学习相关知识. http://www.w3school.com.cn/x.asp
打开servicemix-eip文档,可看到其支持的11种路由方式. 就一般应用而已也是足够的了.
Content-Based Router | 消息内容路由 |
Message Filter | 消息过滤 |
Pipeline | in-only –> in-out 消息桥接. |
Static Recipient List | 多目的消息路由,即one consumer 到 multi provider |
Static Routing Slip | 静态路由规则. 即设定路由线路.使其按照线路一步步走下去 |
Wire Tap | 消息监听路由 |
XPath Splitter | 消息分割路由.即把单一消息切割成多个消息 |
Aggregator | 消息聚合路由.即上面的反过来 |
Content Enricher | 内容再造路由.消息通过此路由可以进行一些额外的交互,比如数据库 |
Resequencer | 消息重组.即把多条散列数据重组 |
AsyncBridge | in-out –> in-only 消息桥接. |
上表简单对路由功能进行概述. 常用的是这几个路由
- Content-Based Router
- Static Recipient List
- Wire Tap
- Aggregator
- XPath Splitter
稍微对上面几个常用路由的运用场景进行解释和介绍,更多路由可以购买或下载上面提到的《Enterprise Integration Patterns 》一书.
一、Content-Based Route
最经典的一个路由,基于一个消息的内容的不同,把消息路由到不同的端口上去.
eg. 创建一个客户,ESB接受到客户信息数据后,可以判断客户的级别,把不同级别的客户发往不同的服务提供者上去.
二、Static Recipient List
静态的设定当ESB收到一个条数据后,同时发给多个服务提供者.
eg. 电信前台CRM创建一个客户账户的时候,这个客户信息同事要传递给计费系统BSS又要传递给施工系统OSS,同事建立起客户基本信息.
三、Wire Tap
消息监听模式,当一条消息不管采用in-only还是in-out通过时,都可以对消息进行监听,此过程是异步的.
eg. 做消息监听日志
四、Aggregator
把多条数据聚合后送往一个服务提供者. 多用于复杂数据交互场景. 适用于异步模式.
eg. 银行查询一个人账户的信誉等级. 同时向多家机构发出查询请求, 多家机构对结果通过ESB设置的规则,统一汇总后返回. 比如A机构给出的评价是10分, B机构给出的评价是6分. 通过聚合处理后,可以同事把A和B的评价接收,而不是单独的接收每个系统的数据.
五、Xpath Splitter
消息切割,可以把一个消息按照某种规则,切割成多个小片段的数据.
eg. 一个新系统要采购一个书包名单,往往是发出一个书包名单的集合,而如果目标是一个老系统,接口每次只能处理一本书时,在不改变2个系统接口上,通过配置消息切割路由,在ESB把多本数据切割成单本书,一次传递给老系统.
下一章会实例讲解下EIP的配置.
近期评论