第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
<a href="http://idcbgp.cn/wiki/djangolesson">1. Django 框架簡(jiǎn)介</a>

既然這么課程是要學(xué)習(xí) Django 框架,那么肯定要對(duì)這個(gè)框架做一個(gè)系統(tǒng)的介紹,在本節(jié)課程中會(huì)以下面的幾個(gè)角度去帶大家認(rèn)識(shí) Django 框架:Django 的創(chuàng)造背景:這個(gè)框架是什么時(shí)候誕生的,作者是誰,而作者又是出于什么目的來開發(fā)的 Django 框架?Django 的架構(gòu)模式:主流的架構(gòu)模式有哪些,這些架構(gòu)模式有什么區(qū)別?Django 選擇的是那種架構(gòu)模式,有什么好處?Django 的主要版本:從 Django 誕生一來經(jīng)歷了多少次的重大更新,每一次更新會(huì)給 Django 框架帶來什么樣的改變?Django 與其他框架的對(duì)比:市面上有眾多的 Web 框架,Django 與其他 Web 框架相比優(yōu)勢(shì)在哪里,為什么能脫穎而出呢?

4.1 布局文件

首先編寫布局文件,我們需要 4 個(gè) TextView,分別用來顯示觸摸起點(diǎn)的 X 軸、Y 軸坐標(biāo),以及滑動(dòng)時(shí)的 X 軸、Y 軸偏移量,最后創(chuàng)建一個(gè) View 用作觸摸事件的接收源。內(nèi)容非常簡(jiǎn)單,代碼如下:<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="20dp" android:transitionGroup="true" tools:context=".MainActivity"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="Android 事件處理" android:textSize="35dp" /> <TextView android:id="@+id/down_x" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/title" android:layout_alignStart="@+id/title" android:layout_marginTop="30dp" android:hint="點(diǎn)擊的X軸坐標(biāo)" android:textColor="@color/colorPrimary" /> <TextView android:id="@+id/down_y" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/down_x" android:layout_alignStart="@+id/down_x" android:layout_marginTop="10dp" android:hint="點(diǎn)擊的Y軸坐標(biāo)" android:textColor="@color/colorPrimary" /> <TextView android:id="@+id/move_x" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/down_y" android:layout_alignStart="@+id/down_y" android:layout_marginTop="60dp" android:hint="移動(dòng)位置的X軸坐標(biāo)" android:textColor="@color/colorPrimaryDark" /> <TextView android:id="@+id/move_y" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/move_x" android:layout_alignStart="@+id/move_x" android:hint="移動(dòng)位置的Y軸坐標(biāo)" android:textColor="@color/colorPrimaryDark" /> <TextView android:id="@+id/touch" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="點(diǎn)我開始滑動(dòng)" android:textColor="#ff5480ff" android:textSize="35sp" /></RelativeLayout>

1.2 帶參數(shù)的 get 請(qǐng)求

