SpringBoot SpEL语法扫盲与查询手册的实现

Spring 表达式语言简称为 SpEL,一种类似 Ognl 的对象图导航语言(对于 ognl 不熟悉的同学可以参考一下: Ognl 系列博文)

SeEL 为 Spring 提供了丰富的想象空间,除了一些基本的表达式操作之外,还支持

  • 访问 bean 对象
  • 调用方法,访问(修改)类(对象)属性
  • 计算表达式
  • 正则匹配
  • ...

 I. 语法百科

以下内容均来自官方文档: https://docs.spring.io/spring-framework/docs/5.2.1.RELEASE/spring-framework-reference/core.html#expressions

1. 字面表达式

Spel 支持strings, numeric values (int, real, hex), boolean, and null等基本类型,实例如下

ExpressionParser parser = new SpelExpressionParser();

// evals to "Hello World"
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();

// double 类型
double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();

// evals to 2147483647
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();

boolean trueValue = (Boolean) parser.parseExpression("true").getValue();

Object nullValue = parser.parseExpression("null").getValue();

请注意,字符串需要用单引号包括,浮点数默认为 double 类型,用null表示null object

输出结果

str: Hello World
double: 6.0221415E23
int: 2147483647
bool: true
null: null

2. Inline List

通过{}来表明 List 表达式,一个空的列表直接用{}表示

ExpressionParser parser = new SpelExpressionParser();
// Integer列表
List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue();
System.out.println("list: " + numbers);

// List的元素为List
List<List> listlOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue();
System.out.println("List<List> : " + listlOfLists);

输出结果

list: [1, 2, 3, 4]
List<List> : [[a, b], [x, y]]

3. Inline map

{key:value}来表示 map 表达式,空 Map 直接用{:}表示

private void map() {
  ExpressionParser parser = new SpelExpressionParser();
  Map map = (Map) parser.parseExpression("{txt:'Nikola',dob:'10-July-1856'}").getValue();
  System.out.println("map: " + map);
  Map mapOfMaps =
      (Map) parser.parseExpression("{txt:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}")
          .getValue();
  System.out.println("Map<Map>: " + mapOfMaps);
}

输出结果

map: {txt=Nikola, dob=10-July-1856}
Map<Map>: {txt={first=Nikola, last=Tesla}, dob={day=10, month=July, year=1856}}

4. 数组

数组可以借助new构造方法来实现,通过下标ary[index]的方式访问数组中的元素

private void array() {
   ExpressionParser parser = new SpelExpressionParser();
   int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue();
   System.out.println("array: " + JSON.toJSONString(numbers1));

   // Array with initializer
   int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue();
   System.out.println("array: " + JSON.toJSONString(numbers2));

   // Multi dimensional array
   int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue();
   System.out.println("array: " + JSON.toJSONString(numbers3));

   int[] nums = new int[]{1, 3, 5};
   EvaluationContext context = new StandardEvaluationContext();
   context.setVariable("num", nums);

   // 通过下标访问数组中的元素
   Integer numVal = parser.parseExpression("#num[1]").getValue(context, Integer.class);
   System.out.println("numVal in array: " + numVal);
}

输出如下

array: [0,0,0,0]
array: [1,2,3]
array: [[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]]
numVal in array: 3

5. 表达式

Spel 支持一些 Java 语法中常规的比较判断,算数运算,三元表达式,类型判断,matches正则匹配等基表表达式

下面给出一些简单的实例

public void expression() {
  ExpressionParser parser = new SpelExpressionParser();
  // 运算
  System.out.println("1+2= " + parser.parseExpression("1+2").getValue());
  // 比较
  System.out.println("1<2= " + parser.parseExpression("1<2").getValue());
  System.out.println("true ? hello : false > " + parser.parseExpression("3 > 2 ? 'hello': 'false' ").getValue());
  // instanceof 判断,请注意静态类,用T进行包装
  System.out.println("instance : " + parser.parseExpression("'a' instanceof T(String)").getValue());
  //正则表达式
  System.out.println("22 是否为两位数字 :" + parser.parseExpression("22 matches '\\d{2}'").getValue());
}

输出结果

1+2= 3
1<2= true
true ? hello : false > hello
instance : true
22 是否为两位数字 :true

6. Type 与静态类

如果想获取 Class 对象,或者访问静态成员/方法,可以借助T()语法来实现

