一、概要

  1. Tornado FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像web.py 或者 Google webapp,不过为了能有效利用非阻塞
    式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化。
  2.  
  3. Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对 epoll
    的运用,Tornado 每秒可以处理数以千计的连接,这意味着对于实时 Web 服务来说,Tornado是一个理想的 Web 框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed
    的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。

(关于如何扩容 服务器,以处理数以千计的客户端的连接的问题请点击我

下载安装:

pip3 install tornado

源码安装

https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz

  1. Tornado 各主要模块
  2. web - FriendFeed 使用的基础 Web 框架,包含了 Tornado 的大多数重要的功能
  3. escape - XHTML, JSON, URL 的编码/解码方法
  4. database - MySQLdb 的简单封装,使其更容易使用
  5. template - 基于 Python web 模板系统
  6. httpclient - 非阻塞式 HTTP 客户端,它被设计用来和 web httpserver 协同工作
  7. auth - 第三方认证的实现(包括 Google OpenID/OAuthFacebook PlatformYahoo BBAuthFriendFeed OpenID/OAuthTwitter OAuth
  8. locale - 针对本地化和翻译的支持
  9. options - 命令行和配置文件解析工具,针对服务器环境做了优化
  10.  
  11. 底层模块
  12. httpserver - 服务于 web 模块的一个非常简单的 HTTP 服务器的实现
  13. iostream - 对非阻塞式的 socket 的简单封装,以方便常用读写操作
  14. ioloop - 核心的 I/O 循环

Tornado 各主要模块

二、框架的初步使用

  1. 二、 #!/usr/bin/env python
  2. # -*- coding:utf- -*-
  3.  
  4. # 首先导入模块
  5. import tornado.ioloop
  6. import tornado.web
  7. # 让这个类继承 执行
  8. class MainHandler(tornado.web.RequestHandler):
  9. def get(self):
  10. # self.write("Hello, world")
  11. # 默认在当前的目录中寻找
  12. self.render("s1.html")
  13. # 然后创建这个对象
  14. # 路由映射,也可以叫做路由系统
  15. application = tornado.web.Application([
  16. (r"/index", MainHandler),
  17. ])
  18. if __name__ == "__main__":
  19. # 下面是创建了socket,循环,以及epoll io多路复用 socket运行起来
  20. application.listen()
  21. tornado.ioloop.IOLoop.instance().start()

快速上手

流程说明:

上面执行流程:首先导入模块,之后创建类,然后通过路由系统监听端口并且执行,用户连接就执行get等方法来给用户返回数据

三、框架的方法和配置

配置:

  1. import tornado.ioloop
  2. import tornado.web
  3. # import uimodules as md
  4. # import uimethods as mt
  5.  
  6. class MainHandler(tornado.web.RequestHandler):
  7. def get(self):
  8. self.write("Hello, world")
  9.  
  10. settings = {
  11. 'template_path': 'views', # html文件
  12. 'static_path': 'statics', # 静态文件(css,js,img)
  13. 'static_url_prefix': '/statics/',# 静态文件前缀
  14. 'cookie_secret': 'suoning', # cookie自定义字符串加盐
  15. # 'xsrf_cookies': True, # 防止跨站伪造
  16. # 'ui_methods': mt, # 自定义UIMethod函数
  17. # 'ui_modules': md, # 自定义UIModule类
  18. }
  19.  
  20. application = tornado.web.Application([
  21. (r"/", MainHandler),
  22. ], **settings)
  23.  
  24. if __name__ == "__main__":
  25. application.listen()
  26. tornado.ioloop.IOLoop.instance().start()

hello world

  1. 、首先配置字典
  2. 配置模板路径的配置,其中template是自己创建的目录名字,字典中的key是不能更改的
  3. settings={
  4. template_path”:”template”,
  5. }
  6. 、添加配置文件
  7. 在路由映射里面添加配置文件 (路由系统的两个参数,第一个刹那函数是接受一个列表,第二个 参数是接受一个配置)
  8. application=tonardo.web.Application([(r”/index”,MainHandler)],**settings)
  9. 配置静态文件路径
  10. 如果cssjs需要导入到html文件中,就需要在tonardo中配置静态文件路径,要不然就不会生效
  11. settings={
  12. static_path”:”static”,
  13. }
  14.  
  15. 、给url添加前缀
  16. settings里面添加“static_url_prefix”:”/sss/”, 后面的这三个sss要和html中的文件href路径前面一样

配置文件说明

方法:请求来时,程序会用正则匹配相应路由地址,并交付于 tornado.web.RequestHandler 的子类处理;子类会根据请求方式(post / get / delete ...)的不同调用并执行相应的方法,方法返回字符串内容并发送到浏览器。

  1. self.write("") # 把字符串发送到客户端
  2. self.render("index.html") # 返回html文件,调用render_string(),内部其实是打开并读取文件,返回内容 如果把html单独放到一个目录中,那么需要在render方法中加上路径
  3. self.redirect("s1.html",permanent=False) # 跳转重定向,参数代表是否永久重定向
  4.  
  5. name = self.get_argument("name") # 获取客户端传入的参数值
  6. name = self.get_arguments("name") # 获取多个值,类别形式
  7. file = self.request.files["filename"] # 获取客户端上传的文件
  8.  
  9. raise tornado.web.HTTPError() # 返回错误信息给客户端

方法

  1. tonardo配置方法:
  2. self.write(“”):这里面填入字符串
  3. self.render(“s1.html”):这个是把同目录的s1.html内容引入,用户连接tonardo的时候返回的内容
  4. 如果把html文件单独放入一个目录的话,那么需在render方法里面加上路径
  5. 如:把s1文件放入到目录tempalete目录中,那么执行self.render(“template/s1.html”)
  6.  
  7. 但是文件html文件太多,不应该每个都加上路径,那么就可以配置文件
  8. 、首先配置字典
  9. 配置模板路径的配置,其中template是自己创建的目录名字,字典中的key是不能更改的
  10. settings={
  11. template_path”:”template”,
  12. }
  13. 、添加配置文件
  14. 在路由映射里面添加配置文件 (路由系统的两个参数,第一个刹那函数是接受一个列表,第二个 参数是接受一个配置)
  15. application=tonardo.web.Application([(r”/index”,MainHandler)],**settings)
  16.  
  17. 配置静态文件路径
  18. 如果cssjs需要导入到html文件中,就需要在tonardo中配置静态文件路径,要不然就不会生效
  19. settings={
  20. static_path”:”static”,
  21. }
  22.  
  23. 、给url添加前缀 这个不太重要
  24. settings里面添加“static_url_prefix”:”/sss/”, 后面的这三个sss要和html中的文件href路径前面一样

总结

四、写tornado框架

写tornado框架

1、  首先导入tornado

2、  继承里面的类,书写方法

3、  创建对象

4、  配置文件、模板路径

下面是利用模板语言,用输入的数据展示出来:实例贴吧,发帖就展示出来

1、  写上form表单,用于用户提交内容,用post方法提交

2、  用self.get_argument(“”)方法获取用户输入的内容,并且把获取的内容添加到列表中

3、  用模板语言,来遍历这个列表。最后随着页面展现出来

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <link rel="stylesheet" href="/sss/commons.css"/>
  7. </head>
  8. <body>
  9. <h1>提交内容</h1>
  10. <form method="post" action="/index">
  11. <input type="text" name="xx"/>
  12. <input type="submit" value="提交"/>
  13. <h1>展示内容</h1>
  14. <ul>
  15. {% for item in xxoo %}
  16. <li>{{item}}</li>
  17. {% end %}
  18. </ul>
  19. </form>
  20. </body>
  21. </html>

HTML代码

  1. #!/usr/bin/env python
  2. # -*- coding:utf- -*-
  3.  
  4. # 首先导入模块
  5. import tornado.ioloop
  6. import tornado.web
  7. # 让这个类继承 执行
  8.  
  9. INPUT_LIST=[]
  10. class MainHandler(tornado.web.RequestHandler):
  11. def get(self):
  12. # 、打开s1.html文件,读取内容(包含特殊语法)
  13. #、xxoo=INPUT_LIST && 读取内容(包含特殊语法)
  14. #、得到新的字符串
  15. #、返回给用户
  16. self.render("s1.html",xxoo=INPUT_LIST)
  17. def post(self, *args, **kwargs):
  18. # 这个方法是接收用户输入的内容
  19. name=self.get_argument("xx")
  20. INPUT_LIST.append(name)
  21. self.render("s1.html",xxoo=INPUT_LIST)
  22. settings={
  23. "template_path":"template", #模板路径的配置,value是目录的名字,但是key不能改名字
  24. "static_path":"static", #配置静态文件路径
  25. "static_url_prefix":"/sss/", #为url加上前缀
  26. }
  27. # 然后创建这个对象
  28. # 路由映射,也可以叫做路由系统,下面是参数第一个是接受一个列表,第二个接受一个配置
  29. application = tornado.web.Application([
  30. (r"/index", MainHandler),
  31. ],**settings)
  32. if __name__ == "__main__":
  33. # 下面是创建了socket,循环,以及epoll io多路复用 socket运行起来
  34. application.listen()
  35. tornado.ioloop.IOLoop.instance().start()

python代码

  1. 上面执行流程
  2. 用户访问,执行get方法展现
  3. 用户通过form表单,接收到用户输入的内容,存放到列表中,然后执行post方法,跳转到这个页面返回给用户页面和列表
  4. 、注意这个是前台把内容发送到后台

执行流程

写完上面的程序,那么就可以对其进行补充:通过self.get_argument(“xxx”)# 获取用户提交的数据

  1. 区别:
  2. 对于GETURL中传输数据
  3. 对于POST 只能通过提交传输数据

post和get区别

  1. 下面就是在get方法中通过get_argument的方法来获取用户的数据通过列表的方式来返回给用户,注意这里的argument中的参数,None 默认为空
  2. INPUT_LIST=[]
  3. class MainHandler(tornado.web.RequestHandler):
  4. def get(self):
  5. # 、打开s1.html文件,读取内容(包含特殊语法)
  6. #、xxoo=INPUT_LIST && 读取内容(包含特殊语法)
  7. #、得到新的字符串
  8. #、返回给用户
  9. name=self.get_argument("xx",None)
  10. if name:
  11. INPUT_LIST.append(name)
  12. self.render("s1.html",xxoo=INPUT_LIST)

get_argument用法

五、模板语言

模板语言分为三类

第一种是{% for iyem in xxoo%} 代码块

需要注意的是这种代码的的结尾都必须要有{% end %},并且要和循环的对应类似于shell中的循环

  1. <h1>展示内容</h1>
  2. <ul>
  3. {% for item in xxoo %}
  4. {% if item=="aa" %}
  5. <li style="background-color: red;">{{item}}</li>
  6. {% else %}
  7. <li>{{item}}</li>
  8. {% end %}
  9. {% end %}
  10. </ul>

第二种是<li>{{item}}</li>代表的是表达式或者值

第三种是自定义的

自定义函数里面有两类  定义什么就返回什么

1、 uimethod

首先在html中自己定义一个执行的函数方法  {{方法名(参数)}}

  1. <form method="get" action="/index">
  2. <input type="text" name="xx"/>
  3. <input type="submit" value="提交"/>
  4. <h1>展示内容</h1>
  5. <h1>{{npm}}</h1>
  6. <h3>{{func(npm)}}</h3>
  7. </body>
  8. </html>

html文件

之后自己定义一个单独的文件(模块),内容为在html自己定义的函数 ,文件名为

  1. #/usr/bin/env python
  2. #-*- coding:utf- -*-
  3. def func(self,arg):
  4. print(arg)
  5. # 返回给用户大写变小写
  6. return arg.lower()
  7.  
  8. 上面的函数名为func,参数arg是传入的npm --》get方法中self.rendernpm=”NPM=”)

uimethod.py

之后在settings字典中添加”ui_methods”:mt,并且导入上面创建的模块

  1. #!/usr/bin/env python
  2. # -*- coding:utf- -*-
  3.  
  4. # 首先导入模块
  5. import tornado.ioloop
  6. import tornado.web
  7. import uimethod as mt
  8. # 让这个类继承 执行
  9.  
  10. INPUT_LIST=[]
  11. class MainHandler(tornado.web.RequestHandler):
  12. def get(self):
  13. # 、打开s1.html文件,读取内容(包含特殊语法)
  14. #、xxoo=INPUT_LIST && 读取内容(包含特殊语法)
  15. #、得到新的字符串
  16. #、返回给用户
  17. name=self.get_argument("xx",None)
  18. if name:
  19. INPUT_LIST.append(name)
  20. self.render("s1.html",npm="NPM888",xxoo=INPUT_LIST)
  21. # def post(self, *args, **kwargs):
  22. # # 这个方法是接收用户输入的内容
  23. # # name=self.get_argument("xx",None)
  24. # # INPUT_LIST.append(name)
  25. # self.render("s1.html",npm="NPM",xxoo=INPUT_LIST)
  26. settings={
  27. "template_path":"template", #模板路径的配置,value是目录的名字,但是key不能改名字
  28. "static_path":"static", #配置静态文件路径
  29. "static_url_prefix":"/sss/", #为url加上前缀
  30. "ui_methods":mt
  31. }
  32. # 然后创建这个对象
  33. # 路由映射,也可以叫做路由系统,下面是参数第一个是接受一个列表,第二个接受一个配置
  34. application = tornado.web.Application([
  35. (r"/index", MainHandler),
  36. ],**settings)
  37. if __name__ == "__main__":
  38. # 下面是创建了socket,循环,以及epoll io多路复用 socket运行起来
  39. application.listen()
  40. tornado.ioloop.IOLoop.instance().start()

后台代码

  1. 总结:
  2. 定义
  3. 首先在html中自定义函数,然后创建一个模块,内容就是自定义函数的执行方法,
  4. 注册
  5. 最后在tornado中导入这个模块,重命名,并且加到配置中

总结

2、 uimodule

需要写一个类,这个类必须继承uimodule

首先自己定制一个模块,名字为uimodule,里面要写上类,并且这个类要继承UIModule

  1. #!/usr/bin/env python
  2. # -*- coding:utf- -*-
  3. from tornado.web import UIModule
  4. from tornado import escape
  5.  
  6. class custom(UIModule):
  7.  
  8. def render(self, *args, **kwargs):
  9. return ""

模块代码

  1. #!/usr/bin/env python
  2. # -*- coding:utf- -*-
  3.  
  4. # 首先导入模块
  5. import tornado.ioloop
  6. import tornado.web
  7. import uimethod as mt
  8. import uimodule as md
  9. # 让这个类继承 执行
  10.  
  11. INPUT_LIST=[]
  12. class MainHandler(tornado.web.RequestHandler):
  13. def get(self):
  14. name=self.get_argument("xx",None)
  15. if name:
  16. INPUT_LIST.append(name)
  17. self.render("s1.html",npm="NPM888",xxoo=INPUT_LIST)
  18. settings={
  19. "template_path":"template", #模板路径的配置,value是目录的名字,但是key不能改名字
  20. "static_path":"static", #配置静态文件路径
  21. "static_url_prefix":"/sss/", #为url加上前缀
  22. "ui_methods":mt, #注册
  23. "ui_modules":md, #注册
  24. }
  25. # 然后创建这个对象
  26. # 路由映射,也可以叫做路由系统,下面是参数第一个是接受一个列表,第二个接受一个配置
  27. application = tornado.web.Application([
  28. (r"/index", MainHandler),
  29. ],**settings)
  30. if __name__ == "__main__":
  31. # 下面是创建了socket,循环,以及epoll io多路复用 socket运行起来
  32. application.listen()
  33. tornado.ioloop.IOLoop.instance().start()

注册代码

在html中自定义,即{% module 类()%}

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <link rel="stylesheet" href="/sss/commons.css"/>
  7. </head>
  8. <body>
  9. <h1>提交内容</h1>
  10. <form method="get" action="/index">
  11. <input type="text" name="xx"/>
  12. <input type="submit" value="提交"/>
  13. <h1>展示内容</h1>
  14. <h1>{{npm}}</h1>
  15.  
  16. <h3>{{func(npm)}}</h3>
  17. <h3>{% module custom() %}</h3>
  18. </form>
  19. </body>
  20. </html>

html代码

  1. 总结:通过自定义来可以用python语言来写模板语言的功能
  2. uimethod:
  3. 这个是自定义函数,通过函数来返回给用户数据
  4. uimodule:
  5. 这个是自定义类的,通过类中的函数来给用户返回数据
  6. 注意:如果get方法中传入参数,和模板函数相关,那么post也要有这个参数

总结

模板方法

escape都是转义的功能

  • escape: tornado.escape.xhtml_escape 的別名
  • xhtml_escape: tornado.escape.xhtml_escape 的別名
  • url_escape: tornado.escape.url_escape 的別名
  • json_encode: tornado.escape.json_encode 的別名   用作json处理的
  • squeeze: tornado.escape.squeeze 的別名
  • linkify: tornado.escape.linkify 的別名   生成a标签的
  • datetime: Python 的 datetime 模组       用的python的datatime模块
  • handler: 当前的 RequestHandler 对象        self.self,handler是self对象
  • request: handler.request 的別名            self封装的所有的request信息
  • current_user: handler.current_user 的別名    所有的handler都是self对象
  • locale: handler.locale 的別名
  • _: handler.locale.translate 的別名
  • static_url: for handler.static_url 的別名   这个是做缓存用的
  • xsrf_form_html: handler.xsrf_form_html 的別名   防止跨站请求用的
  • static_url: for handler.static_url 的別名   这个是做缓存用的

具体用法: 在静态文件前面添加

下面黄色部分

外部是单引号,之后两个大括号,之后小括号是应用的静态文件名字

‘{{static_url(“文件名”)}}’

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <link rel="stylesheet" href='{{ static_url("commons.css")}} '/>
  7. </head>
  8. <body>
  9. <div>提交内容</div>
  10. <form method="get" action="/index">
  11. <input type="text" name="xx"/>
  12. <input type="submit" value="提交"/>
  13. <h1>展示内容</h1>
  14. <h1>{{npm}}</h1>
  15.  
  16. <h3>{{func(npm)}}</h3>
  17. <h3>{% module custom() %}</h3>
  18. <ul>
  19. {% for item in xxoo %}
  20. {% if item=="aa" %}
  21. <li style="background-color: red;">{{item}}</li>
  22. {% else %}
  23. <li>{{item}}</li>
  24. {% end %}
  25. {% end %}
  26. </ul>
  27. </form>
  28. </body>
  29. </html>

模板引用静态文件用法

作用:用户浏览器接收数据,如果md5变化了,那么缓存就更新为静态文件做缓存,从浏览器中查看,下面的v后面的内容是md5序列号

六、tornado框架之模板引擎的本质

模板引擎在内部就是做了字符串拼接

模板引擎的本质  字符窜分割:

本质就是处理html文件内容将html文件内容转换成函数,然后为该函数提供全局变量环境(即:我们想要嵌套进html中的值和框架自带的值),再之后执行该函数从而获取到处理后的结果,再再之后则执行UI_Modules继续丰富返回结果,例如:添加js文件、添加js内容块、添加css文件、添加css内容块、在body内容第一行插入数据、在body内容最后一样插入数据,最终,通过soekct客户端对象将处理之后的返回结果(字符串)响应给请求用户。

上图就是把左侧的html代码转换成字符串,然后用接受一个字符串通过compile和exec执行,放到一个字典中,然后通过字典执行转化成

函数的方法转换成函数

  1. #/usr/bin/env python
  2. #-*-coding:utf- -*-
  3.  
  4. namespace={'name':'pyrene','data':[,,],}
  5. code='''def hellocute():return "name %s,age %d" %(name,data[0],)'''
  6.  
  7. #把code编译成字节码对象,第二个参数是声明类型,第三个参数表示这是一个序列类型
  8. #编译成函数
  9. func=compile(code,'<string>',"exec")
  10. #执行,把func放入到namespace字典里面
  11. exec(func,namespace)
  12.  
  13. result=namespace['hellocute']()
  14.  
  15. print(result)

例子

补充知识:

1、Python标准库:内置函数compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)

