Java开发 - Spring框架初体验

news2024/11/19 14:54:16

目录

 

前言 

了解框架的概念

Spring框架

关于Spring

在Maven中使用Spring

Spring怎么管理对象

spring怎么创建对象

通过@Bean注解创建对象

通过组件扫描创建对象

关于@ComponentScan("xxxxxx") 

Spring Bean的作用域

自动装配技术

什么是自动装配

补充

IoC与DI

@Qualifier注解

@Resource注解

未提到的内容

结语


前言 

学过Java的小伙伴都知道,Spring框架在Java中已经不是一个简单的框架那么简单了,它是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力。关于其历史,博主不再介绍,今天这篇博客的作用是帮助初学者认识这个框架,了解它的基本功能,这对后续了解SSM框架乃至微服务的开发都有极其重要的作用。

了解框架的概念

框架( Framework )是构成一类特定软件可复用设计的一组相互协作的类。框架规定了你的应用的体系结构。它定义了整体结构,类和对象的分割,各部分的主要责任,类和对象怎么协作,以及控制流程。框架预定义了这些设计参数,以便于应用设计者或实现者能集中精力于应用本身的特定细节。

你可以将框架理解为现实生活中的“毛胚房”,它已经完成了住房最基础 部分的设计,例如打地基、设计住房的基本格局、预留电路、水路的线路 接入等……当你使用一个框架时,就相当于得到了一间毛胚房,如果你想住进去,你需要做的事情主要是“装修”,把这个毛胚房加工成你希望的样子。

我们可以认为框架已经帮我们做好了基础的部分。框架对我们的帮助很大,但也因此对我们造成了一定的限制。因为需要遵守框架定下来的一些规则协议。所以在学医框架时,首先要做的就是掌握框架的使用方法,这样才能达到我们预期的目标,而关于实现原理这些,可以等到彻底掌握之后再去了解不迟。

Spring框架

Spring框架主要解决了创建对象、管理对象的问题。Spring框架的核心价值在于:开发者可以通过Spring框架提供的机制,将创建对象、管理对象的任务交给Spring来完成,而开发者不必在关注这个过程,只需要在需要创建对象的时候,通过Spring来获取即可。对了,框架我们也称之为容器,所以,Spring框架也称作Spring容器,当别人在谈到容器的时候,不至于不知道说的是什么。

Spring框架很好的支持了AOP,关于AOP,这是一块比较大比较复杂的内容,所以这里暂不多做介绍,将会在后期推出专门的博客来进行说明,本篇的意义在于让大家快速的了解Spring框架,为Java入门作基础。

关于Spring

public class UserMapper { 
    //向用户表中中插入数据 
    public void insert() {
        
    }
}

这是一个mapper类,作用是来操作操作sql来执行一些增删改查的命令的,假设我们要创建一个这样的对象:

UserMapper userMapper = new UserMapper();

只需要这么做就可以,但是在实际开发中,会存在类之间相互依赖的情况,一个对象可能需要被频繁创建,在客户端,我会声明一个全局变量,或者是属性,以方便在整个类中使用,在Java中我们当然希望也是这样的方式。事实上,你可以照猫画虎,也这样做,但是Java中提供了一种方式连对象初始化创建都不需要我们自己做,可以帮助我们大大提高开发的效率,而这,就是框架的好处。

比如:

public class UserController { 
    public UserMapper userMapper;
    public void register() { 
        userMapper.insert();
    }
}

在controller中,我们要在注册的时候使用前面的那个mapper,调用insert方法插入注册的用户数据 ,userMapper需要被new出来,我们先前说了,框架提供了便捷的方式帮助我们初始化。为什么要这么做呢?如果自行创建对象,当多个类都依赖UserMapper时,各自创建UserMapper对象, 违背了“只需要1个”的思想。 

在开发中,有许多类型的对象、配置值都需要常驻内存、需要有唯一性,或都需要多处使用,自行维护这些对象或值是非常繁琐的,比如单例。通过 Spring框架可以极大的简化这些操作,曾经听别人说过:Spring框架这种自动创建对象的能力也是一种“单例”,此单例非彼单例,只思想上是单例,以后有机会再讲。