比如我们有一个静态类

public static class StaClz {
  public static String txt = "静态属性";

  public static String hello(String tag) {
    return txt + " : " + tag;
  }
}

如果希望访问静态属性txt, 表达式可以写成T(com.git.hui.boot.spel.demo.BasicSpelDemo.StaClz).txt,请注意圆括号中的是完整签名;访问静态方法方式类似

public void type() {
  // class,静态类
  ExpressionParser parser = new SpelExpressionParser();
  String name =
      parser.parseExpression("T(com.git.hui.boot.spel.demo.BasicSpelDemo.StaClz).txt").getValue(String.class);
  System.out.println("txt: " + name);

  String methodReturn =
      parser.parseExpression("T(com.git.hui.boot.spel.demo.BasicSpelDemo.StaClz).hello" + "('一灰灰blog')")
          .getValue(String.class);
  System.out.println("static method return: " + methodReturn);

  // class类获取
  Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);
  System.out.println("class: " + stringClass.getName());
}

输出结果如下

txt: 静态属性
static method return: 静态属性 : 一灰灰blog
class: java.lang.String

上面的写法,请重点看一下T(String),这里的 String 没有用完整的包路径,即直接位于java.lang包下的类,是可以省略掉完整包名的,就像我们平时写代码时,也不需要显示的加一个import java.lang.*

7. 构造方法

上面介绍 array 的时候,就介绍了使用new来创建数组对象,当然也可以直接构造其他的普通对象, 如我们新建一个测试类

public static class Person {
  private String name;

  private int age;

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String getName() {
    return name;
  }

  public int getAge() {
    return age;
  }

  @Override
  public String toString() {
    return "Person{" + "txt='" + name + '\'' + ", age=" + age + '}';
  }
}

通过 SpEl 创建一个对象的实例

public void construct() {
  ExpressionParser parser = new SpelExpressionParser();
  Person person = parser.parseExpression("new com.git.hui.boot.spel.demo.BasicSpelDemo.Person('一灰灰', 20)")
      .getValue(Person.class);
  System.out.println("person: " + person);
}

输出结果如下:

person: Person{txt='一灰灰', age=20}

请注意,构造方法中类的完整签名

8. 变量引用

细心的小伙伴,在上面介绍数组的成员演示的实例中,写法如"#num[1]",这个 num 前面有一个#,这是一个语法定义,有#修饰的表示变量访问

要理解这一小节,首先得理解EvaluationContext, 在我们的 SpEL 表达式的解析中,getValue有一个参数就是这个 Context,你可以将他简单理解为包含一些对象的上下文,我们可以通过 SpEL 的语法,来访问操作 Context 中的某些成员、成员方法属性等

一般的操作过程如下:

  • context.setVariable("person", person); 向EvaluationContext中塞入成员变量
  • parser.parseExpression(xxx).getValue(context) 解析 SpEL 表达式,context 必须作为传参丢进去哦

一个简单的实例

public void variable() {
  ExpressionParser parser = new SpelExpressionParser();
  Person person = new Person("一灰灰blog", 18);
  EvaluationContext context = new StandardEvaluationContext();
  context.setVariable("person", person);

  String name = parser.parseExpression("#person.getName()").getValue(context, String.class);
  System.out.println("variable name: " + name);

  Integer age = parser.parseExpression("#person.age").getValue(context, Integer.class);
  System.out.println("variable age: " + age);
}

输出结果如下

variable name: 一灰灰blog
variable age: 18

友情提示,如果访问对象的私有 Field/method,会抛异常

9. 函数

Context 中的变量,除了是我们常见的基本类型,普通的对象之外,还可以是方法,在setVariable时,设置的成员类型为method即可

public void function() {
  try {
    ExpressionParser parser = new SpelExpressionParser();
    EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    // 注册一个方法变量,参数为method类型
    context.setVariable("hello", StaClz.class.getDeclaredMethod("hello", String.class));

    String ans = parser.parseExpression("#hello('一灰灰')").getValue(context, String.class);
    System.out.println("function call: " + ans);
  } catch (Exception e) {
    e.printStackTrace();
  }
}

输出结果如下

function call: 静态属性 : 一灰灰

10. bean 访问

在 Spring 中,什么对象最常见?当然是 bean, 那么我们可以直接通过 SpEL 访问 bean 的属性、调用方法么?