我們?cè)賮砜纯?get 請(qǐng)求帶參數(shù)的方式,示例代碼如下:>>> payload = {'key1': 'value1', 'key2': 'value2'}>>> r = requests.get('https://httpbin.org/get', params=payload)>>> r.url'https://httpbin.org/get?key1=value1&key2=value2'可以看到 get 請(qǐng)求所攜帶的參數(shù)就是在 url 后使用 ? 將參數(shù)的 key 和 value 組合起來,形成完整的請(qǐng)求 url。下面是 get 請(qǐng)求帶參數(shù)的另一個(gè)例子,這里參數(shù) key2 的值是一個(gè)列表。>>> payload = {'key1': 'value1', 'key2': ['value2', 'value3']}>>> r = requests.get('https://httpbin.org/get', params=payload)>>> r.url'https://httpbin.org/get?key1=value1&key2=value2&key2=value3'來看看 request 庫請(qǐng)求的結(jié)果:>>> type(r)<class 'requests.models.Response'>>>> dir(r)['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_content', '_content_consumed', '_next', 'apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'next', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']這里用的最多的有5個(gè),分別為 enconding、status_code、text、content 和 url,它們的含義如下:encoding:當(dāng)讀取 r.text 時(shí)會(huì)使用該值進(jìn)行編解碼;status_code:請(qǐng)求返回狀態(tài)碼,200 表示正常;text:返回請(qǐng)求的內(nèi)容,使用 unicode 編碼;content:返回請(qǐng)求的內(nèi)容,字節(jié)編碼;url:最終請(qǐng)求的 url。此外,對(duì)于所有的請(qǐng)求,可以帶上 headers 參數(shù),這樣可以模擬成瀏覽器的行為。通常不帶 headers 很容易就被識(shí)別為爬蟲程序,通過百度網(wǎng)站的 get 請(qǐng)求就可以看到。帶上正常的 header 和 不帶或者帶上錯(cuò)誤的 header 得到的結(jié)果不一樣:>>> url = 'https://www.baidu.com'>>> headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'}>>> r = requests.get(url, headers=headers)>>> r.text[:1000]'<!DOCTYPE html><!--STATUS OK-->\n\n\n <html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta content="always" name="referrer"><meta name="theme-color" content="#2932e1"><meta name="description" content="全球最大的中文搜索引擎、致力于讓網(wǎng)民更便捷地獲取信息,找到所求。百度超過千億的中文網(wǎng)頁數(shù)據(jù)庫,可以瞬間找到相關(guān)的搜索結(jié)果。"><link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /><link rel="search" type="application/opensearchdescription+xml" href="/content-search.xml" title="百度搜索" /><link rel="icon" sizes="any" mask ><link rel="dns-prefetch" /><link rel="dns-prefetch" /><link rel="dns-prefetch" /><link rel="dns-prefetch" /><link rel="dns-prefetch" /><link rel="dns-prefetch" /><title>百度一下,你就知道</title><style index="newi" type="text/css">>>> headers = {'user-agent': 'my-app/0.0.1'}>>> r = requests.get(url, headers=headers)>>> r.text'<html>\r\n<head>\r\n\t<script>\r\n\t\tlocation.replace(location.href.replace("https://","http://"));\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>\r\n</body>\r\n</html>'前面我們也介紹過 requests 庫的 post 請(qǐng)求,其參數(shù)通過 data 進(jìn)行傳遞,下面繼續(xù)看幾個(gè)示例:>>> payload_tuples = [('key1', 'value1'), ('key1', 'value2')]>>> r1 = requests.post('https://httpbin.org/post', data=payload_tuples)>>> payload_dict = {'key1': ['value1', 'value2']}>>> r2 = requests.post('https://httpbin.org/post', data=payload_dict)>>> print(r1.text){ "args": {}, "data": "", "files": {}, "form": { "key1": [ "value1", "value2" ] }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "23", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.24.0", "X-Amzn-Trace-Id": "Root=1-5ef49697-c3f6e2a809e33d4895ee6938" }, "json": null, "origin": "47.115.61.209", "url": "https://httpbin.org/post"}

3.2 XMLHttpRequest 的方法

3.2.1 標(biāo)準(zhǔn)方法方法名備注abort中止請(qǐng)求getAllResponseHeaders返回所有用 CRLF 分隔的響應(yīng)頭的字符串的形式。沒有收到響應(yīng)則返回 null。getResponseHeader返回指定響應(yīng)頭的字符串。未收到響應(yīng),或者響應(yīng)不存在該報(bào)頭,返回 null。open初始化一個(gè)請(qǐng)求。overrideMimeType重寫 MIME 類型。send發(fā)送請(qǐng)求。setRequestHeader設(shè)置 HTTP 請(qǐng)求頭。3.2.2 非標(biāo)準(zhǔn)方法方法名備注openRequest初始化一個(gè)請(qǐng)求。

2.5 隱藏輸入框

JavaScript 沒有全局變量的功能,有時(shí)需要定義全局變量,可以用 cookie 來實(shí)現(xiàn),但是瀏覽器可以關(guān)閉 cookie ,而且 cookie 在發(fā)送 HTTP 時(shí)會(huì)被帶上,浪費(fèi)數(shù)據(jù)傳輸,這時(shí)使用隱藏域的方式實(shí)現(xiàn)比較簡(jiǎn)單。例如:1020上述代碼通過定義隱藏域,當(dāng)點(diǎn)擊提交按鈕時(shí)將該頁面的上個(gè)頁面的 URL 傳輸給表單的目標(biāo) URL,做到傳輸值的作用。

1. xml 的優(yōu)勢(shì)

XML 是一種標(biāo)記語言,我們目前接觸最多的用法就是用來寫布局文件。但其實(shí),xml 被廣泛用于網(wǎng)絡(luò)數(shù)據(jù)傳輸中,它是一種非常流行的網(wǎng)絡(luò)數(shù)據(jù)格式。比如我們可以使用上一節(jié)學(xué)到的 HttpURLConnect 去向 Service 發(fā)起一個(gè) Http 請(qǐng)求,那么 Service 就可以將數(shù)據(jù)用 xml 的形式下發(fā),無論是從保存還是從解析的角度,xml 都提供了極大的便利。

3.2 rewrite 指令

Syntax: rewrite regex replacement [flag];Default: --Context: server, location, if1、將 regex 指定的 url 替換成 replacement 這個(gè)新的 url,可以使用正則表達(dá)式及變量提取。2、當(dāng) replacement 以 http:// 或者 https:// 或者 $schema 開頭,則直接返回 302 重定向3、替換后的 url 根據(jù) flag 指定的方式進(jìn)行處理last: 用 replacement 這個(gè) url 進(jìn)行新的 location 匹配break: break 指令停止當(dāng)前腳本指令的執(zhí)行redirect:返回 302 重定向permanent: 返回 301 重定向

3.1 編寫布局文件

布局文件很簡(jiǎn)單,只需要在根布局的位置添加一個(gè) AutoCompleteTextView 標(biāo)簽,然后加上適當(dāng)?shù)膶傩约纯桑?lt;?xml version="1.0" encoding="utf-8"?><AutoCompleteTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/autoCompleteTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:completionHint="請(qǐng)輸入您要查找的內(nèi)容" android:completionThreshold="1" android:dropDownHorizontalOffset="10dp" />通過android:completionHint設(shè)置當(dāng)前 AutoCompleteTextView 的功能提示,android:completionThreshold="1"表示當(dāng)用戶輸入一個(gè)字符時(shí)就開始做補(bǔ)全提示,最后通過android:dropDownHorizontalOffset設(shè)置一個(gè)水平間距。