在Maven中使用Spring

当使用Spring时,我们一般使用maven工程,在pom文件中添加依赖如下:

<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-context</artifactId> 
    <version>5.3.14</version> 
</dependency>

版本号可按需调整。推荐大家使用旧的版本,因为相对稳定一些。 

Spring怎么管理对象

spring怎么创建对象

  • Spring管理对象需要先创建对象,然后spring才能获取到对象并进行管理;
  • Spring管理的对象,我们称为Spring Bean;
  • 创建对象我们常用两种方式:
    • 通过@Bean注解
    • 通过组件扫描

不懂没关系,接下来我们分别来说说他们分别是什么。

通过@Bean注解创建对象

我们先创建一个类,比如路径如下:cn.codingfire.spring.SpringBeanPro

public class SpringBeanPro {

}

在类中添加方法:

@Configuration
public class SpringBeanPro {
    @Bean
    public Random random() {
        return new Random();
    }
}

可自定义一个类去返回一个对象,博主懒,通过Random来做。要注意的是,@Configuration注解必不可少, 方法上的@Bean注解也必不可少,不要问为什么,因为不这么做,无法达到效果,记住即可,关于这些注解的作用,其实很难描述清楚,很多注解在不同环境下语义是不一样的,但有时候,用什么注解都是一个效果,此处可不行啊,后续会出一篇注解大全来总结介绍Java中常用的注解,请大家暂时不要纠结这些注解。

本例中:

@Configuration添加在类的生明之前,表示此类是配置类,会自动执行配置类中的@Bean方法,并解读配置类上的其他注解。

@Bean添加在配置类中用于创建对象的方法之前,使得Spring框架自动调用次方法,并管理次方法饭蝴蝶结果,@Bean方法必须存在于@Configuration注解下的类中

接着,我们需要测试我们的类是否已经被spring管理,所以,需要来测试下:

  • 让Spring先跑起来,这个代码很长了,看看:
AnnotationConfigApplicationContext ac
                = new AnnotationConfigApplicationContext(SpringBeanPro.class);

这玩意不需要纠结,它只是用于加载Spring配置,注意,要在构造方法中添加参数,即我们的类。 

  • 从Spring中获取对象
Random random = (Random) ac.getBean("random");

其实就是方法的名称,这里运用了反射机制,听过的大概知道原理,不懂的也不再额外介绍,嗯~大概就是通过字符串获取实体类或方法的一种机制。 

  • 输出测试,看看有没有获取到对象
System.out.println(random);
  • 结束
ac.close();

以上代码,你需要知道的有三点:

  • getBean方法,次方法会被重载多次:
    • Object getBean(String beanName) 通过此方法,传入的beanName必须是有效的,否则将导致 NoSuchBeanDefinitionException
    • T getBean(Class<T> beanClass);使用此方法时,传入的类型在Spring中必须有且仅有1个对象,如果Spring容器中没 有匹配类型的对象,将导致NoSuchBeanDefinitionException,如果有2个或更多, 将导致NoUniqueBeanDefinitionException
    • T getBean(String beanName, Class<T> beanClass) ;此方法仍是根据传入的beanName获取对象,并且根据传入的beanClass进行类型转换
  • 两个注解,缺一不可,有意思的是,@Configuration注解并不是必须的, 但@Bean方法的使用规范是将其声明在@Configuration类中
  • 使用的@Bean注解可以传入String类型的参数,如果传入,则此注解对应的方法的返回结果的beanName就是@Bean注解中传入的String参数值,后续调用getBean() 方法时,如果需要传入beanName,就应该传入在@Bean注解中配置的String参数值,而不是方法名
@Configuration
public class SpringBeanPro {
    @Bean("random")
    public Random xxxxx() {
        return new Random();
    }
}

通过组件扫描创建对象

话不多说,直接上代码:

package cn.codingfire.spring;

import org.springframework.stereotype.Component;

