Vue躬行記(9)——Vuex

  Vuex是一個專為Vue.js設計的狀態管理庫,適用於多組件共享狀態的場景。Vuex能集中式的存儲和維護所有組件的狀態,並提供相關規則保證狀態的獨立性、正確性和可預測性,這不僅讓調試變得可追蹤,還讓代碼變得更結構化且易維護。本文所使用的Vuex,其版本是3.1.1。

一、基本用法

  首先需要引入Vue和Vuex兩個庫,如果像下面這樣在Vue之後引入Vuex,那麼Vuex會自動調用Vue.use()方法註冊其自身;但如果以模塊的方式引用,那麼就得顯式地調用Vue.use()。注意,因為Vuex依賴Promise,所以對於那些不支持Promise的瀏覽器,要使用Vuex的話,得引入相關的polyfill庫,例如es6-promise。

<script src="js/vue.js"></script>
<script src="js/vuex.js"></script>

  然後創建Vuex應用的核心:Store(倉庫)。它是一個容器,保存着大量的響應式狀態(State),並且這些狀態不能直接修改,需要顯式地將修改請求提交到Mutation(變更)中才能實現更新,因為這樣便於追蹤每個狀態的變化。在下面的示例中,初始化了一個digit狀態,並在mutations選項中添加了兩個可將其修改的方法。

const store = new Vuex.Store({
  state: {
    digit: 0
  },
  mutations: {
    add: state => state.digit++,
    minus: state => state.digit--
  }
});

  接着創建根實例,並將store實例注入,從而讓整個應用都能讀寫其中的狀態,在組件中可通過$store屬性訪問到它,如下所示,以計算屬性的方式讀取digit狀態,並通過調用commit()方法來修改該狀態。

var vm = new Vue({
  el: "#container",
  store: store,
  computed: {
    digit() {
      return this.$store.state.digit;
    }
  },
  methods: {
    add() {
      this.$store.commit("add");
    },
    minus() {
      this.$store.commit("minus");
    }
  }
});

  最後將根實例中的方法分別註冊到兩個按鈕的點擊事件中,如下所示,每當點擊這兩個按鈕時,狀態就會更新,並在頁面中显示。

<div id="container">
  <p>{{digit}}</p>
  <button @click="add">增加</button>
  <button @click="minus">減少</button>
</div>

二、主要組成

  Vuex的主要組成除了上一節提到的Store、State和Mutation之外,還包括Getter和Action,本節會對其中的四個做重點講解,它們之間的關係如圖2所示。

圖2  四者的關係

1)State

  State是一個可存儲狀態的對象,在應用的任何位置都能被訪問到,並且作為單一數據源(Single Source Of Truth)而存在。

  當組件需要讀取大量狀態時,一個個的聲明成計算屬性會顯得過於繁瑣而冗餘,於是Vuex提供了一個名為mapState()的輔助函數,用來將狀態自動映射成計算屬性,它的參數既可以是數組,也可以是對象。

  當計算屬性的名稱與狀態名稱相同,並且不需要做額外處理時,可將名稱組成一個字符串數組傳遞給mapState()函數,在組件中可按原名調用,如下所示。

var vm = new Vue({
  computed: Vuex.mapState([ "digit" ])
});

  當計算屬性的名稱與狀態名稱不同,或者計算屬性讀取的是需要處理的狀態時,可將一個對象傳遞給mapState()函數,其鍵就是計算屬性的名稱,而其值既可以是函數,也可以是字符串,如下代碼所示。如果是函數,那麼它的第一個參數是state,即狀態對象;如果是字符串,那麼就是從state中指定一個狀態作為計算屬性。

var vm = new Vue({
  computed: Vuex.mapState({
    digit: state => state.digit,
    alias: "digit"        //相當於state => state.digit
  })
});

  因為mapState()函數返回的是一個對象,所以當組件內已經包含計算屬性時,可以對其應用擴展運算符(…)來進行合併,如下所示,這是一種極為簡潔的寫法。

var vm = new Vue({
  computed: {
    name() {},
    ...Vuex.mapState([ "digit" ])
  }
});