要访问 bean 对象,所以我们的EvaluationContext中需要包含 bean 对象才行

借助BeanResolver来实现,如context.setBeanResolver(new BeanFactoryResolver(applicationContext));
其次访问 bean 的前缀修饰为@符号
为了演示这种场景,首先创建一个普通的 Bean 对象

@Data
@Component
public class BeanDemo {

  private String blog = "https://spring.hhui.top";

  private Integer num = 8;

  public String hello(String name) {
    return "hello " + name + ", welcome to my blog " + blog + ", now person: " + num;
  }
}

接着我们需要获取ApplicationContext,所以可以稍微改一下我们的测试类,让它继承自ApplicationContextAware

private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  this.applicationContext = applicationContext;
}

public void bean() {
  ExpressionParser parser = new SpelExpressionParser();
  StandardEvaluationContext context = new StandardEvaluationContext();
  context.setBeanResolver(new BeanFactoryResolver(applicationContext));

  // 获取bean对象
  BeanDemo beanDemo = parser.parseExpression("@beanDemo").getValue(context, BeanDemo.class);
  System.out.println("bean: " + beanDemo);

  // 访问bean方法
  String ans = parser.parseExpression("@beanDemo.hello('一灰灰blog')").getValue(context, String.class);
  System.out.println("bean method return: " + ans);
}

上面的写法和之前的并没有太大的区别,实际输出结果如下