source 是编译的对象

filename 声明该对象的类型

mode  用什么类型来编译

2、内置函数exec(object[, globals[, locals]])

执行函数,把对象放入到 后面变量中

compile只编译字符串代码,不做任何的执行,但是可以编译表达式和语句

exec函数是只执行语句代码,不执行表达式代码,因为他没有返回值

eval  只执行表达式代码,不执行语句代码x = eval('%d + 6' % x)

  1. . #exec()
  2. .
  3. . exec('if True: print(100)')
  4. . exec('''''
  5. . x =
  6. . if x > :
  7. . print(x + )
  8. . ''')

例子

web框架详解之tornado 一 模板语言以及框架本质的更多相关文章

  1. web框架详解之 tornado 四 模板引擎、session、验证码、xss

    一.模板引擎 基本使用 继承,extends 页面整体布局用继承 导入,include 如果是小组件等重复的那么就用导入 下面是目录 首先在controllers里面创建一个文件,文件里面是页面类 # ...

  2. web框架详解之tornado 三 url和分页

    一.代码目录构建 controllers  :处理业务逻辑的 account:处理账户相关的 上面目录作用和内容 controllers 包 :处理业务逻辑的 account:处理账户相关的 home ...

  3. web框架详解之tornado 二 cookie

    一.tornado之cookie一 目录: <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  4. Solon 框架详解(十一)- Solon Cloud 的配置说明

    Solon 详解系列文章: Solon 框架详解(一)- 快速入门 Solon 框架详解(二)- Solon的核心 Solon 框架详解(三)- Solon的web开发 Solon 框架详解(四)- ...

  5. Spark2.1.0——内置Web框架详解

    Spark2.1.0——内置Web框架详解 任何系统都需要提供监控功能,否则在运行期间发生一些异常时,我们将会束手无策.也许有人说,可以增加日志来解决这个问题.日志只能解决你的程序逻辑在运行期的监控, ...

  6. (转) shiro权限框架详解06-shiro与web项目整合(上)

    http://blog.csdn.net/facekbook/article/details/54947730 shiro和web项目整合,实现类似真实项目的应用 本文中使用的项目架构是springM ...

  7. JAVA Eclipse使用Maven构建web项目详解(SSM框架)

    tips: 启动项目后,welcome-file的链接即为测试用例 部署maven web项目 Eclipse使用Maven构建web项目详解 pom.xml添加webapp依赖: <depen ...

  8. Solon 框架详解(十)- Solon 的常用配置

    Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...

  9. jQuery Validate验证框架详解

    转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...