2)Getter

  Getter是從State中派生出的狀態,當多個組件要對同一個狀態進行相同的處理時,就需要將狀態轉移到Getter中,以免產生重複的冗餘代碼。

  Getter相當於Store的計算屬性,它能接收兩個參數,第一個是state對象,第二個是可選的getters對象,該參數能讓不同的Getter之間相互訪問。Getter的返回值會被緩存,並且只有當依賴值發生變化時才會被重新計算。不過當返回值是函數時,其結果就不會被緩存,如下所示,其中caculate返回的是個数字,而sum返回的是個函數。

const store = new Vuex.Store({
  state: {
    digit: 0
  },
  getters: {
    caculate: state => {
      return state.digit + 2;
    },
    sum: state => right => {
      return state.digit + right;
    }
  }
});

  在組件內可通過this.$store.getters訪問到Getter中的數據,如下所示,讀取了上一個示例中的兩個Getter。

var vm = new Vue({
  methods: {
    add() {
      this.$store.getters.caculate;
      this.$store.getters.sum(1);
    }
  }
});

  Getter也有一個輔助函數,用來將Getter自動映射為組件的計算屬性,名字叫mapGetters(),其參數也是數組或對象。但與之前的mapState()不同,當參數是對象時,其值不能是函數,只能是字符串,如下所示,為了對比兩種寫法,聲明了兩個computed選項。

var vm = new Vue({
  computed: Vuex.mapGetters([ "caculate" ]),
  computed: Vuex.mapGetters({
    alias: "caculate"
  })
});

3)Mutation

  更改狀態的唯一途徑是提交Mutation,Vuex中的Mutation類似於事件,也包含一個類型和回調函數,在函數體中可進行狀態更改的邏輯,並且它能接收兩個參數,第一個是state對象,第二個是可選的附加數據,叫載荷(Payload)。下面這個Mutation的類型是“interval”,接收了兩個參數。

const store = new Vuex.Store({
  state: {
    digit: 0
  },
  mutations: {
    interval: (state, payload) => state.digit += payload.number
  }
});

  在組件中不能直接調用Mutation的回調函數,得通過this.$store.commit()方法觸發更新,如下所示,採用了兩種提交方式,第一種是傳遞type參數,第二種是傳遞包含type屬性的對象。

var vm = new Vue({
  methods: {
    interval() {
      this.$store.commit("interval", { number: 2 });             //第一種
      this.$store.commit({ type: "interval", number: 2 });       //第二種
    }
  }
});

  當多人協作時,Mutation的類型適合寫成常量,這樣更容易維護,也能減少衝突。

const INTERVAL = "interval";

  Mutation有一個名為mapMutations()的輔助函數,其寫法和mapState()相同,它能將Mutation自動映射為組件的方法,如下所示。

var vm = new Vue({
  methods: Vuex.mapMutations(["interval"])
  //相當於
  methods: {
    interval(payload) {
      this.$store.commit(INTERVAL, payload);
    }
  }
});

  注意,為了能追蹤狀態的變更,Mutation只支持同步的更新,如果要異步,那麼得使用Action。

4)Action

  Action類似於Mutation,但不同的是它可以包含異步操作,並且只能用來通知Mutation,不會直接更新狀態。Action的回調函數能接收兩個參數,第一個是與Store實例具有相同屬性和方法的context對象(注意,不是Store實例本身),第二個是可選的附加數據,如下所示,調用commit()方法提交了一個Mutation。

const store = new Vuex.Store({
  actions: {
    interval(context, payload) {
      context.commit("interval", payload);
    }
  }
});

  在組件中能通過this.$store.dispatch()方法分發Action,如下所示,與commit()方法一樣,它也有兩種提交方式。

var vm = new Vue({
  methods: {
    interval() {
      this.$store.dispatch("interval", { number: 2 });            //第一種
      this.$store.dispatch({type: "interval", number: 2});        //第二種
    }
  }
});

  注意,由於dispatch()方法返回的是一個Promise對象,因此它能以一種更優雅的方式來處理異步操作,如下所示。

