激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SpringBoot SpringEL表達式的使用

SpringBoot SpringEL表達式的使用

2021-10-21 10:51TianXinCoord Java教程

本文主要介紹了SpringEL表達式的使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

一、SpringEL-基礎介紹

什么是SpringEL(SpEL)?

  • Spring3中引入了Spring表達式語言—SpringEL,SpEL是一種強大,簡潔的裝配Bean的方式
  • SpringEL可以通過運行期間執行的表達式將值裝配到我們的屬性或構造函數當中
  • SpringEL可以調用JDK中提供的靜態常量,獲取外部Properties文件中的的配置

為什么要使用SpringEL?

  • 平常通過配置文件或Annotaton注入的Bean,其實都可以稱為靜態性注入
  • 如Bean A中有變量A,它的值需要根據Bean B的B變量為參考,在這場景下靜態注入就對這樣的處理顯得非常無力
  • 而Spring3增加的SpringEL就可以完全滿足這種需求,而且還可以對不同Bean的字段進行計算再進行賦值,功能非常強大

如何使用SpringEL?

  • SpringEL從名字來看就能看出和EL是有點關系的,SpringEL的使用和EL表達式的使用非常相似
  • EL表達式在JSP頁面更方便的獲取后臺中的值,而SpringEL就是為了更方便獲取Spring容器中的Bean的值
  • EL使用${},而SpringEL使用#{}進行表達式的聲明

兩者主要區別

  • $是去找外部配置的參數,將值賦過來
  • #是SpEL表達式,去尋找對應變量的內容
  • 也可以直接使用@value("常量")注入不使用EL,這樣寫法與直接賦值等價

如果是在Spring中使用可以使用**@PropertySource("classpath:my.properties")**加載對應配置文件

二、EL表達式-基礎使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
# 配置文件
com:
  codecoord:
    el:
      num: 1001
      name: el
      language:
        - java
        - spring
        - mysql
        - linux
      # 逗號分隔可以注入列表
      language02: java,spring,mysql,linux

使用EL注入簡單值

?
1
2
3
4
5
6
/**
 * 注入簡單值,直接注入不使用EL,EL不支持直接指定常量
 * 直接在EL中指定的常量會當做配置處理,和直接賦值等價
 */
@Value("1432516744")
private Integer no;

注入配置文件屬性值

?
1
2
3
4
5
6
7
8
9
10
/**
 * 注入整型屬性值
 */
@Value("${com.codecoord.el.num}")
private Integer num;
/**
 * 注入字符屬性值
 */
@Value("${com.codecoord.el.name}")
private String name;

注入默認值

?
1
2
3
4
5
6
/**
 * 注入字符不存在屬性值并指定默認值,默認值使用過冒號分隔 :
 * 注入常量其實就可以指定一個不存在的配置然后使用默認值,此處skill的值為java
 */
@Value("${com.codecoord.el.skill:java}")
private String skill;

注入列表

  • 不支持直接配置文件中數組語法格式注入列表
  • 可以識別使用逗號,分隔的配置,spring默認以,分隔
?
1
2
3
4
5
// 錯誤寫法:不支持直接注入yml列表格式語法列表
@Value("${com.codecoord.el.language}")
private List<String> listLanguage;
@Value("${com.codecoord.el.language}")
private String[] strLanguage;
?
1
2
3
4
5
6
7
/**
 * 支持,分隔的注入列表
 */
@Value("${com.codecoord.el.language02}")
private List<String> listLanguage02;
@Value("${com.codecoord.el.language02}")
private String[] strLanguage02;

完整參考如下

配置文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
server:
  port: 8888
com:
  codecoord:
    el:
      num: 1001
      name: el
      language:
        - java
        - spring
        - mysql
        - linux
      # 逗號分隔可以注入列表
      language02: java,spring,mysql,linux

屬性配置類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
import java.util.List;
 