随机推荐

  1. c++打印蛇形矩阵

    一个m*n的矩阵里按照下图形式填充,最后形成的矩阵即为蛇形矩阵,下图是m=4, n =5时的蛇形矩阵: 方法一:逐层循环 #include <iostream> using namespa ...

  2. 开发中可能会用到的几个小tip----QT, pycharm, android, 等

    QT: 如果是在windows下开发的话,添加外部库,外部包含头文件路径的时候,要注意用相对路径,或者在项目上右键添加外部库的路径或者头文件路径,否则,会卡在这里开始怀疑人生... 如果是在linux ...

  3. JS-以鼠标位置为中心的滑轮放大功能demo1

    以鼠标位置为中心的滑轮放大功能demo1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &qu ...

  4. 利用NIO的Selector处理服务器-客户端模型

    package NIOTEST; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocket ...

  5. [译]GLUT教程 - 交换菜单

    Lighthouse3d.com >> GLUT Tutorial >> Pop-up Menus >> Swapping Menus GLUT甚至可以在应用程序过 ...

  6. NHibernate二级缓存(第十一篇)

    NHibernate二级缓存(第十一篇) 一.NHibernate二级缓存简介 NHibernate由ISessionFactory创建,可以被所有的ISession共享. 注意NHibernate查 ...

  7. Docker-Compose 自动创建的网桥与局域网冲突解决方案

    环境: 使用docker-compose.yml 部署应用,docker 默认的网络模式是bridge ,默认网段是172.17.0.1/16  ,不巧的是我们局域网也使用的172.22. xx 网段 ...

  8. vim visual模式 复制

    按ESC再按“V”,进入visual模式 用键盘向左向右箭头选中要复制的文字,按两下"Y"键 再到要粘贴的地方,按“P”键即可. 转自: http://jingyan.baidu. ...

  9. iOS_3_图片浏览

    终于效果图: BeyondViewController.h // // BeyondViewController.h // 03_图片浏览 // // Created by beyond on 14- ...

  10. WPF Button TextBox 圆角

    <!--圆角button--> <Style TargetType="Button"> <Setter Property="FontSize ...