var vm = new Vue({
  methods: {
    interval() {
      this.$store.dispatch("interval", { number: 2 }).then(() => {
        console.log("success");
      });
    }
  }
});

  Action有一個名為mapActions()的輔助函數,其寫法和mapState()相同,它能將Action自動映射為組件的方法,如下所示。

var vm = new Vue({
  methods: Vuex.mapActions([ "interval" ])
});

三、模塊

  當應用越來越大時,為了避免Store變得過於臃腫,有必要將其拆分到一個個的模塊(Module)中。每個模塊就是一個對象,包含屬於自己的State、Getter、Mutation和Action,甚至還能嵌套其它模塊。

1)局部狀態

  對於模塊內部的Getter和Mutation,它們接收的第一個參數是模塊的局部狀態,而Getter的第三個參數rootState和Action的context.rootState屬性可訪問根節點狀態(即全局狀態),如下所示。

const moduleA = {
  state: { digit: 0 },
  mutations: {
    add: state => state.digit++
  },
  getters: {
    caculate: (state, getter, rootState) => {
      return state.digit + 2;
    }
  },
  actions: {
    interval(context, payload) {
      context.commit("add", payload);
    }
  }
};

2)命名空間

  默認情況下,只有在訪問State時需要帶命名空間,而Getter、Mutation和Action的調用方式不變。將之前的moduleA模塊註冊到Store實例中,如下所示,modules選項的值是一個子模塊對象,其鍵是模塊名稱。

const store = new Vuex.Store({
  modules: {
    a: moduleA
  }
});

  如果要訪問模塊中的digit狀態,那麼可以像下面這樣寫。

store.state.a.digit;

  當模塊的namespaced屬性為true時,它的Getter、Mutation和Action也會帶命名空間,在使用時,需要添加命名空間前綴,如下代碼所示,此舉大大提升了模塊的封裝性和復用性。

const moduleA = {
  namespaced: true
};
var vm = new Vue({
  el: "#container",
  store: store,
  methods: {
    add() {
      this.$store.commit("a/add");
    },
    caculate() {
      this.$store.getters["a/caculate"];
    }
  }
});

  如果要在帶命名空間的模塊中提交全局的Mutation或分發全局的Action,那麼只要將{root: true}作為第三個參數傳給commit()或dispatch()就可實現,如下所示。

var vm = new Vue({
  methods: {
    add() {
      this.$store.dispatch("add", null, { root: true });
      this.$store.commit("add", null, { root: true });
    }
  }
});

  如果要在帶命名空間的模塊中註冊全局的Action,那麼需要將其修改成對象的形式,然後添加root屬性並設為true,再將Action原先的定義轉移到handler()函數中,如下所示。

const moduleA = {
  actions: {
    interval: {
      root: true,
      handler(context, payload) {}
    }
  }
};

3)輔助函數

  當使用mapState()、mapGetters()、mapMutations()和mapActions()四個輔助函數對帶命名空間的模塊做映射時,需要顯式的包含命名空間,如下所示。

var vm = new Vue({
  computed: Vuex.mapState({
    digit: state => state.a.digit
  }),
  methods: Vuex.mapMutations({
    add: "a/add"
  })
});

  這四個輔助函數的第一個參數都是可選的,用於綁定命名空間,可簡化映射過程,如下所示。

var vm = new Vue({
  computed: Vuex.mapState("a", {
    digit: state => state.digit
  }),
  methods: Vuex.mapMutations("a", {
    add: "add"
  })
});

  Vuex還提供了另一個輔助函數createNamespacedHelpers(),可創建綁定命名空間的輔助函數,如下所示。

const { mapState, mapMutations } = Vuex.createNamespacedHelpers("a");

四、動態註冊

  在創建Store實例后,可通過registerModule()方法動態註冊模塊,如下代碼所示,調用了兩次registerModule()方法,第一次註冊了模塊“a”,第二次註冊了嵌套模塊“a/b”。

const store = new Vuex.Store();
store.registerModule("a", moduleA);    
store.registerModule(["a", "b"], moduleAB);

  通過store.state.a和store.state.a.b可訪問模塊的局部狀態。如果要卸載動態註冊的模塊,那麼可以通過unregisterModule()方法實現。

  registerModule()方法的第三個參數是可選的配置對象,當preserveState屬性的值為true時(如下所示),在註冊模塊時會忽略模塊中的狀態,即無法在store中讀取模塊中的狀態。

