# 向cookie中存儲(chǔ)數(shù)據(jù)
self.set_cookie("info", "msg")
#取cookie中的數(shù)據(jù)
info_ = self.get_cookie("info")
# 但上面簡單的cookies直接顯示數(shù)據(jù),容易被他人利用,使用加密的cookie
# 向cookie中存儲(chǔ)數(shù)據(jù)
self.set_secure_cookie("info", "msg")
info_ = self.get_secure_cookie("info")
# 添加混淆碼,加密cookie
app = Application(
[......],
#混淆碼一般用 base64.b64encode 格式的隨機(jī)碼
cookie_secret='yYsdHBeySj2XPhzewQYsycmLHRwXsko9lz4c3sEGLMnJix0cF7JKPZc+HN7BBizJ'
)
# 清除cookie
clear_cookie()
- cookie有時(shí)間設(shè)置,通過self.cookie(name, value, expires_days)來給添加一個(gè)cookie數(shù)據(jù),如果不設(shè)置過期時(shí)間expries_days,該cookie就是一個(gè)會(huì)話級(jí)別的臨時(shí)cookie,一旦會(huì)話超時(shí)或者瀏覽器完全關(guān)閉的情況下,cookie中存儲(chǔ)的數(shù)據(jù)就會(huì)丟失;如果設(shè)置了過期時(shí)間expires_days該cookie就是一個(gè)永久cookie,永久的cookie默認(rèn)為30天時(shí)限。永久時(shí)間設(shè)置:為None時(shí),關(guān)閉會(huì)話立即失效, 小于等于0時(shí)cookie沒作用,創(chuàng)建后立即過期.
- 附加
# 轉(zhuǎn)碼encode
# 解碼decode
# 禁止跨域請(qǐng)求,APP添加設(shè)置
xsrf_cookies=True,
# 前端網(wǎng)頁請(qǐng)求時(shí)添加令牌
{% module xsrf_form_html() %}
登錄認(rèn)證
#導(dǎo)入登錄認(rèn)證模塊
from tornado.web import authenticated
# 在函數(shù)處理中添加 get_current_user()函數(shù),判斷current_user當(dāng)前用戶是否登錄的認(rèn)證。
# 重寫get_current_user()函數(shù)~指定在什么情況下用戶是登錄狀態(tài)!
def get_current_user(self):
name = self.get_secure_cookie("login")
if name is not None:
return True
return False
# authenticated裝飾器~用于判斷用戶是否具有登錄狀態(tài)
@authenticated
def get(self):
# 獲取cookie中的數(shù)據(jù)
name = self.get_secure_cookie("login")
self.render("index.html", name=name)
if __name__ == "__main__":
app = Application(
[......],
# 設(shè)置錯(cuò)誤信息顯示是否詳細(xì)
debug=True,
# 這是登錄認(rèn)證判斷沒有登錄(cookie ‘login’ 沒有用戶)時(shí)跳轉(zhuǎn)的路由
# 當(dāng)完成登錄時(shí)會(huì)自動(dòng)返回當(dāng)時(shí)請(qǐng)求的頁面。有記憶功能。
login_url='/login',
)
異步
- 前端異步
- 通過前端Ajax實(shí)現(xiàn)異步處理,和其他服務(wù)器項(xiàng)目進(jìn)行數(shù)據(jù)通信
如天氣預(yù)報(bào)接口: (http://wthrcdn.etouch.cn/weather_mini?city=)
通過前端頁面提交城市到天氣預(yù)報(bào)服務(wù)器查詢,返回?cái)?shù)據(jù)到前端頁面,自己服務(wù)器不參與。
- 注意:有時(shí)數(shù)據(jù)返回的是字符串,要轉(zhuǎn)化為json格式供自己使用
// 獲取天氣數(shù)據(jù),轉(zhuǎn)換數(shù)據(jù)~string->json
var _weather = JSON.parse(data).data;
// DOM操作渲染數(shù)據(jù)
var $today1 = $("<p>").text("日期:" + _weather.forecast[0].date);
- 后端同步
- 前端請(qǐng)求時(shí)通過自己的服務(wù)器向他人的服務(wù)器獲取數(shù)據(jù),再返還給前端.
# 引入需要的模塊
from tornado.httpclient import HTTPClient
# 定義一個(gè)天氣預(yù)報(bào)處理類
class WeatherHandler(RequestHandler):
# 同步方式~從其他服務(wù)器獲取數(shù)據(jù)
def get(self):
# 前端接收的數(shù)據(jù)
city = self.get_argument("city")
# 創(chuàng)建一個(gè)客戶端對(duì)象
client = HTTPClient()
# 抓取指定的url地址中的數(shù)據(jù),得到一個(gè)響應(yīng)對(duì)象response
# 抓取到的數(shù)據(jù)是存放在body屬性中
response = client.fetch("http://wthrcdn.etouch.cn/weather_mini?city=" + city)
self.write(response.body)
- 后端異步
# 異步操作對(duì)象 模塊
from tornado.httpclient import AsyncHTTPClient
# 定義異步操作天氣預(yù)報(bào)的視圖處理類
class WeatherHandler(RequestHandler):
# 通過注解裝飾器,告訴tornado這個(gè)get處理方法是異步的~不需要自動(dòng)返回?cái)?shù)據(jù)
@asynchronous
def get(self):
# 獲取參數(shù)數(shù)據(jù)
city = self.get_argument("city")
# 創(chuàng)建一個(gè)異步操作對(duì)象
client = AsyncHTTPClient()
# 異步對(duì)象抓取數(shù)據(jù)
client.fetch("http://wthrcdn.etouch.cn/weather_mini?city=" + city,
callback=self.deal_response)
# 這個(gè)函數(shù)就是異步對(duì)象的回調(diào)函數(shù),當(dāng)異步數(shù)據(jù)獲取完成時(shí)調(diào)用執(zhí)行的函數(shù)
def deal_response(self, response):
content = response.body
# 將數(shù)據(jù)返回給前端頁面
self.write(content)
# 通過finish()函數(shù)告訴tornado異步操作結(jié)束,手工控制返回?cái)?shù)據(jù)
self.finish()
-
附加
- 后端同步與異步的區(qū)別:通過siege壓力測試工具壓力測試,可以看出同步與異步的差距。
- 當(dāng)并發(fā)量與訪問時(shí)間相同時(shí),異步的處理效率遠(yuǎn)高于同步的方式。
長連接(聊天室,網(wǎng)頁客服)
<script>
// 創(chuàng)建一個(gè)js中的 websocket 對(duì)象,保持和服務(wù)器之間的通信
// var _websocket = new WebSocket("websocket連接字符串,使用websocket協(xié)議連接")
var _websocket = new WebSocket("ws://192.168.11.102:8000/chat");
// 隨時(shí)等待接收服務(wù)器的消息:保持一個(gè)長連接,一旦服務(wù)器有消息的話,需要實(shí)時(shí)接收。
_websocket.onmessage = function(e) {
// 接受服務(wù)器發(fā)送的數(shù)據(jù) e 一般默認(rèn)為 e
var _content = e.data;
};
$("#send").click(function() {
// 當(dāng)點(diǎn)擊按鈕的時(shí)候,需要給服務(wù)器發(fā)送數(shù)據(jù)
var $msg = $("#msg").val();
_websocket.send($msg)
})
// 處理讓消息窗口的滾動(dòng)條顯示在最底下的位置
$("#history").scrollTop($("#history")[0].scrollHeight)
</script>
# 導(dǎo)入后端服務(wù)器長連接模塊
from tornado.websocket import WebSocketHandler
# 定義聊天消息長連接處理類
# 和客戶端保持長連接的視圖處理類需要重寫父類的方法完成和客戶端的通信
class ChatHandler(WebSocketHandler):
# 定義一個(gè)保存所有用戶的集合 set()
online_users = set()
# 1.重寫open()函數(shù),保存接入的用戶數(shù)據(jù)
def open(self):
# 新的客戶端連接的時(shí)候,open()函數(shù)自動(dòng)執(zhí)行,
# 將接入的數(shù)據(jù)保存到集合中 add(self)
self.online_users.add(self)
# 向所有人發(fā)送消息,用戶誰連接上了
for user in self.online_users:
# 發(fā)送數(shù)據(jù) write_message() 獲取用戶IP self.request.remote_ip
user.write_message("[%s上線了]" % self.request.remote_ip)
# 2.重寫on_message()函數(shù),獲取客戶端發(fā)送的消息并轉(zhuǎn)發(fā)給所有用戶
def on_message(self, message):
# 函數(shù)on_message會(huì)自動(dòng)接收客戶端發(fā)送的數(shù)據(jù),數(shù)據(jù)包含在message變量中
# 向所有人發(fā)送消息,用戶誰說了什么
# 重寫on_close()函數(shù),當(dāng)斷開某個(gè)連接時(shí),移除在服務(wù)器記錄的數(shù)據(jù)
def on_close(self):
# 當(dāng)一個(gè)客戶端連接斷開時(shí)自動(dòng)執(zhí)行的函數(shù)on_close()
# 移除用戶數(shù)據(jù) remove(self)
self.online_users.remove(self)
# 向所有人發(fā)送消息,用戶誰離開了
# 允許跨域訪問,不然無法訪問
def check_origin(self, origin):
return True