<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          首頁

          你真的了解重排和重繪嗎?

          前端達人

          做過前端開發的小伙伴就算不是非常理解重排與重繪,但是肯定都聽過這兩個詞。那為什么這兩個東西這么重要?因為他與我們的頁面性能息息相關,今天,我們就來好好研究一下這兩個東西。



          瀏覽器的渲染流程

          在講解重排和重繪之前,我們有必要說一下瀏覽器的渲染流程。下面是瀏覽器渲染過程中最關鍵的幾個部分。如果想了解完整的瀏覽器渲染流程,推薦大家去閱讀李兵老師的瀏覽器工作原理實踐,需要付費閱讀。后期我也會整理一下再出一篇博客詳細介紹瀏覽器的渲染過程。


          點擊查看原圖


          JavaScript:一般來說,我們會使用 JavaScript 來實現一些視覺變化的效果。比如用 jQuery 的 animate 函數做一個動畫、對一個數據集進行排序或者往頁面里添加一些 DOM 元素等。當然,除了 JavaScript,還有其他一些常用方法也可以實現視覺變化效果,比如:CSS Animations、Transitions 和 Web Animation API。
          樣式計算:此過程是根據匹配選擇器(例如 .headline 或 .nav > .nav__item)計算出哪些元素應用哪些 CSS 規則的過程。從中知道規則之后,將應用規則并計算每個元素的最終樣式。
          布局:在知道對一個元素應用哪些規則之后,瀏覽器即可開始計算它要占據的空間大小及其在屏幕的位置。網頁的布局模式意味著一個元素可能影響其他元素,例如 元素的寬度一般會影響其子元素的寬度以及樹中各處的節點,因此對于瀏覽器來說,布局過程是經常發生的。
          繪制:繪制是填充像素的過程。它涉及繪出文本、顏色、圖像、邊框和陰影,基本上包括元素的每個可視部分。繪制一般是在多個表面(通常稱為層)上完成的。
          合成:由于頁面的各部分可能被繪制到多層,由此它們需要按正確順序繪制到屏幕上,以便正確渲染頁面。對于與另一元素重疊的元素來說,這點特別重要,因為一個錯誤可能使一個元素錯誤地出現在另一個元素的上層。
          其中,重排和重繪影響的就是其中的布局和繪制過程。

          什么是重排和重繪制
          重排:當DOM的變化引發了元素幾何屬性的變化,比如改變元素的寬高,元素的位置,導致瀏覽器不得不重新計算元素的幾何屬性,并重新構建渲染樹,這個過程稱為“重排”。
          重繪:完成重排后,要將重新構建的渲染樹渲染到屏幕上,這個過程就是“重繪”。
          簡單來說,涉及元素的幾何更新時,叫重排。而只涉及樣式更新而不涉及幾何更新時,叫重繪。對于兩者來說,重排必定引起重繪,但是重繪并不一定引起重排。所以,當涉及重排時,瀏覽器會將上述的步驟再次執行一遍。當只涉及重繪時,瀏覽器會跳過Layout步驟,即:


          點擊查看原圖


          而如果既不需要重排,也不需要重繪,那么就是下面這樣:


          點擊查看原圖



          瀏覽器會直接跳到合成階段。顯然,對于頁面性能來說,不重排也不重繪 > 重繪 > 重排。

          什么操作會引起重排和重繪
          顯然,觸發重排的一般都是幾何因素,這是比較好理解的:

          頁面第一次渲染 在頁面發生首次渲染的時候,所有組件都要進行首次布局,這是開銷最大的一次重排
          瀏覽器窗口尺寸改變
          元素位置和尺寸發生改變的時候
          新增和刪除可見元素
          內容發生改變(文字數量或圖片大小等等)
          元素字體大小變化
          還有其他一些操作也可能引發重排

          查詢某些屬性或調用某些方法
          offset(Top|Left|Width|Height)
          scroll(Top|Left|Width|Height)
          client(Top|Left|Width|Height)
          getComputedStyle()
          我們可能不太理解為什么這些操作也能引起重排,這里我先簡單解釋一下。因為現在的瀏覽器已經非常完善了,會自動幫我們做一些優化。當我們用js操作DOM的時候,瀏覽器并不是立馬執行的,而是將操作存儲在一個隊列中。當達到一定數量或者經過一定時間以后瀏覽器再統一的去執行隊列中的操作。那么回到我們剛才的問題,為什么查詢這些屬性也會導致重排?因為當你查詢這些屬性時,瀏覽器就會強制刷新隊列,因為如果不立馬執行隊列中的操作,有可能得到的結果就是錯誤的。所以相當于你強制打斷了瀏覽器的優化流程,引發了重排。下面我們通過一些小例子來進一步理解這段話:

          首先我們來一個顯然會引發重排的操作

          <!DOCTYPE html>
          <html lang="en">
          <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Document</title>
            <style>
              #test {
                width: 100px;
                height: 100px;
                background-color: red;
                position: relative;
              }
            </style>
          </head>
          <body>
            <div id="test">
          
            </div>
            <button onclick="reflow()">click</button>
            <script>
              function reflow() {
                var div = document.querySelector("#test");
                div.style.left = '200px';
              }
            </script>
          </body>
          </html>
          



          把時間軸往后拉,可以看到這幾個過程,先簡單介紹一些這些名詞代表的含義:

          Recalculate Style:這個過程就是生成CSSOM的過程
          Layout:這就是布局階段,即重排的過程
          Update Layer Tree:這個階段是更新層樹的過程
          Paint:該階段是為每一層準備繪制列表的過程
          Composite Layers:該階段是利用繪制列表來生成相應圖層的位圖了,還涉及到合成線程和光柵化,performence面板中的Raster就是光柵化線程池 。
          這里只做一個簡單的介紹,對其中內容不太明白的同學可以參考李兵老師的文章或者在我的下一篇介紹瀏覽器渲染過程的文章中會詳細解釋。

          那通過這個圖我們可以看到,我們改變了div的left之后就觸發了Layout,即重排的過程。下面我們僅改變div的背景顏色,給大家一個對比。


          即不重排也不重繪
          說完了重排和重繪,不要忘記我們最開始提到的,最的方式就是跳過重排和重繪階段。你可能會想,什么情況下可以做到這一點?其實這就是我們平時說的GPU加速,具體是如何實現呢?在開發過程中,如果我們使用了某些屬性,瀏覽器會幫助我們將使用了該屬性的div提升到一個單獨的合成層,而在后面的渲染中,提升到該層的div將跳過重排和重繪的操作,直接到合成階段。在stack overflow上有問題提到了這塊內容。我們翻譯一下就是:
          下面幾個屬性能讓瀏覽器幫助我們將div提升到一個單獨的合成層:

          圖層具有3D或透視變換CSS屬性
          使用加速視頻解碼的 video 元素
          擁有 3D(WebGL) 上下文或者加速 2D 上下文的 canvas 元素
          混合插件(Flash)
          對自己的 opacity 做 CSS 動畫或使用一個動畫 webkit 變換的元素
          圖層使用加速的CSS過濾器
          層具有作為合成層的后代
          圖層具有較低z索引的同級元素,該同級元素具有合成層(換句話說,該層在合成層的頂部渲染)
          css will-change屬性
          最后一點是我加上去的,同時根據文中的內容我們可以知道,css3硬件加速是瀏覽器的行為,所以在不同瀏覽器下可能會有不同的表現形式。下面我們用一個例子來理解一下。這是李兵老師在他的專欄中提出的一個例子,我拿過來借用一下,注意box中的will-change屬性:

          <html>
          
            <head>
                <title>觀察will-change</title>
                <style>
                    .box {
                        will-change: transform, opacity;
                        display: block;
                        float: left;
                        width: 40px;
                        height: 40px;
                        margin: 15px;
                        padding: 10px;
                        border: 1px solid rgb(136, 136, 136);
                        background: rgb(187, 177, 37);
                        border-radius: 30px;
                        transition: border-radius 1s ease-out;
                    }
          
                    body {
                        font-family: Arial;
                    }
                </style>
            </head>
          
            <body>
                <div id="controls">
                    <button id="start">start</button>
                    <button id="stop">stop</button>
                </div>
                <div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                    <div class="box">旋轉盒子</div>
                </div>
                <script>
          
                    let boxes = document.querySelectorAll('.box');
                    let boxes1 = document.querySelectorAll('.box1');
                    let start = document.getElementById('start');
                    let stop = document.getElementById('stop');
                    let stop_flag = false
          
                    start.addEventListener('click', function () {
                        stop_flag = false
                        requestAnimationFrame(render);
                    })
          
                    stop.addEventListener('click', function () {
                        stop_flag = true
                    })
          
                    let rotate_ = 0
                    let opacity_ = 0
                    function render() {
                        if (stop_flag)
                            return 0
                        rotate_ = rotate_ + 6
                        if (opacity_ > 1)
                            opacity_ = 0
                        opacity_ = opacity_ + 0.01
                        let command = 'rotate(' + rotate_ + 'deg)';
                        for (let index = 0; index < boxes.length; index++) {
                            boxes[index].style.transform = command
                            boxes[index].style.opacity = opacity_
                        }
                        requestAnimationFrame(render);
                    }
                </script>
            </body>
          
            </html>
          



          ————————————————
          版權聲明:本文為CSDN博主「溪寧」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
          原文鏈接:https://blog.csdn.net/qq_38164763/article/details/105406580

          【CSS基礎學習】復雜選擇器

          前端達人

          文章目錄

            • CSS第二課-復雜選擇器
              • 群組選擇器
              • 屬性選擇器
              • 派生選擇器
              • CSS第二課-復雜選擇器

                群組選擇器

                格式

                選擇器1,選擇器2,,,選擇器n{聲明的屬性和屬性值}

                p,h1{
                    color: blue;
                }


                用于對于多個選擇器進行樣式修改,由簡單選擇器組合而成的選擇器,可以是簡單選擇器中的任意組合,如上面代碼例,就是修改了p標簽和h1標簽的字體顏色。

                屬性選擇器

                根據屬性名查找元素

                格式

                元素[屬性名]{
                    聲明的屬性和屬性值;
                }


                p[id]{
                    color: blue;
                }


                前面添加元素的名字,然后后面加上屬性名,比如上例,就是p標簽,其中帶有id的元素,然后把字體顏色設置為藍色。

                根據屬性值查找

                格式

                元素[屬性名=屬性值]{
                    聲明的屬性和屬性值;
                }


                p[class = 'p2']{
                    color: blue;
                }


                和上面的根據屬性名查找差不多,只不過更加了,到了屬性名后面的屬性值,上例就是作用于p標簽,只不過條件是為帶有class屬性,并且屬性值為p2的p標簽。

                多屬性選擇器

                格式


                元素[屬性名或屬性表達式][屬性名或屬性表達式]..{
                    聲明的屬性和屬性值;
                }
                p[title][class]{
                    color: blue;
                }



                元素后面加。屬性名或屬性表達式,可以加+∞個,但是沒必要。上例為:設置title屬性和class屬性的段落p標簽的樣式

                根據屬性值近似查找

                格式


                元素[元素名~=屬性值]{
                    聲明的屬性和屬性值;
                }


                元素[屬性名|=值]{
                    聲名的屬性和屬性值;
                }


                p[class~='red']{
                    color: blue;
                }



                注意,這里是~=,為約等于,就是找滿足符合約等于條件的標簽,上例為:設置class屬性的值,包含red屬性名的標簽

                根據標簽查找

                格式


                元素名1~元素名2{
                    聲名的屬性和屬性值;
                }


                a~p{
                    color: blue;
                }


                a標簽后面的每一個p標簽,都進行了樣式的修改。

                派生選擇器

                后代選擇器

                格式


                父類標簽 子類標簽{ /*注意倆標簽中間有空格*/
                    聲名的屬性和屬性值;
                }


                div strong{
                    color: blue;
                }


                相鄰兄弟選擇器

                格式


                父標簽+子標簽{
                    聲名的屬性和屬性值;
                }


                #div1 + p{
                    color: blue;
                }


                相鄰兄弟選擇器可選擇緊接在另一個元素后的元素,且二者具有相同的父親元素。注釋:與子結合符一樣,相鄰兄弟結合符旁邊可以有空白符。




                ————————————————
                版權聲明:本文為CSDN博主「董小宇」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
                原文鏈接:https://blog.csdn.net/lolly1023/article/details/105413125

          uni-app uni.request接口封裝

          seo達人

          uni-app uni.request接口封裝

          今天在做uni-app項目時,發現在uni-app中 調取后臺接口需要大量的重復編輯,就在想能不能封裝一個如同Vue項目中的this.$axios.get(url,data).then();格式,這樣就減少了很多代碼重復!!

          封裝為如同this.$axios.get(url,data).then();格式

          第一步、

          我們先在index首頁中的組件部分,創建一個js文件;





          第二步、

          我們在uni-app的入口文件中引入request.js文件;

          在入口文件中掛載到uni-app實例上;





          第三步、

          開始接口封裝:

          (以下為js文件代碼)



          //先把接口暴露出去

          export default{

          //我們先定一個uni-app方法 以便于以下操作使用uni-app調取接口時便利

          request(options){

          ///我們使用Promise方法來實現調用接口時后面多個.then()的方法

          //只有Promise能實現如同$axios后面連續多個.then()的方法

          return new Promise((reslove,reject)=>{

          uni.request({

          ...options,

          success:res=>{

          //判斷我們在使用封裝的自定義時第三個參數是否為native

          //當native為true時 我們返回原數據

          if(options.native){

          reslove(res)

          }

          //當native為false時 我們直接返回data中的數據

          if(res.statusCode === 200){

          reslove(res.data)

          }else{

          //加入接口參數錯誤或接口地址錯誤時 我們返回原錯誤提示

          reject(res)

          }

          }

          })

          })

          },

          //在方法中 第二個參數和第三個參數用ES6新語法來添加默認值

          //接口調取get方法

          get(url,data={},options={}){

          //我們把傳過來的參數賦給options,這樣我們在使用uni-app

          //this.request()方法時 傳遞一個參數就可以

          options.url = url;

          options.data = data;

          options.method = 'get';

          //調用上面自己定義的this.request()方法傳遞參數

          return this.request(options)

          },

          //接口調取post方法

          post(url,data={},options={}){

          options.url = url;

          options.data = data;

          options.method = 'post';

          return this.request(options)

          }

          }



          這樣我們就已經封裝完成啦,接下來就是 在頁面內使用!

          第四步、

          我們可以在頁面中來調取已經封裝好的自定義事件啦



          例一:

          個人建議使用ES6新語法 箭頭函數 不然使用this還要重新在外面聲明定義,太麻煩了,使用箭頭函數就會方便很多



          // 已封裝好的接口方法

          //本案例調取接口時 沒有參數上傳 直接調用的

          //這樣使用方法時只傳遞了一個參數,也就是接口地址

          //第二個參數沒有寫,默認為空;假如有參數的話 可以直接填寫

          //后面的參數都為接口內已經定義好的默認值:{}空對象

          //里面的res為接口返回數據中的data里面的內容

          this.$H.get('/api/getIndexCarousel.jsp').then(res=>{

          //res打印出來是接口返回數據中data里面的數據

          console.log(res)

          //賦給數據區的變量,方便本頁面使用

          this.swiperData = res

          });



          例二、



          // 已封裝好的接口方法

          //本案例使用時 傳遞了三個參數

          //第一個為:接口地址

          //第二個為:調取接口傳遞的參數,方法使用時不用傳參,寫空對象就好

          //第三個為:自定義事件中 native 的屬性 若為true 則返回原數據

          //若想返回原數據,必須要填寫第二個參數,若沒有參數,也要寫空對象

          //因為方法調用時 是按照傳參順序調用的,若不寫 參數傳遞就會出錯

          this.$H.get('/api/getIndexCarousel.jsp',{},{

          native:true

          }).then(res=>{

          //res打印出來的數據是接口返回來的原數據

          console.log(res)

          //賦給數據區的變量,方便本頁面使用

          this.swiperData = res

          });




          每天學習一個Android中的常用框架——1.Litepal

          seo達人

          文章目錄

          1.簡介

          2.特性

          3.演示

          3.1 集成

          3.2 配置

          3.3 創建數據庫

          3.4 升級數據庫

          3.5 插入數據

          3.6 查詢數據

          3.7 更新數據

          3.8 刪除數據

          4.版本異同

          5.源碼地址

          1.簡介

          Litepal——作為帶我入行的第一本教學書籍《Android第一行代碼》的作者郭霖老師所寫出來的持久化框架,幾乎算是我接觸Android世界之后第一個遇到的框架,故將該框架列為一系列學習框架博客的首位。

          根據Litepal的GitHub主頁:Litepal,可以看到該框架的一些簡介:



          LitePal is an open source Android library that allows developers to use SQLite database extremely easy. You can finish most of the database operations without writing even a SQL statement, including create or upgrade tables, crud operations, aggregate functions, etc. The setup of LitePal is quite simple as well, you can integrate it into your project in less than 5 minutes.



          事實上,正如這段簡介所說,集成Litepal相當簡單,不需要超過五分鐘時間。使用Litepal,也適合對sql語言還不熟悉的開發者快速上手。



          2.特性

          讓我們繼續瀏覽Litepal的GitHub主頁,可以發掘Litepal的一些特性:



          Using object-relational mapping (ORM) pattern.

          Almost zero-configuration(only one configuration file with few properties).

          Maintains all tables automatically(e.g. create, alter or drop tables).

          Multi databases supported.

          Encapsulated APIs for avoiding writing SQL statements.

          Awesome fluent query API.

          Alternative choice to use SQL still, but easier and better APIs than the originals.

          More for you to explore.

          用大白話來描述的話,可以列舉如下:



          Litepal使用了ORM(對象關系映射)模型

          Litepal幾乎是無配置的,僅需極少的配置文件

          Litepal幾乎包括所有的CRUD操作,也支持多張表格的操作

          Litepal可以僅調用api進行CRUD操作而避免編寫sql語句

          總之,看到Litepal具有這么多良好的特性,讀者是否心動了呢。理論的話不多說,我們現在就開始正式地使用Litepal進行數據庫的相關操作

          PS:如果有曾經學習過Java的ORM框架——Mybatis的讀者,應該不會對Litepal的使用太陌生,因為它們都使用了xml文件進行相應的配置



          3.演示

          3.1 集成

          現在Android框架的集成相比于IDE還為ADT的時代,要方便了許多。原因是現在的主流IDE是Android Studio,而AS默認使用了Gradle進行版本的配置管理,這讓集成框架變得簡單了許多。

          在build.gradle下,添加以下語句,然后重新sync,即可將Litepal集成到你的項目中:



          implementation 'org.litepal.android:java:3.0.0'

          1

          當然,目前Android的主流開發語言,除了Java之外,還有Kotlin,Litepal同樣具有Kotlin版本的(這里的演示僅針對Java,Kotlin版本的異曲同工)依賴:



          implementation 'org.litepal.android:kotlin:3.0.0'

          1

          可以根據個人需求進行配置。



          3.2 配置

          集成了Litepal之后,要想正式使用它還需要進行一些配置



          在assets目錄下新建litepal.xml,作為Litepal的全局配置文件,相應的條目信息已作出注釋,代碼如下:

          <?xml version="1.0" encoding="utf-8"?>

          <litepal>

              <!--  數據庫名  -->

              <dbname value="androidframelearn"/>



              <!--  數據庫版本號  -->

              <version value="1"/>



              <!--  指定映射模型  -->

              <list>

                 

              </list>



              <!--  指定文件的存儲方式  -->

              <!--  <storage value="external" />-->

          </litepal>



          在你的應用下配置Litepal,有兩種方式可以實現:

          修改清單文件,將你的應用名修改為:android:name="org.litepal.LitePalApplication"

          新建一個自己寫的MyOwnApplication類,然后將清單文件中的應用名定位到該類,即:android:name="com.example.MyOwnApplication",然后再編寫MyOwnApplication類,代碼如下:

          public class MyOwnApplication extends Application {



          @Override

          public void onCreate() {

              super.onCreate();

              LitePal.initialize(this);

          }

          ...

          }



          兩種方式亦可,Litepal的作者建議若使用第二種方式,需要盡快地調用LitePal.initialize(this);所以將其放在onCreate()方法是最好的。



          3.3 創建數據庫

          剛才在介紹的時候已經說過,Litepal采取的是對象關系映射(ORM)的模式,那么什么是對象關系映射呢?簡單點說,我們使用的編程語言是面向對象語言,而使用的數據庫則是關系型數據庫,那么將面向對象的語言和面向關系的數據庫之間建立一種映射關系,這就是對象關系映射了。

          不過你可千萬不要小看對象關系映射模式,它賦予了我們一個強大的功能,就是可以用面向對象的思維來操作數據庫,而不用再和SQL語句打交道了,不信的話我們現在就來體驗一下。像往常使用SQLiteOpenHelper類,為了創建一張Book表需要先分析表中應該包含哪些列,然后再編寫出一條建表語句,最后在自定義的SQLiteOpenHelper中去執行這條建表語句。但是使用LitePal,你就可以用面向對象的思維來實現同樣的功能了,定義一個Book類,代碼如下所示:



          package com.androidframelearn.dao_litapal;



          import org.litepal.crud.LitePalSupport;



          public class Book extends LitePalSupport {

              private int id;

              private String author;

              private double price;

              private int pages;

              private String name;

              public int getId(){

                  return id;

              }

              public void setId(int id){

                  this.id = id;

              }



              public String getAuthor(){

                  return author;

              }

              public void setauthor(String author){

                  this.author = author;

              }



              public double getPrice(){

                  return price;

              }

              public void setPrice(double price){

                  this.price = price;

              }



              public int getPages(){

                  return pages;

              }

              public void setPages(int pages){

                  this.pages = pages;

              }



              public String getName(){

                  return name;

              }

              public void setName(String name){

                  this.name = name;

              }

          }



          這里使用標簽來聲明我們要配置的映射模型類,注意一定要使用完整的類名。不管有多少模型類需要映射,都使用同樣的方式配置在標簽下即可。

          沒錯,這樣就已經把所有工作都完成了,現在只要進行任意一次數據庫的操作,BookStore.db數據庫應該就會自動創建出來。為了更好地演示代碼,我們將布局文件所需要的功能一次性編寫好,activity_main.xml代碼如下:



          <?xml version="1.0" encoding="utf-8"?>

          <LinearLayout 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"

              tools:context=".MainActivity"

              android:orientation="vertical">



              <Button

                  android:id="@+id/btn_db_create"

                  android:layout_width="match_parent"

                  android:layout_height="wrap_content"

                  android:text="創建數據庫"/>



              <Button

                  android:id="@+id/btn_db_query"

                  android:layout_width="match_parent"

                  android:layout_height="wrap_content"

                  android:text="查詢數據"/>



              <Button

                  android:id="@+id/btn_db_insert"

                  android:layout_width="match_parent"

                  android:layout_height="wrap_content"

                  android:text="插入數據"/>



              <Button

                  android:id="@+id/btn_db_update"

                  android:layout_width="match_parent"

                  android:layout_height="wrap_content"

                  android:text="更新數據"/>



              <Button

                  android:id="@+id/btn_db_delete"

                  android:layout_width="match_parent"

                  android:layout_height="wrap_content"

                  android:text="刪除數據"/>



          </LinearLayout>





          接下來,修改MainActivity,除了給按鈕注冊點擊事件,還需要編寫不同的方法代表不同的邏輯,其中,創建數據庫的方法代碼如下:



          private void createDBbyLitePal() {

                  btn_db_create.setOnClickListener(new View.OnClickListener() {

                      @Override

                      public void onClick(View v) {

                          Log.i(TAG,"創建數據庫成功");

                          LitePal.getDatabase();

                      }

                  });

              }



          僅僅通過點擊按鈕,調用LitePal.getDatabase();這句api,就可以創建出數據庫,讓我們實際進入項目中嘗試一下吧!點擊該按鈕,然后查看控制臺,如圖所示:



          出現該句日記,說明數據庫創建成功,接下來我們看看這個數據庫是否按照我們所設置好的格式創建出來了,進入data/data/你的項目包名/databases,即可查看到該數據庫已經放置到該目錄下,如圖所示:





          3.4 升級數據庫

          事實上,若想對現有數據庫進行升級,也是可以實現的。以前我們使用SQLiteOpenHelper來升級數據庫的方式,雖說功能是實現了,但你有沒有發現一個問題,,就是升級數據庫的時候我們需要先把之前的表drop掉,然后再重新創建才行。這其實是一個非常嚴重的問題,因為這樣會造成數據丟失,每當升級一次數據庫,之前表中的數據就全沒了。

          而使用Litepal,就可以很好地避免這個問題。假設我們現在有一張新的表Category要加進去,同樣編寫它的實體類,代碼如下:



          package com.androidframelearn.dao_litapal;



          public class Category {

              private int id;

              private String categoryName;

              private int categoryCode;

              public int getId(){

                  return id;

              }

              public void setId(int id){

                  this.id = id;

              }



              public String getCategoryName(){

                  return categoryName;

              }

              public void setCategoryName(String categoryName){

                  this.categoryName = categoryName;

              }



              public int getCategoryCode(){

                  return categoryCode;

              }

              public void setCategoryCode(int categoryCode){

                  this.categoryCode = categoryCode;

              }

          }



          改完了所有我們想改的東西,只需要記得在litepal.xml將版本號加1就行了。當然由于這里還添加了一個新的模型類,因此也需要將它添加到映射模型列表中。修改litepal.xml中的代碼,如下所示:



          <?xml version="1.0" encoding="utf-8"?>

          <litepal>

              <!--  數據庫名  -->

              <dbname value="androidframelearn"/>



              <!--  數據庫版本號  -->

              <version value="2"/>



              <!--  指定映射模型  -->

              <list>

                  <mapping class="com.androidframelearn.dao_litapal.Book"/>

                  <mapping class="com.androidframelearn.dao_litapal.Category"/>

              </list>



              <!--  指定文件的存儲方式  -->

              <!--  <storage value="external" />-->

          </litepal>



          重新運行一下程序,再次創建數據庫,就可以完美地完成數據庫的升級了。這里的調試可以使用sqlite工具,這里不再贅述。



          3.5 插入數據

          在講述本節時,首先回顧一下之前添加數據的方法,我們需要創建出一個Contentvalues對象,然后將所有要添加的數據put到這個Contentvalues對象當中,最后再調用SQLiteDatabase的insert() 方法將數據添加到數據庫表當中,步驟相當繁瑣。

          而使用LitePal來添加數據,這些操作可以簡單到讓你驚嘆!我們只需要創建出模型類的實例,再將所有要存儲的數據設置好,最后調用一下save()方法就可以了。

          同樣地,修改MainActivity,增加插入數據的事件方法,代碼如下:



          private void insertDatabyLitePal() {

                  btn_db_insert.setOnClickListener(new View.OnClickListener() {

                      @Override

                      public void onClick(View v) {

                          Book book = new Book();

                          book.setName("The Da Vinci Code");

                          book.setauthor("Dan Brown");

                          book.setPages(454);

                          book.setPrice(16.96);

                          book.save();

                          Log.i(TAG,"插入數據成功");

                      }

                  });

              }



          同樣運行程序,查看控制臺,如圖所示:



          當點擊查詢數據(下一節將介紹該邏輯)時,控制臺打印剛剛插入的數據,如圖所示:





          3.6 查詢數據

          使用Litepal同樣可以很輕易地查詢數據,當然了,由于篇幅限制,這里僅僅貼出最簡單的查詢方式,至于關聯查詢等稍復雜的查詢方式,可以去GItHub上參考Litepal的官方文檔進行相關調用即可。

          同樣地,修改MainActivity,增加查看數據的事件方法,代碼如下:



          private void queryDatabyLitePal() {

                  btn_db_query.setOnClickListener(new View.OnClickListener() {

                      @Override

                      public void onClick(View v) {

                          List<Book> books = LitePal.findAll(Book.class);

                          for (Book book : books){

                              Log.i(TAG,"查詢數據成功");

                              Log.d("MainActivity","書名是"+book.getName());

                              Log.d("MainActivity","書的作者是"+book.getAuthor());

                              Log.d("MainActivity","書的頁數是"+book.getPages());

                              Log.d("MainActivity","書的價格是"+book.getPrice());

                          }

                      }

                  });

              }



          相關的運行結果上一小節以貼出,這里不再重復。



          3.7 更新數據

          更新數據要比添加數據稍微復雜一點,因為它的API接口比較多,這里我們只介紹最常用的幾種更新方式。

          首先,最簡單的一種更新方式就是對已存儲的對象重新設值,然后重新調用save()方法即可。那么這里我們就要了解一個概念,什么是已存儲的對象?

          對于LitePal來說,對象是否已存儲就是根據調用model.isSaved()方法的結果來判斷的, 返回true就表示已存儲,返回false就表示未存儲。那么接下來的問題就是,什么情況下會返回true,什么情況下會返回false呢?

          實際上只有在兩種情況下model.isSave()方法才會返回true, 一種情況是已經調用過model. save()方法去添加數據了,此時model會被認為是已存儲的對象。另一種情況是model對象是通過LitePal提供的查詢API查岀來的,由于是從數據庫中查到的對象,因此也會被認為是已存儲的對象。

          由于查詢API相對復雜,因此只能先通過第一種情況來進行驗證。修改MainActivity中的代碼,如下所示:



          private void updateDatabyLitePal() {

                  btn_db_update.setOnClickListener(new View.OnClickListener() {

                      @Override

                      public void onClick(View v) {

                          Book book = new Book();

                          book.setName("The Lost Symbol");

                          book.setauthor("Dan Brown");

                          book.setPages(510);

                          book.setPrice(19.95); // 第一次設置商品價格

                          book.save();

                          book.setPrice(10.99); // 第二次設置商品價格

                          book.save();

                          Log.i(TAG,"更新數據成功");

                      }

                  });

              }



          可以看到,我們做了跟插入數據類似的事情,但是我們對數據的價格進行了設置,運行程序,如圖所示:



          可以看到,除了剛剛插入的數據,還有第二條剛剛更新過后的數據。然而這種更新方式只能對已存儲的對象進行操作,限制性比較大,接下來我們學習另外一種更加靈巧的更新方式,可以調用以下api:



          book.updateAll("name = ? and author = ?","The Lost Symbol","Dan Brown");

          1

          這里僅貼出其中一條api,其他的可以參考官方文檔,這里不再贅述。



          3.8 刪除數據

          使用Litepal刪除數據的方式主要有兩種,第一種比較簡單,就是直接調用已存儲對象的delete()方法就可以了,對于已存儲對象的概念,我們在之前已經學習過了。也就是說,調用過save()方法的對象,或者是通過LitePal提供的查詢API查出來的對象,都是可以直接使用delete()方法來刪除數據的。這種方式比較簡單,我們就不進行代碼演示了,下面直接來看另外一種刪除數據的方式。

          代碼如下:



          private void deleteDatabyLitePal() {

                  btn_db_delete.setOnClickListener(new View.OnClickListener() {

                      @Override

                      public void onClick(View v) {

                          LitePal.deleteAll(Book.class,"price < ?","15");

                          Log.i(TAG,"刪除成功");

                      }

                  });

              }



          運行程序,刪除過后,按照代碼邏輯,已經刪除掉了所有price小于15的條目,如圖所示:





          4.版本異同

          之前閱讀了郭霖老師所著《Android第一行代碼 第二版》時,所記載的Litepal版本為:



          compile 'org.litepal.android:core:1.4.1'

          1

          而的Litepal版本(Java版本,另有Kotlin版本,導入的依賴稍有不同)為:



          implementation 'org.litepal.android:java:3.0.0'

          1

          新舊版本的主要區別是一些類名的劃分,例如老板本的DataSupport變成了LitePalSupport,除此之外,一些api的名稱也稍有變動,讀者在使用時最好可以參考GitHub上的官方文檔,及時更新代碼,做到與時俱進。



          5.源碼地址

          AFL——Android框架學習


          TinyUI-TUIListView最簡單的使用

          seo達人

                在TinyUI簡介的博客中提到其特點中包含一條,即多數大控件的使用方法和android一直,除了語言差異之外,本篇我們就介紹列表控件TUIListView最簡單的使用方法。



                  列表組件/控件作為目前Android/iOS的APP中最常用的控件,該控件的設計同時參考Android、windows、Qt等使用的經驗進行篩選,最終選擇了Android的ListView設計,其他平臺的列表中使用難以程度或設計上略遜于Android,因為Android給與了開發者最大的發揮控件,你可以在列表中可以顯示任何控件。



                  TUIListView中的每一行每一列你可以放置任何UI組件,使用TUIListView需要配合TUIAdapter進行使用,而TinyUI和Android一樣提供了內置的簡單使用的TUISimpleAdapter。TUISimpleAdapter主要用于顯示文本(即每一行都是只能顯示文字),如果需要在列表中顯示其他UI組件,則需要自定義一個Adapter,關于自定義Adapter將在后續進行詳細講解。



                  本篇既然是TUIListView最簡單的使用,我們就使用TUISimpleAdapter來顯示文本你列表,TUISimpleAdapter最好只用于數據步發生變化的情況,因為其存放的數據使用了C++標準庫的vector容器,而非使用list容器,vector容器的特點是訪問速度快,但其缺點是vector的內存是連續的,因此內容發生變化可能會造成內存申請和拷貝的動作;而list容器使用的雙向鏈表,其特點是插入數據快,但訪問速度慢。



                  本篇我們仍然使用上一篇中自定義的MyWindow來顯示TUIListView。



          使用方法/步驟

          1. 定義listView和andapter



                    MyWindow中包含TUISimpleAdapter.h的頭文件,并定義listView和adapter



            MyWindow.h


            ifndef MY_WINDOW_H

            define MY_WINDOW_H

            include <TUIWindow.h>

            include <TUISimpleAdapter.h>

             

             

             

            class MyWindow : public TUIWindow

            {

            public:

                MyWindow(TUIWindow* parent = nullptr);

                virtual ~MyWindow();

             

                void onShow();

                void onClose();

             

            private:

                TUIListView listView;

                TUISimpleAdapter adapter;

            };

             

            endif // !MY_WINDOW_H

             


          2. 填充數據,并把adapter設置到listView中



            MyWindow.cpp


            include "MyWindow.h"

             

             

             

            MyWindow::MyWindow(TUIWindow* parent)

                : TUIWindow(parent)

            {

                setContentView(&this->listView); // 把listView作為當前窗口的內容視圖

             

             

                vector<string> data; // 使用vector<string>類型的data存放數據

             

                for (int32_t i = 0; i < 20; i++)

                {

                    data.push_back(to_string(i)); // 生成0~20的數值-轉換成字符串,放到data中

                }

             

                this->adapter.setData(data); // 把data設置到adapter中

             

                this->listView.setAdapter(&this->adapter); // 把adapter設置到listView,作為listView數據來源和操作對象

            }

             

            MyWindow::~MyWindow()

            {

            }

             

            void MyWindow::onShow()

            {

            }

             

            void MyWindow::onClose()

            {

            }

            到目前為止窗口顯示列表控件已全部完成,接下來和上一篇一樣調用MyWindow的show()方法即可顯示,最終結果如下圖所示:


          call、apply、bind 原理實現

          seo達人

          目錄

          1. call 的模擬實現
          2. apply 的模擬實現
          3. bind 的模擬實現
          4. 三者異同



            學習并參考于:



            JavaScript深入之call和apply的模擬實現



            JS的call,apply與bind詳解,及其模擬實現





            (一)call的模擬實現

            call 用法 : MDN Function.prototype.call()



            call() 方法使用一個指定的 this 值和可選的參數列表來調用一個函數。



            call() 提供新的 this 值給當前調用的函數/方法。


          5. call 實現主要思路:

            將函數設為對象的屬性



            執行該函數



            刪除該函數



            另外還有考慮:



            call 函數還能給定參數執行函數

            this 參數不傳,或者傳null,undefined, this指向window對象

            函數是可以有返回值的
          6. 實現:

            Function.prototype.myCall = function () {

              if (typeof this !== 'function') {

                throw new TypeError('error!')

              }

              let context = arguments[0] || window   //this 參數可以傳 null,當為 null 的時候,視為指向 window

              context.fn = this  // 首先要獲取調用call的函數,用this可以獲取

              let args = [...arguments].slice(1) //從 Arguments 對象中取值,取出第二個到最后一個參數   

              let result = context.fn(...args)  //函數是可以有返回值的

              delete context.fn

              return result

            }


          7. 測試:

            // 測試一下上面實現的myCall

            var value = 2;



            var obj = {

                value: 1

            }



            function bar(name, age) {

                console.log(this.value);

                return {

                    value: this.value,

                    name: name,

                    age: age

                }

            }



            bar.call(null); // 2



            console.log(bar.myCall(obj, 'kevin', 18));

            // 1

            // Object {

            //    value: 1,

            //    name: 'kevin',

            //    age: 18

            // }



            (二)apply 的模擬實現

            apply 用法:MDN Function.prototype.apply()



            apply() 方法使用一個指定的 this 值和可選的參數數組 來調用一個函數。



            apply 的實現跟 call 類似。


          8. 實現:

            Function.prototype.myApply = function () {

              if (typeof this !== 'function') {

                throw new TypeError('error!')

              }

              let context = arguments[0] || window

              context.fn = this

              let result = arguments[1] ? context.fn(...arguments[1]) : context.fn()

              delete context.fn

              return result

            }


          9. 測試:

            var foo = {

                value: 1

            }

            function bar(name, age) {

                console.log(name)

                console.log(age)

                console.log(this.value);

            }

            bar.myApply(foo, ['black', '18']) // black 18 1



            (三)bind 的模擬實現

            bind 用法:MDN Function.prototype.bind()



            bind()方法會創建一個新函數,稱為綁定函數。當這個新函數被調用時,bind() 的第一個參數將作為它運行時的 this,之后的一序列參數將會在傳遞的實參前傳入作為它的參數。



            bind是ES5新增的一個方法,不會執行對應的函數,而是返回對綁定函數的引用。


          10. 實現:

            Function.prototype.customBind = function () {

              if (typeof this !== 'function') {

                throw new TypeError('error!')

              }

              const that = this   // 首先要獲取調用bind的函數,用this獲取并存放在that中

              let context = arguments[0] || window

              const args = [...arguments].slice(1)

              return function() {

                return that.apply(context, args.concat([...arguments]))

              }

            }



            (四)三者異同
          11. 相同:

            改變函數體內 this 的指向
          12. 不同:

            call、apply的區別:call方法接受的是參數列表,而apply方法接受的是一個參數數組。

            bind不立即執行。而call或apply會自動執行對應的函數。


          JavaScript 的簡述與基礎語法

          前端達人

          目錄

          JavaScript

          1. JS 發展歷史
          2. JS 的特點
          3. JS 的組成
          4. JS 的基礎語法

            a. 兩種引入方式 type src

            b. 三種輸出方式 console.log document.write alert

            c. 變量聲明 var let const typeof undefined

            d. 數據類型簡介 string number boolean object undefined

            e. 運算符 + - * / % = < > && || !

            i. 全等符與不全等符 === !==

            f. 流程控制語句

            i. 條件語句 if else switch case default break

            ii. 循環語句 while dowhile fori forin forof



            JavaScript

            • JS 用于完成頁面與用戶的交互功能;

            1. JS 發展歷史
            JavaScript 在 1995 年由 Netscape 公司的 Brendan Eich,在網景導航者瀏覽器上首次設計實現而成。因為 Netscape 與 Sun 合作,Netscape 管理層希望它外觀看起來像 Java,因此取名為 JavaScript。但實際上它的語法風格與 Self 及 Scheme 較為接近;
            歐洲計算機制造聯盟(ECMA)在 1997 制定腳本語言規范 ECMA Script1 (ES1),2009 年發布了 ECMA Script5(ES5),在 2015 年發布了 ECMA Script 2015(ES6),所有的瀏覽器的都支持 ES6;

          5. JS 的特點

            JS 設計模仿了 Java 語言,不同如下:

            JS 不需要編譯,由瀏覽器直接解釋執行;

            JS 是弱類型語言,JS 變量聲明不需要指明類型,不同類型的數據可以賦值給同一變量;
          6. JS 的組成

            ECMA Script 是 JS 的基礎語法;

            BOM(Brower Object Model)是瀏覽器對象模型;

            DOM(Document Object Model)是文檔對象模型;
          7. JS 的基礎語法

            a. 兩種引入方式 type src




            <!DOCTYPE html>
            <html lang="zh">
            <head>
            <meta charset="UTF-8">
            <title>JS兩種引入方式</title>
            </head>
            <body>
            <!-- JS兩種引入方式:JS和CSS一樣都需要引入到html頁面中,瀏覽器才會解釋執行,JS有兩種引入方式:
                1.內嵌(內部)腳本:在script標簽中寫js代碼,script標簽推薦放置在body標簽的底部,理論上和style標簽一樣可以放置位置任意;
                2.外部腳步:使用script標簽的src屬性引入外部js文件,使用注意事項: script標簽使用了src屬性以后內部的代碼不再被瀏覽器解釋執行,script引入外部腳本時不能使用自閉合格式 -->
            <!--告訴瀏覽器把解析器切換為js解析器 type="text/javascript"可以省略-->
            <script type="text/javascript"> document.write("<h1>內部腳本</h1>");//向body中追加html內容 </script>
            <script src="../js/外部腳本.js"></script>
            </body>
            </html>
            






            b. 三種輸出方式 console.log document.write alert

            <!DOCTYPE html>
            <html lang="zh">
            <head>
            <meta charset="UTF-8">
            <title>JS三種輸出方式</title>
            </head>
            <body>
            <!-- JS三種輸出方式:
                1.輸出到瀏覽器控制臺;
                2.輸出html內容到頁面;
                3.瀏覽器彈框輸出字符 -->
            <script>
            //1.輸出到瀏覽器控制臺
            console.log("1. 輸出到瀏覽器控制臺");//開發者專用
            //2.輸出html內容到頁面
            document.write("2. 輸出html內容到頁面");//向body中追加html內容
            //3.瀏覽器彈框輸出字符
            alert("3. 瀏覽器彈框輸出字符");//阻塞執行
            </script>
            </body>
            </html>
            


            c. 變量聲明 var let const typeof undefined


            <!DOCTYPE html>
            <html lang="zh">
            <head>
            <meta charset="UTF-8">
            <title>JS變量</title>
            </head>
            <body>
            <!-- JS變量用來存放數據;
                es5以前變量聲明使用var;
                es6之后變量聲明使用let,常量聲明使用const。他們用于替代es6的var聲明方式;
             JS是弱類型語言: 
                聲明變量時不知道變量的類型(undefined),只有在賦值之后js變量才確定類型;
                typeof(a) 或 typeof a 輸出變量的類型;
                undefined表示變量未賦值,未知類型 -->
            <script>
            //字符串 Java聲明 String str ="張三";
            let str ="張三";
            console.log(str);
            //整數 Java聲明 int k = 5;
            let k = 5;
            console.log(k);
            //小數 Java聲明 float f = 7.5;
            let f = 7.5;
            console.log(f);
            //常量 Java聲明 final Integer PI = 3.14;
            const PI = 3.14;
            console.log(PI);
            //演示弱類型語言
            let a;//聲明變量不需要指明類型
            console.log(typeof a);//undefined 未賦值類型,未知類型
            a = "你好";
            console.log(typeof a);//string
            a = 123;
            console.log(typeof a);//number
            a = true;
            console.log(typeof a);//boolean
            a = new Object();
            console.log(typeof a);//object
            </script>
            </body>
            </html>
            


            d. 數據類型簡介 string number boolean object undefined


            <!DOCTYPE html>
            <html lang="zh">
            <head>
            <meta charset="UTF-8">
            <title>JS數據類型</title>
            </head>
            <body>
            <!-- JS數據類型,常用數據類型:
                1.string 字符串類型;
                2.number 數字.包括整數和小數類型;
                3.boolean 布爾類型.值只有true和false兩個;
                4 object 對象類型,空對象使用null表示,有兩種格式:
                    new Object(); 
                    JSON格式.例如:{name:"張三",age:18};
                5.undefined 變量未賦值 -->
            <script>
            //1. string 字符串
            let str = "你好";
            console.log(str);
            console.log(typeof str);//string
            // 2. number 數字
            let n = 123.456;
            console.log(n);
            console.log(typeof n);//number
            // 3. boolean 布爾類型
            let boo = false;
            console.log(boo);
            console.log(typeof boo);//boolean
            // 4. object 對象類型,空對象使用 null表示
            let obj = null;//或 new Object();
            console.log(obj);
            console.log(typeof obj);//object
            // 5. undefined 變量未賦值
            let u = undefined;
            console.log(u);//值是undefined
            console.log(typeof u);//類型是undefined
            // Object類型
            let stu = new Object();//創建一個js對象,js對象的屬性想要直接加上
            stu.id = 1;
            stu.name = "劉一";
            stu.age = 18;
            console.log(stu);//{id: 1, name: "劉一", age: 18}
            console.log(typeof stu);//object
            // JS對象取屬性值有兩種方式:
            // 1. obj.key
            console.log(stu.name);//劉一
            // 2. obj["key"]
            console.log(stu["name"]); //劉一 == stu.name
            let b = "age";
            console.log(stu[b]);//可以取不定屬性的值
            </script>
            </body>
            </html>
            


            e. 運算符 + - * / % = < > && || !


            i. 全等符與不全等符 === !==


            <!DOCTYPE html>
            <html lang="zh">
            <head>
            <meta charset="UTF-8">
               <title>JS運算符</title>
            </head>
            <body>
            <!--
            JS運算符
            js運算符和Java運算符基本相同
            只有一個特殊的比較運算符
            === 判斷js變量的值和類型都相等才為true
            !== 不全等,判斷js變量的值和類型有一個不等就為true
            -->
            <script> let a = 3;
            let b = "3";
            console.log(a == b);//true
            // 全等 運算符 ===
            console.log(a === b);//false
            // 不全等 運算符 !==
            console.log(a !== b);//true
            // 三元(三目)運算符 布爾表達式?真:假
            let str = a===b?"全等":"不全等";
            console.log(str);//不全等
            </script>
            </body>
            </html>
            


            f. 流程控制語句

            i. 條件語句 if else switch case default break


            <!DOCTYPE html>
            <html lang="zh">
            <head>
            <meta charset="UTF-8">
            <title>條件語句</title>
            </head>
            <body>
            <!-- 條件語句JS的條件語句和Java語法基本一樣,但是對數據類型的真假判斷有些區別 JS中對各種數據類型作為布爾值的特點:(重點掌握) 1. string 空字符串""為false,其余都為true 2. number 數字 只有0為false,其余數字都為true 3. boolean 布爾類型 值只有 true和false 兩個
            循環語句
          8. object 對象類型 空對象null表示false,其它對象都是true 5. undefined 變量未賦值 為false 常用語法格式 if ... else if ... else switch case break default -->
            <script>
            //if ... else
            //if(true){
            //if(""){// string 只有空字符為假
            //if(0){number 只有0為假
            //if(false){//boolean false為假 true為真
            //if(null){//object null為假
            //if(undefined){//undefined永為假
            if("undefined"){//undefined永為假
            console.log("滿足條件");
            }else{
            console.log("不滿足條件");
            }

            //switch case break default
            let k =1;
            switch (k) {
            case 1:
            console.log("111");break;
            case 2:
            console.log("222");break;
            default: console.log("其它情況"); }
            </script>
            </body>
            </html>


            ii. 循環語句 while dowhile fori forin forof


            <!DOCTYPE html>
            <html lang="zh">
            <head>
            <meta charset="UTF-8">
            <title>循環語句</title>
            </head>
            <body>
            <!-- 循環語句
                while,do while,fori 和Java一樣;
                forin
                    1.遍歷出數組中的索引和元素
                    2.遍歷出對象中的屬性和元素
                forof 
                    1.遍歷出數組中的元素
                forin 與 forof 區別:
                    1.forin可以遍歷對象,forof不能遍歷對象
                    2.forin可以遍歷出數組中的索引,forof只能遍歷出數組中的元素 -->
            <script>
            //while 和Java一樣
            let k=1;
            while (k<3){
                console.log(k++);
            }
            
            //do while 和Java一樣
            k =1;
            do{
                console.log(k++);
            }while (k<3)
            
            //fori 和Java一樣
            for(let i=0;i<3;i++){
                console.log(i);
            }
            
            //forin 可以遍歷數組和對象
            let arr = ["劉一","陳二","張三"];//JS數組使用中括號[]定義
            let stu = {id:5,name:"李四",age:18};//JS對象使用大括號定義
                //1.forin 遍歷出數組中的索引
            for(let index in arr){
                console.log(index);//數組的索引 0,1,2
                console.log(arr[index]);//數組中的元素
            }
                //2.forin 遍歷出對象中的屬性名key
            for(let k in stu){
                console.log(k);//字符串屬性 id,name,age
                console.log(stu[k]);//對象中的屬性值
            }
            
            //forof 可以遍歷數組
            for(let e of arr){
                console.log(e);//數組中的元素
            }</script>
            </body>
            </html>
            
            
            
            
            
            ————————————————
            版權聲明:本文為CSDN博主「Regino」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
            原文鏈接:https://blog.csdn.net/Regino/article/details/105321573
            

          原文鏈接:https://blog.csdn.net/Regino/article/details/105321573 





          關于HTTP請求出現 405狀態碼 not allowed的解決辦法

          seo達人

          發現httppost請求目標網站會出現405 狀態碼,原因為 Apache、IIS、Nginx等絕大多數web服務器,都不允許靜態文件響應POST請求

          所以將post請求改為get請求即可

          跨域,請求按要求配置完畢之后,options預請求老是報錯。原因是webapi 默認的web.config有配置

          有這么個配置,導致不行。要把他刪掉,還要加上

          淺談JavaScript實現可視化展示冒泡排序過程

          seo達人



          <!DOCTYPE html>

          <html>

          <head>

          <title>JavaScript實現可視化展示冒泡排序過程</title>

          <style>

          #boxes{

          border:1px solid grey;

          width:1320px;

          height:300px;

          margin-top:10px;

          position:relative;

          }

          .box{

          background:red;

          width:20px;

          line-height:30px;

          text-align:center;

          font-family:Microsoft Yahei;

          font-size:15px;

          color:white;

          margin:0 1px;

          position:absolute;

          }

          </style>

          </head>

          <body>

          <div id="boxes"></div>

          <script>

          function random(){

          var numbers = [];

          for (var i = 0; i < 60; i++) {

          var number = Math.floor(Math.random() 90 + 10);

          numbers.push(number);

          var divElement = document.createElement("div");

          var parentElement = document.getElementById("boxes");

          divElement.style.left = i
          20 + i 2 + "px";

          divElement.style.top = 300 - 3
          number + "px";

          divElement.style.height = 3 number + "px";

          divElement.setAttribute("class","box");

          parentElement.appendChild(divElement);

          }

          return numbers;

          }

          function sort(){

          var numbers = random();

          var parentElement = document.getElementById("boxes");

          var i = 0, j = 0;

          var time = setInterval(function() {

          if (i < numbers.length) {

          if (j < numbers.length - i) {

          if (numbers[j] > numbers[j + 1]) {

          var temp = numbers[j];

          numbers[j] = numbers[j + 1];

          numbers[j + 1] = temp;

          parentElement.innerHTML = "";

          for (var k = 0; k < numbers.length; k++) {

          var textNode = document.createTextNode(numbers[k]);

          var divElement = document.createElement("div");

          divElement.appendChild(textNode);

          divElement.style.left = k
          20 + k 2 + "px";

          divElement.style.top = 300 - 3
          numbers[k] + "px";

          divElement.style.height = 3 * numbers[k] + "px";

          divElement.setAttribute("class","box");

          parentElement.appendChild(divElement);

          }

          }

          j++;

          }

          else{

          i++;

          j = 0;

          }

          }

          else {

          clearInterval(time); 

          return;

          }

          }, 100);  

          }

          sort();

          </script>

          </body>

          </html>

          ————————————————

          版權聲明:本文為CSDN博主「筱葭」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

          原文鏈接:https://blog.csdn.net/zhouziyu2011/java/article/details/53899692

          http的狀態碼(中英文)

          seo達人

           1**:請求收到,繼續處理

          2**:操作成功收到,分析、接受

          3**:完成此請求必須進一步處理

          4**:請求包含一個錯誤語法或不能完成

          5**:服務器執行一個完全有效請求失敗

          100——客戶必須繼續發出請求

          101——客戶要求服務器根據請求轉換HTTP協議版本

          200——交易成功

          201——提示知道新文件的URL

          202——接受和處理、但處理未完成

          203——返回信息不確定或不完整

          204——請求收到,但返回信息為空

          205——服務器完成了請求,用戶代理必須復位當前已經瀏覽過的文件

          206——服務器已經完成了部分用戶的GET請求

          300——請求的資源可在多處得到

          301——刪除請求數據

          302——在其他地址發現了請求數據

          303——建議客戶訪問其他URL或訪問方式

          304——客戶端已經執行了GET,但文件未變化

          305——請求的資源必須從服務器指定的地址得到

          306——前一版本HTTP中使用的代碼,現行版本中不再使用

          307——申明請求的資源臨時性刪除

          400——錯誤請求,如語法錯誤

          401——請求授權失敗

          402——保留有效ChargeTo頭響應

          403——請求不允許

          404——沒有發現文件、查詢或URl

          405——用戶在Request-Line字段定義的方法不允許

          406——根據用戶發送的Accept拖,請求資源不可訪問

          407——類似401,用戶必須首先在代理服務器上得到授權

          408——客戶端沒有在用戶指定的餓時間內完成請求

          409——對當前資源狀態,請求不能完成

          410——服務器上不再有此資源且無進一步的參考地址

          411——服務器拒絕用戶定義的Content-Length屬性請求

          412——一個或多個請求頭字段在當前請求中錯誤

          413——請求的資源大于服務器允許的大小

          414——請求的資源URL長于服務器允許的長度

          415——請求資源不支持請求項目格式

          416——請求中包含Range請求頭字段,在當前請求資源范圍內沒有range指示值,請求

          也不包含If-Range請求頭字段

          417——服務器不滿足請求Expect頭字段指定的期望值,如果是代理服務器,可能是下

          一級服務器不能滿足請求

          500——服務器產生內部錯誤

          501——服務器不支持請求的函數

          502——服務器暫時不可用,有時是為了防止發生系統過載

          503——服務器過載或暫停維修

          504——關口過載,服務器使用另一個關口或服務來響應用戶,等待時間設定值較長

          505——服務器不支持或拒絕支請求頭中指定的HTTP版本

          ==========================================================

          英文版:

          100:Continue

          101:Switching Protocols

          102:Processing

          200:OK

          201:Created

          202:Accepted

          203:Non-Authoriative Information

          204:No Content

          205:Reset Content

          206:Partial Content

          207:Multi-Status

          300:Multiple Choices

          301:Moved Permanently

          302:Found

          303:See Other

          304:Not Modified

          305:Use Proxy

          306:(Unused)

          307:Temporary Redirect

          400:Bad Request

          401:Unauthorized

          402:Payment Granted

          403:Forbidden

          404:File Not Found

          405:Method Not Allowed

          406:Not Acceptable

          407:Proxy Authentication Required

          408:Request Time-out

          409:Conflict

          410:Gone

          411:Length Required

          412:Precondition Failed

          413:Request Entity Too Large

          414:Request-URI Too Large

          415:Unsupported Media Type

          416:Requested range not satisfiable

          417:Expectation Failed

          422:Unprocessable Entity

          423:Locked

          424:Failed Dependency

          500:Internal Server Error

          501:Not Implemented

          502:Bad Gateway

          503:Service Unavailable

          504:Gateway Timeout

          505:HTTP Version Not Supported

          507:Insufficient Storage

          完整的 HTTP 1.1規范說明書來自于RFC 2616,你可以在rfc-editor在線查閱。HTTP 1.1的狀態碼被標記為新特性,因為許多瀏覽器只支持 HTTP 1.0。你應只把狀態碼發送給支持 HTTP 1.1的客戶端,支持協議版本可以通過調用request.getRequestProtocol來檢查。

          本部分余下的內容會詳細地介紹 HTTP 1.1中的狀態碼。這些狀態碼被分為五大類:

          100-199 用于指定客戶端應相應的某些動作。

          200-299 用于表示請求成功。

          300-399 用于已經移動的文件并且常被包含在定位頭信息中指定新的地址信息。

          400-499 用于指出客戶端的錯誤。

          500-599 用于支持服務器錯誤。

          HttpServletResponse中的常量代表關聯不同標準消息的狀態碼。在servlet程序中,你會更多地用到這些常量的標識來使用狀態碼。例如:你一般會使用response.setStatus(response.SC_NO_CONTENT)而不是 response.setStatus(204),因為后者不易理解而且容易導致錯誤。但是,你應當注意到服務器允許對消息輕微的改變,而客戶端只注意狀態碼的數字值。所以服務器可能只返回 HTTP/1.1 200 而不是 HTTP/1.1 200 OK。

          100 (Continue/繼續)

          如果服務器收到頭信息中帶有100-continue的請求,這是指客戶端詢問是否可以在后續的請求中發送附件。在這種情況下,服務器用100(SC_CONTINUE)允許客戶端繼續或用417 (Expectation Failed)告訴客戶端不同意接受附件。這個狀態碼是 HTTP 1.1中新加入的。

          101 (Switching Protocols/轉換協議)

          101 (SC_SWITCHING_PROTOCOLS)狀態碼是指服務器將按照其上的頭信息變為一個不同的協議。這是 HTTP 1.1中新加入的。

          200 (OK/正常)

          200 (SC_OK)的意思是一切正常。一般用于相應GET和POST請求。這個狀態碼對servlet是缺省的;如果沒有調用setStatus方法的話,就會得到200。

          201 (Created/已創建)

          201 (SC_CREATED)表示服務器在請求的響應中建立了新文檔;應在定位頭信息中給出它的URL。

          202 (Accepted/接受)

          202 (SC_ACCEPTED)告訴客戶端請求正在被執行,但還沒有處理完。

          203 (Non-Authoritative Information/非官方信息)

          狀態碼203 (SC_NON_AUTHORITATIVE_INFORMATION)是表示文檔被正常的返回,但是由于正在使用的是文檔副本所以某些響應頭信息可能不正確。這是 HTTP 1.1中新加入的。

          204 (No Content/無內容)

          在并沒有新文檔的情況下,204 (SC_NO_CONTENT)確保瀏覽器繼續顯示先前的文檔。這各狀態碼對于用戶周期性的重載某一頁非常有用,并且你可以確定先前的頁面是否已經更新。例如,某個servlet可能作如下操作:

          int pageVersion =Integer.parseInt(request.getParameter("pageVersion"));

          if (pageVersion >;= currentVersion) {

          response.setStatus(response.SC_NO_CONTENT);

          } else {

          // Create regular page

          }

          但是,這種方法對通過刷新響應頭信息或等價的HTML標記自動重載的頁面起作用,因為它會返回一個204狀態碼停止以后的重載。但基于JavaScript腳本的自動重載在這種情況下仍然需要能夠起作用??梢蚤喿x本書7.2 ( HTTP 1.1 Response Headers and Their Meaning/HTTP 1.1響應頭信息以及他們的意義)部分的詳細討論。

          205 (Reset Content/重置內容)

          重置內容205 (SC_RESET_CONTENT)的意思是雖然沒有新文檔但瀏覽器要重置文檔顯示。這個狀態碼用于強迫瀏覽器清除表單域。這是 HTTP 1.1中新加入的。

          206 (Partial Content/局部內容)

          206 (SC_PARTIAL_CONTENT)是在服務器完成了一個包含Range頭信息的局部請求時被發送的。這是 HTTP 1.1中新加入的。

          300 (Multiple Choices/多重選擇)

          300 (SC_MULTIPLE_CHOICES)表示被請求的文檔可以在多個地方找到,并將在返回的文檔中列出來。如果服務器有首選設置,首選項將會被列于定位響應頭信息中。

          301 (Moved Permanently)

          301 (SC_MOVED_PERMANENTLY)狀態是指所請求的文檔在別的地方;文檔新的URL會在定位響應頭信息中給出。瀏覽器會自動連接到新的URL。

          302 (Found/找到)

          與301有些類似,只是定位頭信息中所給的URL應被理解為臨時交換地址而不是永久的。注意:在 HTTP 1.0中,消息是臨時移動(Moved Temporarily)的而不是被找到,因此HttpServletResponse中的常量是SC_MOVED_TEMPORARILY不是我們以為的SC_FOUND。

          注意

          代表狀態碼302的常量是SC_MOVED_TEMPORARILY而不是SC_FOUND。

          狀態碼302是非常有用的因為瀏覽器自動連接在定為響應頭信息中給出的新URL。這非常有用,而且為此有一個專門的方法——sendRedirect。使用response.sendRedirect(url)比調用response.setStatus(response.SC_MOVED_TEMPORARILY)和response.setHeader("Location", url)多幾個好處。首先,response.sendRedirect(url)方法明顯要簡單和容易。第二,servlet自動建立一頁保存這一連接以提供給那些不能自動轉向的瀏覽器顯示。最后,在servlet 2.2版本(J2EE中的版本)中,sendRedirect能夠處理相對路徑,自動轉換為絕對路徑。但是你只能在2.1版本中使用絕對路徑。

          如果你將用戶轉向到站點的另一頁中,你要用 HttpServletResponse 中的 encodeURL 方法傳送URL。這么做可預防不斷使用基于URL重寫的會話跟蹤的情況。URL重寫是一種在你的網站跟蹤不使用 cookies 的用戶的方法。這是通過在每一個URL尾部附加路徑信息實現的,但是 servlet 會話跟蹤API會自動的注意這些細節。會話跟蹤在第九章討論,并且養成使用 encodeURL 的習慣會使以后添加會話跟蹤的功能更容易很多。

          核心技巧

          如果你將用戶轉向到你的站點的其他頁面,用 response.sendRedirect(response.encodeURL(url)) 的方式事先計劃好會話跟蹤(session tracking)要比只是調用 response.sendRedirect(url) 好的多。

          這個狀態碼有時可以與301交換使用。例如,如果你錯誤的訪問了某路徑信息不完整),有些服務器就會回復301狀態碼而有些則回復302。從技術上說,如果最初的請求是GET瀏覽器只是被假定自動轉向。如果想了解更多細節,請看狀態碼307的討論。

          303 (See Other/參見其他信息)

          這個狀態碼和 301、302 相似,只是如果最初的請求是 POST,那么新文檔(在定位頭信息中給出)藥用 GET 找回。這個狀態碼是新加入 HTTP 1.1中的。

          304 (Not Modified/為修正)

          當客戶端有一個緩存的文檔,通過提供一個 If-Modified-Since 頭信息可指出客戶端只希望文檔在指定日期之后有所修改時才會重載此文檔,用這種方式可以進行有條件的請求。304 (SC_NOT_MODIFIED)是指緩沖的版本已經被更新并且客戶端應刷新文檔。另外,服務器將返回請求的文檔及狀態碼 200。servlet一般情況下不會直接設置這個狀態碼。它們會實現getLastModified方法并根據修正日期讓默認服務方法處理有條件的請求。這個方法的例程已在2.8部分(An Example Using Servlet Initialization and Page Modification Dates/一個使用servlet初始化和頁面修正日期的例子)給出。

          305 (Use Proxy/使用代理)

          305 (SC_USE_PROXY)表示所請求的文檔要通過定位頭信息中的代理服務器獲得。這個狀態碼是新加入 HTTP 1.1中的。

          307 (Temporary Redirect/臨時重定向)

          瀏覽器處理307狀態的規則與302相同。307狀態被加入到 HTTP 1.1中是由于許多瀏覽器在收到302響應時即使是原始消息為POST的情況下仍然執行了錯誤的轉向。只有在收到303響應時才假定瀏覽器會在POST請求時重定向。添加這個新的狀態碼的目的很明確:在響應為303時按照GET和POST請求轉向;而在307響應時則按照GET請求轉向而不是POST請求。注意:由于某些原因在HttpServletResponse中還沒有與這個狀態對應的常量。該狀態碼是新加入HTTP 1.1中的。

          注意

          在 HttpServletResponse 中沒有 SC_TEMPORARY_REDIRECT 常量,所以你只能顯示的使用307狀態碼。

          400 (Bad Request/錯誤請求)

          400 (SC_BAD_REQUEST)指出客戶端請求中的語法錯誤。

          401 (Unauthorized/未授權)

          401 (SC_UNAUTHORIZED)表示客戶端在授權頭信息中沒有有效的身份信息時訪問受到密碼保護的頁面。這個響應必須包含一個WWW-Authenticate的授權信息頭。例如,在本書4.5部分中的“Restricting Access to Web Pages./限制訪問Web頁?!?

          403 (Forbidden/禁止)

          403 (SC_FORBIDDEN)的意思是除非擁有授權否則服務器拒絕提供所請求的資源。這個狀態經常會由于服務器上的損壞文件或目錄許可而引起。

          404 (Not Found/未找到)

          404 (SC_NOT_FOUND)狀態每個網絡程序員可能都遇到過,他告訴客戶端所給的地址無法找到任何資源。它是表示“沒有所訪問頁面”的標準方式。這個狀態碼是常用的響應并且在HttpServletResponse類中有專門的方法實現它:sendError("message")。相對于setStatus使用sendError得好處是:服務器會自動生成一個錯誤頁來顯示錯誤信息。但是,Internet Explorer 5瀏覽器卻默認忽略你發揮的錯誤頁面并顯示其自定義的錯誤提示頁面,雖然微軟這么做違反了 HTTP 規范。要關閉此功能,在工具菜單里,選擇Internet選項,進入高級標簽頁,并確認“顯示友好的 HTTP 錯誤信息”選項(在我的瀏覽器中是倒數第8各選項)沒有被選。但是很少有用戶知道此選項,因此這個特性被IE5隱藏了起來使用戶無法看到你所返回給用戶的信息。而其他主流瀏覽器及IE4都完全的顯示服務器生成的錯誤提示頁面??梢詤⒖紙D6-3及6-4中的例子。

          核心警告

          默認情況下,IE5忽略服務端生成的錯誤提示頁面。

          405 (Method Not Allowed/方法未允許)

          405 (SC_METHOD_NOT_ALLOWED)指出請求方法(GET, POST, HEAD, PUT, DELETE, 等)對某些特定的資源不允許使用。該狀態碼是新加入 HTTP 1.1中的。

          406 (Not Acceptable/無法訪問)

          406 (SC_NOT_ACCEPTABLE)表示請求資源的MIME類型與客戶端中Accept頭信息中指定的類型不一致。見本書7.2部分中的表7.1(HTTP 1.1 Response Headers and Their Meaning/HTTP 1.1響應頭信息以及他們的意義)中對MIME類型的介紹。406是新加入 HTTP 1.1中的。

          407 (Proxy Authentication Required/代理服務器認證要求)

          407 (SC_PROXY_AUTHENTICATION_REQUIRED)與401狀態有些相似,只是這個狀態用于代理服務器。該狀態指出客戶端必須通過代理服務器的認證。代理服務器返回一個Proxy-Authenticate響應頭信息給客戶端,這會引起客戶端使用帶有Proxy-Authorization請求的頭信息重新連接。該狀態碼是新加入 HTTP 1.1中的。

          408 (Request Timeout/請求超時)

          408 (SC_REQUEST_TIMEOUT)是指服務端等待客戶端發送請求的時間過長。該狀態碼是新加入 HTTP 1.1中的。

          409 (Conflict/沖突)

          該狀態通常與PUT請求一同使用,409 (SC_CONFLICT)狀態常被用于試圖上傳版本不正確的文件時。該狀態碼是新加入 HTTP 1.1中的。

          410 (Gone/已經不存在)

          410 (SC_GONE)告訴客戶端所請求的文檔已經不存在并且沒有更新的地址。410狀態不同于404,410是在指導文檔已被移走的情況下使用,而404則用于未知原因的無法訪問。該狀態碼是新加入 HTTP 1.1中的。

          411 (Length Required/需要數據長度)

          411 (SC_LENGTH_REQUIRED)表示服務器不能處理請求(假設為帶有附件的POST請求),除非客戶端發送Content-Length頭信息指出發送給服務器的數據的大小。該狀態是新加入 HTTP 1.1的。

          412 (Precondition Failed/先決條件錯誤)

          412 (SC_PRECONDITION_FAILED)狀態指出請求頭信息中的某些先決條件是錯誤的。該狀態是新加入 HTTP 1.1的。

          413 (Request Entity Too Large/請求實體過大)

          413 (SC_REQUEST_ENTITY_TOO_LARGE)告訴客戶端現在所請求的文檔比服務器現在想要處理的要大。如果服務器認為能夠過一段時間處理,則會包含一個Retry-After的響應頭信息。該狀態是新加入 HTTP 1.1的。

          414 (Request URI Too Long/請求URI過長)

          414 (SC_REQUEST_URI_TOO_LONG)狀態用于在URI過長的情況時。這里所指的“URI”是指URL中主機、域名及端口號之后的內容。該狀態是新加入 HTTP 1.1的。

          415 (Unsupported Media Type/不支持的媒體格式)

          415 (SC_UNSUPPORTED_MEDIA_TYPE)意味著請求所帶的附件的格式類型服務器不知道如何處理。該狀態是新加入 HTTP 1.1的。

          416 (Requested Range Not Satisfiable/請求范圍無法滿足)

          416表示客戶端包含了一個服務器無法滿足的Range頭信息的請求。該狀態是新加入 HTTP 1.1的。奇怪的是,在servlet 2.1版本API的HttpServletResponse中并沒有相應的常量代表該狀態。

          注意

          在servlet 2.1的規范中,類HttpServletResponse并沒有SC_REQUESTED_RANGE_NOT_SATISFIABLE 這樣的常量,所以你只能直接使用416。在servlet 2.2版本之后都包含了此常量。

          417 (Expectation Failed/期望失敗)

          如果服務器得到一個帶有100-continue值的Expect請求頭信息,這是指客戶端正在詢問是否可以在后面的請求中發送附件。在這種情況下,服務器也會用該狀態(417)告訴瀏覽器服務器不接收該附件或用100 (SC_CONTINUE)狀態告訴客戶端可以繼續發送附件。該狀態是新加入 HTTP 1.1的。

          500 (Internal Server Error/內部服務器錯誤)

          500 (SC_INTERNAL_SERVER_ERROR) 是常用的“服務器錯誤”狀態。該狀態經常由CGI程序引起也可能(但愿不會如此!)由無法正常運行的或返回頭信息格式不正確的servlet引起。

          501 (Not Implemented/未實現)

          501 (SC_NOT_IMPLEMENTED)狀態告訴客戶端服務器不支持請求中要求的功能。例如,客戶端執行了如PUT這樣的服務器并不支持的命令。

          502 (Bad Gateway/錯誤的網關)

          502 (SC_BAD_GATEWAY)被用于充當代理或網關的服務器;該狀態指出接收服務器接收到遠端服務器的錯誤響應。

          503 (Service Unavailable/服務無法獲得)

          狀態碼503 (SC_SERVICE_UNAVAILABLE)表示服務器由于在維護或已經超載而無法響應。例如,如果某些線程或數據庫連接池已經沒有空閑則servlet會返回這個頭信息。服務器可提供一個Retry-After頭信息告訴客戶端什么時候可以在試一次。

          504 (Gateway Timeout/網關超時)

          該狀態也用于充當代理或網關的服務器;它指出接收服務器沒有從遠端服務器得到及時的響應。該狀態是新加入 HTTP 1.1的。

          505 (HTTP Version Not Supported/不支持的 HTTP 版本)

          505 (SC_HTTP_VERSION_NOT_SUPPORTED)狀態碼是說服務器并不支持在請求中所標明 HTTP 版本。該狀態是新加入 HTTP 1.1的。


          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合