store.registerModule("a", moduleA, { preserveState: true });

五、表單處理

  表單默認能直接修改組件的狀態,但是在Vuex中,狀態只能由Mutation觸發更新。為了能更好的追蹤狀態的變化,也為了能更符合Vuex的思維,需要讓表單控件與狀態綁定在一起,並通過input或change事件監聽狀態更新的行為,如下所示。

<div id="container">
  <input :value="digit" @input="add" />
</div>

  然後在Store實例中初始化digit狀態,並添加更新狀態的Mutation,如下所示。

const store = new Vuex.Store({
  state: {
    digit: 0
  },
  mutations: {
    add: (state, value) => {
      state.digit = value;
    }
  }
});

  最後在創建根實例時,將digit狀態映射成它的計算屬性,在事件處理程序add()中調用commit()方法,並將控件的值作為第二個參數傳入,如下所示。

var vm = new Vue({
  el: "#container",
  store: store,
  computed: Vuex.mapState(["digit"]),
  methods: {
    add(e) {
      this.$store.commit("add", e.target.value);
    }
  }
});

  還有一個方法也能實現相同的功能,那就是在控件上使用v-model指令,但需要與帶setter的計算屬性配合,如下所示(只給出了關鍵部分的代碼)。

<div id="container">
  <input v-model="digit" />
</div>
<script>
  var vm = new Vue({
    computed: {
      digit: {
        get() {
          return this.$store.state.digit;
        },
        set(value) {
          this.$store.commit("add", value);
        }
      }
    }
  });
</script>

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

要吸管請「開金口」 加州餐廳明年起不主動提供

摘錄自2018年9月21日蘋果日報美國加州報導

美聯社報導,加州州長布朗(Jerry Brown)簽署通過法案,明年起禁止州內餐廳主動提供顧客塑膠吸管服務,首開全美先例。餐廳業者若不配合將先予以警告,兩次警告後開罰,每年最高300美元(約9,200台幣),由州內衛生人員負責不定時執行稽查。不過,此法僅適用於正式、有服務生點餐的餐廳,速食業者不再此限。儘管不是直接禁止,部分共和黨人仍批評這項新法「管太多」。

民主黨的布朗將環保議題列為優先施政考量。他指,每年大量塑膠垃圾流入海中,殺死鯨魚和魚類,污染最終進到民眾的食物和供水:「我們對一次性便利用具的迷戀,將招致災難性的後果。所有形式的塑膠製品,塑膠吸管、寶特瓶、包裝、塑膠袋等,都在使地球窒息。」

同天,布朗簽署通過另項法案,規定販售兒童餐的各級餐廳,都必須將菜單飲料預設為牛奶和開水。兩項法案皆從明年1月1日開始生效。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

Model 3 接單爆量部分是膨風?Musk:重複訂單將取消

