28 / 03 / 2011 buling

      诚然我知道很晚了,但是我还是想记录一下,不是因为我喝了酒,是因为真的应该记录。一直以来我总以为一个人最能说明自己的无非是考个很好的成绩,即便是只是数学,或者工作上被别人所认可很重要。但今天,大家一起喝酒,一起敞开心扉的聊天,我赫然感觉,原来我有这么伤人的一面。
      今晚真的很happy,毕业以后,我从没喝过这么多酒,之前总是我们(@王凤、@王猛、@杨正胜一起喝白酒),以前在业务开发从没人喝酒,即便红酒,一杯都能喝几次,深圳人,你怎么了。今天感觉到了,我们部门就是不一样,思昌说的很好,我们工资虽然少了点,但我们这个环境很好,大家都不舍得离开。这不是主要的,主要的是他站在一个他人的立场说出了我的致命点:感觉你一直很强势,很难相处,之前听说你们搞德州很想一起参加。突然发现,原来我再别人心中是这个形象,其实之前我也隐约感觉,真的,我容不了别人不客观的思想,容不了别人不正确的想法,因为我坚信自己想的是有理由的,从没怀疑过。
      今天上午,星哥最终还是把sso登陆的项目给了我,即便我想了很多次我可以协助zhaok一起完成,但上午听他讲思路的时候我还是由不得已的问了一句:你知道cookie和session的区别么?对此我表示很抱歉,之前我修改passport的时候气都不打一处出,这哪是代码,这完全是扯蛋,一堆与登陆不相关的代码错综复杂的交替着。所以我打算彻底分离所有模块。
      不过很高兴,今天喝的这么开心,lids和cd是之前比较熟悉的,今晚开始发现思昌豪迈的一面,要是能相处,肯定能合的来。星哥第一次看见他喝这么多酒,哈哈,应该是大家真的很高兴,加油,大家一起加油。
      睡之前很想说,哥几个我们下次来白的。

      想安装一个android开发环境,因为快有M9,至少要个helloword才能过意的去吧…..趁安装较麻烦,来发个博客。之前说过做的电信、联通、移动的短信网关正式上线了,前几天很折腾,主要是连接断后没有达到想像中的自动重启,后来花了两天调整,本来打算周末看能不能出现断掉的情况,昨晚没出现,寄希望于今晚了,因为有双色球开奖,这个很容易出现。
      查询短信接收情况的时候发现一个大问题,浙江和河北两个地方的移动手机号出现:IB:0079错误,通过抓包对比,我们怀疑是业务代码填空导致,所以改为EIE,后来恢复正常。主要想说的是,出现错误时一般估计是地域问题,但是要查询一大批用户手机号码归属地….一个一个的查感觉怎么样,所以写了个批量查询的,体验地址:http://www.quou.cn/wp-code/jsonp/
      利用的是网易的API:http://www.youdao.com/smartresult-xml/search.s?jsFlag=true&type=mobile&q=13632580530,访问可以看到返回:updateCall(1, {‘product’:’mobile’,’phonenum’:’13632580530′,’location’:’广东 深圳’} , ”); 建议本人不想对字符串做解析,所以就用jsonp直接实现了,来看代码:
整个html页面很简单,一点修饰都没有,主要是不想折腾

< !DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">