@Component
public class UserMapper {

}
package cn.codingfire.spring;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("cn.codingfire.spring")
public class SpringConfig {

}

 接着进行测试,和上面其实是一样的:

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
UserMapper bean = ac.getBean(UserMapper.class);
System.out.println(bean);
ac.close();

刚刚没有把跑的结果贴出来,这里贴出来给大家看看:

cn.codingfire.spring.UserMapper@52aa2946

Process finished with exit code 0

可以看到获取到的对象是真实存在的。 这里对关键部位做个说明:

@ComponentScan注解是执行组件扫描的关键,当创建AnnotationConfigApplicationContext对象时,传入的SpringConfig配置类添加了这个注解,Spring框架就会扫描配置下的包中的所有组件类,然后为组件创建对象并管理,而UserMapper类必须在@ComponentScan注解配置的包中,否则Spring框架找不到这个类,无法创建对象。@Component仅表示此类是一个组件类,但也很重要,没有此注解,将不会创建此对象。

@ComponentScan("cn.codingfire.spring")相当重要,这是扫描的路径,如果括号中内容变成,cn.codingfire,它下面有这些包:cn.codingfire.spring,cn.codingfire.controller,cn.codingfire.mapper,cn.codingfire.pojo等等,这些包统统都会被扫描到,这一点要注意,不要扫描不需要的包,对性能是有影响的。

另外,前面说过getBean扫描的方式,这里再次重申一遍:不指定beanName,默认的beanName都是类的首字母小写的名字,仅适用于类名中的第1个字母是大写,且第2个字母是小写的情况,否则,将传入完整的类名。一般我们指定beanName多一些,会更安全。

为@Component注解指定beanName案例:

@Component("userMapperBeanName")

关于@ComponentScan("xxxxxx") 

我们点进去看下源码:

可以知道@ComponentScan("xxxxx")中的参数,如果传一个,可以不显示的指定默认参数名:value,如果需要配置多个属性,需要显示指定。

传入多个参数时,比如要扫描多个包的情况,我们看到

String[] value() default {};

说明它是一个数组类型的,可以传多个包名,但需要使用大括号:

@ComponentScan({"xxxxx"})

Spring Bean的作用域

前面提到,Spring这种创建管理对象的方式很像单例,所以:

  • 我们通常认为,Spring Bean的作用域是单例的
  • 单例的特点是:实例唯一,任何时候,类的实例对象只能有一个,创建出来后,需常驻内存,直到程序运行结束或者ApplicationContext调用了销毁的方法
  • 上面也提到过,此单例非彼单例,莫要混为一谈,只是作用域的表现完全和单例一致

那么作用域是否可以修改呢?答案是肯定的。通过在@Bean注解之前添加过@Scope注解来改变其作用域,作用域有三类,默认是单例的:

  • singleton:单例的,这是默认值,在scopeName属性的源码上明确的说明了:Defaults to an empty string "" which implies ConfigurableBeanFactory.SCOPE_SINGLETON
  • prototype:原型,也就是非单例的
  • 还有其它取值,都是不常用取值,可不用关心,自定了解即可

Spring Bean是预加载的,关于此,我们知道的还有一个懒加载,通过@Lazy来表示,如必要,可创建为懒加载的。@Lazy注解的value属性是boolean类型的,表示“是否懒加载” 。

预加载何懒加载,我不说,大家也应该知道这是什么意思,在其他语言中,我们很多时候使用懒加载来降低资源的损耗,但是在Java中略有不同,为了避免高并发时懒加载去创建对象出现问题,我们通常在Java只能够采用预加载的方式。

自动装配技术

什么是自动装配

Spring的自动装配是,当某个量需要被赋值时,可以使用特定的语法,使得Spring尝试从容器找到合适的值,并自动完成赋值其中最典型的代表是@Autowired注解,Spring会尝试从容器中找到生明的对象并初始化来为此属性赋值。

举个例子:

package cn.codingfire.spring;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("cn.codingfire.spring")
public class SpringConfig {

}
package cn.codingfire.spring;

import org.springframework.stereotype.Component;

@Repository
public class UserMapper {
    public void insert() {}
}
package cn.codingfire.spring; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 