特斯拉(Tesla Motors)平價電動車「Model 3」3 月 31 日亮相一週就狂接了 32.5 萬筆訂單,執行長 Elon Musk 之後更於 4 月 22 日指稱 Model 3 已接獲近 40 萬筆訂單。   不過,許多人對此抱持懷疑態度,認為或許有顧客重複下單導致數據「膨風」,分析師 Anton Wahlman 上週更在 Seeking Alpha 網站發文宣稱,雖然特斯拉限制每人只能預購兩台 Model 3,但他個人卻已成功下了 20 筆訂單。   Yahoo! Finance 的新聞記者隨後也宣稱,只要以不同表格遞交多筆訂單,就能成功突破每人限購 2 台的限制。   Wahlman 宣稱,這意味著特斯拉接獲的 40 萬筆訂單有一部份也許來自投機客,Model 3 龐大的需求可能只是膨風。   對此,Musk 決定重新檢視顧客的下單狀況,並把多餘的訂單全部取消。MarketWatch 2 日報導,Musk 4 月 29 日透過 Twitter 指出,重複的訂單將被刪除,每位客戶都只限購 2 台,而所有訂單中僅有 5% 預購了 2 台 Model 3,因此不太可能有投機客。   儘管如此,投機客瘋狂預購 Model 3,仍代表這款車種深獲顧客期待,畢竟 Model 3 在還未亮相前,搶著掏錢預訂 Model 3 的粉絲們就已在實體門市外排起超長人龍,這樣的熱絡景象真的是前所未見。   現在特斯拉遇到的問題,應該不是需求疲軟、而是訂單太多。有分析師認為,特斯拉當前產能不足以應付爆量需求,未來可能得籌錢擴產、甚至打造第二座組裝廠。   CNBC、Forbes 4 月中報導,巴克萊分析師 Brian Johnson 表示,他估計特斯拉需要另行籌資 30 億美元,才能滿足如雪片飛來的訂單。他說,特斯拉訂單暴增,或許會以需要打造更多汽車和電池工廠為由,尋求額外資金。   從特斯拉生產情況看來,確實有擴產需要。今年第一季,特斯拉交車數量僅有 14,820 輛,低於預期的 16,000 輛。今年全年特斯拉預計交車 80,000~90,000 輛。這讓外界憂心忡忡,擔心該公司無法從小眾車廠,蛻變為大型公司。特斯拉的加州組裝工廠,以往為通用汽車(GM)和豐田(Toyota)的合資企業,年度產能達 50 萬輛,意味特斯拉仍有大幅增產空間,能加裝設備,生產 Model 3。    (本文內容由授權使用;首圖來源: CC BY 2.0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

【Elasticsearch 7 探索之路】(三)倒排索引

上一篇,我們介紹了 ES 文檔的基本 CURE 和批量操作。我們都知道倒排索引是搜索引擎非常重要的一種數據結構,什麼是倒排索引,倒排索引的原理是什麼。

1 索引過程

在講解倒排索引前,我們先了解索引創建,下圖是 Elasticsearch 中數據索引過程的流程。

從上圖可以看到,文檔未在 ES 中進行索引,而是 由 Analyzer 組件對其執行一些操作並將其拆分為 token/term。然後將這些術語作為倒排索引存儲在磁盤中。假設我們有兩個名為 name 和 age 字段,當要將文檔索引到 ES 時,Analyzers 組件 以某些定界符(有默認定界符,例如空格,句號等)將它們分割開獲取 token,再對每個 token 應用特定的過濾器。經過分析的這些標記稱為 term。然後將這些 term 針對該字段)存儲在倒排列表中。

2 倒排索引

2.1 正排與倒排索引

一般在我們閱讀圖書,我們會根據目錄快速定位想要閱讀的章節,過了一段時間,你想要的回顧之前某一個知識點,你發現從目錄難以查找到對應的地方,這時你可能就會從索引頁從去查找對應內容索引,從而找到頁碼。

搜索引擎其實跟我們的使用圖書很相似,下面我來對圖書和搜索引擎進行一個簡單的類比,來看一下搜素引擎中正排和倒排索引。

  • 圖書
    • 正排索引-目錄頁
    • 倒排索引-索引頁
  • 搜索引擎
    • 正排索引-文檔 Id 到文檔內容和單詞的關聯
    • 倒排索引-單詞到文檔 Id 的關係

2.2 倒排索引的核心組成

舉個例子,假設我們有 3 個文檔:

Doc 1:breakthrough drug for schizophrenia

Doc 2:new schizophrenia drug 

Doc 3:new approach for treatment of schizophrenia

經過分析,文件中的術語如下

文檔 分詞結果
Doc 1 breakthrough,drug,for,schizophrenia
Doc 2 new,schizophrenia,drug
Doc 3 new,approach,for,treatment,of

倒排列表的元數據結構:

(DocID;TF;<POS>)

其中:

  • DocID:出現某單詞的文檔ID

  • TF(詞頻):單詞在該文檔中出現的次數

  • POS:單詞在文檔中的位置

則它們生成的倒排索引

