日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

TOMCAT源碼分析(啟動(dòng)框架)

系統(tǒng) 2168 0

TOMCAT源碼分析(啟動(dòng)框架)
前言:
?? 本文是我閱讀了TOMCAT源碼后的一些心得。 主要是講解TOMCAT的系統(tǒng)框架, 以及啟動(dòng)流程。若有錯(cuò)漏之處,敬請(qǐng)批評(píng)指教!
建議:
?? 畢竟TOMCAT的框架還是比較復(fù)雜的, 單是從文字上理解, 是不那么容易掌握TOMCAT的框架的。 所以得實(shí)踐、實(shí)踐、再實(shí)踐。 建議下載一份TOMCAT的源碼, 調(diào)試通過(guò), 然后單步跟蹤其啟動(dòng)過(guò)程。 如果有不明白的地方, 再來(lái)查閱本文, 看是否能得到幫助。 我相信這樣效果以及學(xué)習(xí)速度都會(huì)好很多!
??
1. Tomcat的整體框架結(jié)構(gòu)
?? Tomcat的基本框架, 分為4個(gè)層次。
?? Top Level Elements:
??? Server
??? Service??
?? Connector
??? HTTP
??? AJP
?? Container
?? Engine
???? Host
?? Context
?? Component?
??? manager
?? logger
?? loader
?? pipeline
?? valve
???????? ...
?? 站在框架的頂層的是Server和Service
?? Server:? 其實(shí)就是BackGroud程序, 在Tomcat里面的Server的用處是啟動(dòng)和監(jiān)聽(tīng)服務(wù)端事件(諸如重啟、關(guān)閉等命令。 在tomcat的標(biāo)準(zhǔn)配置文件:server.xml里面, 我們可以看到“<Server port="8005" shutdown="SHUTDOWN" debug="0">”這里的"SHUTDOWN"就是server在監(jiān)聽(tīng)服務(wù)端事件的時(shí)候所使用的命令字)
?? Service: 在tomcat里面, service是指一類問(wèn)題的解決方案。? 通常我們會(huì)默認(rèn)使用tomcat提供的:Tomcat-Standalone 模式的service。 在這種方式下的service既給我們提供解析jsp和servlet的服務(wù), 同時(shí)也提供給我們解析靜態(tài)文本的服務(wù)。
??
?? Connector: Tomcat都是在容器里面處理問(wèn)題的, 而容器又到哪里去取得輸入信息呢?
Connector就是專干這個(gè)的。 他會(huì)把從socket傳遞過(guò)來(lái)的數(shù)據(jù), 封裝成Request, 傳遞給容器來(lái)處理。
?? 通常我們會(huì)用到兩種Connector,一種叫http connectoer, 用來(lái)傳遞http需求的。 另一種叫AJP, 在我們整合apache與tomcat工作的時(shí)候, apache與tomcat之間就是通過(guò)這個(gè)協(xié)議來(lái)互動(dòng)的。 (說(shuō)到apache與tomcat的整合工作, 通常我們的目的是為了讓apache 獲取靜態(tài)資源, 而讓tomcat來(lái)解析動(dòng)態(tài)的jsp或者servlet。)
?? Container: 當(dāng)http connector把需求傳遞給頂級(jí)的container: Engin的時(shí)候, 我們的視線就應(yīng)該移動(dòng)到Container這個(gè)層面來(lái)了。
?? 在Container這個(gè)層, 我們包含了3種容器: Engin, Host, Context.
?? Engin: 收到service傳遞過(guò)來(lái)的需求, 處理后, 將結(jié)果返回給service( service 是通過(guò) connector 這個(gè)媒介來(lái)和Engin互動(dòng)的 ).
?? Host: Engin收到service傳遞過(guò)來(lái)的需求后,不會(huì)自己處理, 而是交給合適的Host來(lái)處理。
Host在這里就是虛擬主機(jī)的意思, 通常我們都只會(huì)使用一個(gè)主機(jī),既“l(fā)ocalhost”本地機(jī)來(lái)處理。
?? Context: Host接到了從Host傳過(guò)來(lái)的需求后, 也不會(huì)自己處理, 而是交給合適的Context來(lái)處理。
?? 比如: < http://127.0.0.1:8080/foo/index.jsp >
???????? < http://127.0.1:8080/bar/index.jsp >
?? 前者交給foo這個(gè)Context來(lái)處理, 后者交給bar這個(gè)Context來(lái)處理。
?? 很明顯吧! context的意思其實(shí)就是一個(gè)web app的意思。
?? 我們通常都會(huì)在server.xml里面做這樣的配置
?? <Context path="/foo" docBase="D:/project/foo/web" />
?? 這個(gè)context容器,就是用來(lái)干我們?cè)摳傻氖聝旱牡胤降摹?
??
?? Compenent: 接下來(lái), 我們繼續(xù)講講component是干什么用的。
?? 我們得先理解一下容器和組件的關(guān)系。
?? 需求被傳遞到了容器里面, 在合適的時(shí)候, 會(huì)傳遞給下一個(gè)容器處理。
?? 而容器里面又盛裝著各種各樣的組件, 我們可以理解為提供各種各樣的增值服務(wù)。
?? manager: 當(dāng)一個(gè)容器里面裝了manager組件后,這個(gè)容器就支持session管理了, 事實(shí)上在tomcat里面的session管理, 就是靠的在context里面裝的manager component.
?? logger: 當(dāng)一個(gè)容器里面裝了logger組件后, 這個(gè)容器里所發(fā)生的事情, 就被該組件記錄下來(lái)啦! 我們通常會(huì)在logs/ 這個(gè)目錄下看見(jiàn) catalina_log.time.txt 以及 localhost.time.txt 和localhost_examples_log.time.txt。 這就是因?yàn)槲覀兎謩e為:engin, host以及context(examples)這三個(gè)容器安裝了logger組件, 這也是默認(rèn)安裝, 又叫做標(biāo)配 :)
?? loader: loader這個(gè)組件通常只會(huì)給我們的context容器使用, loader是用來(lái)啟動(dòng)context以及管理這個(gè)context的classloader用的。
??? pipline: pipeline是這樣一個(gè)東西, 當(dāng)一個(gè)容器決定了要把從上級(jí)傳遞過(guò)來(lái)的需求交給子容器的時(shí)候, 他就把這個(gè)需求放進(jìn)容器的管道(pipeline)里面去。 而需求傻呼呼得在管道里面流動(dòng)的時(shí)候, 就會(huì)被管道里面的各個(gè)閥門攔截下來(lái)。 比如管道里面放了兩個(gè)閥門。 第一個(gè)閥門叫做“access_allow_vavle”, 也就是說(shuō)需求流過(guò)來(lái)的時(shí)候,它會(huì)看這個(gè)需求是哪個(gè)IP過(guò)來(lái)的, 如果這個(gè)IP已經(jīng)在黑名單里面了, sure, 殺! 第二個(gè)閥門叫做“defaul_access_valve”它會(huì)做例行的檢查, 如果通過(guò)的話,OK, 把需求傳遞給當(dāng)前容器的子容器。 就是通過(guò)這種方式, 需求就在各個(gè)容器里面?zhèn)鬟f,流動(dòng), 最后抵達(dá)目的地的了。
??? valve: 就是上面所說(shuō)的閥門啦。
?? Tomcat里面大概就是這么些東西, 我們可以簡(jiǎn)單地這么理解tomcat的框架,它是一種自上而下, 容器里又包含子容器的這樣一種結(jié)構(gòu)。
2. Tomcat的啟動(dòng)流程
?? 這篇文章是講tomcat怎么啟動(dòng)的,既然我們大體上了解了TOMCAT的框架結(jié)構(gòu)了, 那么我們可以望文生意地就猜到tomcat的啟動(dòng), 會(huì)先啟動(dòng)父容器,然后逐個(gè)啟動(dòng)里面的子容器。 啟動(dòng)每一個(gè)容器的時(shí)候, 都會(huì)啟動(dòng)安插在他身上的組件。 當(dāng)所有的組件啟動(dòng)完畢, 所有的容器啟動(dòng)完畢的時(shí)候, tomcat本身也就啟動(dòng)完畢了。
?? 順理成章地, 我們同樣可以猜到, tomcat的啟動(dòng)會(huì)分成兩大部分, 第一步是裝配工作。 第二步是啟動(dòng)工作。
?? 裝配工作就是為父容器裝上子容器, 為各個(gè)容器安插進(jìn)組件的工作。 這個(gè)地方我們會(huì)用到digester模式, 至于digester模式什么, 有什么用, 怎么工作的. 請(qǐng)參考 < http://software.ccidnet.com/pub/article/c322_a31671_p2.html >
?? 啟動(dòng)工作是在裝配工作之后, 一旦裝配成功了, 我們就只需要點(diǎn)燃最上面的一根導(dǎo)線, 整個(gè)tomcat就會(huì)被激活起來(lái)。 這就好比我們要開一輛已經(jīng)裝配好了的汽車的時(shí)候一樣,我們只要把鑰匙插進(jìn)鑰匙孔,一擰,汽車的引擎就會(huì)發(fā)動(dòng)起來(lái),空調(diào)就會(huì)開起來(lái), 安全裝置就會(huì)生效, 如此一來(lái),汽車整個(gè)就發(fā)動(dòng)起來(lái)了。(這個(gè)過(guò)程確實(shí)和TOMCAT的啟動(dòng)過(guò)程不謀而和, 讓我們不得不懷疑 TOMCAT的設(shè)計(jì)者是在GE做JAVA開發(fā)的)。
2.1 一些有意思的名稱:
?? Catalina
?? Tomcat
?? Bootstrap
?? Engin
?? Host
?? Context
?? 他們的意思很有意思:
?? Catalina: 遠(yuǎn)程轟炸機(jī)
?? Tomcat: 熊貓轟炸機(jī) -- 轟炸機(jī)的一種(這讓我想起了讓國(guó)人引以為豪的熊貓手機(jī),是不是英文可以叫做tomcat??? , 又讓我想起了另一則廣告: 波導(dǎo)-手機(jī)中的戰(zhàn)斗機(jī)、波音-客機(jī)中的戰(zhàn)斗機(jī) )
?? Bootstap: 引導(dǎo)
?? Engin: 發(fā)動(dòng)機(jī)
?? Host: 主機(jī),領(lǐng)土
?? Context: 內(nèi)容, 目標(biāo), 上下文
??
?? ... 在許多許多年后, 現(xiàn)代人類已經(jīng)滅絕。 后現(xiàn)代生物發(fā)現(xiàn)了這些單詞零落零落在一塊。 一個(gè)自以為聰明的家伙把這些東西翻譯出來(lái)了:
?? 在地勤人員的引導(dǎo)(bootstrap)下, 一架轟炸架(catalina)騰空躍起, 遠(yuǎn)看是熊貓轟炸機(jī)(tomcat), 近看還是熊貓轟炸機(jī)! 憑借著優(yōu)秀的發(fā)動(dòng)機(jī)技術(shù)(engin), 這架熊貓轟炸機(jī)飛臨了敵國(guó)的領(lǐng)土上空(host), 對(duì)準(zhǔn)目標(biāo)(context)投下了毀天滅地的核彈頭,波~ 現(xiàn)代生物就這么隔屁了~
?
?? 綜上所述, 這又不得不讓人聯(lián)想到GE是不是也參與了軍事設(shè)備的生產(chǎn)呢?
?? 反對(duì)美帝國(guó)主義! 反對(duì)美霸權(quán)主義! 和平萬(wàn)歲! 自由萬(wàn)歲!
??
2.2? 歷史就是那么驚人的相似! tomcat的啟動(dòng)就是從org.apache.catalina.startup.Bootstrap這個(gè)類悍然啟動(dòng)的!
?? 在Bootstrap里做了兩件事:
?? 1. 指定了3種類型classloader:
????? commonLoader: common/classes、common/lib、common/endorsed
????? catalinaLoader: server/classes、server/lib、commonLoader
????? sharedLoader:? shared/classes、shared/lib、commonLoader
?? 2. 引導(dǎo)Catalina的啟動(dòng)。
????? 用Reflection技術(shù)調(diào)用org.apache.catalina.startup.Catalina的process方法, 并傳遞參數(shù)過(guò)去。
??
2.3 Catalina.java
?? Catalina完成了幾個(gè)重要的任務(wù):
?? 1. 使用Digester技術(shù)裝配tomcat各個(gè)容器與組件。
????? 1.1?裝配工作的主要內(nèi)容是安裝各個(gè)大件。 比如server下有什么樣的servcie。 Host會(huì)容納多少個(gè)context。 Context都會(huì)使用到哪些組件等等。
????? 1.2?同時(shí)呢, 在裝配工作這一步, 還完成了mbeans的配置工作。 在這里,我簡(jiǎn)單地但不十分精確地描述一下mbean是什么,干什么用的。
????????? 我們自己生成的對(duì)象, 自己管理, 天經(jīng)地義! 但是如果我們創(chuàng)建了對(duì)象了, 想讓別人來(lái)管, 怎么辦呢? 我想至少得告訴別人我們都有什么, 以及通過(guò)什么方法可以找到? 吧! JMX技術(shù)給我們提供了一種手段。 JMX里面主要有3種東西。Mbean, agent, connector.
?????? Mbean: 用來(lái)映射我們的對(duì)象。也許mbean就是我們創(chuàng)建的對(duì)象, 也許不是, 但有了它, 就可以引用到我們的對(duì)象了。
?????? Agent:? 通過(guò)它, 就可以找到mbean了。
?????? Connector: 連接Agent的方式。 可以是http的, 也可以是rmi的,還可以直接通過(guò)socket。
????? 發(fā)生在tomcat 裝配過(guò)程中的事情:? GlobalResourcesLifecycleListener 類的初始化會(huì)被觸發(fā):
???????? protected static Registry registry = MBeanUtils.createRegistry();? 會(huì)運(yùn)行
???????? MBeanUtils.createRegistry()? 會(huì)依據(jù)/org/apache/catalina/mbeans/mbeans-descriptors.xml這個(gè)配置文件創(chuàng)建 mbeans. Ok, 外界就有了條途徑訪問(wèn)tomcat中的各個(gè)組件了。(有點(diǎn)像后門兒)
?? 2. 為top level 的server 做初始化工作。 實(shí)際上就是做通常會(huì)配置給service的兩條connector.(http, ajp)
?? 3. 從server這個(gè)容器開始啟動(dòng), 點(diǎn)燃整個(gè)tomcat.
?? 4. 為server做一個(gè)hook程序, 檢測(cè)當(dāng)server shutdown的時(shí)候, 關(guān)閉tomcat的各個(gè)容器用。
?? 5. 監(jiān)聽(tīng)8005端口, 如果發(fā)送"SHUTDOWN"(默認(rèn)培植下字符串)過(guò)來(lái), 關(guān)閉8005serverSocket。
2.4 啟動(dòng)各個(gè)容器
?? 1. Server
????? 觸發(fā)Server容器啟動(dòng)前(before_start), 啟動(dòng)中(start), 啟動(dòng)后(after_start)3個(gè)事件, 并運(yùn)行相應(yīng)的事件處理器。
????? 啟動(dòng)Server的子容器:Servcie.
?? 2. Service
????? 啟動(dòng)Service的子容器:Engin
????? 啟動(dòng)Connector
?? 3. Engin
????? 到了Engin這個(gè)層次,以及以下級(jí)別的容器, Tomcat就使用了比較一致的啟動(dòng)方式了。
????? 首先,? 運(yùn)行各個(gè)容器自己特有一些任務(wù)
????? 隨后,? 觸發(fā)啟動(dòng)前事件
????? 立即,? 設(shè)置標(biāo)簽,就表示該容器已經(jīng)啟動(dòng)
????? 接著,? 啟動(dòng)容器中的各個(gè)組件: loader, logger, manager等等
????? 再接著,啟動(dòng)mapping組件。(注1)
????? 緊跟著,啟動(dòng)子容器。
????? 接下來(lái),啟動(dòng)該容器的管道(pipline)
????? 然后,? 觸發(fā)啟動(dòng)中事件
????? 最后,? 觸發(fā)啟動(dòng)后事件。
?
????? Engin大致會(huì)這么做, Host大致也會(huì)這么做, Context大致還是會(huì)這么做。 那么很顯然地, 我們需要在這里使用到代碼復(fù)用的技術(shù)。 tomcat在處理這個(gè)問(wèn)題的時(shí)候, 漂亮地使用了抽象類來(lái)處理。 ContainerBase. 最后使得這部分完成復(fù)雜功能的代碼顯得干凈利落, 干練爽快, 實(shí)在是令人覺(jué)得嘆為觀止, 細(xì)細(xì)品來(lái), 直覺(jué)如享佳珍, 另人齒頰留香, 留戀往返啊!
?????
????? Engin的觸發(fā)啟動(dòng)前事件里, 會(huì)激活綁定在Engin上的唯一一個(gè)Listener:EnginConfig。
????? 這個(gè)EnginConfig類基本上沒(méi)有做什么事情, 就是把EnginConfig的調(diào)試級(jí)別設(shè)置為和Engin相當(dāng)。 另外就是輸出幾行文本, 表示Engin已經(jīng)配置完畢, 并沒(méi)有做什么實(shí)質(zhì)性的工作。
????? 注1: mapping組件的用處是, 當(dāng)一個(gè)需求將要從父容器傳遞到子容器的時(shí)候, 而父容器又有多個(gè)子容器的話, 那么應(yīng)該選擇哪個(gè)子容器來(lái)處理需求呢? 這個(gè)由mapping 組件來(lái)定奪。
???
?? 4. Host
?????? 同Engin一樣, 也是調(diào)用ContainerBase里面的start()方法, 不過(guò)之前做了些自個(gè)兒的任務(wù),就是往Host這個(gè)容器的通道(pipline)里面, 安裝了一個(gè)叫做
?“org.apache.catalina.valves.ErrorReportValve”的閥門。
?????? 這個(gè)閥門的用處是這樣的:? 需求在被Engin傳遞給Host后, 會(huì)繼續(xù)傳遞給Context做具體的處理。 這里需求其實(shí)就是作為參數(shù)傳遞的Request, Response。 所以在context把需求處理完后, 通常會(huì)改動(dòng)response。 而這個(gè)org.apache.catalina.valves.ErrorReportValve的作用就是檢察response是否包含錯(cuò)誤, 如果有就做相應(yīng)的處理。
?? 5. Context
?????? 到了這里, 就終于輪到了tomcat啟動(dòng)中真正的重頭戲,啟動(dòng)Context了。
?StandardContext.start() 這個(gè)啟動(dòng)Context容器的方法被StandardHost調(diào)用.
?5.1 webappResources 該context所指向的具體目錄
?5.2 安裝defaultContex, DefaultContext 就是默認(rèn)Context。 如果我們?cè)谝粋€(gè)Host下面安裝了DefaultContext,而且defaultContext里面又安裝了一個(gè)數(shù)據(jù)庫(kù)連接池資源的話。 那么其他所有的在該Host下的Context, 都可以直接使用這個(gè)數(shù)據(jù)庫(kù)連接池, 而不用格外做配置了。
? 5.3 指定Loader. 通常用默認(rèn)的org.apache.catalina.loader.WebappLoader這個(gè)類。?? Loader就是用來(lái)指定這個(gè)context會(huì)用到哪些類啊, 哪些jar包啊這些什么的。
?5.4 指定 Manager. 通常使用默認(rèn)的org.apache.catalina.session. StandardManager 。 Manager是用來(lái)管理session的。
???? 其實(shí)session的管理也很好實(shí)現(xiàn)。 以一種簡(jiǎn)單的session管理為例。 當(dāng)需求傳遞過(guò)來(lái)的時(shí)候, 在Request對(duì)象里面有一個(gè)sessionId 屬性。 OK, 得到這個(gè)sessionId后, 我們就可以把它作為map的key,而value我們可以放置一個(gè)HashMap. HashMap里邊兒, 再放我們想放的東西。
?5.5 postWorkDirectory (). Tomcat下面有一個(gè)work目錄。 我們把臨時(shí)文件都扔在那兒去。 這個(gè)步驟就是在那里創(chuàng)建一個(gè)目錄。 一般說(shuō)來(lái)會(huì)在%CATALINA_HOME%/work/Standalone\localhost\ 這個(gè)地方生成一個(gè)目錄。
5.6? Binding thread。到了這里, 就應(yīng)該發(fā)生 class Loader 互換了。 之前是看得見(jiàn)tomcat下面所有的class和lib. 接下來(lái)需要看得見(jiàn)當(dāng)前context下的class。 所以要設(shè)置contextClassLoader, 同時(shí)還要把舊的ClassLoader記錄下來(lái),因?yàn)橐院筮€要用的。
5.7? 啟動(dòng) Loader. 指定這個(gè)Context具體要使用哪些classes, 用到哪些jar文件。 如果reloadable設(shè)置成了true, 就會(huì)啟動(dòng)一個(gè)線程來(lái)監(jiān)視classes的變化, 如果有變化就重新啟動(dòng)Context。
5.8? 啟動(dòng)logger
5.9? 觸發(fā)安裝在它身上的一個(gè)監(jiān)聽(tīng)器。
?lifecycle.fireLifecycleEvent(START_EVENT, null);
?作為監(jiān)聽(tīng)器之一,ContextConfig會(huì)被啟動(dòng). ContextConfig就是用來(lái)配置web.xml的。 比如這個(gè)Context有多少Servlet, 又有多少Filter, 就是在這里給Context裝上去的。
?5.9.1 defaultConfig. 每個(gè)context都得配置 tomcat/conf/web.xml 這個(gè)文件。
?5.9.2 applicationConfig 配置自己的 WEB-INF/web.xml 文件
5.9.3 validateSecurityRoles 權(quán)限驗(yàn)證。 通常我們?cè)谠L問(wèn)/admin 或者/manager的時(shí)候,需要用戶要么是admin的要么是manager的, 才能訪問(wèn)。 而且我們還可以限制那些資源可以訪問(wèn), 而哪些不能。 都是在這里實(shí)現(xiàn)的。
5.9.4 tldScan: 掃描一下, 需要用到哪些標(biāo)簽(tag lab)
5.10 啟動(dòng) manager
5.11 postWelcomeFiles() 我們通常會(huì)用到的3個(gè)啟動(dòng)文件的名稱:
index.html、index.htm、index.jsp 就被默認(rèn)地綁在了這個(gè)context上
?5.12 listenerStart 配置listener
?5.13 filterStart 配置 filter
?5.14 啟動(dòng)帶有<load-on-startup>1</load-on-startup>的Servlet.
? 順序是從小到大: 1,2,3… 最后是0
? 默認(rèn)情況下, 至少會(huì)啟動(dòng)如下3個(gè)的Servlet:
? org.apache.catalina.servlets.DefaultServlet??
????? 處理靜態(tài)資源的Servlet. 什么圖片啊, html啊, css啊, js啊都找他
? org.apache.catalina.servlets.InvokerServlet
????? 處理沒(méi)有做Servlet Mapping的那些Servlet.
? org.apache.jasper.servlet.JspServlet
????? 處理JSP文件的.
?????? 5.15? 標(biāo)識(shí)context已經(jīng)啟動(dòng)完畢。
?走了多少個(gè)步驟啊, Context總算是啟動(dòng)完畢嘍。
??? OK! 走到了這里, 每個(gè)容器以及組件都啟動(dòng)完畢。 Tomcat終于不辭辛勞地為人民服務(wù)了!
3. 參考文獻(xiàn):
??? < http://jakarta.apache.org/tomcat/ >
??? < http://www.onjava.com/pub/a/onjava/2003/05/14/java_webserver.html >
???
4. 后記
??? 這篇文章是講解tomcat啟動(dòng)框架的,還有篇文章是講解TOMCAT里面的消息處理流程的細(xì)節(jié)的。 文章內(nèi)容已經(jīng)寫好了, 現(xiàn)在正在整理階段。 相信很快就可以做出來(lái), 大家共同研究共同進(jìn)步。
??? 這篇文章是獨(dú)自分析TOMCAT源碼所寫的, 所以一定有地方是帶有個(gè)人主觀色彩, 難免會(huì)有片面之處。若有不當(dāng)之處敬請(qǐng)批評(píng)指教,這樣不僅可以使剛開始研究TOMCAT的兄弟們少走彎路, 我也可以學(xué)到東西。
??? email: sojan_java@yahoo.com.cn

5. tomcat源碼分析(消息處理)

TOMCAT源碼分析(啟動(dòng)框架)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 德令哈市| 招远市| 伊金霍洛旗| 德化县| 平乡县| 三门峡市| 盖州市| 边坝县| 兴城市| 成武县| 姚安县| 略阳县| 香格里拉县| 廊坊市| 乐东| 孟村| 榆林市| 虹口区| 河津市| 温泉县| 漯河市| 云和县| 石林| 资阳市| 日照市| 怀柔区| 邢台县| 南宁市| 印江| 淮滨县| 喀什市| 富裕县| 清远市| 堆龙德庆县| 犍为县| 上犹县| 岢岚县| 会泽县| 离岛区| 吴旗县| 苍梧县|