@Controller 
public class UserController { 
    @Autowired //使用了自动装配的注解 
    private UserMapper userMapper; 
    public void registor() { 
        userMapper.insert(); //这里调用了userMapper属性的方法 
    }
}

看到没?看到没?userMapper我们没有自己初始化,但我就是可以在注册方法中使用它的insert方法,有点小激动,有木有?

测试部分不再贴了,大家可以复制代码自行尝试下,注意包名,千万要写自己的包名,也可以按照博主的包名来创建。

关于@Autowired注解,作用就是自动装配,体现为,当某个属性需要被Spring注解装配值时,在属性之前添加此注解,另外,此注解可以添加在setter方法,构造方法之前,用于在存在多个构造方法的情况下,执行加了此注解的方法,这里也不再多讲了,等你成为一只老鸟,你会在很多地方看到这种用法,但通常我们不需要这么做。

对方法的参数自动装配时,如果方法有多个参数,各参数的先后顺序是不重要的。

关于@Autowired的装配机制,它会根据需要装配的数据的类型,在 Spring容器中统计匹配的Bean(对象)的数量 。

当匹配的Bean数量为0个时,判断@Autowired注解的required属性值,true(默认):装配失败,启动项目时即抛出NoSuchBeanDefinitionException,若是设置为false:放弃自动装配,不会报告异常,使用此属性时,会出现NPE ,即null异常。

当匹配的Bean数量为1个时,将直接装配,并装配成功。

当匹配的Bean数量为多个时:自动尝试按照名称实现装配,存在与属性名称匹配的Spring Bean时装配成功,不存在时装配失败,会抛出NoUniqueBeanDefinitionExcept。

补充

IoC与DI

IoC(Inversion of Control:控制反转)是Spring框架的核心,在传统的开发模式下,是由开发者创建对象、为对象的属性赋值、管理对象的作 用域和生命周期等,所以,是开发者拥有“控制权”,当使用了Spring之 后,这些都交给Spring框架去完成了,开发者不必关心这些操作的具体实现,所以,称之为“控制反转” 。

DI(Dependency Injection:依赖注入)是Spring框架实现IoC的核心实现,当某个类中声明了另一个类的属性(例如在UserController类中声明 了UserMapper类型的属性),则称之为依赖(即UserController依赖了 UserMapper),Spring框架会帮你完成依赖项的赋值,称为注入。

@Qualifier注解

此注解用于在自动装配中指定beanName,在同时存在多个类型匹配的bean时才会用得到,一般来说,我们不太会让这种情况发生,谁也不想给自己找事不是?具体表现为:

@Controller 
public class UserController { 
    @Autowired 
    @Qualifier("userMapper") 
    private UserMapper mapper; 
    public void registor() { 
        mapper.insert(); 
    } 
}

这里要解说下,自动装配,Bean注解这些,名字是有要求的,要和类名的首字母小写后一致,若是我不想用呢?就可以用mapper,但是我通过Qualifier注解来指定正确的名字,这样也是可以的。总感觉这么做会比较累,大家看看就好,实际开发中不要这么做,把自己搞乱了就不好了。

@Resource注解

先尝试根据名称进行装配(即:要求属 性名称与beanName相同),如果失败,则尝试根据类型装配,如果不存此在类型的Bean,则抛出NoSuchBeanDefinitionException,如果只有1 个匹配类型的Bean,则装配成功,如果匹配类型的Bean超过1个,则抛出NoUniqueBeanDefinitionException。

这里说的都是特殊情况,实际开发中,其实很难出现两个相同的Bean,我们不会给自己找不痛快。

和@Autowired,@Resource区别:

  • @Autowired可以添加在构造方法的声明之前,@Resource不可以
  • @Resource可以添加在类的声明之前(但不会装配属性的值),@Autowired不可以
    • 如果有多个同类型的Bean时,@Autowired需要通过@Qualifier指定beanName,而@Resource可以 直接配置name属性以指定beanName。
    • 当装配方法的参数时(例如添加了@Autowired的构造方法的参数),@Autowired仍可使用@Qualifier指定beanName,而@Resource无法解决此问题