1.4 如何編寫自己的模塊

想要編寫 Nginx 模塊,首先需要對(duì) Nginx 模塊中的源碼以及相關(guān)的數(shù)據(jù)結(jié)構(gòu)有所了解,還要知曉 Nginx HTTP 模塊的調(diào)用流程。假設(shè)我要實(shí)現(xiàn)前面第三方模塊Echo的最簡(jiǎn)單形式,即只輸出相應(yīng)的字符串即可。假定模塊支持的指令名稱還是 echo, 這個(gè) echo 指令需要跟一個(gè)參數(shù),即輸出的字符串。我們需要做如下幾步:確定模塊名稱,以及模塊中的指令以及參數(shù),還有運(yùn)行的環(huán)境。這里涉及的結(jié)構(gòu)是 ngx_command_t,它定義了模塊里的所有指令格式。下面的代碼表示該模塊中只有一個(gè) echo 指令,它出現(xiàn)的上下文環(huán)境為 location,且有一個(gè)參數(shù)(NGX_CONF_TAKE1)。當(dāng)某個(gè)配置塊中出現(xiàn)echo指令時(shí),Nginx 將調(diào)用ngx_http_echo方法。然后在該方法中,會(huì)設(shè)置處理請(qǐng)求的 handler,這個(gè) handler 就是處理請(qǐng)求的方法。 static ngx_command_t ngx_http_echo_commands[] = { { ngx_string("echo"), /* 指令名稱,利用ngx_string宏定義 */ NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, /* 用在 location 指令塊內(nèi),且有1個(gè)參數(shù) */ ngx_http_echo, /* 處理回調(diào)函數(shù) */ NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, ed), /* 指定參數(shù)讀取位置 */ NULL }, ngx_null_command };完成請(qǐng)求處理的 handler 函數(shù),最重要的部分就在這里; static char * ngx_http_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_core_loc_conf_t *clcf; /* 找到指令所屬的配置塊,這里我們限定echo指令的上下文環(huán)境只有l(wèi)ocation */ clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); /* 指定處理的handler */ clcf->handler = ngx_http_echo_handler; ... return NGX_CONF_OK; } static ngx_int_t ngx_http_echo_handler(ngx_http_request_t *r) { ... /* 向用戶發(fā)送相應(yīng)包 */ return ngx_http_output_filter(r, &out); }一些收尾工作,比如配置模塊介入 http 請(qǐng)求的哪些階段等。 /* Http context of the module */ static ngx_http_module_t ngx_http_echo_module_ctx = { NULL, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ ngx_http_echo_create_loc_conf, /* create location configration */ ngx_http_echo_merge_loc_conf /* merge location configration */ }; /* Module */ ngx_module_t ngx_http_echo_module = { NGX_MODULE_V1, &ngx_http_echo_module_ctx, /* module context */ ngx_http_echo_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING };完成以上幾步,一個(gè)簡(jiǎn)易的自定義模塊就算大功告成了。接下來我們動(dòng)手完成第一個(gè)自定義的模塊,將其編譯進(jìn)Nginx 二進(jìn)制文件中并進(jìn)行測(cè)試。

2. 使用注解解析數(shù)據(jù)

原生 Servlet 開發(fā)過程中,開發(fā)者定義的 Servlet 具有請(qǐng)求響應(yīng)功能。因?yàn)?J2EE 中的 Servlet 僅僅只是提供了編寫企業(yè)級(jí)應(yīng)用程序的規(guī)范,并沒有提供更多實(shí)質(zhì)性的功能。在執(zhí)行響應(yīng)邏輯之前或之后需要開發(fā)者編寫一些通用的功能代碼。如解析請(qǐng)求包中的數(shù)據(jù)、構(gòu)建響應(yīng)路徑……Spring MVC 提供了很多實(shí)用的注解,用來解析請(qǐng)求包、自動(dòng)綁定請(qǐng)求包中不同位置的數(shù)據(jù)。在使用注解解析請(qǐng)求包中的數(shù)據(jù)前,先了解一下請(qǐng)求包的格式。WEB 應(yīng)用程序中, 所謂的請(qǐng)求包是指遵循 HTTP 協(xié)議的一種數(shù)據(jù)格式包。在某些文章中,稱請(qǐng)求包為報(bào)文。一個(gè)完整的請(qǐng)求包應(yīng)該由 3 個(gè)部分組成:請(qǐng)求行: 包括請(qǐng)求方法、請(qǐng)求的資源地址(URL) 、HTTP 協(xié)議版本號(hào);消息頭: 消息頭是傳送給服務(wù)器的信息,以 key:value 的格式描述;實(shí)體部分或報(bào)文體: 以 key=value 的數(shù)據(jù)格式保存客戶端傳遞給應(yīng)用程序的數(shù)據(jù)。

