整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Vue實戰041:獲取當前客戶端IP地址詳解(內網和外網)

          我們經常會有需求,希望能獲取的到當前用戶的IP地址,而IP又分為公網ip(也稱外網)和私網IP(也稱內網IP),IP地址是IP協議提供的一種統一的地址格式,每臺設備都設定了一個唯一的IP地址”,從而確保了用戶在連網的計算機上操作時,能夠快速地從互聯網中找到自己所需的對象。

          外網IP和內網IP的區別

          1,外網IP是全球唯一的IP地址,僅分配給某一臺網絡設備。內網IP是由路由器分配給每一臺設備內部使用的IP地址;

          2,外網IP任何一臺設備都可以ping通。內網IP只有在同一環境的內部設備才能ping通;

          3,外網用戶無法直接訪問到內網用戶,內網用戶可以訪問外網用戶,因為內網的所有用戶都是通過同一個外網IP進行上網的;

          如何獲取外網IP

          這里我們可以借助現成的接口,搜狐提供的一個JS接口獲取IP地址,我們只需在入口index.html中直接引入該接口即可輕松獲取到當前用戶的外網ip,Vue中在public中的index.html中引入接口,然后再需要獲取的地方通過returnCitySN['cip']即可拿到IP地址,然后將IP存到localstorage或者Vuex中,這樣隨時可以調用了。

          //引入JS
           <script src="http://pv.sohu.com/cityjson?ie=utf-8"></script>
          //在組件中獲取,可以選擇在首頁載入前獲取該參數
          var Ip=returnCitySN['cip']
          localStorage.setItem('Ip', Ip)
          

          如何獲取內網IP

          獲取內網IP相對來說會復雜些,畢竟沒有現成的接口可以調用,這里我們用到了WebRTC(網頁即時通信),在WebRTC規范中,RTCPeerConnection可以用于視頻流/音頻流、以及數據的傳輸。這里們通過RTCPeerConnection 對象建立一個連接通道,下面3個或對象是針對不同瀏覽器來創建的。

          var RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
          

          當RTCPeerConnection對象存在時,我們就可以實例化該對象并創建一個可以發送任意數據的數據通道,此時我們的RTCPeerConnection對象中數據基本都是null。

          var RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
           if (RTCPeerConnection) (()=>{
           var rtc = new RTCPeerConnection()
           rtc.createDataChannel(''); //創建一個可以發送任意數據的數據通道
           })()
          

          什么是SDP

          SDP 是一種會話描述格式 ,由許多文本行組成,文本行的格式為<類型>=<值>,<類型>是一個字母,<值>是結構化的文本串。SDP中包含了很多媒體信息,包括了媒體類型(video)、傳輸協議(RTP/UDP/IP)、媒體格式(H.264 video)、多播或單播地址和端口、本端的帶寬信息、本端的加密信息等。

          建立sdp數據

          我們從要做的就是從SDP中拿到傳輸協議中的信息,創建一條sdp數據并將數據存入LocalDescription對象中。這樣我們在LocalDescription中就得到了所有的SDP數據,從下圖中我們可以看到有IP地址在里面,接下來就可以從sdq中提取ip地址了。

          rtc.createOffer( offerDesc => { //創建并存儲一條sdp數據
           rtc.setLocalDescription(offerDesc)
          }, e => { console.warn(e)})
          

          監聽candidate事件

          onicecandidate屬性在RTCPeerConnection實例上發生icecandidate事件時要調用的函數,當我們向服務器發送消息時觸發并獲取到SDP中的candidate屬性,而candidate中正好有我們想要的IP地址,你可以直接獲取var ip_addr = evt.candidate.address。當然你也可以從candidate屬性中獲取,不過這里就會復雜點,用個正則來提取吧(顯然方法一簡單)。

           rtc.onicecandidate =(evt) => { //監聽candidate事件
           if (evt.candidate) {
           //方法一:
           var ip_addr = evt.candidate.address
           //方法二:
           let ip_rule = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.
           var ip_addr = ip_rule.exec(evt.candidate.candidate)[1]
           console.log("ip_addr==",ip_addr)
           }}
          

          代碼封裝

          最后整理下代碼,封裝成一個方法需要的時候直接調用即可,通過localStorage來存儲獲取到的ip_addr(或者Vuex存儲),然后我們只需要通過localStorage.getItem('ip_addr'))就可以獲取到我們的內網IP地址了。

          getUserIP(){
           var RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
           if (RTCPeerConnection) (()=>{
           var rtc = new RTCPeerConnection()
           rtc.createDataChannel(''); //創建一個可以發送任意數據的數據通道
           rtc.createOffer( offerDesc => { //創建并存儲一個sdp數據
           rtc.setLocalDescription(offerDesc)
           }, e => { console.log(e)})
           rtc.onicecandidate =(evt) => { //監聽candidate事件
           if (evt.candidate) {
           var ip_addr = evt.candidate.address
           localStorage.setItem('ip_addr',ip_addr)
           }}
           })()
           else{console.log("目前僅測試了chrome瀏覽器OK")}
          }
          

          歡迎關注本人的公眾號:編程手札,文章也會在公眾號更新

          、總線的概念

          所謂總線(Bus),是指計算機設備和設備之間傳輸信息的公共數據通道。總線是連接計算機硬件系統內多種設備的通信線路,它的一個重要特征是由總線上的所有設備共享,可以將計算機系統內的多種設備連接到總線上。如果是某兩個設備或設備之間專用的信號連線,就不能稱之為總線。系統總線架構圖如下所示:

          微機中的總線分為數據總線、地址總線和控制總線3類。不同型號的CPU芯片,其數據總線、地址總線和控制總線的條數可能不同。

          數據總線DB用來傳送數據信息,是雙向的。CPU既可通過DB從內存或輸入設備讀入數據,又可通過DB將內部數據送至內存或輸出設備。DB的寬度決定了CPU和計算機其他設備之間每次交換數據的位數。

          地址總線AB用于傳送CPU發出的地址信息,是單向的。傳送地址信息的目的是指明與CPU交換信息的內存單元或I/O設備。存儲器是按地址訪問的,所以每個 存儲單元都有一個固定地址,要訪問1MB存儲器中的任一單元,需要給出1M個地址,即需要20位地址(220=1M)。因此,地址總線的寬度決定了CPU 的最大尋址能力。

          控制總線CB用來傳送控制信號、時序信號和狀態信息等。其中有的是CPU向內存或外部設備發出的信息,有的是內存或外部設備向CPU發出的信息。顯然,CB中的每一條線的信息傳送方向是一定的、單向的,但作為一個整體則是雙向的。所以,在各種結構框圖中,凡涉及到控制總線CB,均是以雙向線表示。

          總線的性能直接影響到整機系統的性能,而且任何系統的研制和外圍模塊的開發都必須依從所采用的總線規范??偩€技術隨著微機結構的改進而不斷發展與完善。

          二. 常見總線

          QPI總線

          Intel的QuickPath Interconnect技術縮寫為QPI,譯為快速通道互聯, 用來實現處理器之間的直接互聯. QPI是一種基于包傳輸的串行式高速點對點連接協議,采用差分信號與專門的時鐘進行傳輸。它的特點是:高速帶寬,低功耗,支持熱插拔。

          Memory總線(內存總線)

          用來實現處理器和內存的之間的連接.處理器里集成的內存控制器負責通過內存總線和內存模組通訊,例如尋址、讀寫等。目前內存總線所支持的內存模組有DDR2, DDR3, 將來還會支持DDR4。

          JTAG接口

          主要用于芯片或處理器內部測試和調試的接口.通過連接調試器, 可以對芯片或處理器的運行進行跟蹤和調試。

          DMI總線

          DMI是指Direct Media Interface(直接媒體接口)。用來連接處理器和南橋的總線.它是基于PCIE總線,因此具有PCI-E總線的優勢,這個高速接口集成了高級優先服務,允許并發通訊和真正的同步傳輸能力。它的基本功能對于軟件是完全透明的,因此早期的軟件也可以正常操作。

          USB總線

          USB,是英文Universal Serial BUS(通用串行總線)的縮寫,而其中文簡稱為“通串線,是一個外部總線標準,用于規范電腦與外部設備的連接和通訊。USB接口支持設備的即插即用和熱插拔功能。USB總線會根據外設情況在兩種傳輸模式中自動地動態轉換。USB是基于令牌的總線。類似于令牌環網絡或FDDI基于令牌的總線。USB主控制器廣播令牌,總線上設備檢測令牌中的地址是否與自身相符,通過接收或發送數據給主機來響應。USB通過支持懸掛/恢復操作來管理USB總線電源。USB系統采用級聯星型拓撲,該拓撲由三個基本部分組成:主機(Host),集線器(Hub)和功能設備。

          SMBUS/I2C總線

          I2C(Inter-Integrated Circuit)總線和SMBus (System Management Bus 的縮寫,譯為系統管理總線)是一種二線制串行總線,它主要應用的場合:不需要高速通訊,但希望通過一條廉價并且功能強大的總線(由兩條線組成),來控制主板上的設備并收集相應的信息。SMBUS大部分基于I2C總線規范。和 I2C一樣,SMBus不需增加額外引腳,創建該總線主要是為了增加新的功能特性,但只工作在100kHz且專門面向智能電池管理應用, 也被用來連接各種設備,包括電源相關設備,系統傳感器,EEPROM等等。它工作在主/從模式:主器件提供時鐘,在其發起一次傳輸時提供一個起始位,在其終止一次傳輸時提供一個停止位;從器件擁有一個唯一的7或10位從器件地址。

          SMBus與I2C總線之間在時序特性上存在一些差別。首先,SMBus需要一定數據保持時間,而 I2C總線則 是從內部延長數據保持時間。SMBus具有超時功能,因此當SCL太低而超過35 ms時,從器件將復位正在進行的通信。相反,I2C采用硬件復位。SMBus具有一種警報響應地址(ARA),因此當從器件產生一個中斷時,它不會馬上清 除中斷,而是一直保持到其收到一個由主器件發送的含有其地址的ARA為止。SMBus只工作在從10kHz到最高100kHz。最低工作頻率10kHz是由SMBus超時功能決定的。

          SPI總線

          SPI(Serial Peripheral Interface--串行外設接口)總線系統是一種同步串行外設接口,它可以使南橋與各種外圍設備以串行方式進行通信以交換信息。SPI接口主要應用在連接EEPROM、FLASH、實時時鐘、AD轉換器,還有數字信號處理器和數字信號解碼器之間。在Intel架構中放BIOS/UEFI固件的Flash可以通過SPI總線和南橋連接。

          LPC總線

          LPC(Low Pin Count, 少引腳數)接口一個取代傳統ISA總線的一種新接口規范,主要用于和傳統的外圍設備連接讓系統能向下兼容。以往為了連接ISA擴充槽、適配器、ROM BIOS芯片、Super I/O等接口,南橋芯片必須保留一個ISA總線,并且連通Super I/O芯片,以控制傳統的外圍設備。傳統ISA 總線速率大約在7.159~8.33MHz,提供的理論尖峰傳輸值為16MB/s,但是ISA總線與傳統的PCI總線的電氣特性、信號定義方式迥異,南橋芯片、Super I/O芯片得多浪費針腳來做處理,主板的線路設計也顯得復雜。 intel所定義的LPC接口,將以往ISA BUS的地址/數據分離譯碼,改成類似PCI的地址/數據信號線共享的譯碼方式,信號線數量大幅降低,工作速率由PCI總線速率同步驅動,雖然改良過的LPC接口一樣維持最大傳輸值16MB/s,不過所需要的信號腳位數大幅降低25~30個,以LPC接口設計的Super I/O芯片、Flash芯片都能享有腳位數減少、體積微縮的好處,主板的設計也可以簡化,這也就是取名LPC——Low Pin Count的原因。

          PS/2接口

          PS/2 (Personal System 2, 個人系統2)接口主要用于連接輸入設備,而不是傳輸接口。所以PS2口根本沒有傳輸速率的概念,只有掃描速率。PS/2接口設備不支持熱插拔,強行帶電插拔有可能燒毀主板。

          RS-232接口

          RS-232-C是美國電子工業協會EIA(Electronic Industry Association)制定的一種異步傳輸串行物理接口標準。RS是英文“推薦標準”的縮寫,232為標識號,C表示修改次數。RS-232-C總線標準設有25條信號線。一般個人計算機上會有兩組 RS-232 接口,分別稱為 COM1 和 COM2。

          LPT接口

          打印終端(line print terminal)接口,通常稱呼為LPT并口,是一種增強了的雙向并行傳輸接口,在USB接口出現以前是掃描儀,打印機最常用的接口。其默認的中斷號是IRQ7,采用25腳的DB-25接頭。并口的工作模式主要有三種:1、SPP標準工作模式。SPP數據是半雙工單向傳輸,傳輸速率較慢,僅為15Kbps,但應用較為廣泛,一般設為默認的工作模式。2、EPP增強型工作模式。EPP采用雙向半雙工數據傳輸,其傳輸速率比SPP高很多,可達2Mbps,目前已有不少外設使用此工作模式。3、ECP擴充型工作模式。ECP采用雙向全雙工數據傳輸,傳輸速率比EPP還要高一些,但目前支持的設備少。

          前端總線

          前端總線的英文名字是Front Side Bus,通常用FSB表示,是將CPU連接到北橋芯片的總線。選購主板和 CPU時,要注意兩者搭配問題,一般來說,如果CPU不超頻,那么前端總線是由CPU決定的,如果主板不支持CPU所需要的前端總線,系統就無法工作。也 就是說,需要主板和CPU都支持某個前端總線,系統才能工作,只不過一個CPU默認的前端總線是唯一的,因此看一個系統的前端總線主要看CPU就可以。北橋芯片負責聯系內存、顯卡等數據吞吐量最大的部件,并和南橋芯片連接。CPU就是通過前端總線(FSB)連接到北橋芯片,進而通過北橋芯片和內存、顯卡交換數據。前端總線是CPU和外界交換數據的最主要通道,因此前端總線的數據傳輸能力對計算機整體性能作用很大,如果沒足夠快的前端總線,再強的CPU也不能明顯提高計算機整體速度。數據傳輸最大帶寬取決于所有同時傳輸的數據的寬度和傳輸頻率,即數據帶寬=(總線頻率×數據位寬)÷8。下圖為FSB示意圖。

          PCI總線

          Intel公司首先提出了PCI的概念,并聯合IBM、Compaq、AST、HP、DEC等100多家公司成立了PCI集團,其英文全稱為:Peripheral Component Interconnect Special Interest
          Group(外圍部件互連專業組),簡稱PCISIG。PCI是一種先進的局部總線,已成為局部總線的新標準。

          最早提出的PCI總線工作在33MHz頻率之下,傳輸帶寬達到132MB/s(33MHz * 32bit/8),基本上滿足了當時處理器的發展需要。隨著對更高性能的要求,后來又提出把PCI 總線的頻率提升到66MHz,傳輸帶寬能達到264MB/s。1993年又提出了64bit的PCI總線,稱為PCI-X,目前廣泛采用的是32-bit、33MHz或者32-bit、66MHz的PCI 總線,64bit的PCI-X插槽更多是應用于服務器產品。和PCIE總線一樣,它用來外接擴展板卡,支持即插即用 (plug and play)。但和PCIE不同,PCI允許多路復用技術(分時復用),即允許一個以上的電子信號同時存在于總線之上,但相對PCIE,它的帶寬和速度比較慢。

          PCI總線是一種不依附于某個具體處理器的局部總線。從結構上看,PCI是在CPU和原來的系統總線之間插入的一級總線,具體由一個橋接電路實現對這一層的管理,并實現上下之間的接口以協調數據的傳送。管理器提供了信號緩沖,使之能支持10種外設,并能在高時鐘頻率下保持高性能。PCI總線也支持總線主控技術,允許智能設備在需要時取得總線控制權,以加速數據傳送。 PCI總線支持10臺外設 ,總線時鐘頻率33.3MHz/66MHz,最大數據傳輸速率133MB/s,時鐘同步方式 ,與CPU及時鐘頻率無關 ,總線寬度 32位(5V)/64位(3.3V),能自動識別外設 ,特別適合與Intel的CPU協同工作; 具有與處理器和存儲器子系統完全并行操作的能力,具有隱含的中央仲裁系統,采用多路復用方式(地址線和數據線)減少了引腳數,支持64位尋址,完全的多總線主控能力,提供地址和數據的奇偶校驗,可以轉換5V和3.3V的信號環境。

          PCI-E總線

          PCI Express是新一代的總線接口。早在2001年的春季,英特爾公司就提出了要用新一代的技術取代PCI總線和多種芯片的內部連接,并稱之為第三代I/O總線技術。隨后在2001年底,包括Intel、AMD、DELL、IBM在內的20多家業界主導公司開始起草新技術的規范,并在2002年完成,對其正式命名為PCI Express。它采用了目前業內流行的點對點串行連接,比起PCI以及更早期的計算機總線的共享并行架構,每個設備都有自己的專用連接,不需要向整個總線請求帶寬,而且可以把數據傳輸率提高到一個很高的頻率,達到PCI所不能提供的高帶寬。

          PCI Express的接口根據總線位寬不同而有所差異,包括X1、X4、X8以及X16(X2模式將用于內部接口而非插槽模式)。較短的PCI Express卡可以插入較長的PCI Express插槽中使用。PCI Express接口能夠支持熱拔插,這也是個不小的飛躍。PCI Express卡支持的三種電壓分別為+3.3V、3.3Vaux以及+12V。用于取代AGP接口的PCI Express接口位寬為X16,將能夠提供5GB/s的帶寬,即便有編碼上的損耗但仍能夠提供4GB/s左右的實際帶寬,遠遠超過AGP 8X的2.1GB/s的帶寬。

          PCI Express規格從1條通道連接到32條通道連接,有非常強的伸縮性,以滿足不同系統設備對數據傳輸帶寬不同的需求。例如,PCI Express X1規格支持雙向數據傳輸,每向數據傳輸帶寬250MB/s,PCI Express X1已經可以滿足主流聲效芯片、網卡芯片和存儲設備對數據傳輸帶寬的需求,但是遠遠無法滿足圖形芯片對數據傳輸帶寬的需求。因此,必須采用PCI Express X16,即16條點對點數據傳輸通道連接來取代傳統的AGP總線。PCI Express X16也支持雙向數據傳輸,每向數據傳輸帶寬高達4GB/s,雙向數據傳輸帶寬有8GB/s之多。

          PCIe屬于高速串行點對點雙通道高帶寬傳輸,所連接的設備分配獨享通道帶寬,不共享資源,主要支持主動電源管理,錯誤報告,端對端的可靠性傳輸,熱插拔以及服務質量(QOS)等功能。它主要用來和一些需要高速通訊的外部板卡設備控制器連接,例如顯示卡,網卡,聲卡等, 相對于老的并行的PCI總線,它具有針腳少,速度快, 更好的電源管理等優點。

          PCI-Express 3.0 規范

          早在2007年上半年PCI-E 2.0版規范剛剛公布的時候,PCI Express技術標準組織PCI-SIG就準備用兩年多的時間將其快速進化到第三代,但是誰也沒想到PCI-E 3.0的醞釀過程會如此一波三折,直到今天才終于修成正果。

          PCI-SIG主席兼總裁幾乎淚流滿面:“PCI-SIG始終致力于I/O創新,我們也很驕傲
          地向我們的成員發布PCI-E 3.0規范。PCI-E 3.0架構從細節上對前兩代PCI-E規范進行了極大地改進,為我們的成員在各自領域繼續創新提供了所必需的性能和功能?!?/p>

          在對可制造性、成本、功耗、復雜性、兼容性等諸多方面進行綜合、平衡之后,PCI-E 3.0規范將數據傳輸率提升到8GHz|8GT/s(最初也預想過10GHz),并保持了對PCI-E 2.x/1.x的向下兼容,繼續支持2.5GHz、5GHz信號機制?;诖耍琍CI-E 3.0架構單信道(x1)單向帶寬即可接近1GB/s,十六信道(x16)雙向帶寬更是可達32GB/s。

          PCI-E 3.0同時還特別增加了128b/130b解碼機制,可以確保幾乎100%的傳輸效率,相比此前版本的8b/10b機制提升了25%,從而促成了傳輸帶寬的翻番,延續了PCI-E規范的一貫傳統。

          新規范在信號和軟件層的其他增強之處還有數據復用指示、原子操作、動態電源調整機制、延遲容許報告、寬松傳輸排序、基地址寄存器(BAR)大小調整、I/O頁面錯誤等等,從而全方位提升平臺效率、軟件模型彈性、架構伸縮性。

          PCI-E 3.0規范完整文檔現已向PCI-SIG組織成員公布其中詳細描述了PCI-E架構、互聯屬性、結構管理、編程接口等等,但沒有公開發表。另外,intel X79高端芯片組經已完整支持pci-e 3.0規格,AMD最新架構旗艦顯卡AMD Radeon 7970,以及其他采用pci-e 3.0規格的顯卡將于2012年陸續發布。

          PCI Express總線的特點和長處

          PCI Express總線是一種完全不同于過去PCI總線的一種全新總線規范,與PCI總線共享并行架構相比,PCI Express總線是一種點對點串行連接的設備連接方式,點對點意味著每一個PCI Express設備都擁有自己獨立的數據連接,各個設備之間并發的數據傳輸互不影響,而對于過去PCI那種共享總線方式,PCI總線上只能有一個設備進行通信,一旦PCI總線上掛接的設備增多,每個設備的實際傳輸速率就會下降,性能得不到保證。現在,PCI Express以點對點的方式處理通信,每個設備在要求傳輸數據的時候各自建立自己的傳輸通道,對于其他設備這個通道是封閉的,這樣的操作保證了通道的專有性,避免其他設備的干擾。

          在傳輸速率方面,PCI Express總線利用串行的連接特點將能輕松將數據傳輸速度提 到一個很高的頻率,達到遠超出PCI總線的傳輸速率。PCI Express的接口根據總線位寬不同而有所差異,包括x1、x4、x8以及x16(x2模式將用于內部接口而非插槽模式),其中X1的傳輸速度為 250MB/s,而X16就是等于16倍于X1的速度,即是4GB/s。與此同時,PCI Express總線支持雙向傳輸模式,還可以運行全雙工模式,它的雙單工連接能提供更高的傳輸速率和質量,它們之間的差異跟半雙工和全雙工類似。因此連接的每個裝置都可以使用最大帶寬,PCI Express接口設備將有著比PCI設備優越的多的資源可用。

          除了這些,PCI Express設備能夠支持熱拔插以及熱交換特性,支持的三種電壓分別為+3.3V、3.3Vaux以及+12V。考慮到現在顯卡功耗的日益上漲,PCI Express而后在規范中改善了直接從插槽中取電的功率限制,16x的最大提供功率達到了70W,比AGP 8X接口有了很大的提高?;究梢詽M足未來中高端顯卡的需求。這一點可以從AGP、PCI Express兩個不同版本的6600GT上就能明顯地看到,后者并不需要外接電源。


          可以看到PCI Express只是南橋的擴展總線,它與操作系統無關,所以也保證了它與原有PCI的兼容性,也就是說在很長一段時間內在主板上PCI Express接口將和PCI接口共存,這也給用戶的升級帶來了方便。由此可見,PCI Express最大的意義在于它的通用性,不僅可以讓它用于南橋和其他設備的連接,也可以延伸到芯片組間的連接,甚至也可以用于連接圖形芯片,這樣,整個I/O系統將重新統一起來,將更進一步簡化計算機系統,增加計算機的可移植性和模塊化。PCI Express已經為PC的未來發展重新鋪設好了路基,下面就要看PCI Express產品的應用情況了。

          硬盤的總線

          一般有SCSI、ATA、SATA等幾種。

          SCSI(Small Computer System Interface),一種用于計算機和智能設備之間(硬盤、軟驅、光驅、打印機、掃描儀等)系統級接口的獨立處理器標準。 SCSI是一種智能的通用接口標準。它是各種計算機與外部設備之間的接口標準。SCSI具有以下特點:SCSI可支持多個設備;SCSI還允許在對一個設備傳輸數據的同時,另一個設備對其進行數據查找,SCSI占用CPU極低;SCSI設備還具有智能化,SCSI卡自己可對CPU指令進行排隊;最快的SCSI總線有160MB/s的帶寬。

          ATA技術是一個關于IDE(Integrated Device Electronics)的技術規范族。最初,IDE只是一項企圖把控制器與盤體集成在一起為主要意圖的硬盤接口技術。 隨著IDE/EIDE得到的日益廣泛的應用,全球標準化協議將該接口自誕生以來使用的技術規范歸納成為全球硬盤標準,這樣就產生了ATA(Advanced Technology Attachment)。

          SATA全稱是Serial Advanced Technology Attachment(串行高級技術附件,一種基于行業標準的串行硬件驅動器接口),由Intel、IBM、Dell、APT、Maxtor和Seagate公司共同提出的硬盤接口規范,主要用來后硬盤等大容量存儲器的連接。它具有支持熱插拔,傳輸速度快,執行效率高等優點。Serial ATA采用串行連接方式,串行ATA總線使用嵌入式時鐘信號,具備了更強的糾錯能力,與以往相比其最大的區別在于能對傳輸指令(不僅僅是數據)進行檢查,如果發現錯誤會自動矯正,這在很大程度上提高了數據傳輸的可靠性。串行接口還具有結構簡單、支持熱插拔的優點。 串口硬盤是一種完全不同于并行ATA的新型硬盤接口類型,由于采用串行方式傳輸數據而知名。相對于并行ATA來說,就具有很多的優勢。首先,Serial ATA以連續串行的方式傳送數據,一次只會傳送1位數據。這樣能減少SATA接口的針腳數目,使連接電纜數目變少,效率也會更高。實際上,Serial ATA 僅用四支針腳就能完成所有的工作,分別用于連接電纜、連接地線、發送數據和接收數據,同時這樣的架構還能降低系統能耗和減小系統復雜性。

          小型計算機系統接口(SCSI)

          小型計算機系統接口是一套用于在計算機與外圍設備之間進行物理連接和數據傳輸的標準。

          串行ATA(SATA)

          磁盤、光驅 EIDE 的替代品

          SATA 1.0 速度為 150 MB/s

          串行(1 位數據路徑),點到點專用鏈路

          薄型,1 米電纜長度

          每根電纜一臺設備

          支持固定連接或熱插拔

          串行連接SCSI (SAS)

          SAS 支持小尺寸、更長的布線距離、更好的尋址能力,并兼容 SCSI

          SAS 1.0 在SCSI 和 RAID 控制器中替換 Ultra320 SCSI

          全雙工、雙口、點到點連接

          更高的帶寬

          Ultra320
          - 每通道 320 MBps

          SAS
          – 8 端口,每個端口支持高達 3 Gbps 的速率

          寬端口(4 口) – 12 Gbps

          兩個寬端口(8 口)– 24 Gbps

          受到PCI-X/PCI 總線速度的限制

          更大的驅動支持

          基于 SCSI 的產品 - 每通道 14 個驅動器

          基于 SAS 的產品 - 每四個端口 72 個驅動器

          本文轉載自: http://wangboxyk.cn/post/Zongxian-Bus-QPI-Memory.html


          、目的

          做這個項目的初衷是因為我去年在微信賣老家水果,好多朋友下單后都問我快遞單號,每天發貨后我都要挨個甄別這個人是哪個快遞信息,很麻煩一部小心就搞錯了?;谶@件小事我有了自助快遞查詢的這個想法。將發貨的快遞信息導入到我的系統里,用戶訪問我的系統,通過輸入手機號就可以查看自己的快遞物流信息。 項目是去年8月寫的,一直擱淺在哪,最近無意間翻看我發的那篇文章自助快遞單號查詢閱讀量竟然都1.8w了,有圖有真相。

          這著實讓我很震驚,看來自助快遞查詢這塊確實是個熱點。今天我就講一下我手擼的快遞查詢系統。

          二、開發

          項目地址:github.com/hellowHuaai… 有興趣的可以直接下載源碼,覺得項目不錯的伙伴記得點個star,謝謝啦!

          2.1技術棧

          項目涉及到的技術棧有:

          • SpringBoot: 一款 Java 微服務框架。Spring boot 是 Spring 家族中的一個新框架,它用來簡化 Spring 應用程序的創建和開發。
          • Mybitas: 一款ORM框架,即對象關系映射。ORM框架的作用是把持久化對象的保存、修改、刪除等操作,轉換成對數據庫的操作。
          • Jquery:一個輕量級的寫的少,做的多的 JavaScript 函數庫。
          • Bootstrap:Bootstrap 是一個用于快速開發 Web 應用程序和網站的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的。

          2.2后端開發

          創建entity 創建快遞單實體類,屬性包括id,用戶名(userName),電話(phone),快遞單號(kuaidiNo),快遞公司(company),數據創建時間(createTime)。代碼如下:

          @Data
          @Builder
          public class KuaiDi {
              private Integer id;
              /* 收件人姓名 */
              private String userName;
              /**收件人電話*/
              private String phone;
              /* 快遞單號*/
              private String kuaidiNo;
              /*快遞公司名稱(拼音)*/
              private String company;
              /*訂單創建時間*/
              private Date createTime;
              
              public KuaiDi(Integer id, String userName, String phone, String kuaidiNo, String company, Date createTime) {
                  this.id = id;
                  this.userName = userName;
                  this.phone = phone;
                  this.kuaidiNo = kuaidiNo;
                  this.company = company;
                  this.createTime = createTime;
              }
              public KuaiDi(Integer id, String userName, String phone, String kuaidiNo, String company) {
                  this.id = id;
                  this.userName = userName;
                  this.phone = phone;
                  this.kuaidiNo = kuaidiNo;
                  this.company = company;
              }
          }

          service,mapper是常規的增刪查改操作,就是保存快遞的基本信息在數據庫中,并可以對數據進行簡單的維護功能。詳細可參考項目源碼。接下來看核心代碼。

          查詢快遞信息 快遞的基本信息存入數據庫,然后就是通過這些信息查詢快遞的詳細物流信息。這里我做過很多嘗試,想直接調用一些快遞公司的快遞信息查詢接口,但是都發現接口都有session,當session失效后就無法查詢到數據或者就查詢到的數據不正確。最終在網上找到一種付費的方案,使用快遞100接口。www.kuaidi100.com/ 查詢快遞的demo代碼如下:

          public class SynQueryDemo {
          
          	/**
          	 * 實時查詢請求地址
          	 */
          	private static final String SYNQUERY_URL = "http://poll.kuaidi100.com/poll/query.do";
          	
          	private String key;			//授權key
          	private String customer;	//實時查詢公司編號
          
          	public SynQueryDemo(String key, String customer) {
          		this.key = key;
          		this.customer = customer;
          	}
          	
          	/**
          	 * 實時查詢快遞單號
          	 * @param com			快遞公司編碼
          	 * @param num			快遞單號
          	 * @param phone			手機號
          	 * @param from			出發地城市
          	 * @param to			目的地城市
          	 * @param resultv2		開通區域解析功能:0-關閉;1-開通
          	 * @return
          	 */
          	public String synQueryData(String com, String num, String phone, String from, String to, int resultv2) {
          
          		StringBuilder param = new StringBuilder("{");
          		param.append("\"com\":\"").append(com).append("\"");
          		param.append(",\"num\":\"").append(num).append("\"");
          		param.append(",\"phone\":\"").append(phone).append("\"");
          		param.append(",\"from\":\"").append(from).append("\"");
          		param.append(",\"to\":\"").append(to).append("\"");
          		if(1 == resultv2) {
          			param.append(",\"resultv2\":1");
          		} else {
          			param.append(",\"resultv2\":0");
          		}
          		param.append("}");
          		
          		Map<String, String> params = new HashMap<String, String>();
          		params.put("customer", this.customer);
          		String sign = MD5Utils.encode(param + this.key + this.customer);
          		params.put("sign", sign);
          		params.put("param", param.toString());
          		
          		return this.post(params);
          	}
          	
          	/**
          	 * 發送post請求
          	 */
          	public String post(Map<String, String> params) {
          		StringBuffer response = new StringBuffer("");
          		
          		BufferedReader reader = null;
          		try {
          			StringBuilder builder = new StringBuilder();
          			for (Map.Entry<String, String> param : params.entrySet()) {
          				if (builder.length() > 0) {
          					builder.append('&');
          				}
          				builder.append(URLEncoder.encode(param.getKey(), "UTF-8"));
          				builder.append('=');
          				builder.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
          			}
          			byte[] bytes = builder.toString().getBytes("UTF-8");
          
          			URL url = new URL(SYNQUERY_URL);
          			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          			conn.setConnectTimeout(3000);
          			conn.setReadTimeout(3000);
          			conn.setRequestMethod("POST");
          			conn.setRequestProperty("accept", "*/*");
                      conn.setRequestProperty("connection", "Keep-Alive");
          			conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
          			conn.setRequestProperty("Content-Length", String.valueOf(bytes.length));
          			conn.setDoOutput(true);
          			conn.getOutputStream().write(bytes);
          
          			reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
          			
          			String line = "";
                      while ((line = reader.readLine()) != null) {
                      	response.append(line);
                      }
          		} catch (Exception e) {
          			e.printStackTrace();
          		} finally {
          			try {
          				if (null != reader) {
          					reader.close();
          				}
          			} catch (IOException e) {
          				e.printStackTrace();
          			}
          		}
          		
          		return response.toString();
          	}
          }

          上面的代碼就是通過java代碼調用kuaidi100的查詢接口,這個查詢接口會通過快遞單號自動識別快遞是屬于哪個快遞公司,然后調用對應快遞公司接口獲取響應數據。付費購買接口使用權其實就是生成一個授權key和實時查詢公司編號customer,在線調用會做身份認證。這樣就可以獲取快遞信息的json數據了。我已經購買了100塊大洋的接口使用權,大家可直接調用快遞查詢接口。

          controller代碼 快遞信息增刪查改的controller就不在列了,這里主要看下我對查詢快遞的接口進行了一次包裝處理。代碼如下:

          @RestController
          public class KuaiDiQueryController {
          
              @Autowired
              private KuaiDiService kuaiDiService;
              @Autowired
              private KuaiDiQueryService kuaiDiQueryService;
          
              /**
               * 返回json數據
               * @param com
               * @param no
               * @return
               */
              @GetMapping("/getKuaiDiInfoByJson")
              @ResponseBody
              public String queryKuadiInfoByJson(String com, String no) {
                  return kuaiDiQueryService.synQueryData(com, no,"", "", "", 0);
              }
          
              @GetMapping("/getKuaiDiInfoByPhone")
              @ResponseBody
              public Response queryKuaidiByPhone(String phone){
                  Response response = new Response();
                  if(StringUtils.isNotEmpty(phone)){
                      List<ResponseData> responseDataList = new ArrayList<>();
                      //  1.通過手機號查詢下面的所有訂單號
                      List<KuaiDi> kuaiDiList = kuaiDiService.getList("", phone);
                      if(!CollectionUtils.isEmpty(kuaiDiList)){
                          kuaiDiList.forEach(kuaiDi -> {
                              //  2.依次查出所有的訂單號
                              String responseDataStr = kuaiDiQueryService.synQueryData(kuaiDi.getCompany(), kuaiDi.getKuaidiNo(),"", "", "", 0);
                              ResponseData responseData = CommonUtils.convertJsonStr2Object(responseDataStr);
                              responseDataList.add(responseData);
                          });
                      }
                      // 3.組裝數據返回給前臺
                      response.setDataList(responseDataList);
                  }
                  return response;
              }
          }

          2.3前端開發

          前端展示主要包括兩個頁面,管理員頁面和客戶頁面。管理員頁面功能包括快遞信息的新增,修改,刪除,分頁查詢,在線快遞物流信息接口??蛻繇撁姘爝f信息的分頁查詢和在線快遞物流信息接口。所以主要看一下管理員頁面。

          html頁面 html頁面引入了jQuery和Bootstrap,jQuery已經過時了,但是使用起來還是很方便的。

          <html>
          <head>
            <title>快遞單號查詢</title>
              <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
              <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
              <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
              <script src="https://cdn.bootcss.com/bootbox.js/4.4.0/bootbox.min.js"></script>
              <link href="https://cdn.bootcss.com/bootstrap-table/1.11.1/bootstrap-table.min.css" rel="stylesheet">
              <script src="https://cdn.bootcss.com/bootstrap-table/1.11.1/bootstrap-table.min.js"></script>
              <script src="https://cdn.bootcss.com/bootstrap-table/1.11.1/locale/bootstrap-table-zh-CN.min.js"></script>
            ...
          </head>
          <body>
              <div class="container-fluid">
          
                  <div class="row">
                      <nav class="navbar navbar-inverse navbar-fixed-top">
                          <a class="navbar-brand" href="http://mhtclub.com">我的個人主頁</a>
                          <button class="navbar-toggle" data-toggle="collapse" data-target="#collapseMenu">
                              <span class="icon-bar"></span>
                              <span class="icon-bar"></span>
                              <span class="icon-bar"></span>
                          </button>
                          <div class="collapse navbar-collapse" id="collapseMenu">
                              <ul class="nav navbar-nav">
                                  <li class="nav-li">
                                      <a href="https://github.com/hellowHuaairen/kuaidi" target="_blank">本項目github</a>
                                  </li>
                              </ul>
                          </div>
                      </nav>
                  </div>
          
                  <h1 class="page-header">
                      快遞單號自助查詢
                  </h1>
          
                  <!-- 查詢工具欄 -->
                  <div class="form-inline">
                      <div class="form-group">
                          <label for="queryNameText">收件人姓名:</label>
                          <input id="queryNameText" class="form-control input-sm">
                      </div>
                      <div class="form-group">
                          <label for="queryPhoneText">收件人電話:</label>
                          <input id="queryPhoneText" class="form-control input-sm">
                      </div>
                      <button class="btn btn-primary btn-sm" id="queryBtn">查詢</button>
                      <button class="btn btn-primary btn-sm" id="resetBtn">重置</button>
                      <button class="btn btn-primary btn-sm" id="addBtn">新增</button>
                  </div>
                  <hr>
          
                  <table id="testTable"></table>
          
                  <!-- 查看訂單信息模態窗 -->
                  <div class="modal fade" id="viewModal">
                      <div class="modal-dialog">
                          <div class="modal-content">
                              <div class="modal-header">
                                  <button type="button" class="close" data-dismiss="modal">×</button>
                                  <h4 class="modal-title">訂單信息</h4>
                              </div>
                              <div class="modal-body" id="viewDataList"></div>
                              <div class="modal-footer">
                                  <button class="btn btn-default" data-dismiss="modal">關閉</button>
                              </div>
                          </div>
                      </div>
                  </div>
                  <!-- 新增模態窗 -->
                  <div class="modal fade" id="addModal">
                      <div class="modal-dialog">
                          <div class="modal-content">
                              <div class="modal-header">
                                  <button type="button" class="close" data-dismiss="modal">×</button>
                                  <h4 class="modal-title">新增信息</h4>
                              </div>
                              <div class="modal-body">
                                  <div class="form-inline">
          
                                  </div>
                                  <div class="form-group">
                                      <label for="addNameText">收件人姓名:</label>
                                      <input id="addNameText" class="form-control input-sm">
                                  </div>
                                  <div class="form-group">
                                      <label for="addPhoneText">收件人電話:</label>
                                      <input id="addPhoneText" class="form-control input-sm">
                                  </div>
                                  <div class="form-group">
                                      <label for="addKuaiDiNoText">快遞單號:</label>
                                      <input id="addKuaiDiNoText" class="form-control input-sm">
                                  </div>
                                  <div class="form-group">
                                      <label for="addCompanyText">快遞公司(拼音):</label>
                                      <input id="addCompanyText" class="form-control input-sm">
                                  </div>
                              </div>
                              <div class="modal-footer">
                                  <button class="btn btn-default" data-dismiss="modal">關閉</button>
                                  <button class="btn btn-primary" id="saveAdd">保存</button>
                              </div>
                          </div>
                      </div>
                  </div>
          
                  <!-- 修改模態窗 -->
                  <div class="modal fade" id="modifyModal">
                      <div class="modal-dialog">
                          <div class="modal-content">
                              <div class="modal-header">
                                  <button type="button" class="close" data-dismiss="modal">×</button>
                                  <h4 class="modal-title">修改信息</h4>
                              </div>
                              <div class="modal-body">
                                  <div class="form-inline">
          
                                  </div>
                                  <div class="form-group">
                                      <label for="modifyNameText">收件人姓名:</label>
                                      <input id="modifyNameText" class="form-control input-sm">
                                  </div>
                                  <div class="form-group">
                                      <label for="modifyPhoneText">收件人電話:</label>
                                      <input id="modifyPhoneText" class="form-control input-sm">
                                  </div>
                                  <div class="form-group">
                                      <label for="modifyKuaiDiNoText">快遞單號:</label>
                                      <input id="modifyKuaiDiNoText" class="form-control input-sm">
                                  </div>
                                  <div class="form-group">
                                      <label for="modifyCompanyText">快遞公司(拼音):</label>
                                      <input id="modifyCompanyText" class="form-control input-sm">
                                  </div>
                              </div>
                              <div class="modal-footer">
                                  <button class="btn btn-default" data-dismiss="modal">關閉</button>
                                  <button class="btn btn-primary" id="saveModify">保存</button>
                              </div>
                          </div>
                      </div>
                  </div>
              </div>  <!-- container-fluid -->
          
              <script type="text/javascript" src="js/admin.js"></script>
          </body>
          </html>

          admin.js 這里說明一下前端我引入的jQuery,包括新增,修改,刪除,查詢的功能,查詢事件添加了對電話號碼的必填校驗。

          var $testTable = $('#testTable');
          $testTable.bootstrapTable({
              url: 'getList',
              queryParams: function (params) {
                  return {
                      offset: params.offset,
                      limit: params.limit,
                      userName: $('#queryNameText').val(),
                      phone: $('#queryPhoneText').val()
                  }
              },
              columns: [{
                  field: 'id',
                  title: '編號'
              }, {
                  field: 'userName',
                  title: '收件人姓名'
              }, {
                  field: 'phone',
                  title: '收件人電話'
              },  {
                  field: 'company',
                  title: '快遞公司'
              },{
                  field: 'kuaidiNo',
                  title: '快遞單號',
                  formatter: function (value, row, index) {
                      return [
          				'<a onclick="kuaidiRecordInfo(' + "'" + row.kuaidiNo + "','" + row.company + "')" + '">' + row.kuaidiNo +'</a>',
                      ].join('');
                  },
              }, {
                  formatter: function (value, row, index) {
                      return [
                          '<a href="javascript:modifyKuaiDi(' + row.id + ",'" + row.userName + "'," + row.phone + ",'" + row.kuaidiNo + "'" + ')">' +
                              '<i class="glyphicon glyphicon-pencil"></i>修改' +
                          '</a>',
                          '<a href="javascript:delKuaiDi(' + row.id + ')">' +
                              '<i class="glyphicon glyphicon-remove"></i>刪除' +
                          '</a>'
                      ].join('');
                  },
                  title: '操作'
              }],
              striped: true,
              pagination: true,
              sidePagination: 'server',
              pageSize: 10,
              pageList: [5, 10, 25, 50, 100],
              rowStyle: function (row, index) {
                  var ageClass = '';
                  if (row.age < 18) {
                      ageClass = 'text-danger';
                  }
                  return {classes: ageClass}
              },
          });
          
          // 設置bootbox中文
          bootbox.setLocale('zh_CN');
          
          var titleTip = '提示';
          
          function kuaidiRecordInfo(no, company) {
              $('#viewModal').modal('show');
              $.ajax({
                  type:'get',
                  url:'getKuaiDiInfoByJson?com='+ company +'&no=' + no,
                  cache:false,
                  dataType:'json',
                  success:function(result){
                      // 顯示詳細信息 發送請求通過單號
          			$("#viewDataList").empty();
                      console.log(result.data);
                      var dataList = result.data;
                      if(null != dataList){
          				$("#viewDataList").append('<li class="accordion-navigation"><a href="#kuaidi'+ '">快遞單號:'+ result.nu +'</a><div id="kuaidi'+ '" class="content"></div></li>');
          				$("#kuaidi").append('<section class="result-box"><div id="resultTop" class="flex result-top"><time class="up">時間</time><span>地點和跟蹤進度</span></div><ul id="reordList'+'" class="result-list sortup"></ul></section>');  
                          for(var i=0;i<dataList.length; i++){
                              var kuaiRecodList = dataList[i];
                              if( i == 0){
                                  $("#reordList").append('<li class="last finish"><div class="time"> '+ kuaiRecodList.ftime + '</div><div class="dot"></div><div class="text"> '+ kuaiRecodList.context +'</div></li>');
                              }else{
                                  $("#reordList").append('<li class=""><div class="time"> '+ kuaiRecodList.ftime + '</div><div class="dot"></div><div class="text"> '+ kuaiRecodList.context +'</div></li>');
                              }
                          }
                      }
                  }
              });
          }
          
          // 驗證姓名和地址是否為空
          function verifyNameAndAddress(name, address) {
              if (name != '' && address != '') {
                  return true;
              }
              return false;
          }
          
          function nullAlert() {
              bootbox.alert({
                  title: titleTip,
                  message: '所有項均為必填!'
              });
          }
          
          // 點擊查詢按鈕
          $('#queryBtn').click(function () {
              var age = $('#queryAgeText').val();
              // 刷新并跳轉到第一頁
              $testTable.bootstrapTable('selectPage', 1);
          
          });
          
          // 點擊重置按鈕,清空查詢條件并跳轉回第一頁
          $('#resetBtn').click(function() {
              $('.form-group :text').val('');
              $testTable.bootstrapTable('selectPage', 1);
          });
          
          // 用于修改服務器資源
          function exchangeData(path, id, userName, phone, kuaiDiNo, company) {
              $.ajax({
                  url: path,
                  type: 'post',
                  data : {
                      id: id,
                      userName: userName,
                      phone: phone,
                      kuaiDiNo: kuaiDiNo,
                      company: company
                  },
                  success: function(res) {
                      bootbox.alert({
                          title: titleTip,
                          message: res.message
                      });
                      // 在每次提交操作后返回首頁
                      $testTable.bootstrapTable('selectPage', 1);
                  }
              });
          }
          
          // 新增
          $('#addBtn').click(function() {
              $('#addNameText').val('');
              $('#addPhoneText').val('');
              $('#addKuaiDiNoText').val('');
          	   $('#addCompanyText').val('');
              $('#addModal').modal('show');
          });
          
          $('#saveAdd').click(function() {
              $('#addModal').modal('hide');
              bootbox.confirm({
                  title: titleTip,
                  message: '確認增加?',
                  callback: function (flag) {
                      if (flag) {
                          var userName = $('#addNameText').val();
                          var phone = $('#addPhoneText').val();
                          var kuaiDiNo = $('#addKuaiDiNoText').val();
                          var company = $('#addCompanyText').val();
                          if (verifyNameAndAddress(userName, kuaiDiNo)) {
                              exchangeData('addKuaiDi', null, userName, phone, kuaiDiNo, company);
                          } else {
                              nullAlert();
                          }
                      }
                  }
              });
          });
          
          var mid;
          
          // 修改
          function modifyKuaiDi(id, name, age, address) {
              mid = id;
              $('#modifyNameText').val(name);
              $('#modifyPhoneText').val(age);
              $('#modifyKuaiDiNoText').val(address);
          	$('#modifyCompanyText').val(address);
              $('#modifyModal').modal('show');
          }
          
          $('#saveModify').click(function() {
              $('#modifyModal').modal('hide');
              bootbox.confirm({
                  title: titleTip,
                  message: '確認修改?',
                  callback: function (flag) {
                      if (flag) {
                          var userName = $('#modifyNameText').val();
                          var phone = $('#modifyPhoneText').val();
                          var kuaiDiNo = $('#modifyKuaiDiNoText').val();
                          var company = $('#modifyCompanyText').val();
                          if (verifyNameAndAddress(userName, phone)) {
                              exchangeData('modifyKuaiDi', mid, userName, phone, kuaiDiNo, company);
                          } else {
                              nullAlert();
                          }
                      }
                  }
              });
          });
          
          // 刪除
          function delKuaiDi(id) {
              bootbox.confirm({
                  title: titleTip,
                  message: '確認刪除?',
                  callback: function(flag) {
                      if (flag) {
                          exchangeData("delKuaiDi", id);
                      }
                  }
              });
          

          2.4運行項目

          修改配置文件 項目配置文件src/resources/application.properties,根據實際情況修改對應的數據庫連接信息。

          #MySQL配置
          spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
          spring.datasource.url=jdbc:mysql://localhost:3306/kuaidi?useUnicode=true&characterEncoding=UTF-8
          spring.datasource.username=root #數據庫賬號
          spring.datasource.password=root #數據庫密碼
          #MyBatis日志配置
          mybatis.mapperLocations=classpath:mapper/*.xml
          mybatis.config-location=classpath:/config/mybatis-config.xml
          #端口配置
          server.port=8082
          
          # 定位模板的目錄
          spring.mvc.view.prefix=classpath:/templates/
          # 給返回的頁面添加后綴名
          spring.mvc.view.suffix=.html

          創建數據庫表 表結構如下:

          DROP TABLE IF EXISTS `kuaidi`;
          CREATE TABLE `kuaidi`  (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人姓名',
            `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人電話',
            `kuaidi_no` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '快遞單號',
            `company` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '快遞公司名稱拼音',
            `create_time` datetime(0) NULL DEFAULT NULL,
            PRIMARY KEY (`id`) USING BTREE
          ) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

          運行 將項目導入Idea工具,找到com.wangzg.kuaidi.KuaiDiApplication文件,執行main方法即可,如下圖:

          三、部署

          3.1 jar部署

          上傳安裝包 在服務器創建/usr/myworkspace,執行下面命令可直接創建:

          mkdir -p /usr/myworkspace
          復制代碼

          下載相關文件,上傳到服務器/usr/myworkspace。下載地址:github.com/hellowHuaai… 文件主要包括:

          • application.properties 說明:項目配置文件,可能會涉及到修改服務器端口,數據庫訪問、端口、賬號、密碼等。
          • kuaidi.jar 說明:后端服務的可執行jar文件。
          • kuaidi.sql 說明:數據庫初始化腳本。
          • start.sh 說明: 啟動服務器shell腳本。
          • stop.sh 說明: 停止服務器shell腳本。

          初始化數據庫 打開Navicat工具,選中數據庫,右鍵選擇運行SQL文件...,具體操作,這樣數據庫就初始化完成。

          運行項目
          在服務器/usr/myworkspace目錄下,執行如下命令,即可運行項目:

          chmod +x *.sh #給所有 .sh文件添加執行權限
          ./start.sh

          3.2 Docker部署

          Docker 容器化部署項目,需要創建一個 mysql 的容器,創建kuaidi的容器,再初始化一下數據庫。

          創建數據庫容器 代碼如下:

          docker run -d --name mysql5.7 -e MYSQL_ROOT_PASSWORD=root -it -p 3306:3306 daocloud.io/library/mysql:5.7.7-rc

          導入數據庫腳本 數據庫腳本kuaidi.sql內容如下:

          create DATABASE kuaidi;
          use kuaidi;
          
          SET NAMES utf8mb4;
          SET FOREIGN_KEY_CHECKS = 0;
          
          DROP TABLE IF EXISTS `kuaidi`;
          CREATE TABLE `kuaidi`  (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人姓名',
            `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人電話',
            `kuaidi_no` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '快遞單號',
            `company` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '快遞公司名稱拼音',
            `create_time` datetime(0) NULL DEFAULT NULL,
            PRIMARY KEY (`id`) USING BTREE
          ) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

          然后執行下面命令,就可以導入kuaidi.sql腳本:

          docker exec -i mysql5.7 mysql -uroot -proot mysql < kuaidi.sql

          創建kuaidi容器 執行下面命令就可以創建容器:

          docker run -d -p 9082:8082 -v application.properties:/home/conf/application.properties --name kuaidi1 huaairen/kuaidi:latest

          注:application.properties文件為項目的配置文件,在src/main/resources目錄下;huaairen/kuaidi:latest是我打包好的鏡像,直接下載就可以。

          四、最后

          項目功能還特別簡陋,很多功能需要開發和完善。如果你也遇到類似的問題我們可以一起討論,合作共贏哦!

          作者:不安分的猿人

          鏈接:https://juejin.im/post/5e9313ece51d4546c62f9ac4

          來源:掘金


          主站蜘蛛池模板: 日本精品一区二区在线播放| 91精品国产一区| 国产无线乱码一区二三区| 2018高清国产一区二区三区| 在线视频一区二区三区四区| 无码av免费一区二区三区试看| 国产精品成人免费一区二区| 日韩一区二区电影| 亚洲一区免费观看| 精品人妻中文av一区二区三区| 无码精品前田一区二区| 乱人伦一区二区三区| 国产在线观看一区二区三区四区| 亚洲欧洲∨国产一区二区三区| 一区二区三区电影网| 另类国产精品一区二区| 三级韩国一区久久二区综合| 一区二区三区美女视频| 国产激情一区二区三区成人91| 久久久久人妻一区二区三区vr| 日本内射精品一区二区视频 | 国产日韩精品一区二区在线观看| 一区二区三区观看免费中文视频在线播放 | 亚洲av乱码一区二区三区按摩 | 成人区人妻精品一区二区三区 | 日本一区二区视频| 精品动漫一区二区无遮挡| 亚洲国产高清在线一区二区三区| 亚洲日韩一区精品射精| 日本一区精品久久久久影院| 精品无码一区二区三区在线| 中文字幕永久一区二区三区在线观看 | 最新欧美精品一区二区三区 | 国产AⅤ精品一区二区三区久久 | 熟女少妇丰满一区二区| 人妻体内射精一区二区| 亚洲色精品VR一区区三区| 国产免费一区二区三区不卡| 亚洲AV无码一区二区乱子仑| 国产av天堂一区二区三区| 福利视频一区二区牛牛 |