單詞 逆向文檔頻率 倒排列表(DocID;TF; ))
breakthrough 1 (1;1;<1>)
drug 2 (1;1;<2>),(2;1;<3>)
for 2 (1;1;<3>),(3;1;<3>)
schizophrenia 2 (1;1;<4>),(2;1;<2>)
new 2 (2;1;<1>),(3;1;<1>)
approach 1 (3;1;<2>)
treatment 1 (3;1;<4>)
of 1 (3;1;<5>)
  • ES 倒排索引包含兩個部分

    • 單詞詞典 (Term Dictionary),索引最小單位,記錄所有文檔的單詞,記錄單詞到倒排列表的關聯關係
      • 單詞詞典一般都會非常多,通過 B+ 樹或 Hash 表方式以滿足高性能的插入與查詢
    • 倒排列表(Posting List)-由倒排索引項(Posting)組成
      • 文檔 ID
      • 詞頻 TF,該單詞在文檔中出現的次數,用於相關性評分
      • 位置(Position),單詞在文檔中分詞的位置。用於語句搜索(phrase query)
      • 偏移(Offset),記錄單詞的開始結束位置,實現高亮显示

ES 也可以指定對某些字段不做索引

  • 優點:節省存儲空間
  • 缺點:字段無法被搜索

3 總結

在之前文章說了 ES 的文檔是基於 JSON 格式,在我們創建索引的時候,對每一個文檔記錄對應索引相關的信息。在對倒排索引進行搜索時,查詢單詞是否在單詞字典,獲取單詞在倒排列表的指針,獲取有該單詞單詞的文檔 Id 列表,通過 ES 的倒排索引,我們輕易對全文進行快速搜素。

系列文章

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

研擬非洲送電到中東 波灣六國還要減少石油依賴

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

使用Spring安全表達式控制系統功能訪問權限

一、SPEL表達式權限控制

spring security 3.0開始已經可以使用spring Expression表達式來控制授權,允許在表達式中使用複雜的布爾邏輯來控制訪問的權限。Spring Security可用表達式對象的基類是SecurityExpressionRoot。

表達式函數 描述
hasRole([role]) 用戶擁有指定的角色時返回true (Spring security默認會帶有ROLE_前綴),去除前綴參考
hasAnyRole([role1,role2]) 用戶擁有任意一個指定的角色時返回true
hasAuthority([authority]) 擁有某資源的訪問權限時返回true
hasAnyAuthority([auth1,auth2]) 擁有某些資源其中部分資源的訪問權限時返回true
permitAll 永遠返回true
denyAll 永遠返回false
anonymous 當前用戶是anonymous時返回true
rememberMe 當前用戶是rememberMe用戶返回true
authentication 當前登錄用戶的authentication對象
fullAuthenticated 當前用戶既不是anonymous也不是rememberMe用戶時返回true
hasIpAddress('192.168.1.0/24')) 請求發送的IP匹配時返回true

部分朋友可能會對Authority和Role有些混淆。Authority作為資源訪問權限可大可小,可以是某按鈕的訪問權限(如資源ID:biz1),也可以是某類用戶角色的訪問權限(如資源ID:ADMIN)。當Authority作為角色資源權限時,hasAuthority(’ROLE_ADMIN’)與hasRole(’ADMIN’)是一樣的效果。

二、SPEL在全局配置中的使用

我們可以通過繼承WebSecurityConfigurerAdapter,實現相關的配置方法,進行全局的安全配置(之前的章節已經講過) 。下面就為大家介紹一些如何在全局配置中使用SPEL表達式。

2.1.URL安全表達式

config.antMatchers("/system/*").access("hasAuthority('ADMIN') or hasAuthority('USER')")
      .anyRequest().authenticated();