3. 小結(jié)

Restful 風(fēng)格一般指的是 API 的設(shè)計(jì)規(guī)范,REST 是由 Roy Thomas Fielding 教授提出來的,該作者同時(shí)是 HTTP 協(xié)議的重要參與者。REST 的論文中對(duì) Web 系統(tǒng)機(jī)構(gòu)提出了一些指導(dǎo)的理論,這些思想都非常不錯(cuò),但是我們今天的軟件架構(gòu)正變得越來越復(fù)雜,熔斷 / 限流 / 鏈路跟蹤 等等,還有很多要考慮的。

5. 小結(jié)

本節(jié)內(nèi)容主要是介紹 Nginx 中的緩存功能。一個(gè)是針對(duì)瀏覽器的緩存控制,另一個(gè)是針對(duì)上游服務(wù)器對(duì) http 請(qǐng)求進(jìn)行緩存,以減輕上游服務(wù)器的負(fù)載,這在高流量場(chǎng)景下是非常必要的。接下來,我們完成兩個(gè)實(shí)驗(yàn),測(cè)試前面講到的緩存指令,并實(shí)際觀察緩存效果。

4.2 布局文件

布局文件就按照片一般播放器的擺放方式就可以,上面通常是頁面的主題和描述,下方就是進(jìn)度條、歌曲名稱時(shí)長(zhǎng)等等。<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="30dp" tools:context=".MainActivity"> <TextView android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="音樂播放器" android:textSize="35dp" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textview" android:layout_centerHorizontal="true" android:text="慕課Android教程" android:textColor="#ff7aff24" android:textSize="35dp" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_alignParentBottom="true" android:text="前進(jìn)" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_toRightOf="@id/button" android:text="暫停" /> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/button2" android:layout_toEndOf="@+id/button2" android:text="播放" /> <Button android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/button3" android:layout_toEndOf="@+id/button3" android:layout_toRightOf="@+id/button3" android:text="后退" /> <SeekBar android:id="@+id/seekBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/button" android:layout_alignStart="@+id/textview" android:layout_alignEnd="@+id/textview" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/seekBar" android:text="超哥音樂選集" android:textAppearance="?android:attr/textAppearanceSmall" /> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/seekBar" android:layout_alignEnd="@+id/button4" android:text="02:23" android:textAppearance="?android:attr/textAppearanceSmall" /> <TextView android:id="@+id/textView4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/textView2" android:layout_alignBottom="@+id/textView2" android:layout_centerHorizontal="true" android:text="超哥吉他" android:textAppearance="?android:attr/textAppearanceMedium" /></RelativeLayout>當(dāng)然也可以按照你自己的設(shè)計(jì)去擺放播放器的布局樣式,編譯之后如下:

4. 學(xué)習(xí)基礎(chǔ)

為了學(xué)好該框架以及熟練使用 Scrapy 開發(fā)爬蟲項(xiàng)目,我們需要具備以下基礎(chǔ):簡(jiǎn)單的網(wǎng)頁基礎(chǔ),HTML/CSS等;Python 基礎(chǔ);簡(jiǎn)單的計(jì)算機(jī)網(wǎng)絡(luò)基礎(chǔ),比如了解 HTTP 協(xié)議、TCP/IP 協(xié)議等;本課程會(huì)假定你已經(jīng)了解或者熟悉上述基礎(chǔ)知識(shí),并在后面不會(huì)對(duì)一些簡(jiǎn)單的問題作出解釋,重點(diǎn)放到剖析這個(gè)框架并熟練掌握。

1. WebSocket的反向代理