bean: BeanDemo(blog=https://spring.hhui.top, num=8)
bean method return: hello 一灰灰blog, welcome to my blog  https://spring.hhui.top, now person: 8

11. ifElse

SpEL 支持三元表达式,在上述的表达式中也给出了实例

public void ifThenElse() {
  // 三元表达式,? :
  ExpressionParser parser = new SpelExpressionParser();
  String ans = parser.parseExpression("true ? '正确': '错误'").getValue(String.class);
  System.out.println("ifTheElse: " + ans);
}

输出结果如下

ifTheElse: 正确

12. elvis

xx != null ? xx : yy => xx?:yy

这个也属于我们经常遇到的一种场景,如果 xx 为 null,则返回 yy;否则直接返回 xx;简化写法为 elvis 写法: xx?:yy

public void elvis() {
  // xx != null ? xx : yy => xx?:yy
  ExpressionParser parser = new SpelExpressionParser();
  EvaluationContext context = new StandardEvaluationContext();
  context.setVariable("name", null);
  String name = parser.parseExpression("#name?:'Unknown'").getValue(context, String.class);
  System.out.println("elvis-before " + name);

  context.setVariable("name", "Exists!");
  name = parser.parseExpression("#name?:'Unknown'").getValue(context, String.class);
  System.out.println("elvis-after " + name);
}

输出结果如下

elvis-before Unknown
elvis-after Exists!

13. 安全表达式

在 java 中,最常见最讨厌的是一个就是 NPE 的问题,SpEL 中当然也可能出现这种情况,但是若在 SpEL 中进行非空判断,那就很不优雅了,SpEL 提供了xx?.yy的写法来避免 npe,即

xx == null ? null : xx.yy => xx?.yy

举例说明

public void safeOperate() {
  // 防npe写法, xx == null ? null : xx.yy => xx?.yy
  ExpressionParser parser = new SpelExpressionParser();
  Person person = new Person(null, 18);

  String name = parser.parseExpression("name?.length()").getValue(person, String.class);
  System.out.println("safeOperate-before: " + name);

  person.name = "一灰灰blog";
  name = parser.parseExpression("name?.length()").getValue(person, String.class);
  System.out.println("safeOperate-after: " + name);
}

输出结果如下

safeOperate-before: null
safeOperate-after: 7

14. 容器截取

遍历容器,获取子集,相当于 jdk8 Stream 中 filter 用法,语法格式如下

xx.?[expression], 请注意中括弧中的表达式必须返回 boolean

举例说明

public void collectionSelection() {
  // 容器截取,返回满足条件的子集
  // xx.?[expression] , 将满足expression的子元素保留,返回一个新的集合,类似容器的 filter
  List<Integer> list = new ArrayList<>(Arrays.asList(1, 3, 4, 6, 7, 8, 9));
  ExpressionParser parser = new SpelExpressionParser();

  EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
  context.setVariable("list", list);
  // 用 #this 来指代列表中的迭代元素
  List<Integer> subList = (List<Integer>) parser.parseExpression("#list.?[#this>5]").getValue(context);
  System.out.println("subList: " + subList);

  Map<String, Integer> map = new HashMap<>();
  map.put("a", 1);
  map.put("b", 10);
  map.put("c", 4);
  map.put("d", 7);
  context.setVariable("map", map);
  // 表达式内部用key, value 来指代map的k,v
  Map subMap = parser.parseExpression("#map.?[value < 5]").getValue(context, Map.class);
  System.out.println("subMap: " + subMap);

  subMap = parser.parseExpression("#map.?[key == 'a']").getValue(context, Map.class);
  System.out.println("subMap: " + subMap);
}

输出结果如下

subList: [6, 7, 8, 9]
subMap: {a=1, c=4}
subMap: {a=1}

注意

  • 在列表表达式中,可以通过#this来指代列表中的每一个元素
  • 在 map 表达式中,通过key, value来分别指代 map 中的k,v

15. 容器映射

将一个集合通过某种规则,映射为另一种集合,相当于 jdk8 Stream 中的 map 用法,语法如下

xx.![expression], 将表达式计算的结果作为输出容器中的成员

举例如下

public void collectionProjection() {
  // 容器操作之后,生成另一个容器, 类似lambda中的map方法
  // xx.![expression]

  List<Integer> list = new ArrayList<>(Arrays.asList(1, 3, 4, 6, 7, 8, 9));
  ExpressionParser parser = new SpelExpressionParser();
  EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
  context.setVariable("list", list);

  // 用 #this 来指代列表中的迭代元素
  List newList = parser.parseExpression("#list.![#this * 2]").getValue(context, List.class);
  System.out.println("newList: " + newList);

  Map<String, Integer> map = new HashMap<>();
  map.put("a", 1);
  map.put("b", 10);
  map.put("c", 4);
  map.put("d", 7);
  context.setVariable("map", map);
  List newListByMap = parser.parseExpression("#map.![value * 2]").getValue(context, List.class);
  System.out.println("newListByMap: " + newListByMap);
}

输出结果如下:

newList: [2, 6, 8, 12, 14, 16, 18]
newListByMap: [2, 20, 8, 14]

16. 表达式模板

SpEL 还提供了一种自定义表达式模板的方式,将字面量和表达式放在一起使用,比如下面这一条语句

"random number is #{T(java.lang.Math).random()}"

其中#{T(java.lang.Math).random()}是一个 SpEL 表达式,左边的是普通字符串,这种写法也常见于@Value注解中的属性写法,当然直接通过上面的写法执行这个语句会报错,这个时候需要指定ParserContext

举例说明

public void template() {
  // 模板,混合字面文本与表达式,使用 #{} 将表达式包裹起来
  ExpressionParser parser = new SpelExpressionParser();
  String randomPhrase = parser.parseExpression("random number is #{T(java.lang.Math).random()}",
      ParserContext.TEMPLATE_EXPRESSION).getValue(String.class);
  System.out.println("template: " + randomPhrase);
}

输出结果如下

template: random number is 0.10438946298113871

17. 小结

SpEL 属于非常强大的表达式语言了,就我个人的感觉而言,它和 OGNL 有些像,当它们的上下文中包含了 Spring 的上下文时,可以访问任何的 bean,而你可以借助它们的语法规范,做各种事情

推荐我之前的一个项目,https://github.com/liuyueyi/quick-fix,利用 ognl 结合ApplicationContext,可以随心所欲的访问控制应用中的任何 bean 对象

II. 其他

0. 项目

工程:https://github.com/liuyueyi/spring-boot-demo

源码:https://github.com/liuyueyi/spring-boot-demo/spring-boot/013-spel

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解spring boot引入外部jar包的坑

    前言:由于项目需求,短信验证码的接口需要换成阿里大于的,但是尴尬的发现阿里大于的jar包没有maven版本的,于是便开始了一上午的操蛋引包之路.按照套路来说,自然应该是百度一波,但是百度了好久,找了好多方案之后发现,没一个有用的,而且文章的抄袭.拷贝十分严重,试了N种方案,都是错的,都没有将外部jar包打包到BOOK-INF文件夹下.最终,在第N次尝试之后,终于在打的jar包里将外部的jar包导入进来.特此记录下,防止再犯!!! 首先在新建libs文件夹(根目录或者resource目录下都可以)

  • Spring Boot 日志配置方法(超详细)

    默认日志 Logback : 默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台.在运行应用程序和其他例子时,你应该已经看到很多INFO级别的日志了. 从上图可以看到,日志输出内容元素具体如下: 时间日期:精确到毫秒 日志级别:ERROR, WARN, INFO, DEBUG or TRACE 进程ID 分隔符:- 标识实际日志的开始 线程名:方括号括起来(可能会截断控制台输出) Logger名:通常使用源代码的类名 日志内容 添加日志依赖 假如mave

  • springboot与mybatis整合实例详解(完美融合)

    简介 从 Spring Boot 项目名称中的 Boot 可以看出来,Spring Boot 的作用在于创建和启动新的基于 Spring 框架的项目.它的目的是帮助开发人员很容易的创建出独立运行和产品级别的基于 Spring 框架的应用.Spring Boot 会选择最适合的 Spring 子项目和第三方开源库进行整合.大部分 Spring Boot 应用只需要非常少的配置就可以快速运行起来. Spring Boot 包含的特性如下: 创建可以独立运行的 Spring 应用. 直接嵌入 Tomc

  • springboot项目打成war包部署到tomcat遇到的一些问题

    开发环境使用jdk1.8.0_60,把springboot 项目打成war包后, 部署到apache-tomcat-7.0.68时报错如下,换成apache-tomcat-8.0.9解决 org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/my-springboot-web-0.0.1

  • 详解SpringBoot配置连接池

    内置的连接池 目前spring Boot中默认支持的连接池有dbcp,dbcp2, tomcat, hikari三种连接池. 数据库连接可以使用DataSource池进行自动配置. 由于Tomcat数据源连接池的性能和并发,在tomcat可用时,我们总是优先使用它. 如果HikariCP可用,我们将使用它. 如果Commons DBCP可用,我们将使用它,但在生产环境不推荐使用它. 最后,如果Commons DBCP2可用,我们将使用它. 以上的几种连接池,可以通过在配置application文

  • 详解eclipse下创建第一个spring boot项目

    spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者.也就是说,Spring Boot是为了简化Spring开发而生,主要思想是降低spring的入门,使得新手可以以最快的速度让程序在spring框架下跑起来. 今天我们就来创建

  • Spring boot实现热部署的两种方式详解

    热部署是什么 大家都知道在项目开发过程中,常常会改动页面数据或者修改数据结构,为了显示改动效果,往往需要重启应用查看改变效果,其实就是重新编译生成了新的 Class 文件,这个文件里记录着和代码等对应的各种信息,然后 Class 文件将被虚拟机的 ClassLoader 加载. 而热部署正是利用了这个特点,它监听到如果有 Class 文件改动了,就会创建一个新的 ClaassLoader 进行加载该文件,经过一系列的过程,最终将结果呈现在我们眼前. 类加载机制 Java 中的类经过编译器可以把代

  • Spring boot 默认静态资源路径与手动配置访问路径的方法

    在application.propertis中配置 ##端口号 server.port=8081 ##默认前缀 spring.mvc.view.prefix=/ ## 响应页面默认后缀 spring.mvc.view.suffix=.html # 默认值为 /** spring.mvc.static-path-pattern=/** # 这里设置要指向的路径,多个使用英文逗号隔开,默认值为 classpath:/META-INF/resources/,classpath:/resources/,

  • 详解SpringBoot AOP 拦截器(Aspect注解方式)

    常用用于实现拦截的有:Filter.HandlerInterceptor.MethodInterceptor 第一种Filter属于Servlet提供的,后两者是spring提供的,HandlerInterceptor属于Spring MVC项目提供的,用来拦截请求,在MethodInterceptor之前执行. 实现一个HandlerInterceptor可以实现接口HandlerInterceptor,也可以继承HandlerInterceptorAdapter类,两种方法一样.这个不在本文

  • SpringBoot SpEL语法扫盲与查询手册的实现

    Spring 表达式语言简称为 SpEL,一种类似 Ognl 的对象图导航语言(对于 ognl 不熟悉的同学可以参考一下: Ognl 系列博文) SeEL 为 Spring 提供了丰富的想象空间,除了一些基本的表达式操作之外,还支持 访问 bean 对象 调用方法,访问(修改)类(对象)属性 计算表达式 正则匹配 ...  I. 语法百科 以下内容均来自官方文档: https://docs.spring.io/spring-framework/docs/5.2.1.RELEASE/spring-

  • Spring实战之SpEl语法实例详解

    本文实例讲述了Spring实战之SpEl语法.分享给大家供大家参考,具体如下: 一 Bean package org.crazyit.app.domain; import java.util.Date; public class Person { private Integer id; private String name; private int height; public Person() { } // 初始化全部成员变量的构造器 public Person(Integer id , S

  • springboot整合mybatis-plus 实现分页查询功能

    建一个config类 @Configuration public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor(){ return new PaginationInterceptor(); } } 编写controller post /article/search/{page}/{size} @PostMapping("search/{page}/{size}") p

  • 使用Springboot注解形式进行模糊查询

    Springboot注解形式进行模糊查询 需求: 功能需要按照商户名字做模糊查询,sql我们项目中使用的是mybatis封装好的一些常见增删改查方法(通用sql需要在pom.xml文件中加入依赖): <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter --> <dependency> <groupId>tk.mybatis</groupId> <ar

  • springboot构造树形结构数据并查询的方法

    因为项目需要,页面上需要树形结构的数据进行展示(类似下图这样),因此需要后端返回相应格式的数据. 不说废话,直接开干!!! 我这里用的是springboot+mybatis-plus+mysql,示例的接口是查询一级权限以及二级权限.三级权限整个权限树- 下面是导入的maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-

  • SpringBoot整合高德地图天气查询的全过程

    目录 申请key 相关代码 启动服务 总结 申请key 登录高德,注册,添加应用,创建key 官网api: https://lbs.amap.com/api/webservice/guide/api/weatherinfo 调用步骤: 第一步,申请"web服务 API"密钥(Key): 第二步,拼接HTTP请求URL,第一步申请的Key需作为必填参数一同发送: 第三步,接收HTTP请求返回的数据(JSON或XML格式),解析数据. 如无特殊声明,接口的输入参数和输出数据编码全部统一为U

  • SpringBoot整合PageHelper实现分页查询功能详解

    前言 本文介绍的是MyBatis 分页插件 PageHelper,如果你也在用 MyBatis,建议尝试该分页插件,这一定是最方便使用的分页插件.分页插件支持任何复杂的单表.多表分页. 官方文档:https://pagehelper.github.io/ 项目地址:https://github.com/pagehelper/Mybatis-PageHelper 使用方法 导入依赖 在中央仓库sonatype中搜索 pageHelper,找到 pagehelper-spring-boot-star

  • SpringBoot+Querydsl 框架实现复杂查询解析

    目录 概述 定义查询请求 google-like查询 特定字段的类sql查询 使用Spring Data Querydsl 利用Spring Query DSL实现动态查询 概述 查询功能是在各种应用程序里面都有应用,且非常重要的功能.用户直接使用的查询功能往往是在我们做好的UI界面上进行查询,UI会将查询请求发给查询实现的服务器,或者专门负责实现查询的一个组件.市场上有专门做查询的框架,其中比较出名,应用也比较广泛的是elasticsearch. 定义查询请求 对于服务端来说,前端UI发送过来

  • SpringBoot yaml语法与数据读取操作详解

    目录 yaml yaml语法规则 字面值表示方式: 数组表示方式: 对象数组格式: 对象数组缩略格式: 读取yaml数据 编写yaml文件 读取单一数据 读取二级数据 读取数组数据 读取服务器端口号 读取对象属性 封装全部数据到Environment对象 读取yaml引用类型属性数据 application.yml MyDataSource 读取数据 变量的引用 application.yml 读取数据 context-path @Autowired报错解决方案 yaml YAML是一种数据序列

  • MySQL中explain使用快速查询手册

    目录 一. 前言 二 . explain 使用 三. 业务实践 3.1 以 user_id 为条件进行查找的思路 3.2 以更新时间为查询条件 3.3 简单优化通过 orgId 进行切割 3.4 多索引条件的抉择 3.5 连表查询的关注点 四. 深入问题 4.1 explain 的结果能作为最终决策吗? 总结 参考 : 一. 前言 上一篇整理完了 MySQL 的性能优化方式 , 其中最常用的就是 explain . 这一篇来详细看看 explain 中各个参数的含义和扩展 , 整理出来便于使用时

随机推荐