這裏我們定義了應用/person/*URL的範圍,只有擁有ADMIN或者USER權限的用戶才能訪問這些person資源。

2.2.安全表達式中引用bean

這種方式,比較適合有複雜權限驗證邏輯的情況,當Spring Security提供的默認表達式方法無法滿足我們的需求的時候。首先我們定義一個權限驗證的RbacService。

@Component("rbacService")
@Slf4j
public class RbacService {
    //返回true表示驗證通過
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        //驗證邏輯代碼
        return true;
    }
    public boolean checkUserId(Authentication authentication, int id) {
        //驗證邏輯代碼
        return true;
    }
}

對於”/person/{id}”對應的資源的訪問,調用rbacService的bean的方法checkUserId進行權限驗證,傳遞參數為authentication對象和person的id。該id為PathVariable,以#開頭表示。

config.antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication,#id)")
      .anyRequest().access("@rbacService.hasPermission(request,authentication)");

三、 Method表達式安全控制

如果我們想實現方法級別的安全配置,Spring Security提供了四種註解,分別是@PreAuthorize , @PreFilter , @PostAuthorize 和 @PostFilter

3.1.開啟方法級別註解的配置

在Spring安全配置代碼中,加上EnableGlobalMethodSecurity註解,開啟方法級別安全配置功能。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

3.2 使用PreAuthorize註解

@PreAuthorize 註解適合進入方法前的權限驗證。只有擁有ADMIN角色才能訪問findAll方法。

@PreAuthorize("hasRole('ADMIN')")
List<Person> findAll();

3.3 使用PostAuthorize註解

@PostAuthorize 在方法執行后再進行權限驗證,適合根據返回值結果進行權限驗證。Spring EL 提供返回對象能夠在表達式語言中獲取返回的對象returnObject。下文代碼只有返回值的name等於authentication對象的name才能正確返回,否則拋出異常。

@PostAuthorize("returnObject.name == authentication.name")
Person findOne(Integer id);

3.4 使用PreFilter註解

PreFilter 針對參數進行過濾,下文代碼錶示針對ids參數進行過濾,只有id為偶數才能訪問delete方法。

//當有多個對象是使用filterTarget進行標註
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {

3.5 使用PostFilter 註解

PostFilter 針對返回結果進行過濾,特別適用於集合類返回值,過濾集合中不符合表達式的對象。

@PostFilter("filterObject.name == authentication.name")
List<Person> findAll();

期待您的關注

  • 博主最近新寫了一本書:
  • 本文轉載註明出處(必須帶連接,不能只轉文字):。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

特斯拉擠進十大最有價值汽車品牌

特斯拉(Tesla)以矽谷精神來打造汽車,一直受到持「安全第一」保守精神的傳統汽車產業攻擊,不過無可否認的,特斯拉成功在車壇打出一席之地,2016 年 6 月,行銷研究公司 WPP 與 Millward Brown 於 2016 年百大價值品牌報告中,特斯拉品牌價值達 44 億美元,超越凌志(Lexus)成為汽車品牌中第十大最有價值品牌,其中主要原因之一正是其創新精神,儘管如此,特斯拉以矽谷精神造車的品質疑慮卻也從沒停過。   特斯拉的品牌曝光率沒話說,幾乎天天都在媒體版面上,雖然不見得是因為正面的原因,如 Model 3 預購熱賣的消息佔據媒體版面,但隨之而來質疑是否能如期交貨的評論與報導也甚囂塵上。   然而,特斯拉在產業內創新並適應競爭的能力,在 WPP 與 Millward Brown 看來,是未來品牌價值的主要推動力,在兩公司進行的消費者調查中,特斯拉在品牌創新、品牌目標、品牌體驗項目超越平均值,報告中指出,特斯拉的品牌價值在近年來大幅成長,雖然特斯拉以不進行傳統廣告戰聞名,但其少量花費的行銷經費,產生的價值與效用卻相當可觀。   其他汽車品牌則大致沒有變化,豐田(Toyota)以 295 億美元守住王座,福斯(VW)則因為柴油車排放作弊事件形象大受打擊而從第二名跌落,不過旗下保時捷(Porsche)與特斯拉同樣以 44 億美元擠進前十。  
處理問題「誠意」讓人滿意   特斯拉品牌價值節節高升的同時,特斯拉品質疑慮也揮之不去,時常有車主宣稱故障,而 2016 年 4 月時特斯拉回收近 3,000 輛休旅車 Model X,主因為絞鍊故障導致車禍時第三排座椅可能會崩坍,也成為關注焦點。此外,特斯拉傳出 Model S 車主發生事故車輛損毀之後,與特斯拉交涉,最後特斯拉答應支付部分修車費用,但是卻要求車主簽下保密協定。   美國國家公路交通安全管理局(National Highway Traffic Safety Administration,NHTSA)表示這種協定可能妨礙車主向國家公路交通安全管理局回報安全問題,相當不妥,要求特斯拉不可以用保密條文限制車主,特斯拉則回應這只是在給予車主額外福利的同時,不會因此遭認定是車輛本身有安全性問題而遭遇「好心被雷親」賠償損失,並更改與車主間協定的條文。   美國國家公路交通安全管理局對更改後的條文表示滿意,並且檢查 Model S 懸吊系統後,表示沒有安全問題。   事實上 Model S 「問題發生率高於平均」早就為人詬病,不過由於特斯拉保固 8 年,加上高效率的客服,以最快速度幫助消費者解決問題,不論是馬達、差速器、剎車、資訊系統出問題,都以最不讓消費者困擾的方式盡速更換,「誠意」讓人滿意,因此雖故障率高卻還是能享有高滿意度。   但隨著品牌價值登上前十,特斯拉恐怕得更戒慎恐懼,維持得來不易的品牌價值,尤其是當空前數量的 Model 3 大量趕工出貨之後,其品質狀況如何,恐怕將會是特斯拉品牌的生死關鍵。

(首圖來源: CC BY 2.0)

(本文授權轉載自《》─〈〉)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

和大新廠積極導入生產力4.0;評估赴美設廠

汽車傳動系統製造廠和大今(23)日召開股東會,對於今年展望及未來營運規劃,和大董事長沈國榮表示,目前看來,今年整體景氣及產業方面有些遲緩和壓迫,但對於汽車零組件產業而言,今年仍可望緩步提升;他指出,未來兩年是公司成長關鍵,為因應未來發展所需,旗下大埔美分公司已正式設立,該座新廠亦積極導入生產力4.0;同時,為保有穩定的供貨及因應美國客戶特斯拉(TESLA)需求,公司也在評估前往美國設廠。   在提升生產效率方面,沈國榮指出,在持續提升品質及生產效率下,和大2010年到2015年獲利成長達4.5倍,預期今年成長幅度與2010年相比更將達到5倍;而旗下大埔美新廠也將積極推動生產力4.0,除添購自動化及先進檢驗設備外,亦規劃逐步推行智慧型自動化生產及檢驗,可望進一步提升品質管控及生產效率,以及降低人力成本,且該廠可望於8月加入供貨行列。   在其他產能規劃方面,沈國榮表示,未來兩年相當關鍵,過去接到的包括電動車及燃油車客戶訂單開始提高提貨量,兩年後仍有供應不足壓力,且因公司營收比重來自美國客戶達六成,因此,目前公司已著手了解美國相關法令及尋覓土地,評估在美國設廠的可能性,若接單量更為明朗,將赴美設廠就近供應客戶。   (本文內容由授權使用)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

VW電動車電池廠傳將設址中國

電動車的討論與實際需求全球性地提高,傳統汽車廠商也紛紛推出電動車發展時程。德國福斯汽車(Volkswagen,VW)在經歷排氣造假醜聞後,被強迫提前電動車發展時程;而龐大的電池何來?市場傳出VW將在中國設廠的消息。

外電報導,VW已準備開始興建公司第一座專門供應電動車用電池的工廠,廠址位置可能就位於中國。《AutoNews》指出,中國政府積極推動電動車,使中國本地需求潛力龐大;加上中國的原物料、勞力都很豐富,VW可能會考慮在中國設廠,以供應旗下電動車的需求。VW預計在2025年時推出30款電動車產品,旗下車款有三分之一改為電動車款。

VW估計,在中國設置一座電池工廠,約需投資20億歐元;若設置十座工廠,總投資額將達200億歐元。而VW預計,旗下電動車與插電式油電混和車的銷量,到2025年時可達到200~300萬輛。

根據中國工信部近期所推行的電動車補貼清單與辦法可知,中國政府對本國電動車產業採取較明顯的保護手段;直接由海外進口車款、零組件者,較難以獲得購車補貼。國際廠商需在中國本地成立生產鏈,才能獲得補貼資格,進而搶攻中國電動車市場。

(照片來源:Volkswagen)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表