@Data
@Component
public class ElConfig {
    /**
     * 注入簡單值,直接注入不使用EL,EL不支持直接指定常量
     * 直接在EL中指定的常量會當做配置處理,和直接賦值等價
     */
    @Value("1432516744")
    private Integer no;
    /**
     * 注入整型屬性值
     */
    @Value("${com.codecoord.el.num}")
    private Integer num;
    /**
     * 注入字符屬性值
     */
    @Value("${com.codecoord.el.name}")
    private String name;
    /**
     * 注入字符不存在屬性值并指定默認值,默認值使用過冒號分隔 :
     * 注入常量其實就可以指定一個不存在的配置然后使用默認值,此處skill的值為java
     */
    @Value("${com.codecoord.el.skill:java}")
    private String skill;
    /// 不支持直接注入列表
    /*@Value("${com.codecoord.el.language}")
    private List<String> listLanguage;
    @Value("${com.codecoord.el.language}")
    private String[] strLanguage;*/
    /**
     * 支持,分隔的注入列表
     */
    @Value("${com.codecoord.el.language02}")
    private List<String> listLanguage02;
    @Value("${com.codecoord.el.language02}")
    private String[] strLanguage02;
}

向controller中注入配置類,然后訪問接口測試結果如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
 "no": 1432516744,
 "num": 1001,
 "name": "el",
 "skill": "java",
 "listLanguage02": [
  "java",
  "spring",
  "mysql",
  "linux"
 ],
 "strLanguage02": [
  "java",
  "spring",
  "mysql",
  "linux"
 ]
}

三、SpringEL-基礎使用

1、使用SpEL注入簡單值和普通EL注入使用基本一致
2、SpEl注入map

  • 配置文件中需要使用雙引號括起來,否則將會注入失敗,key為單引號
?
1
2
3
# SpEl
spEl:
  mapInject: "{'name': 'SpEl', 'website': 'http://www.codeocord.com'}"

java類中先使用${spEl.mapInject}注入字符串值,#{}會解析字符串的值轉為map

?
1
2
@Value("#{${spEl.mapInject}}")
private Map<String, String> mapInject;

3、SpEl注入list

  • 除了可以通過EL注入listI外,也可以使用#{${}.split('分隔符')}的方式注入List
  • 配置文件中例如使用#分隔
?
1
2
spEl:
  listInject: "44#11#99#100"

java類中先使用${spEl.listInject}注入字符串值,內容使用單引號括起來,然后對字符串使用split方法分隔
提示:避免為空情況,可以給一個默認值空串

?
1
2
@Value("#{'${spEl.listInject:}'.split('#')}")
 private List<String> listInject;

4、動態注入

上述注入都是靜態注入,SpEl支持從Spring容器中注入信息,稱為動態注入。動態注入類如下 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.stereotype.Component;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
@Component
@Data
public class SpElConstant {
    private String name = "SpElConstant-name";
    private String nickname = "tianxin";
    private int num = 100;
    private List<String> product = new ArrayList<String>() {{
        add("huaweiMate30Pro");
        add("xiaomi10x5g");
    }};
    private Map<String, String> productMap = new HashMap<String, String>() {{
        put("huaweiMate30Pro", "5999");
        put("xiaomi10x5g", "4999");
    }};
    private List<City> cityList = new ArrayList<City>() {{
        add(new City("深圳", 1000L));
        add(new City("杭州", 2000L));
        add(new City("貴陽", 900L));
    }};
 
    public String showProperty() {
        return "showProperty-無參數";
    }
 
    public String showProperty(String name) {
        return "showProperty-" + name;
    }
 
    @Data
    @AllArgsConstructor
    static class City {
        private String name;
        private long population;
    }
}

SpEl支持和不支持操作

  • 支持動態注入實例,類似于對象自動注入
  • SPL不支持直接注入配置文件中的配置
  • 支持調用靜態和實例方法
    • 靜態方法:@Value("#{T(package.ClassName).ConstFieldName")
  • 支持調用靜態類或常量
  • 支持運算符運算
  • 支持操作集合
  • 支持查詢篩選集合和投影

注入完整操作如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
import java.util.List;
import java.util.Map;
 