WebSocket 是目前比較成熟的技術(shù)了, WebSocket 協(xié)議為創(chuàng)建客戶端和服務(wù)器端需要實(shí)時(shí)雙向通訊的 webapp 提供了一個(gè)選擇。服務(wù)器可以向?yàn)g覽器推送相關(guān)消息,這樣在前端實(shí)現(xiàn)的某個(gè)頁面中我們可以及時(shí)看到服務(wù)器的狀態(tài)變化而不用使用定時(shí)刷新去獲取后臺(tái)信息。目前大部分瀏覽器都支持 WebSocket 協(xié)議,比如 Firefox,IE,Chrome,Safari,Opera,并且越來越多的服務(wù)器框架現(xiàn)在也同樣支持 WebSocket。此外,在js、java 和 python 中都提供了 Websocket 開發(fā)庫,這也使得 websocket 協(xié)議的廣泛應(yīng)用于 web 服務(wù)的開發(fā)中。當(dāng)然作為瀏覽器和后臺(tái)服務(wù)的中間代理的 Nginx 也必定支持 Websocket,這樣能更好的完成代理角色。在 Nginx 中通過 ngx_http_proxy_module 模塊實(shí)現(xiàn) Websocket 反向代理功能,具體實(shí)現(xiàn)配置如下:proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";上述配置表示將轉(zhuǎn)發(fā)的協(xié)議提升至1.1, 同時(shí)在轉(zhuǎn)發(fā)的 http 請(qǐng)求的頭部中加上如下配置:Upgrade: websocketConnection: upgrade這兩個(gè)字段表示請(qǐng)求服務(wù)器升級(jí)協(xié)議為 WebSocket。上游服務(wù)器處理完請(qǐng)求后,響應(yīng)如下報(bào)文:HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: upgrade這個(gè)響應(yīng)是告訴客戶端已成功切換協(xié)議,升級(jí)為 Websocket 協(xié)議。握手成功之后,服務(wù)器端和客戶端便角色對(duì)等,就像普通的 Socket 一樣,能夠雙向通信。 不再進(jìn)行 HTTP 的交互,而是開始 WebSocket 的數(shù)據(jù)幀協(xié)議實(shí)現(xiàn)數(shù)據(jù)交換。默認(rèn)情況下,連接將會(huì)在無數(shù)據(jù)傳輸60秒后關(guān)閉,proxy_read_timeout 參數(shù)可以延長(zhǎng)這個(gè)時(shí)間。源站通過定期發(fā)送 ping 幀以保持連接并確認(rèn)連接是否還在使用。通過以上簡(jiǎn)簡(jiǎn)單單的三行配置,我們就能在 Nginx 中輕松實(shí)現(xiàn) Websocket 的反向代理,這也說明了 Nginx 的簡(jiǎn)單易用特點(diǎn)。

2.1 會(huì)話模擬

會(huì)話標(biāo)識(shí)因?yàn)?Http 是無狀態(tài)協(xié)議,服務(wù)端為了區(qū)別不同請(qǐng)求分別來自哪個(gè)用戶,一般借助的是 Session 和 Cookies。Session 的數(shù)據(jù)存儲(chǔ)在服務(wù)端,而 Cookies 存儲(chǔ)在客戶端。Cookies 以鍵值對(duì)的方式存儲(chǔ)在瀏覽器中,設(shè)置 Cookies 的時(shí)候如果指定了過期時(shí)間,對(duì)應(yīng)的值就會(huì)寫到本地磁盤中,時(shí)間到了自動(dòng)剔除。如果沒有設(shè)置過期時(shí)間,它的生命周期就是瀏覽器關(guān)閉了就消失了。Session 雖然存儲(chǔ)在服務(wù)端,但是它的 SessionId 也存了一份在客戶端的 Cookies 中的,并且它的生命周期隨著瀏覽器的關(guān)閉而消失。Http 有個(gè)機(jī)制:請(qǐng)求的時(shí)候會(huì)把瀏覽器中當(dāng)前域名對(duì)應(yīng)作用域下的所有 Cookies 都發(fā)送到出去,所以同一個(gè)作用域下的 Cookies 對(duì)象不要太多,會(huì)影響每次請(qǐng)求的帶寬。服務(wù)端就能從請(qǐng)求中拿到 SessionId ,從而查出具體的 Session 對(duì)象。模擬會(huì)話在了解了會(huì)話標(biāo)識(shí)的過程后,我們發(fā)現(xiàn)只要拿到了用戶的 SessionId 就能很容易的假冒用戶的身份去與服務(wù)端交互。場(chǎng)景場(chǎng)景1:開發(fā)中我們會(huì)用 Http 請(qǐng)求工具,如 PostMan 去調(diào)用我的接口,驗(yàn)證接口的出入?yún)?。如果系統(tǒng)需要登錄才能訪問,我們比較簡(jiǎn)便的做法是用瀏覽器先登錄,然后將瀏覽器的 SessionId 設(shè)置到 PostMan 中,此時(shí)接口就能訪問了。場(chǎng)景2:瀏覽器的 SessionId 自己能容易獲得,但是別人要拿到還是相對(duì)困難的,于是有一種名為 CSRF 跨站點(diǎn)請(qǐng)求偽造(Cross—Site Request Forgery) 的攻擊出現(xiàn)。用戶登錄 A 網(wǎng)站,然后又打開了另一個(gè)標(biāo)簽頁訪問 B 網(wǎng)站,如果此時(shí) B 中隱藏了 A 網(wǎng)站某個(gè)請(qǐng)求的鏈接,到用戶點(diǎn)擊了,就會(huì)以當(dāng)前用戶的身份去觸發(fā)對(duì)應(yīng)的事件。