未提到的内容

阿西吧,写了好久啊,感觉还是有些遗漏的,后续博客慢慢补充吧。遗漏部分,个人认为比较重要的:

  • AOP
  • Spring Bean生命周期

还有一些细碎的知识,后续的内容中都会根据实例进行说明,这里两块内容其实很大很多,结合实例来说比较好,暂时不在这里进行说明,掌握了这些,Spring框架你已经可以使用一些基础功能了。

结语

可能在所有的写Spring的博主中,我写的不是最好的,但我也是一步步学的Java,也经历过从什么都不懂到上手写项目。道路千条万条,适合自己的才是最好的。这些内容只是Spring的基础,等你真正开始写项目后,你会发现,这些东西都是最最基础的东西,很常用,也很简单。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/148990.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MATLAB循环码编译码实验

标题循环码编译码实验一、实验目的1、掌握循环码编码原理和译码原理2、练习使用Matlab编程实现循环码编码和译码二、实验原理伴随式译码捕错译码三、实验要求1、编程实现码长n15的各种循环码的编码、译码&#xff0c;给出相应的码生成多项式、&#xff08;典型&#xff09;监督…

Java设计模式中装饰者模式/装饰者模式具体内容是什么/静态代理与装饰者模式联系与区别是什么

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 5.4 装饰者模式 5.4.1 概述 在不改变现有对象结构的情况下&#xff0c;动态给对象增加某些职责或功能的模式 5.4.2 结构 抽象构件(Component)&#xff1a;定义…

Javascript 中的堆、栈、引用和值

学透CSS-强烈推荐 Javascript 中的内存存储 栈-Stack&#xff1a; 这是当前 Javascript 线程的暂存空间。由于 Javascript 通常只有单线程&#xff0c;因此通常只有一个堆栈。堆栈的大小也是有限的。 堆-Heap &#xff0c;它是应用程序级别的动态内存存储。从堆中访问和检索…

java 手把手带你创建一个spring入门案例

查看本文 首先 您需要下载spring 如果没有安装 可以查看我的文章 java spring下载步骤 首先 我们打开idea开发工具 选择左上角 File > New > Project 如下图操作 勾选 然后点击下一步 然后我们选择项目目录 这里我直接用了个中文目录 最好不要跟我学哦 因为个人英文不…

微信语音转换成mp3文件保存的简单详细步骤

目录 读者手册 一、前言 二、操作步骤一 把语音转化为silk文件&#xff08;silk后缀的文件&#xff09; 1.长按语音收藏&#xff08;手机操作&#xff09; 2.找到主页收藏 3.找到收藏的语音 4.转存为笔记 5.点击笔记里面的语音&#xff08;下面全部电脑操作&#xff0…

Kubernetes(k8s) 笔记总结(一)