@Data
@Component
public class SpElConfig {
    /// 不支持直接注入配置文件值
    /*@Value("#{com.codecoord.el.num}")
    private Integer num;*/
    /**
     * 對象注入
     */
    @Value("#{spElConstant}")
    private SpElConstant spElConstant;
    /**
     * 注入ID為spElConstant Bean中的STR常量/變量
     */
    @Value("#{spElConstant.name}")
    private String name;
    /**
     * 調用無參方法
     */
    @Value("#{spElConstant.showProperty()}")
    private String method1;
    /**
     * 有參接收字符串的方法
     */
    @Value("#{spElConstant.showProperty('Hell SpringEL')}")
    private String method2;
    /**
     * 方法返回的String為大寫
     */
    @Value("#{spElConstant.showProperty().toUpperCase()}")
    private String method3;
    /**
     * 若使用method3這種方式,若果showProperty返回為null
     * 將會拋出NullPointerException,可以使用以下方式避免
     * 使用?.符號代表若然左邊的值為null,將不執行右邊方法
     */
    @Value("#{spElConstant.showProperty()?.toUpperCase()}")
    private String method4;
    /**
     * 注入math常量
     */
    @Value("#{T(java.lang.Math).PI}")
    private double pi;
    /**
     * 用random方法獲取返回值
     */
    @Value("#{T(java.lang.Math).random()}")
    private double random;
    /**
     * 獲取文件路徑符號
     */
    @Value("#{T(java.io.File).separator}")
    private String separator;
    /**
     * 拼接字符串
     */
    @Value("#{spElConstant.nickname + ' ' + spElConstant.name}")
    private String concatString;
    /**
     * 對數字類型進行運算,spElConstant擁有num屬性
     */
    @Value("#{3 * T(java.lang.Math).PI + spElConstant.num}")
    private double operation;
    /**
     * 進行邏輯運算
     */
    @Value("#{spElConstant.num > 100 and spElConstant.num <= 200}")
    private boolean logicOperation;
    /**
     * 進行或非邏輯操作
     */
    @Value("#{not (spElConstant.num == 100) or spElConstant.num <= 200}")
    private boolean logicOperation2;
    /**
     * 使用三元運算符
     */
    @Value("#{spElConstant.num > 100 ? spElConstant.num : spElConstant.num + 100}")
    private Integer logicOperation3;
    /**
     * 獲取下標為0的元素
     */
    @Value("#{spElConstant.product[0]}")
    private String str;
    /**
     * 獲取下標為0元素的大寫形式
     */
    @Value("#{spElConstant.product[0]?.toUpperCase()}")
    private String upperStr;
    /**
     * 獲取map中key為hello的value
     */
    @Value("#{spElConstant.productMap['hello']}")
    private String mapValue;
    /**
     * 根據product下標為0元素作為key獲取testMap的value
     */
    @Value("#{spElConstant.productMap[spElConstant.product[0]]}")
    private String mapStrByproduct;
    /**
     * 注入人口大于等于1000人口的城市
     */
    @Value("#{spElConstant.cityList.?[population >= 1000]}")
    private List<SpElConstant.City> cityList;
    /**
     * 注入人口等于900人口的城市
     */
    @Value("#{spElConstant.cityList.?[population == 900]}")
    private SpElConstant.City city;
    /**
     * 注入人口大于等于1000人口的城市,且只保留城市名稱
     */
    @Value("#{spElConstant.cityList.?[population >= 1000].![name]}")
    private List<String> cityName;
}

注入結果

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
{
 "spElConstant": {
  "name": "SpElConstant-name",
  "nickname": "tianxin",
  "num": 100,
  "product": [
   "huaweiMate30Pro",
   "xiaomi10x5g"
  ],
  "productMap": {
   "xiaomi10x5g": "4999",
   "huaweiMate30Pro": "5999"
  },
  "cityList": [
   {
    "name": "深圳",
    "population": 1000
   },
   {
    "name": "杭州",
    "population": 2000
   },
   {
    "name": "貴陽",
    "population": 900
   }
  ]
 },
 "name": "SpElConstant-name",
 "method1": "showProperty-無參數",
 "method2": "showProperty-Hell SpringEL",
 "method3": "SHOWPROPERTY-無參數",
 "method4": "SHOWPROPERTY-無參數",
 "pi": 3.141592653589793,
 "random": 0.19997238292235787,
 "separator": "\\",
 "concatString": "tianxin SpElConstant-name",
 "operation": 109.42477796076938,
 "logicOperation": false,
 "logicOperation2": true,
 "logicOperation3": 200,
 "str": "huaweiMate30Pro",
 "upperStr": "HUAWEIMATE30PRO",
 "mapValue": null,
 "mapStrByproduct": "5999",
 "cityList": [
  {
   "name": "深圳",
   "population": 1000
  },
  {
   "name": "杭州",
   "population": 2000
  }
 ],
 "city": {
  "name": "貴陽",
  "population": 900
 },
 "cityName": [
  "深圳",
  "杭州"
 ]
}