3.2 返回 json 類型

視圖函數(shù)直接返回 json 數(shù)據(jù)是在微服務(wù)架構(gòu)中常見的套路。這里 Django 程序只提供后端數(shù)據(jù)并不提供靜態(tài)資源。針對(duì)返回 json 數(shù)據(jù),在 Django 中專門定義了一個(gè) JsonResponse 類用來生成 json 數(shù)據(jù)。它實(shí)際上是繼承自 HttpResponse 類:# django/http/response.py# 忽略其他內(nèi)容class JsonResponse(HttpResponse): """ 忽略注釋部分內(nèi)容 """ def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs): if safe and not isinstance(data, dict): raise TypeError( 'In order to allow non-dict objects to be serialized set the ' 'safe parameter to False.' ) if json_dumps_params is None: json_dumps_params = {} kwargs.setdefault('content_type', 'application/json') data = json.dumps(data, cls=encoder, **json_dumps_params) super().__init__(content=data, **kwargs)JsonResponse 類的使用和 HttpResponse 類一樣簡(jiǎn)單,我們只需要把字典數(shù)據(jù)傳給 JsonResponse 類進(jìn)行實(shí)例化即可。但是字典數(shù)據(jù)中存在中文時(shí)候,會(huì)出現(xiàn)亂碼,我們只需要在實(shí)例化 JsonResponse 時(shí),多傳入一個(gè)參數(shù)即可:# 在頁面上會(huì)出現(xiàn)亂碼def hello_world(request, *args, **kwargs): data = {'code': 0, "content": "返回中文字符串", "err_msg": ""} return JsonResponse(data)# 經(jīng)過處理后的JsonResponsedef hello_world(request, *args, **kwargs): data = {'code': 0, "content": "返回中文字符串", "err_msg": ""} return JsonResponse(data, json_dumps_params={'ensure_ascii': False})請(qǐng)求結(jié)果:# 第一個(gè)不處理的 JsonResponse 返回[root@server ~]# curl "http://127.0.0.1:8881/hello/"{"code": 0, "content": "\u8fd4\u56de\u4e2d\u6587\u5b57\u7b26\u4e32", "err_msg": ""}# 使用第二個(gè)數(shù)據(jù)處理后的HttpResponse返回[root@server ~]# curl "http://127.0.0.1:8881/hello/"{"code": 0, "content": "返回中文字符串", "err_msg": ""}另外一種比較好的方式是,仿照 JsonResponse 類,定義一個(gè)支持返回包含中文 json 數(shù)據(jù)的 Response 類:# 忽略導(dǎo)入模塊# 將原來支持的json_dumps_params參數(shù)固定寫死成{'ensure_ascii':False}class JsonResponseCn(HttpResponse): """ 忽略注釋部分內(nèi)容 """ def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs): if safe and not isinstance(data, dict): raise TypeError( 'In order to allow non-dict objects to be serialized set the ' 'safe parameter to False.' ) kwargs.setdefault('content_type', 'application/json') data = json.dumps(data, cls=encoder, **{'ensure_ascii':False}) super().__init__(content=data, **kwargs)這樣處理后,我們?cè)诤驮瓉硪粯邮褂?JsonResponseCn 類來返回 json 數(shù)據(jù)即可,不用考慮返回的字典數(shù)據(jù)中是否包含中文字符:def hello_world(request, *args, **kwargs): data = {'code': 0, "content": "返回中文字符串", "err_msg": ""} return JsonResponseCn(data)

4. 小結(jié)

本篇文章中,我們介紹了 Http 請(qǐng)求的 11 個(gè)階段中的中間階段,分別為 preaccess 和 access 階段。在這兩個(gè)階段中,主要生效的指令有l(wèi)imit_conn、limit_req、allow、deny 等,這些指令幾乎都是用來做訪問控制的,用來限制 Nginx 的并發(fā)連接、訪問限速、設(shè)置訪問白名單以及認(rèn)證訪問等。這些安全限制在線上環(huán)境是十分必要的,必須要限制惡意的請(qǐng)求以及添加白名單操作。

1.7 配置 Grafana Dashboard 頁

docker-compose --compatibility up -d啟動(dòng)之后,使用瀏覽器打開 http://127.0.0.1:3000, 即可訪問 grafana Web 頁面。使用admin 和 123456 密碼(GF_SECURITY_ADMIN_PASSWORD指定)登錄。登錄成功后,配置數(shù)據(jù)源。選擇 Prometheus 數(shù)據(jù)源:填寫 Prometheus 地址:保存配置:選擇導(dǎo)入 Dashboard:打開Grafana的官方Dashboard倉庫,找一個(gè)合適的樣式,下載下來。這里我們選擇了這個(gè):回到 Grafana 管理頁面,將下載的 json 文件導(dǎo)入:選擇 Prometheus 數(shù)據(jù)源:import 導(dǎo)入即可看到容器監(jiān)控頁面。

