SpringBoot SpringEL表达式的使用

目录
  • 一、SpringEL-基础介绍
  • 二、EL表达式-基础使用
  • 三、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表达式-基础使用

# 配置文件
com:
  codecoord:
    el:
      num: 1001
      name: el
      language:
        - java
        - spring
        - mysql
        - linux
      # 逗号分隔可以注入列表
      language02: java,spring,mysql,linux

使用EL注入简单值

/**
 * 注入简单值,直接注入不使用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;

注入列表

  • 不支持直接配置文件中数组语法格式注入列表
  • 可以识别使用逗号,分隔的配置,spring默认以,分隔
// 错误写法:不支持直接注入yml列表格式语法列表
@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;

完整参考如下

配置文件

server:
  port: 8888
com:
  codecoord:
    el:
      num: 1001
      name: el
      language:
        - java
        - spring
        - mysql
        - linux
      # 逗号分隔可以注入列表
      language02: java,spring,mysql,linux

属性配置类

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中注入配置类,然后访问接口测试结果如下

{
 "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为单引号
# SpEl
spEl:
  mapInject: "{'name': 'SpEl', 'website': 'http://www.codeocord.com'}"

java类中先使用${spEl.mapInject}注入字符串值,#{}会解析字符串的值转为map

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

3、SpEl注入list

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

java类中先使用${spEl.listInject}注入字符串值,内容使用单引号括起来,然后对字符串使用split方法分隔
提示:避免为空情况,可以给一个默认值空串

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

4、动态注入

上述注入都是静态注入,SpEl支持从Spring容器中注入信息,称为动态注入。动态注入类如下

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")
  • 支持调用静态类或常量
  • 支持运算符运算
  • 支持操作集合
  • 支持查询筛选集合和投影

注入完整操作如下

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;
}

注入结果

{
 "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文件

<!-- 首先通过applicaContext.xml中<util:properties>增加properties文件 -->
<!-- 注意需要引入Spring的util schemea命名空间和注意id属性,id属性将在SpringEL中使用 -->
<util:properties id="db" location="classpath:application.properties"/>
public class TestSpringEL {
 // 注意db为xml文件中声明的id
 @Value("#{db['jdbc.url']}")
 private String propertiesValue;
}

SpringEL在使用时仅仅是一个字符串,不易于排错与测试,也没有IDE检查我们的语法,当出现错误时较难检测,复杂的表达式不建议通过SpringEL方式注入。在非必要情况下,不推荐使用SpEl的复杂注入,清晰可读的代码更为重要且有利于排查问题

四、属性自动注入

上述都是通过指定字段进行注入,可以通过@ConfigurationProperties指定前缀进行自动注入

org.springframework.boot.context.properties.ConfigurationProperties

配置类

user:
  id: ${random.uuid}
  name: autowire
  address: unknown
  website: www.codecoord.com
  age: ${random.int}

自动属性注入类

  • 通过prefix指定前端为user,然后将会把user.后的类型按照名称进行注入
  • 注意必须要提供setter方法
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表达式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot 调度任务及常用任务表达式

    1.首先需要用@EnableScheduling注解到*applicatin.java,用来检测是否有调度任务. 2.@Scheduled 注解用于标注这个方法是一个定时任务的方法.Spring会自动扫描这个注解,启动调度任务. package com.david.translate.quartz; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.schedulin

  • springboot Quartz动态修改cron表达式的方法

    1.概述: 在开发中有的时候需要去手动禁止和启用定时任务,修改定时任务的cron表达式然后再让其动态生效,之前有过SSM的类似的业务的开发但是忘记写下来了...只好重新温习了一次,加上最近比较流行springBoot所以升级了一下用springBoot来完成. 2.关联技术 SpringBoot.Quartz.H2.thymeleaf (好像就这么多) 3.具体流程 1)首先去手动创建一个调度器工厂对象-SchedulerFactoryBean;其实应该不用手动创建的但是为了顾及到业务的复杂性所

  • SpringBoot SpringEL表达式的使用

    目录 一.SpringEL-基础介绍 二.EL表达式-基础使用 三.SpringEL-基础使用 四.属性自动注入 一.SpringEL-基础介绍 什么是SpringEL(SpEL)? Spring3中引入了Spring表达式语言-SpringEL,SpEL是一种强大,简洁的装配Bean的方式 SpringEL可以通过运行期间执行的表达式将值装配到我们的属性或构造函数当中 SpringEL可以调用JDK中提供的静态常量,获取外部Properties文件中的的配置 为什么要使用SpringEL? 平

  • 基于springEL表达式详解及应用

    目录 基于springEL表达式详解及应用 什么是SpringEL? 为什么要使用SpringEL? 如何使用SpringEL? 使用SpringEL注入简单值 使用SpringEL调用方法 SpringEL调用静态类或常量 SpringEL运算 SpringEL使用正则表达式 SpringEL操作集合 Spring操作外部Properties文件 SpringEL查询筛选集合和投影 优点: 缺点: 笔者实际应用: 总结: 基于springEL表达式详解及应用 什么是SpringEL? Spri

  • Java SpringBoot高级用法详解

    目录 1,IDEA中Lombok作用 创建项目 2.pom.xml说明 2.1 pom.xml标签说明 2.2 依赖的相关说明 2.3 SHA1介绍 SpringBoot高级用法 YML文件说明 3.需求说明 3.2利用properties文件为属性赋值 总结 1,IDEA中Lombok作用 数据库: 库 表 字段 对应的值 user表(id,name,age) 实体对象pojo: 用来封装数据库中的数据 User类(id,name,age) 实体对象方法: Get/Set/toString/无

  • SpringBoot中的Condition包下常用条件依赖注解案例介绍

    目录 一.@ConditionalOnClass() Spring中存在指定class对象时,注入指定配置 1.首先引入pom依赖 2.实体类测试对象 3.定义@ConditionalOnClass()配置类 4.启动类测试 二.注入指定配置 1.首先引入pom依赖 2.实体类测试对象 3.定义@ConditionalOnMissingClass()配置类 4.启动类测试 三.加载指定配置 1.首先引入pom依赖 2.实体类测试对象 2.1 引入条件判断实体类 3.定义@ConditionalO

  • SpringBoot Security从入门到实战示例教程

    目录 前言 入门 测试接口 增加依赖 自定义配置 配置密码加密方式 配置AuthenticationManagerBuilder 认证用户.角色权限 配置HttpSecurity Url访问权限 自定义successHandler 自定义failureHandler 自定义未认证处理 自定义权限不足处理 自定义注销登录 前后端分离场景 提供登录接口 自定义认证过滤器 鉴权 1.注解鉴权 2.自定义Bean动态鉴权 3.扩展默认方法自定义扩展根对象SecurityExpressionRoot 登出

  • SpringBoot security安全认证登录的实现方法

    目录 前言 一.登录时序图 二.配置与代码 1.引入库 2.代码文件 参考文档 前言 本文章主要从spring security安全认证登录内部调用流程来流程分析登录过程. 一.登录时序图 时序原图 二.配置与代码 1.引入库 pom.xml: <!-- Spring框架基本的核心工具 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-contex

  • Redis+Caffeine两级缓存的实现

    目录 优点与问题 准备工作 V1.0版本 V2.0版本 V3.0版本 在高性能的服务架构设计中,缓存是一个不可或缺的环节.在实际的项目中,我们通常会将一些热点数据存储到Redis或MemCache这类缓存中间件中,只有当缓存的访问没有命中时再查询数据库.在提升访问速度的同时,也能降低数据库的压力. 随着不断的发展,这一架构也产生了改进,在一些场景下可能单纯使用Redis类的远程缓存已经不够了,还需要进一步配合本地缓存使用,例如Guava cache或Caffeine,从而再次提升程序的响应速度与

  • 详解Spring极速集成注解redis实录

    Redis 做为基于内存的 Key-Value 数据库,用来做缓存服务器性价比相当高. 官方推出的面向 Java 的 Client Jedis,提供了很多接口和方法,可以让 Java 操作使用 Redis. Spring Data Redis 为 Spring 团队对 Jedis 进行了封装,集成 Jedis 的一些命令和方法. 本文重点描述集成过程,能让你迅速的通过 spring-data-redis 将 redis 集成到 spring 项目中,毕竟大家都忙的. 1. 添加项目依赖 <!--

  • Spring maven filtering使用方法详解

    SpringEL表达式取值一般是${var}方式取值, 见于application.properties和@Value("${var}")中 maven的pom.xml文件中也有类似的取值表达式, 也是通过${var}的方式取值 然而: 它们并不是一个东西! EL表达式适用于配置文件及代码中的注解 maven的占位符取值表达式默认仅仅适用于pom.xml文件中 我们的需求大多是想打通二者的交流,如何做? 此时filtering就派上用场了 maven的占位符解析表达式的使用场合默认只在

  • Spring @Cacheable注解中key的使用详解

    目录 Spring @Cacheable注解中key使用 下面是几个使用参数作为key的示例 condition属性指定发生的条件 @CachePut @CacheEvict allEntries属性 beforeInvocation属性 @Caching 使用自定义注解 @Cacheable 拼接key Spring @Cacheable注解中key使用 key属性是用来指定Spring缓存方法的返回结果时对应的key的.该属性支持SpringEL表达式.当我们没有指定该属性时,Spring将

随机推荐