Insert title here


      

          下面就是主要的实现代码了,就不啰嗦了,直接代码:

          这两天一直看ice和icestorm,打算根据自己理解到的做两个小应用,ice做了一个网页版的群聊,icestorm做了一个客服端版的群聊,因为这个客服端版的是基于命令行的,所以想弄个界面,就看了一下python的gui框架tkinter,折腾了很久,终于弄了个界面,因为控件实在比较少,所以几乎没法美化,上图:

          好了,效果有了,来,贴代码,就懒得分块描述了:

    #coding=utf-8
    import time
    import socket
    import pickle
    import tkMessageBox
    from Tkinter import *
    class Talkoo:
        def __init__(self, name='Talkoo!', standard='600x400'):
            self.root = None
            self.wName = name
            self.wStandard = standard
            sName = socket.gethostname()
            self.ipAddr = socket.gethostbyname(sName)
        def initWindow(self):
            '''初始化窗口'''
            self.root = Tk()
            self.root.title(self.wName)
            self.root.geometry(self.wStandard)
            self.root.protocol("WM_DELETE_WINDOW", self.exitWindow) #窗口绑定关闭事件
            self.listframe = Frame(self.root) #创建一个列表框架
            self.textframe = Frame(self.root) #创建一个发送框架
        def enterFun(self, event=None):
            '''点击或回车时方法'''
            res = self.text.get()
            info = '%s %s : %s' % (self.ipAddr, time.strftime('%Y-%m-%d %H:%M:%S'), res)
            if res:
                self.listbox.insert(END, info)
                self.text.delete(0,END)
        def saveMsg(self):
            '''保存窗口列表信息'''
            f = file("notes.db", "wb")
            notes = self.listbox.get(0, END) #取出所有信息
            pickle.dump(notes, f)
            f.close()
        def loadMsg(self):
            '''载入历史记录'''
            try:
                f = file("notes.db", "rb")
                notes = pickle.load(f)
                for i in notes:
                    self.listbox.insert(END, i)
                f.close()
            except:
                pass
        def exitWindow(self):
            '''退出事件'''
            if tkMessageBox.askokcancel("退出", "你确定要退出?"):
                #self.saveMsg()
                self.root.quit()
        def main(self):
            '''窗口控件加载'''
            listframe = self.listframe
            scrollbar = Scrollbar(listframe, orient=VERTICAL)
            self.listbox = Listbox(listframe, yscrollcommand=scrollbar.set)
            scrollbar.configure(command=self.listbox.yview)
            self.listbox.pack(side=LEFT, fill=BOTH, expand=1)
            scrollbar.pack(side=RIGHT, fill=Y)
            textframe = self.textframe
            self.text = text = Entry(textframe, bg='#FFFF00', fg='#FF0000')
            butt = Button(textframe, text="发送", command = self.enterFun)
            text.bind("", self.enterFun)
            text.pack(side=LEFT, fill=X, expand=1)
            butt.pack(side=LEFT)
            listframe.pack(fill=BOTH, expand=1)
            textframe.pack(fill=X)
        def run(self):
            self.initWindow() #初始化窗口
            self.main() #绘制窗口
            #self.loadMsg() #加载信息
            self.root.mainloop() #进入主循环
    if __name__ == '__main__':
        Talkoo().run()
    

          关于ice和icestorm的东西,等我总结完再发出来给大家review一下。最近这几天是我上班以来最闲的几天,没事做一天下来总感觉欠缺点什么,虽然是自己学习,但这东西如果被一些小事打断就很难再连起来了,学习、学习、再学习。
          明天大家准备去州立影院看《洛杉矶之战》,听说不错,好久没看电影了,上次还是《青蜂侠》,我们一起团了巴西烤肉,应该有顿可口的美餐。打算买M9,现展钱不够了,还这么折腾….哎….败家子….

    03 / 03 / 2011 buling

          历时一周的手机竞拍接口正式完成了,刚开始规划的时候感觉不可能,但事实上就是这么快,主要是很多接口都是复制以前的接口就能搞定。一个项目完了总结一下是很有必要的。
          首先这次开发的整个结构沿溪了竞拍web站的风格,遵循统一入口,全面向对象开发。与web站不同的是采用了统一输出,废除了php反射,添加了插件模块,增加调试信息。整个网站结构很清晰。
          index.php?cid=10201&format=xml&charset=gbk; 这个是接口的入口,页面只有两句代码:

    include(_BASE_ROOT_.'/config.php');
    $index = getInstance();
    $index->run();
    

          在config.php页面中主要是做参数配置和得到一个相应处理类实例

    define('VERSION', 'v0.1'); //接口版本
    define('DEBUG', 1); //是否开启调试
    $GLOBALS['comonArgs'] = array('cid', 'tid'); //通用接受参数
     //通用插件,即所有接口都会调用
    $GLOBALS['comonPlugin'] = array('before' => array('refuseSomeUser'), 'after' => array());
    //命令调用配置,不同的命令对应不同的处理方法
    //可以配置是否验证签名,验证登陆,开启插件等
    $GLOBALS['classConfig'] = array(
        '10011' => array('class' => 'User',   'method' => 'login',   'checkSign' => 1,
                 'isLogin' => 0, 'args' => array('username', userpwd), 'before' => array());
    //传入参数格式检查配置
    $GLOBALS['paraConfig'] = array( 'username' => '');
    //错误码配置
    $GLOBALS['errorConfig'] = array( -200 => '登陆失败');
    

          最后还有一个最关键的函数,返回相应类的实例。

    function getInstance(){
        $classConfig = $GLOBALS['classConfig'];
        $cid = request('cid');
        $classFile = _BASE_ROOT_.'/Interface/'.$classConfig[$cid]['class'].'.php';
        include($classFile);
        $className = 'I_'.$classConfig[$cid]['class'];
        if(class_exists($className)){
            return new $className($classConfig[$cid]);
        }
    }
    

          前端请求页面就这些,来看看类文件吧,当然还有个主干页面Icom.php页面还没上呢,这个是页面通用继承类,是所有类的爸爸,既然是长辈肯定要为子女做很多事情了,比如帮他们登陆,帮他们过滤坏人(注入),帮他们规划(统一输出)

    class Icom{
        function __construct($data){
            $this->_conf = $data; //传入配置数据
            $this->_filterArgs(); //过滤get、post、request变量
            $this->_initSystem(); //初始化系统配置
            $this->_checkLogin(); //根据配置是否要求登陆并完成登陆操作
            $this->_checkAuth(); //检查权限,如是否黑名单等。
        }
        function run(){
            $plugin = new I_Plugin($this->_conf, $this->_REQUEST);
            $plugin->runBefore(); //调用前置插件
            $action = $this->_conf['method'];
            $res = $this->$action();
            I_Format::result($res, $this->format, $this->charset, $this->_request('debug'), $this->_debugStr());
            $plugin->runAfter(); //调用结束插件
        }
    }
    

          还有I_Plugin和I_Format类就不多说了,I_Plugin负责找出配置中的所有配置插件,并执行。I_Format类就做统一格式化,一般分json和xml,xml又提供了两种,一种是调用DOMDocument类创建,一种是字符串拼接,当然我们选择了后者,因为性能。
          最想说的是这个插件问题,因为在开发时,发现以前的web竞拍中有大量的判断代码,如内侧资格判断,活动资格判断等等。活动或内侧过期了,那么这里就有一段长长的注释代码,看着人很揪心。所以在开发时加入插件模块,所有的非功能性代码全以插件函数形式加载执行。
          在这次的run函数中没有使用ReflectionClass($this)来反射需要执行的方法,这也是出于性能的因素考虑。不仅代码简单,更重要是更容易理解。
          框架写多了能总结很多,以前写mvc框架的时候接触php反射,所以在web竞拍中就使用上了,当时的模块类中必须有配置代码,现在完全剔除了,给开发者减轻了很多工作量,他们只需要关心功能代码。这次总共14个接口,我自己写了注册、登入、登出、购买拍点、购买拍品、出价6个接口;刘雪飞写了用户相关4个接口;小郭写了竞拍相关4个接口。特别说一下小郭和liuxf之前都没有参加过竞拍开发。特别谢谢,你们的努力大大缩短了开发时间。
          之前做的订制邮件今天下午已经把所有彩种都上了。一下子感觉轻松了很多,本身花不了很多时间,qianqian催的人心咕咕的,现在上完就好了。电信短信网关也上线了,但是response的有点慢,接下来是联通短信网关开发。