文章目录1. 云平台2. 私有网络 VPC(重点&#xff01;&#xff01;&#xff01;)3. Kubernetes 介绍4. k8s 架构5. kubectl 和 kubeadm6. 三台云服务器的 安装部署7. Kubernetes 环境搭建7.1 安装docker环境7.2 安装k8s的 预备环境8. kubernetes集群 安装的三大件(kubelet、kube…

三句话,让Ai帮你画18万张图

本文介绍Stable Diffusion的快速上手&#xff0c;本地部署&#xff0c;以及更多有趣的玩法展示。 在 DALL-E 2 和 Imagen 之后&#xff0c;AI绘图领域又一个热乎的深度学习模型出炉——Stable Diffusion 。8月份发布的 Stable Diffusion 更加高效且轻量&#xff0c;可以在消费…

P4:Transforms的使用

transform.py就像是一个工具箱&#xff0c;里面有很多工具&#xff08;如&#xff1a;totensor、resize等不同的工具&#xff09;。 使用规则&#xff1a; 拿特定格式的图片&#xff0c;通过使用工具&#xff0c;得到想要的结果。 1、transforms.ToTensor()的使用 1、作用&a…

实战1:基于tensorflow卷积网络实现面部关键点检测详细教程(代码+数据)

项目概述: 此任务的目标是预测面部图像上的关键点位置。这可以用作多个应用程序中的构建块,例如:检测面部关键点是一个非常具有挑战性的问题。人脸特征因人而异,即使是单个人,由于 3D 姿势、大小、位置、视角和光照条件等因素也存在很大差异。 直接上结果: 数据集描…

JSP SSM 个人博客系统系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSP SSM 个人博客系统系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代 码和数据库&#xff0c;系统主要采…

vue3-Teleport笔记

简单来写一下Teleport src/components/TeleportLearn.vue <script setup></script><template><div><Teleport to"body"><div>你好</div></Teleport></div> </template><style scoped></style&…

NVMe IO数据传输如何选择PRP or SGL?

在Host与Controller之间有数据交互时&#xff0c;Controller会多次访问Host内存。比如执行NVMe Read/Write:当Host下发NVMe Write命令时&#xff0c;Host会先放数据放在Host内存中&#xff0c;然后通知Controller过来取数据。Controller接到信息后&#xff0c;会通过PCIe Memor…

Python下载ts文件视频并合并

目录 一、ts文件的由来 二、下载ts文件 1.下载index.m3u8&#xff0c;并做相应处理 2.下载ts文件 三、合并ts文件 一、ts文件的由来 ts文件&#xff0c;ts即"Transport Stream"的缩写&#xff0c;特点就是要求从视频流的任一片段开始都是可以独立解码的&#x…

C 程序设计教程(06)—— C 语言的运算符与表达式

C 程序设计教程&#xff08;06&#xff09;—— C 语言的运算符与表达式 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用户阅读。 目录C 程序设计教程&#xff08;0…

【每日一题】【LeetCode】【第七天】盛最多水的容器

解决之路 因为是周日&#xff0c;找个中等题挑战一下。 题目描述 测试案例&#xff08;部分&#xff09; 第一次 想一下&#xff0c;因为涉及到底乘高&#xff0c;所以不能排序。逆序也没必要。 简化一下题干&#xff0c;盛水最多&#xff0c;也就是算面积最大&#xff0c…

【北邮果园大三上】运筹学期中前

第一章.线性规划 1.1例题 根据现实世界中的问题建立模型 一般表达式 ①和式 ②向量式 1.2变化标准&#xff1a; 1.3线性规划求解的基础原理和单纯解法 1.3.1解 ①基础概念 基 可行解与基础解 其他分类 ②判断举例 原式子&#xff1a; 判断标准 将一个未知数作为常熟&#…

从Wireshark看TCP连接的建立与关闭

http://t.zoukankan.com/jonathanlin-p-4282582.html TCP是一种面向连接、可靠的协议。TCP连接的建立与断开&#xff0c;都是需要经过通信双方的协商。用一句话概括就是&#xff1a;三次握手say hello&#xff08;建立连接&#xff09;&#xff1b;四次握手say goodbye&#x…

蓝桥杯Python组排序算法与函数

目录 一、排序算法 二、排序函数 1、Python 的 sort() 函数和 sorted() 函数 2、sort() 例子 3、sorted() 例子 4、部分排序 三、例题 1、统计数字&#xff08;lanqiaoOJ题号535&#xff09; 2、错误票据&#xff08;lanqiaoOJ题号205&#xff09; 3、奖学金&#xf…

线程池 - ThreadPoolExecutor 详解

线程池 - ThreadPoolExecutor 详解 线程池 ThreadPoolExecutor 源码解析参考 juc 专栏系列文章。 基本概述 线程池&#xff1a;一个容纳多个线程的容器&#xff0c;容器中的线程可以重复使用&#xff0c;省去了频繁创建和销毁线程对象的操作。 线程池作用&#xff1a; 降低资…

【基础】Elasticsearch 基础

Elasticsearch 基本概念及使用Elasticsearch 基本概念ES 的简介及使用场景ES 基本概念ES 与 Kibana 的安装Elasticsearch 分词器ES 内置分词器ik 分词器的安装和使用Elasticsearch 基本使用索引操作数据的增删改查DSL 查询聚合查询批量操作Elasticsearch 基本概念 ES 的简介及…