<a href="http://idcbgp.cn/wiki/djangolesson/webfarmwork.html">2. 什么是 Web 框架?</a>

在這個(gè)小節(jié)中會(huì)給大家介紹一下網(wǎng)站開發(fā)的發(fā)展歷程,以及 Web 框架的概念是如何出現(xiàn)的,使用了 Web 框架之后對(duì)網(wǎng)站開發(fā)有什么影響和好處。

4. 常見問題

一般我們比較常見的問題就是安裝 sass 或者 node-sass 特別慢導(dǎo)致安裝失敗,由于國(guó)內(nèi)網(wǎng)絡(luò)的限制我們需要切換 gem 和 npm 源。切換 gem 源使用如下命令:gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/// 查看 gem 源gem sources -l使用 npm 安裝 node-sass 過慢的話我們可以使用 cnpm 來替換 npm ,或者使用如下命令切換 npm 源:npm install -g mirror-config-china --registry=http://registry.npm.taobao.org

2. 為 View 設(shè)置 Drawable

在 xml 中使用是很最常見的用法,而且我們一直在用,回顧一下我們?cè)O(shè)置的圖片資源,比如一個(gè) TextView 的背景樣式,通常會(huì)這么寫:<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/text" android:text="@string/hello_world" />其中 background 屬性的值就是一個(gè) Drawable 對(duì)象,同樣我們可以在 Java 代碼中給 View 設(shè)置一個(gè) Drawable 參數(shù):ImageView imageView = (ImageView) findViewById(R.id.imageview);imageView.setImageResource(R.drawable.image);

3.1 布局文件

布局比較簡(jiǎn)單,主要由三個(gè)部分:?jiǎn)?dòng)任務(wù)進(jìn)度文本進(jìn)度條<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_alignParentTop="true" /> <Button android:id="@+id/start_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/progressBar" android:layout_alignParentStart="true" android:layout_marginStart="24dp" android:layout_marginTop="62dp" android:text="開始任務(wù)" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/start_progress" android:layout_alignBottom="@+id/start_progress" android:layout_alignParentEnd="true" android:layout_marginEnd="85dp" android:gravity="center" android:text="當(dāng)前進(jìn)度:0%" android:textSize="16sp" /></RelativeLayout>

3. 小結(jié)

現(xiàn)代網(wǎng)頁的構(gòu)成幾乎離不開 AJAX 技術(shù),如果 JavaScript 無法發(fā)起 HTTP 請(qǐng)求,幾乎所有的現(xiàn)代網(wǎng)站都會(huì)癱瘓,變得難用。除了 XHR 對(duì)象之外,還有 fetch API 這個(gè)后起之秀,也可以承擔(dān) XHR 對(duì)象的工作。但 fetch 還有部分缺陷,如無法監(jiān)控進(jìn)度,對(duì)狀態(tài)碼的處理邏輯不夠符合業(yè)務(wù),所以用戶面較廣的產(chǎn)品使用一般不會(huì)選擇 fetch。

7. 小結(jié)

本節(jié)課介紹了如何使用 Request 對(duì)象獲取請(qǐng)求信息,首先介紹了如何調(diào)用 Request 請(qǐng)求對(duì)象,然后介紹了如何獲取當(dāng)前請(qǐng)求域名、當(dāng)前訪問端口、當(dāng)前請(qǐng)求的 HTTP 頭信息,最后列舉了 Request 請(qǐng)求對(duì)象中方法的作用說明,若要調(diào)用其他方法可以參考本節(jié)課介紹的幾種方式。Tips: 代碼倉庫:https://gitee.com/love-for-poetry/tp6

2.1 請(qǐng)求的消息格式

請(qǐng)求頭部信息get http://idcbgp.cn/ HTTP/1.1host:117.121.101.134:443關(guān)鍵字說明get請(qǐng)求的方法https://www.baidu.com請(qǐng)求的資源定位,URLHTTP/1.1告訴后臺(tái)服務(wù)器具體請(qǐng)求的協(xié)議版本號(hào)host遠(yuǎn)端服務(wù)器的地址...頭部字段還有很多,這邊只是列舉了必要的,詳細(xì)的見后面具體章節(jié)請(qǐng)求體內(nèi)容keyword:httpname:mooc請(qǐng)求體對(duì)應(yīng)的是具體的業(yè)務(wù)數(shù)據(jù),表單提交的字段,查詢接口的參數(shù)等。

3.3 使用 Swagger2 進(jìn)行接口測(cè)試