Spring操作外部Properties文件

?
1
2
3
<!-- 首先通過applicaContext.xml中<util:properties>增加properties文件 -->
<!-- 注意需要引入Spring的util schemea命名空間和注意id屬性,id屬性將在SpringEL中使用 -->
<util:properties id="db" location="classpath:application.properties"/>
?
1
2
3
4
5
public class TestSpringEL {
 // 注意db為xml文件中聲明的id
 @Value("#{db['jdbc.url']}")
 private String propertiesValue;
}

SpringEL在使用時僅僅是一個字符串,不易于排錯與測試,也沒有IDE檢查我們的語法,當出現錯誤時較難檢測,復雜的表達式不建議通過SpringEL方式注入。在非必要情況下,不推薦使用SpEl的復雜注入,清晰可讀的代碼更為重要且有利于排查問題

四、屬性自動注入

上述都是通過指定字段進行注入,可以通過@ConfigurationProperties指定前綴進行自動注入

?
1
org.springframework.boot.context.properties.ConfigurationProperties

配置類

?
1
2
3
4
5
6
user:
  id: ${random.uuid}
  name: autowire
  address: unknown
  website: www.codecoord.com
  age: ${random.int}

自動屬性注入類

  • 通過prefix指定前端為user,然后將會把user.后的類型按照名稱進行注入
  • 注意必須要提供setter方法
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
@Component
@ConfigurationProperties(prefix = "user")
@Data
public class UserConfig {
    private String id;
    private String name;
    private String address;
    private String website;
    private Integer age;
}

可以通過@EnableConfigurationProperties(value = UserConfig.class)將UserConfig再次強制注入,問題出現在如果UserConfig為第三方jar包內的配置類,則可能出現屬性沒有注入情況,所以可以指定注入

到此這篇關于SpringBoot SpringEL表達式的使用的文章就介紹到這了,更多相關SpringEL表達式內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://juejin.cn/post/6987993458807930893

延伸 · 閱讀

精彩推薦
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7472021-02-04
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
主站蜘蛛池模板: av免费在线观看不卡 | 亚洲成人欧美在线 | 草莓福利视频在线观看 | 看免费毛片 | 91成人免费版 | 日韩精品二区 | 亚洲人成综合第一网 | 国产69精品久久久久久野外 | 在线观看毛片视频 | 色综合久久久久久久久久 | 国产在线a| 在线免费视频a | 精品一区二区久久久久久久网精 | 中国妞xxxhd露脸偷拍视频 | 一级黄色大片在线观看 | 国产欧美亚洲精品a | 欧美一级爱爱 | 国产无区一区二区三麻豆 | 看免费5xxaaa毛片 | 国产超碰人人爽人人做人人爱 | 一本一道久久久a久久久精品91 | 欧美精品1区 | 狠狠干91| 亚洲第一黄色网 | 99久久久国产精品免费观看 | 国产精品二区高清在线 | 有色视频在线观看 | 欧美a在线观看 | 蜜桃视频在线免费观看 | 久久久日韩av免费观看下载 | 91精品国产乱码久久桃 | 黄视频网站免费在线观看 | 综合网日日天干夜夜久久 | 九七在线视频 | 国产va在线观看免费 | 92看片淫黄大片欧美看国产片 | 亚州欧美在线 | 欧美精品久久久久久久久老牛影院 | 久久免费激情视频 | 国产精品久久久久久久久久iiiii | 色污视频|