對于整體布局而言,主要的頁面都在 ViewPager 當(dāng)中,所以我們需要為不同結(jié)構(gòu)的 Page 編寫不同的頁面,由于本例中每個 Page 的頁面結(jié)構(gòu)都一樣,所以可以直接復(fù)用一套,直接在里面放置一個 ImageView 用于展示類別圖片。<?xml version="1.0" encoding="utf-8"?><ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" />
前端訪問網(wǎng)址形式:GET http://127.0.0.1/api/students/?page=4可以在子類中定義的屬性:page_size :每頁數(shù)目;page_query_param :前端發(fā)送的頁數(shù)關(guān)鍵字名,默認(rèn)為"page";page_size_query_param :前端發(fā)送的每頁數(shù)目關(guān)鍵字名,默認(rèn)為None;max_page_size :前端最多能設(shè)置的每頁數(shù)量。from rest_framework.pagination import PageNumberPaginationclass StandardPageNumberPagination(PageNumberPagination): page_size_query_param = 'page_size' # 每頁數(shù)據(jù)條數(shù) max_page_size = 10class StudentViewSet(ModelViewSet): queryset = StudentsModel.objects.all() serializer_class = StudentsSerializer pagination_class = StandardPageNumberPagination
由于 PopupWindow 需要設(shè)置一個 View 樣式,所以除了 Activity 之外還要給 PopupWindow 增加一個布局。3.1.1 Activity 的布局布局文件非常簡單,甚至可以沿用上一節(jié) AlertDialog 的布局,只需要在屏幕中央放置一個 Button 用于觸發(fā) PopupWindow 即可,如下:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:padding="10dp" > <Button android:id="@+id/show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="彈出一個PopupWindow" /></LinearLayout>3.1.2 PopupWindow 的布局PopupWindow 的布局大家可以根據(jù)自己的需求任意定義,沒有什么特別的要求,也體現(xiàn)了 PopupWindow 的靈活性,這里就放置一個 TextView 和一個 Button 用于關(guān)閉,如下:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:background="#000" android:padding="10dp"> <TextView android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="底部彈出的PopupWindow" android:textColor="@android:color/holo_red_dark"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="關(guān)閉" android:id="@+id/close"/></LinearLayout>
當(dāng)一個超鏈接在文章中反復(fù)出現(xiàn)時,可以使用全局聲明的形式,減少文章編寫的工作量。實例 3:#### 聲明超鏈接的細(xì)節(jié)[天壇][tiantan]公園,是明清兩代皇帝每年祭天和祈禱五谷豐收的地方。[天壇][tiantan]以嚴(yán)謹(jǐn)?shù)慕ㄖ季?、奇特的建筑?gòu)造和瑰麗的建筑裝飾著稱于世。[tiantan]: http://www.tiantanpark.com渲染結(jié)果如下:實例 4:超鏈接聲明的另一種形式。#### 聲明超鏈接的細(xì)節(jié)[天壇][]公園,是明清兩代皇帝每年祭天和祈禱五谷豐收的地方。[天壇][]以嚴(yán)謹(jǐn)?shù)慕ㄖ季?、奇特的建筑?gòu)造和瑰麗的建筑裝飾著稱于世。[天壇]: http://www.tiantanpark.com其渲染效果如下:全局的聲明可以寫在文章的任何地方,通常情況下,我們將它寫在整篇文章的結(jié)尾處。
打開 prometheus web UI 頁面 http://127.0.0.1:9090,點擊 alert 標(biāo)簽頁,查看監(jiān)控告警狀態(tài):我們將監(jiān)控的容器 cadvisor 關(guān)掉。docker stop cadvisor幾秒后刷新頁面,發(fā)現(xiàn)告警進(jìn)入 Pending 暫掛狀態(tài):一分鐘后(rule_1.yml 中 for = 1m 配置)告警進(jìn)入 firing 狀態(tài)。查收告警郵件:修復(fù)故障后恢復(fù)正常:docker start cadvisor
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> { @Override protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { if(msg instanceof HttpRequest) { //1.打印瀏覽器的請求地址 System.out.println("客戶端地址:" + ctx.channel().remoteAddress()); //2.給瀏覽器發(fā)送的信息,封裝成ByteBuf ByteBuf content = Unpooled.copiedBuffer("hello world", CharsetUtil.UTF_8); //3.構(gòu)造一個http的相應(yīng),即 httpresponse FullHttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); //4.設(shè)置響應(yīng)頭信息-響應(yīng)格式 response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain"); //5.設(shè)置響應(yīng)頭信息-響應(yīng)數(shù)據(jù)長度 response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); //6.將構(gòu)建好 response返回 ctx.writeAndFlush(response); } }}代碼說明:瀏覽器發(fā)送過來的數(shù)據(jù),被 Netty 給封裝成了 HttpObject 對象,我們需要判斷 HttpObject 具體所屬類型是不是 HttpRequest; 請求信息: 可以打印瀏覽器的請求信息,比如:請求地址、請求方式、請求體內(nèi)容、請求頭內(nèi)容等;響應(yīng)信息: 給瀏覽器響應(yīng),必須構(gòu)造 HttpResponse 對象,并且可以設(shè)置響應(yīng)頭信息、響應(yīng)體信息。特殊說明:如果不嚴(yán)格按照 Http 響應(yīng)格式進(jìn)行輸出,瀏覽器是無法讀取服務(wù)端的響應(yīng)。
在 Django 工程中,由于視圖有兩種:FBV 和 CBV,因此視圖加裝飾器的情況也分為兩種:給視圖函數(shù)加裝飾器和給視圖類加裝飾器。由于視圖函數(shù)是普通的 Python 函數(shù),因此給視圖函數(shù)加裝飾器和給普通函數(shù)加裝飾器方式一致。下面代碼中我們給視圖函數(shù) index 加了一個簡單的裝飾器,用于在執(zhí)行視圖函數(shù)前和后各打印一段字符:from django.shortcuts import render, HttpResponse, redirectdef wrapper(f): def innser(*args, **kwargs): print('before') ret = f(*args, **kwargs) print('after') return ret return innser @wrapperdef index(request): return render(request, 'index.html')由于類中的方法與普通函數(shù)不完全相同,因此不能直接將函數(shù)裝飾器應(yīng)用于類中的方法 ,我們需要先將其轉(zhuǎn)換為方法裝飾器。Django 中提供了 method_decorator 裝飾器用于將函數(shù)裝飾器轉(zhuǎn)換為方法裝飾器:# 定義函數(shù)裝飾器def wrapper(f): def innser(*args, **kwargs): print('before') ret = f(*args, **kwargs) print('after') return ret return innser# 另一個代碼文件中使用wrapper裝飾器from django.views import Viewfrom django.utils.decorators import method_decorator@method_decorator(wrapper, name='get')class HelloView(View): # @method_decorator(wrapper) def get(self, request, *args, **kwargs): print('get') return HttpResponse('get\n') def post(self, request, *args, **kwargs): print('post') return HttpResponse('post\n') def put(self, request, *args, **kwargs): print('put') return HttpResponse('put\n') def delete(self, request, *args, **kwargs): print('delete') return HttpResponse('delete\n') @csrf_exempt # @method_decorator(wrapper) def dispatch(self, request, *args, **kwargs): return super(HelloView, self).dispatch(request, *args, **kwargs)對于給 View 類添加裝飾器,我們有如下幾種性質(zhì):將 method_decorator 裝飾器直接添加到 View 類上。第一個參數(shù)指定需要添加的裝飾器,如 wrapper,name 參數(shù)可以選擇將裝飾器 wrapper 作用到 View 類中的哪個函數(shù)。給類添加裝飾器時,必須要指定 name 參數(shù),不然運行 Django 服務(wù)時會報錯;method_decorator 裝飾器可以直接作用于 View 類中的函數(shù)上。如果是在 get、post 這類 HTTP 請求方法的函數(shù)上,則裝飾器只會作用于調(diào)用該函數(shù)的 http 請求上;如果 method_decorator 裝飾器作用于 dispatch 函數(shù)上。由于對于視圖中所有的 HTTP 請求都會先調(diào)用 dispatch 方法找到對應(yīng)請求方法的函數(shù),然后再執(zhí)行。所以這樣對應(yīng)視圖內(nèi)的所有 HTTP 請求方式都先經(jīng)過裝飾器函數(shù)處理;
通過前面描述我們看到,要實現(xiàn)「記住我」功能,關(guān)鍵在于如何安全的保護(hù)好用戶的認(rèn)證信息 Token。Spring Security 提供了兩種「記住我」的實現(xiàn)方式:使用 Hash 算法加密認(rèn)證信息形成 Token,并將其保存在客戶端中;將認(rèn)證信息保存在數(shù)據(jù)庫中,并將查詢條件保存在客戶端中。3.1.1 基于 Hash 的方式基于 Hash 的方式是一種相對簡單的集成方式。這種方式利用 Hash 的特性,將「記住我」信息進(jìn)行存檔。每當(dāng)用戶認(rèn)證通過,服務(wù)端便生成一條 Hash 記錄,并發(fā)送給客戶端瀏覽器,其中內(nèi)容包括「用戶名」、「Token 過期時間」、「密碼」、「簽名秘鑰」。發(fā)送的具體內(nèi)容為:base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key))username: 根據(jù) UserDetailsService 配置得到用戶名信息。password: 認(rèn)證密碼,確保 UserDetailsService 中可以匹配到目標(biāo)用戶。expirationTime: 「記住我」Roken 的有效期,精確到毫秒。key: 用于給 Token 簽名的密鑰信息,防止該 Token 被篡改。發(fā)送出的 Token 只有到用戶下次需要登錄時才會被使用到,這期間,需要確保用戶名、密碼、密鑰等信息不被改變。還需要注意的是,「記住我」Token 在過期之前,可以在任何地方使用,因此其安全性上有一定的問題,如果使用數(shù)字認(rèn)證一樣。當(dāng)用戶認(rèn)為自己的 Token 不在安全時,最好的辦法是立刻改變自己的認(rèn)證密碼,并且使全部的「記住我」Token 失效。啟動「記住我」功能僅需要一行配置,具體方式為:<http>...<remember-me key="簽名密鑰"/></http>當(dāng)有多個 UserDetailsService 實例時,可以通過 user-service-ref 屬性指定唯一實例。3.1.2 基于存儲的方式使用數(shù)據(jù)庫作為 Token 存儲方式,需要在 <remember-me> 配置中增加 data-source-ref 屬性,配置方式如下:<http>...<remember-me data-source-ref="數(shù)據(jù)源實例"/></http>所用到的數(shù)據(jù)源需要包含 persistent_logins 數(shù)據(jù)表,其結(jié)構(gòu)如下:create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null)
Http 協(xié)議根據(jù)場景約定了一系列請求返回的狀態(tài)碼,方便對請求結(jié)果進(jìn)行細(xì)粒度管理。該狀態(tài)碼由互聯(lián)網(wǎng)號碼分配局維護(hù)管理。狀態(tài)碼是由3位數(shù)字組成,目前總共分為 5 大類,在接下來的章節(jié)中將逐一詳細(xì)介紹。
為了在 HTTP 請求中攜帶 CSRF Token,我們必須要對 HTTP Request 做一些配置,因為它默認(rèn)是不會攜帶 CSRF 相關(guān)參數(shù)的。默認(rèn)情況下,Spring Security 中有 CsrfFilter 判斷請求中是否有 _csrf 參數(shù),通常請求來自于兩種情況,F(xiàn)orm 表單提交或者 Ajax。4.3.1 Form 表單提交使用 Form 表單提交代碼時,我們需要在 Form 參數(shù)中增加一個隱藏項:_csrf,例如:<input type="hidden" name="_csrf" value="4bfd1575-3ad1-4d21-96c7-4ef2d9f86721"/>這里的 _csrf 有幾種配置方式:自動注入Spring Security 通過擴展 Spring 的 RequestDataValueProcessor 類,實現(xiàn)了 RequestDataValueProcessor 類,這意味著如果我們使用 Spring 標(biāo)簽庫、Thymeleaf 模板插件、或者其它集成了 RequestDataValueProcessor 對象的視圖組件是,表單的非冪等請求(例如:POST)都會自動攜帶 CSRF Token。JSP 標(biāo)簽針對 JSP 作為頁面開發(fā)基礎(chǔ),我們可以直接使用 Spring 的表單標(biāo)簽庫或者 CsrfInput 標(biāo)簽。也可以通過更加直接的方式,在使用 HttpServletRequest 屬性 _csrf,代碼如下:<c:url var="logoutUrl" value="/logout"/><form action="${logoutUrl}" method="post"><input type="submit" value="登出" /><input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/></form>4.3.2 Ajax 和 JSON 請求如果使用 Javascript 做為請求提交方式,我們沒法直接使用 Http CSRF 參數(shù),取而代之的是使用 Http 頭的方式。這同樣也有幾種方法:自動注入Spring Security 可以自動將 CSRF Token 保存到 Cookie 中,一些客戶端框架如 AngularJS 會自動從中得到 CSRF Token 并放置到請求頭中。Meta 標(biāo)簽另一種方式是從 Cookie 中解壓 Token 并使用 Meta 標(biāo)簽,如下:<html><head> <meta name="_csrf" content="4bfd1575-3ad1-4d21-96c7-4ef2d9f86721"/> <meta name="_csrf_header" content="X-CSRF-TOKEN"/> <!-- ... --></head>當(dāng) Meta 標(biāo)簽中有 Token 信息時,我們就可以將 Meta 中的 CSRF Token 值用作請求參數(shù)了。以 JQuery 為例:$(function () { var token = $("meta[name='_csrf']").attr("content"); var header = $("meta[name='_csrf_header']").attr("content"); $(document).ajaxSend(function(e, xhr, options) { xhr.setRequestHeader(header, token); });});
今天我們簡單了解了下 Nginx 的配置文件以及相應(yīng)的語法規(guī)則。但是我們僅僅簡單介紹了 Nginx 一些簡單的語法并完成了幾個簡單的案例,接下來我們將簡單學(xué)習(xí) Nginx 的 Http 配置以及反向代理等常用配置。
本節(jié)主要從域名、版本、路徑、HTTP動詞、過濾信息、狀態(tài)碼、錯誤信息、返回結(jié)果、超媒體鏈接、數(shù)據(jù)格式 10 個方面介紹了 RESTful 設(shè)計方法和設(shè)計規(guī)范。為了讓更多的人方便使用所設(shè)計的 API 接口,以上規(guī)范一定要遵守哦!
在啟動類上添加 @EnableAdminServer 注解開啟 Spring Boot Admin 監(jiān)控管理功能,代碼如下:實例:@SpringBootApplication@EnableAdminServer // 開啟監(jiān)控管理public class SpringBootMonitorManagerApplication { public static void main(String[] args) { SpringApplication.run(SpringBootMonitorManagerApplication.class, args); }}然后運行啟動類,訪問 http://127.0.0.1:8080 會發(fā)現(xiàn)界面上已經(jīng)顯示監(jiān)控信息了。Spring Boot Admin 監(jiān)控管理頁面
在配置好 Nexus 之后,我們要在項目中使用私服要如何使用呢?答案是,和使用其他的倉庫沒有太大區(qū)別。接下來,我們來具體介紹一下如何在項目中使用。打開 Maven 的 setting.xml 文件,將其中的 mirrors 節(jié)點和 profiles 節(jié)點改為如下配置;<mirrors> <mirror> <id>mic-maven</id> <mirrorOf>*</mirrorOf> <name>mic maven</name> <url>http://ip:port/nexus/content/groups/public/</url> </mirror></mirrors><profiles> <profile> <id>maven profile</id> <activation> <jdk>1.8</jdk> <activeByDefault>true</activeByDefault> </activation> <repositories> <repository> <id>chenyao-central</id> <name>chenyao maven</name> <url>http://ip:port/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>chenyao-central</id> <name>chenyao maven</name> <url>http://ip:port/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories> </profile></profiles><activeProfiles> <activeProfile>maven profile</activeProfile></activeProfiles>在 setting.xml 文件中配置好 Nexus 之后,我們可以在項目中引入一個 jar 包來試一下,如果能夠成功的將構(gòu)件下載到本地,就說明我們的配置是正確的。介于我們在團(tuán)隊內(nèi)部使用的時候,還需要將項目的構(gòu)建到 Nexus 中,所以,我們還需要進(jìn)行單獨的配置。首先,我們在項目的 pom.xml 文件中,添加 distributionManagement 節(jié)點,用于控制分發(fā)管理;<distributionManagement> <repository> <id>mic-release</id> <name>mic maven</name> <url>http://ip:port/nexus/content/repositories/releases/</url> </repository> <snapshotRepository> <id>mic-snapshot</id> <name>mic maven</name> <url>http://ip:port/nexus/content/repositories/snapshots/</url> </snapshotRepository></distributionManagement>由于 Nexus 需要登陸才能使用,所以需要在 setting.xml 文件中配置服務(wù)器的登陸信息;<servers> <server> <id>mic-release</id> <username>admin</username> <password>admin123</password> </server> <server> <id>mic-snapshot</id> <username>admin</username> <password>admin123</password> </server></servers>配置完成后,我們在 mall-order目錄下執(zhí)行mvn clean deploy;執(zhí)行完之后,我們?nèi)?Nexus 中根據(jù)坐標(biāo)可以查到這個構(gòu)件。至此,我們已經(jīng)能夠讓 Nexus 來代理中央倉庫,并且將我們自己的項目構(gòu)建到私服中去,來提供給其他的項目中使用。
前邊提到 Localstorage 相比較 Cookie 的優(yōu)勢是容量大和節(jié)省 HTTP 帶寬,但是它還是有自身的缺點,下邊羅列了它的缺點5M 容量依然小,用過數(shù)據(jù)庫的同學(xué)應(yīng)該知道,MySQL 隨便一個表加上索引很容易超過 5M不能跨域名訪問,同一個網(wǎng)站可能會牽涉到子域名不能存儲關(guān)系型數(shù)據(jù)不能搜索
以上介紹了 Localstorage 和傳統(tǒng)離線存儲的優(yōu)缺點對比,Localstorage 的使用方法以及項目實戰(zhàn)分析。總的來說 Localstorage 適用于業(yè)務(wù)簡單的輕量級存儲中,通過簡單的 API 操作增刪改查存儲鍵值對,而且可以通過事件監(jiān)聽的方式獲取 Localstorage 的操作事件,無需發(fā)送 HTTP 請求,真正實現(xiàn)了離線存儲
創(chuàng)建 list.xml 布局文件,用來展示英雄的名稱、位置和描述:<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="5dp"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="17sp" android:textStyle="bold" /> <TextView android:id="@+id/designation" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/name" android:layout_marginTop="7dp" android:textColor="#343434" android:textSize="14dp" /> <TextView android:id="@+id/location" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/designation" android:layout_alignBottom="@+id/designation" android:layout_alignParentEnd="true" android:textColor="#343434" android:textSize="14sp" /></RelativeLayout>
所謂限定頭信息,指 Spring MVC 可以通過 HTTP 請求包中的消息頭信息進(jìn)行過濾。如下面的實例:@RequestMapping(value="/test",headers="content-type=text/*")public String test(){ ... }test() 方法只會響應(yīng)請求包中的內(nèi)容類型為 text/* 的請求。無論是方法限定、還是參數(shù)限定或是頭信息限定,其本質(zhì)都是檢查請求包是否符合條件要求。
本節(jié)通過一個具體的例子講解 after_request 與 teardown_request 的區(qū)別,代碼如下:from flask import Flask, request, render_templateapp = Flask(__name__)@app.route('/')def index(): print('execute request without error') return 'Hello World'@app.route('/error')def error(): print('execute request with error') 1 / 0 return 'Hello World'@app.after_requestdef after_request(response): print('after_request') return response@app.teardown_requestdef teardown_request(exception): print('teardown_request:', exception)if __name__ == '__main__': app.run()在第 5 行,訪問頁面 / 時執(zhí)行函數(shù) index(),該函數(shù)打印字符串 ‘execute request without error’,執(zhí)行期間沒有發(fā)生異常。在第 10 行,訪問頁面 /error 時執(zhí)行函數(shù) error(),該函數(shù)打印字符串 ‘execute request with error’,執(zhí)行期間發(fā)生異常。在第 13 行,人為的通過 1 / 0 引發(fā)除零異常。在第 16 行,注冊 after_request 鉤子函數(shù),執(zhí)行請求后會調(diào)用該鉤子函數(shù)。在第 21 行,注冊 teardown_request 鉤子函數(shù),執(zhí)行請求后都會調(diào)用該鉤子函數(shù)。鉤子函數(shù)的第一個參數(shù)是 exception 對象,指向執(zhí)行請求時發(fā)生的錯誤。
爬蟲文件的命名一定要準(zhǔn)確,爬蟲爬取的是哪一個網(wǎng)站就用哪一個網(wǎng)站來進(jìn)行命名,這樣以后我們寫的爬蟲越來越多會方便管理。文件創(chuàng)建好之后首先導(dǎo)入 requests 第三方庫和頁面解析工具 BeautifulSoup:import requests # requests庫,用來發(fā)送網(wǎng)絡(luò)請求from bs4 import BeautifulSoup # 一個解析庫,用來解析網(wǎng)頁結(jié)構(gòu)Tips:BeautifulSoup 我們在后面會講到,這里只是先用一下。
在真實的項目中會經(jīng)常使用到 axios 這樣的 ajax 請求的庫,雖然可以直接使用,但是往往業(yè)務(wù)中會有很多接口請求的地方,而這么多的請求有些固定不變的,每個接口在請求時都需要,如:token,baseURL,timeout 等等,針對這樣的場景,我們可以對 axios 庫進(jìn)行二次業(yè)務(wù)封裝。對于接口不同的返回結(jié)果我們希望有一個全局的提示框,這里我們使用 element-ui 組件庫搭配使用。封裝后的代碼如下:import axios from 'axios';import { baseURL } from '@/config'class Http { constructor(baseUrl) { this.baseURL = baseURL; this.timeout = 3000; } setInterceptor(instance) { instance.interceptors.request.use(config => { return config; }); instance.interceptors.response.use(res => { if (res.status == 200) { return Promise.resolve(res.data); } else { return Promise.reject(res); } }, err => { return Promise.reject(err); }); } mergeOptions(options) { return { baseURL: this.baseURL, timeout: this.timeout, ...options } } request(options) { const instance = axios.create(); const opts = this.mergeOptions(options); this.setInterceptor(instance); return instance(opts); } get(url, config = {}) { return this.request({ method: 'get', url: url, ...config }) } post(url, data) { return this.request({ method: 'post', url, data }) }}export default new Http;
在學(xué)習(xí)Socket編程之前我們要了解一下概念。端口不是物理設(shè)備,而是促進(jìn)服務(wù)器和客戶端之間通信的抽象概念。端口是由一個 2 的 16 次冪的整數(shù)表示的,所以,一臺機器最多可以有65536個端口(0~65535)。端口一共分為三個種類:知名端口:0 ~ 1023(例如:80端口用于http,25端口用于smtp)。注冊端口:1024 ~ 49151。動態(tài)/私有端口:49152 ~ 65535。
本節(jié)主要介紹 Nginx 的進(jìn)程模型以及介紹了 Master 和 Worker 之間的通信過程。此外,我們介紹了 Nginx 的事件驅(qū)動模型。異步、多路IO復(fù)用、非阻塞等特點早就了 Nginx 的高性能。接下來,我們完成了 Nginx 進(jìn)程模型的幾個實驗,直觀體檢 Nginx 的進(jìn)程模型。下一節(jié)將重點介紹 Nginx 模塊相關(guān)的內(nèi)容,并手動實現(xiàn)一個簡單的 http 模塊。
本文主要使用了gin這個第三方開發(fā)包,來搭建了一個Go語言的web應(yīng)用,這個gin包的本質(zhì)還是http包,但是它在其上封裝了一層接口,使我們可以更高效的開發(fā)以及開發(fā)出來的應(yīng)用更安全。在我們Go語言的學(xué)習(xí)和開發(fā)的過程中,在熟悉了官方庫之后,我們也可以去使用一些能更好的幫助我們開發(fā)的第三方包。
經(jīng)過這一番折騰后,Spring MVC 項目的基礎(chǔ)架構(gòu)就完成了,把項目部署到服務(wù)器(tomcat)中。查看 tomcat 啟動時的輸出日志中是否存在下面的信息。如果存在,表示 Spring MVC 項目初始化成功。在瀏覽器的地址欄中輸入:http://localhost:8888/sm-demo/Tips: 我的端口號是 8888。如果瀏覽器中輸出 Hello World ,恭喜,咱們?nèi)〉昧耸褂?Spring MVC 第一階段的成功。
State Drawables 用來描述一個 View 在不同狀態(tài)下的形態(tài),我們可以給每一種狀態(tài)設(shè)置一中背景樣式,比如我們可以讓我們的 Button 在點擊、選擇和默認(rèn)態(tài)下呈現(xiàn)不同的樣式:<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/button_pressed" android:state_pressed="true" /> <item android:drawable="@drawable/button_checked" android:state_checked="true" /> <item android:drawable="@drawable/button_default" /></selector>
產(chǎn)生原因:包管理器源在國外,網(wǎng)絡(luò)不好就很難打開甚至打不開。// 國外的源https://packagecontrol.io/channel_v3.json解決方案:設(shè)置國內(nèi)源,步驟如下:Preferences > Package Settings > Package Control > Settings User,添加如下代碼并保存,解決。Tips: 如果你的電腦不能科學(xué)上網(wǎng)的話,這一步驟還是比較重要的,原因你懂的!類似 npm,google"channels": [ "http://packagecontrol.cn/channel_v3.json"]
本節(jié)內(nèi)容我們主要介紹了如何向視圖函數(shù)傳送參數(shù),包括兩種方式:通過動態(tài)的 URLconf 配置傳遞參數(shù)到視圖函數(shù)中;通過 http 請求帶參數(shù)傳遞給視圖函數(shù)。至此,Django 中的路由系統(tǒng)和視圖函數(shù)已經(jīng)介紹完畢。接下來會介紹 Django 中的模板系統(tǒng)。
由于臨時的服務(wù)器維護(hù)或者過載,服務(wù)器當(dāng)前無法處理請求。這個狀況是臨時的,并且將在一段時間以后恢復(fù)。如果能夠預(yù)計延遲時間,那么響應(yīng)中可以包含一個 Retry-After 頭用以標(biāo)明這個延遲時間。HTTP/1.1 503 Service UnavailableContent-Type text/plainRetry-After: 1800
是指在同一個連接中,不同的請求之間是沒有聯(lián)系的,這次的請求無法知道上次請求的上下文信息。但是,HTTP 又是有會話的,也就是說,我們可以通過 Cookies 來解決不同請求的上下文信息共享。Cookie 的具體內(nèi)容,我們會在后面的章節(jié)進(jìn)行描述。