此時(shí)我們啟動(dòng)項(xiàng)目,然后訪問 http://127.0.0.1:8080/swagger-ui.html ,即可打開自動(dòng)生成的可視化測(cè)試頁面,如下圖。Swagger2 自動(dòng)生成可視化測(cè)試界面嗯,感覺這個(gè)頁面簡(jiǎn)單整潔,直接給測(cè)試人員使用都很方便。我們以 update 方法為例演示下如何測(cè)試。先看看該方法的代碼:實(shí)例: /** * 修改商品 */ @PutMapping("/goods/{id}") public void update(@PathVariable("id") long id, @RequestBody GoodsDo goods) { // 修改指定id的商品信息 goods.setId(id); goodsService.editGoods(goods); }測(cè)試時(shí)先選中對(duì)應(yīng)的方法 update , 然后點(diǎn)擊 Try it out 開始測(cè)試。Swagger2 生成的測(cè)試方法在參數(shù)區(qū)域輸入 id 和 goods 的值。Swagger2 可視化測(cè)試參數(shù)輸入點(diǎn)擊 Execute 后,返回 Code 為 200 表示 http 請(qǐng)求成功!Swagger2 可視化測(cè)試結(jié)果輸出由此可見, Swagger2 將接口以可視化的方式呈現(xiàn)出來,開發(fā)人員不必手輸接口地址、參數(shù)名稱,就可以發(fā)起測(cè)試并查看結(jié)果,確實(shí)非常方便。后端人員在開發(fā)完成后,可以自己使用 Swagger2 測(cè)試下接口可行性。而前端人員也可以打開 Swagger2 網(wǎng)頁直接驗(yàn)證接口功能。

1.1 httpbin

httpbin 這個(gè)網(wǎng)站能測(cè)試 HTTP 請(qǐng)求和響應(yīng)的各種信息,比如 cookie、ip、headers 和登錄驗(yàn)證等,且支持 get、post、put、delete 等多種方法,對(duì) Web 開發(fā)和測(cè)試很有幫助。接下來,我們就用 requests 在這個(gè)網(wǎng)站上測(cè)試下其他的 HTTP 請(qǐng)求:>>> import requests>>> r = requests.post('https://httpbin.org/post', data = {'key':'value'})>>> r.text'{\n "args": {}, \n "data": "", \n "files": {}, \n "form": {\n "key": "value"\n }, \n "headers": {\n "Accept": "*/*", \n "Accept-Encoding": "gzip, deflate", \n "Content-Length": "9", \n "Content-Type": "application/x-www-form-urlencoded", \n "Host": "httpbin.org", \n "User-Agent": "python-requests/2.24.0", \n "X-Amzn-Trace-Id": "Root=1-5ef4800b-da26cce71993bd5eb803d7c9"\n }, \n "json": null, \n "origin": "47.115.61.209", \n "url": "https://httpbin.org/post"\n}\n'>>> r.json(){'args': {'key1': 'value1', 'key2': ['value2', 'value3']}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.24.0', 'X-Amzn-Trace-Id': 'Root=1-5ef48767-49d16380b92523febb87f110'}, 'origin': '47.115.61.209', 'url': 'https://httpbin.org/get?key1=value1&key2=value2&key2=value3'}>>> 在上面的示例代碼中,我們使用 requests 庫模擬發(fā)送了一個(gè) post 請(qǐng)求,且?guī)狭艘粋€(gè)參數(shù): key=value??梢钥吹骄W(wǎng)站返回的結(jié)果是 json 形式的數(shù)據(jù),包括了我們發(fā)生的數(shù)據(jù)、請(qǐng)求的頭部、來源地址等。

前言

本章節(jié)將會(huì)從兩個(gè)方面來講解 Ajax 如何處理服務(wù)端響應(yīng),它們分別是:處理的時(shí)機(jī)處理的方法如果你不知道 Ajax 是如何獲取服務(wù)端響應(yīng)內(nèi)容的,或者你對(duì) HTTP 狀態(tài)碼沒有一個(gè)初步的了解,甚至你還不知道一個(gè) Ajax 請(qǐng)求過程中各個(gè)階段的狀態(tài)表示,那么,我相信這個(gè)章節(jié)會(huì)很適合你。接下來讓我們步入正題,一起來看看 Ajax 是如何處理服務(wù)端響應(yīng)的。

2.2 Prometheus 的優(yōu)勢(shì)

Prometheus 的主要優(yōu)勢(shì)有:由指標(biāo)名稱和和鍵/值對(duì)標(biāo)簽標(biāo)識(shí)的時(shí)間序列數(shù)據(jù)組成的多維數(shù)據(jù)模型;強(qiáng)大的查詢語言 PromQL;不依賴分布式存儲(chǔ);單個(gè)服務(wù)節(jié)點(diǎn)具有自治能力;時(shí)間序列數(shù)據(jù)是服務(wù)端通過 HTTP 協(xié)議主動(dòng)拉取獲得的;也可以通過中間網(wǎng)關(guān)來推送時(shí)間序列數(shù)據(jù);可以通過靜態(tài)配置文件或服務(wù)發(fā)現(xiàn)來獲取監(jiān)控目標(biāo);支持多種類型的圖表和儀表盤。

直播
查看課程詳情
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)