SpringBoot【开发实用篇】---- 数据层解决方案

news2024/12/31 6:57:37

SpringBoot【开发实用篇】---- 数据层解决方案

  • 1. SQL
    • 数据源技术
    • 持久化技术
    • 数据库技术
  • 2. NoSQL
    • SpringBoot整合Redis
      • 安装
      • 基本操作
      • 整合
    • SpringBoot整合MonggoDB
      • 安装
      • 基本操作
      • 整合
    • SpringBoot整合ES
      • 安装
      • 基本操作
      • 整合

开发实用篇前三章基本上是开胃菜,从第四章开始,开发实用篇进入到了噩梦难度了,从这里开始,不再是单纯的在springboot内部搞事情了,要涉及到很多相关知识。本章节主要内容都是和数据存储与读取相关,前期学习的知识与数据层有关的技术基本上都围绕在数据库这个层面上,所以本章要讲的第一个大的分支就是SQL解决方案相关的内容,除此之外,数据的来源还可以是非SQL技术相关的数据操作,因此第二部分围绕着NOSQL解决方案讲解。至于什么是NOSQL解决方案,讲到了再说吧。下面就从SQL解决方案说起。

1. SQL

回忆一下之前做SSMP整合的时候数据层解决方案涉及到了哪些技术?MySQL数据库与MyBatisPlus框架,后面又学了Druid数据源的配置,所以现在数据层解决方案可以说是Mysql+Druid+MyBatisPlus。而三个技术分别对应了数据层操作的三个层面:

  • 数据源技术:Druid
  • 持久化技术:MyBatisPlus
  • 数据库技术:MySQL

下面的研究就分为三个层面进行研究,对应上面列出的三个方面,咱们就从第一个数据源技术开始说起。

数据源技术

目前我们使用的数据源技术是Druid,运行时可以在日志中看到对应的数据源初始化信息,具体如下:

INFO 28600 --- [           main] c.a.d.s.b.a.DruidDataSourceAutoConfigure : Init DruidDataSource
INFO 28600 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited

如果不使用Druid数据源,程序运行后是什么样子呢?是独立的数据库连接对象还是有其他的连接池技术支持呢?将Druid技术对应的starter去掉再次运行程序可以在日志中找到如下初始化信息:

INFO 31820 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
INFO 31820 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.

虽然没有DruidDataSource相关的信息了,但是我们发现日志中有HikariDataSource这个信息,就算不懂这是个什么技术,看名字也能看出来,以DataSource结尾的名称,这一定是一个数据源技术。我们又没有手工添加这个技术,这个技术哪里来的呢?这就是这一节要讲的知识,springboot内嵌数据源。

数据层技术是每一个企业级应用程序都会用到的,而其中必定会进行数据库连接的管理。springboot根据开发者的习惯出发,开发者提供了数据源技术,就用你提供的,开发者没有提供,那总不能手工管理一个一个的数据库连接对象啊,怎么办?我给你一个默认的就好了,这样省心又省事,大家都方便。

springboot提供了3款内嵌数据源技术,分别如下:

  • HikariCP
  • Tomcat提供DataSource
  • Commons DBCP

第一种,HikartCP,这是springboot官方推荐的数据源技术,作为默认内置数据源使用。啥意思?你不配置数据源,那就用这个。

第二种,Tomcat提供的DataSource,如果不想用HikartCP,并且使用tomcat作为web服务器进行web程序的开发,使用这个。为什么是Tomcat,不是其他web服务器呢?因为web技术导入starter后,默认使用内嵌tomcat,既然都是默认使用的技术了,那就一用到底,数据源也用它的。有人就提出怎么才能不使用HikartCP用tomcat提供的默认数据源对象呢?把HikartCP技术的坐标排除掉就OK了。

第三种,DBCP,这个使用的条件就更苛刻了,既不使用HikartCP也不使用tomcat的DataSource时,默认给你用这个。

springboot这心操的,也是稀碎啊,就怕你自己管不好连接对象,给你一顿推荐,真是开发界的最强辅助。既然都给你奶上了,那就受用吧,怎么配置使用这些东西呢?之前我们配置druid时使用druid的starter对应的配置如下:

spring:
  datasource:
    druid:	
   	  url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: root

换成是默认的数据源HikariCP后,直接吧druid删掉就行了,如下:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root

当然,也可以写上是对hikari做的配置,但是url地址要单独配置,如下:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
    hikari:
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: root

这就是配置hikari数据源的方式。如果想对hikari做进一步的配置,可以继续配置其独立的属性。例如:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
    hikari:
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: root
      maximum-pool-size: 50

如果不想使用hikari数据源,使用tomcat的数据源或者DBCP配置格式也是一样的。学习到这里,以后我们做数据层时,数据源对象的选择就不再是单一的使用druid数据源技术了,可以根据需要自行选择。

持久化技术

说完数据源解决方案,再来说一下持久化解决方案。springboot充分发挥其最强辅助的特征,给开发者提供了一套现成的数据层技术,叫做JdbcTemplate。其实这个技术不能说是springboot提供的,因为不使用springboot技术,一样能使用它,谁提供的呢?spring技术提供的,所以在springboot技术范畴中,这个技术也是存在的,毕竟springboot技术是加速spring程序开发而创建的。

这个技术其实就是回归到jdbc最原始的编程形式来进行数据层的开发,下面直接上操作步骤:

步骤①:导入jdbc对应的坐标,记得是starter

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency

步骤②:自动装配JdbcTemplate对象

@SpringBootTest
class Springboot15SqlApplicationTests {
    @Test
    void testJdbcTemplate(@Autowired JdbcTemplate jdbcTemplate){
    }
}

步骤③:使用JdbcTemplate实现查询操作(非实体类封装数据的查询操作)

@Test
void testJdbcTemplate(@Autowired JdbcTemplate jdbcTemplate){
    String sql = "select * from tbl_book";
    List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
    System.out.println(maps);
}

步骤④:使用JdbcTemplate实现查询操作(实体类封装数据的查询操作)

@Test
void testJdbcTemplate(@Autowired JdbcTemplate jdbcTemplate){

    String sql = "select * from tbl_book";
    RowMapper<Book> rm = new RowMapper<Book>() {
        @Override
        public Book mapRow(ResultSet rs, int rowNum) throws SQLException {
            Book temp = new Book();
            temp.setId(rs.getInt("id"));
            temp.setName(rs.getString("name"));
            temp.setType(rs.getString("type"));
            temp.setDescription(rs.getString("description"));
            return temp;
        }
    };
    List<Book> list = jdbcTemplate.query(sql, rm);
    System.out.println(list);
}

步骤⑤:使用JdbcTemplate实现增删改操作

@Test
void testJdbcTemplateSave(@Autowired JdbcTemplate jdbcTemplate){
    String sql = "insert into tbl_book values(3,'springboot1','springboot2','springboot3')";
    jdbcTemplate.update(sql);
}

如果想对JdbcTemplate对象进行相关配置,可以在yml文件中进行设定,具体如下:

spring:
  jdbc:
    template:
      query-timeout: -1   # 查询超时时间
      max-rows: 500       # 最大行数
      fetch-size: -1      # 缓存行数

数据库技术

截止到目前,springboot给开发者提供了内置的数据源解决方案和持久化解决方案,在数据层解决方案三件套中还剩下一个数据库,莫非springboot也提供有内置的解决方案?还真有,还不是一个,三个,这一节就来说说内置的数据库解决方案。

springboot提供了3款内置的数据库,分别是

  • H2
  • HSQL
  • Derby

以上三款数据库除了可以独立安装之外,还可以像是tomcat服务器一样,采用内嵌的形式运行在spirngboot容器中。内嵌在容器中运行,那必须是java对象啊,对,这三款数据库底层都是使用java语言开发的。

我们一直使用MySQL数据库就挺好的,为什么有需求用这个呢?原因就在于这三个数据库都可以采用内嵌容器的形式运行,在应用程序运行后,如果我们进行测试工作,此时测试的数据无需存储在磁盘上,但是又要测试使用,内嵌数据库就方便了,运行在内存中,该测试测试,该运行运行,等服务器关闭后,一切烟消云散,多好,省得你维护外部数据库了。这也是内嵌数据库的最大优点,方便进行功能测试。

下面以H2数据库为例讲解如何使用这些内嵌数据库,操作步骤也非常简单,简单才好用嘛

步骤①:导入H2数据库对应的坐标,一共2个

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

步骤②:将工程设置为web工程,启动工程时启动H2数据库

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

步骤③:通过配置开启H2数据库控制台访问程序,也可以使用其他的数据库连接软件操作

spring:
  h2:
    console:
      enabled: true
      path: /h2

在这里插入图片描述

web端访问路径/h2,访问密码123456,如果访问失败,先配置下列数据源,启动程序运行后再次访问/h2路径就可以正常访问了

datasource:
  url: jdbc:h2:~/test
  hikari:
    driver-class-name: org.h2.Driver
    username: sa
    password: 123456

在这里插入图片描述

步骤④:使用JdbcTemplate或MyBatisPlus技术操作数据库

其实我们只是换了一个数据库而已,其他的东西都不受影响。一个重要提醒,别忘了,上线时,把内存级数据库关闭,采用MySQL数据库作为数据持久化方案,关闭方式就是设置enabled属性为false即可。

2. NoSQL

SQL数据层解决方案说完了,下面来说收NoSQL数据层解决方案。这个NoSQL是什么意思呢?从字面来看,No表示否定,NoSQL就是非关系型数据库解决方案,意思就是数据该存存该取取,只是这些数据不放在关系型数据库中了,那放在哪里?自然是一些能够存储数据的其他相关技术中了,比如Redis等。本节讲解的内容就是springboot如何整合这些技术,在springboot官方文档中提供了10种相关技术的整合方案,我们将讲解国内市场上最流行的几款NoSQL数据库整合方案,分别是Redis、MongoDB、ES。

SpringBoot整合Redis

Redis是一款采用key-value数据存储格式的内存级NoSQL数据库,重点关注数据存储格式,是key-value格式,也就是键值对的存储形式。与MySQL数据库不同,MySQL数据库有表、有字段、有记录,Redis没有这些东西,就是一个名称对应一个值,并且数据以存储在内存中使用为主。什么叫以存储在内存中为主?其实Redis有它的数据持久化方案,分别是RDB和AOF,但是Redis自身并不是为了数据持久化而生的,主要是在内存中保存数据,加速数据访问的,所以说是一款内存级数据库。

Redis支持多种数据存储格式,比如可以直接存字符串,也可以存一个map集合,list集合,后面会涉及到一些不同格式的数据操作,这个需要先学习一下才能进行整合,所以在基本操作中会介绍一些相关操作。下面就先安装,再操作,最后说整合

安装

windows版安装包下载地址:https://github.com/tporadowski/redis/releases

下载的安装包有两种形式,一种是一键安装的msi文件,还有一种是解压缩就能使用的zip文件,哪种形式都行,这里就不介绍安装过程了,本课程采用的是msi一键安装的msi文件进行安装的。

啥是msi,其实就是一个文件安装包,不仅安装软件,还帮你把安装软件时需要的功能关联在一起,打包操作。比如如安装序列、创建和设置安装路径、设置系统依赖项、默认设定安装选项和控制安装过程的属性。说简单点就是一站式服务,安装过程一条龙操作一气呵成,就是为小白用户提供的软件安装程序。

安装完毕后会得到如下文件,其中有两个文件对应两个命令,是启动Redis的核心命令,需要再CMD命令行模式执行。

在这里插入图片描述

启动服务器

redis-server.exe

在这里插入图片描述

初学者无需调整服务器对外服务端口,默认6379。

启动客户端

redis-cli.exe

在这里插入图片描述
如果启动redis服务器失败,可以先启动客户端,然后执行shutdown操作后退出,此时redis服务器就可以正常执行了。

基本操作

服务器启动后,使用客户端就可以连接服务器,类似于启动完MySQL数据库,然后启动SQL命令行操作数据库。

放置一个字符串数据到redis中,先为数据定义一个名称,比如name,age等,然后使用命令set设置数据到redis服务器中即可

set name itheima
set age 12

在这里插入图片描述
从redis中取出已经放入的数据,根据名称取,就可以得到对应数据。如果没有对应数据就会得到(nil)

get name
get age

在这里插入图片描述
以上使用的数据存储是一个名称对应一个值,如果要维护的数据过多,可以使用别的数据存储结构。例如hash,它是一种一个名称下可以存储多个数据的存储模型,并且每个数据也可以有自己的二级存储名称。向hash结构中存储数据格式如下:

hset a a1 aa1		#对外key名称是a,在名称为a的存储模型中,a1这个key中保存了数据aa1
hset a a2 aa2

在这里插入图片描述
获取hash结构中的数据命令如下

hget a a1			#得到aa1
hget a a2			#得到aa2

在这里插入图片描述

整合

在进行整合之前先梳理一下整合的思想,springboot整合任何技术其实就是在springboot中使用对应技术的API。如果两个技术没有交集,就不存在整合的概念了。所谓整合其实就是使用springboot技术去管理其他技术,几个问题是躲不掉的。

第一,需要先导入对应技术的坐标,而整合之后,这些坐标都有了一些变化

第二,任何技术通常都会有一些相关的设置信息,整合之后,这些信息如何写,写在哪是一个问题

第三,没有整合之前操作如果是模式A的话,整合之后如果没有给开发者带来一些便捷操作,那整合将毫无意义,所以整合后操作肯定要简化一些,那对应的操作方式自然也有所不同

按照上面的三个问题去思考springboot整合所有技术是一种通用思想,在整合的过程中会逐步摸索出整合的套路,而且适用性非常强,经过若干种技术的整合后基本上可以总结出一套固定思维。

下面就开始springboot整合redis,操作步骤如下:

步骤①:导入springboot整合redis的starter坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

上述坐标可以在创建模块的时候通过勾选的形式进行选择,归属NoSQL分类中
在这里插入图片描述
步骤②:进行基础配置

spring:
  redis:
    host: localhost
    port: 6379

操作redis,最基本的信息就是操作哪一台redis服务器,所以服务器地址属于基础配置信息,不可缺少。但是即便你不配置,目前也是可以用的。因为以上两组信息都有默认配置,刚好就是上述配置值。

步骤③:使用springboot整合redis的专用客户端接口操作,此处使用的是RedisTemplate

@SpringBootTest
public class RedisTest {

    @Resource
    private RedisTemplate redisTemplate;

    @Test
    void set() {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("age", 44);
    }

    @Test
    void get() {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        Object age = valueOperations.get("age");
        System.out.println(age);
    }

    @Test
    void hset() {
        HashOperations ops = redisTemplate.opsForHash();
        ops.put("info","b","bb");
    }

    @Test
    void hget() {
        HashOperations ops = redisTemplate.opsForHash();
        Object val = ops.get("info", "b");
        System.out.println(val);
    }

}

在操作redis时,需要先确认操作何种数据,根据数据种类得到操作接口。例如使用opsForValue()获取string类型的数据操作接口,使用opsForHash()获取hash类型的数据操作接口,剩下的就是调用对应api操作了。各种类型的数据操作接口如下:

在这里插入图片描述

StringRedisTemplate
由于redis内部不提供java对象的存储格式,因此当操作的数据以对象的形式存在时,会进行转码,转换成字符串格式后进行操作。为了方便开发者使用基于字符串为数据的操作,springboot整合redis时提供了专用的API接口StringRedisTemplate,你可以理解为这是RedisTemplate的一种指定数据泛型的操作API。

@SpringBootTest
public class RedisTemplateTest {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void get() {
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        String name = stringStringValueOperations.get("name");
        System.out.println(name);
    }

}

redis客户端选择

springboot整合redis技术提供了多种客户端兼容模式,默认提供的是lettucs客户端技术,也可以根据需要切换成指定客户端技术,例如jedis客户端技术,切换成jedis客户端技术操作步骤如下:

步骤①:导入jedis坐标

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

jedis坐标受springboot管理,无需提供版本号

步骤②:配置客户端技术类型,设置为jedis

spring:
  redis:
    host: localhost
    port: 6379
    client-type: jedis

步骤③:根据需要设置对应的配置

spring:
  redis:
    host: localhost
    port: 6379
    client-type: jedis
    lettuce:
      pool:
        max-active: 16
    jedis:
      pool:
        max-active: 16

lettcus与jedis区别

  • jedis连接Redis服务器是直连模式,当多线程模式下使用jedis会存在线程安全问题,解决方案可以通过配置连接池使每个连接专用,这样整体性能就大受影响
  • lettcus基于Netty框架进行与Redis服务器连接,底层设计中采用StatefulRedisConnection。 StatefulRedisConnection自身是线程安全的,可以保障并发访问安全问题,所以一个连接可以被多线程复用。当然lettcus也支持多连接实例一起工作

SpringBoot整合MonggoDB

使用Redis技术可以有效的提高数据访问速度,但是由于Redis的数据格式单一性,无法操作结构化数据,当操作对象型的数据时,Redis就显得捉襟见肘。在保障访问速度的情况下,如果想操作结构化数据,看来Redis无法满足要求了,此时需要使用全新的数据存储结束来解决此问题,本节讲解springboot如何整合MongoDB技术。

MongoDB是一个开源、高性能、无模式的文档型数据库,它是NoSQL数据库产品中的一种,是最像关系型数据库的非关系型数据库。

上述描述中几个词,其中对于我们最陌生的词是无模式的。什么叫无模式呢?简单说就是作为一款数据库,没有固定的数据存储结构,第一条数据可能有A、B、C一共3个字段,第二条数据可能有D、E、F也是3个字段,第三条数据可能是A、C、E3个字段,也就是说数据的结构不固定,这就是无模式。有人会说这有什么用啊?灵活,随时变更,不受约束。基于上述特点,MongoDB的应用面也会产生一些变化。以下列出了一些可以使用MongoDB作为数据存储的场景,但是并不是必须使用MongoDB的场景:

  • 淘宝用户数据
    • 存储位置:数据库
    • 特征:永久性存储,修改频度极低
  • 游戏装备数据、游戏道具数据
    • 存储位置:数据库、Mongodb
    • 特征:永久性存储与临时存储相结合、修改频度较高
  • 直播数据、打赏数据、粉丝数据
    • 存储位置:数据库、Mongodb
    • 特征:永久性存储与临时存储相结合,修改频度极高
  • 物联网数据
    • 存储位置:Mongodb
    • 特征:临时存储,修改频度飞速

安装

windows版安装包下载地址:https://www.mongodb.com/try/download

下载的安装包也有两种形式,一种是一键安装的msi文件,还有一种是解压缩就能使用的zip文件,哪种形式都行,本课程采用解压缩zip文件进行安装。

解压缩完毕后会得到如下文件,其中bin目录包含了所有mongodb的可执行命令
在这里插入图片描述
mongodb在运行时需要指定一个数据存储的目录,所以创建一个数据存储目录,通常放置在安装目录中,此处创建data的目录用来存储数据,具体如下
在这里插入图片描述
如果在安装的过程中出现了如下警告信息,就是告诉你,你当前的操作系统缺少了一些系统文件,这个不用担心。
在这里插入图片描述
根据下列方案即可解决,在浏览器中搜索提示缺少的名称对应的文件,并下载,将下载的文件拷贝到windows安装目录的system32目录下,然后在命令行中执行regsvr32命令注册此文件。根据下载的文件名不同,执行命令前更改对应名称。

regsvr32 vcruntime140_1.dll

启动服务器

mongod --dbpath=..\data\db

启动服务器时需要指定数据存储位置,通过参数–dbpath进行设置,可以根据需要自行设置数据存储路径。默认服务端口27017。
在这里插入图片描述
启动客户端

mongo --host=127.0.0.1 --port=27017

在这里插入图片描述

基本操作

MongoDB虽然是一款数据库,但是它的操作并不是使用SQL语句进行的,因此操作方式各位小伙伴可能比较陌生,好在有一些类似于Navicat的数据库客户端软件,能够便捷的操作MongoDB,先安装一个客户端,再来操作MongoDB。

同类型的软件较多,本次安装的软件时Robo3t,Robot3t是一款绿色软件,无需安装,解压缩即可。解压缩完毕后进入安装目录双击robot3t.exe即可使用。

在这里插入图片描述
打开软件首先要连接MongoDB服务器,选择【File】菜单,选择【Connect…】
在这里插入图片描述
进入连接管理界面后,选择左上角的【Create】链接,创建新的连接设置
在这里插入图片描述
如果输入设置值即可连接(默认不修改即可连接本机27017端口)
在这里插入图片描述
连接成功后在命令输入区域输入命令即可操作MongoDB。

创建数据库:在左侧菜单中使用右键创建,输入数据库名称即可

创建集合:在Collections上使用右键创建,输入集合名称即可,集合等同于数据库中的表的作用

新增文档:(文档是一种类似json格式的数据,初学者可以先把数据理解为就是json数据)

db.集合名称.insert/save/insertOne(文档)

删除文档:

db.集合名称.remove(条件)

修改文档:

db.集合名称.update(条件,{操作种类:{文档}})

查询文档:

基础查询
查询全部:		   db.集合.find();
查第一条:		   db.集合.findOne()
查询指定数量文档:	db.集合.find().limit(10)					//查10条文档
跳过指定数量文档:	db.集合.find().skip(20)					//跳过20条文档
统计:			  	db.集合.count()
排序:				db.集合.sort({age:1})						//按age升序排序
投影:				db.集合名称.find(条件,{name:1,age:1})		 //仅保留name与age域

条件查询
基本格式:			db.集合.find({条件})
模糊查询:			db.集合.find({域名:/正则表达式/})		  //等同SQL中的like,比like强大,可以执行正则所有规则
条件比较运算:		   db.集合.find({域名:{$gt:值}})				//等同SQL中的数值比较操作,例如:name>18
包含查询:			db.集合.find({域名:{$in:[1,值2]}})		//等同于SQL中的in
条件连接查询:		   db.集合.find({$and:[{条件1},{条件2}]})	   //等同于SQL中的and、or

整合

使用springboot整合MongDB该如何进行呢?其实springboot为什么使用的开发者这么多,就是因为他的套路几乎完全一样。导入坐标,做配置,使用API接口操作。整合Redis如此,整合MongoDB同样如此。

第一,先导入对应技术的整合starter坐标

第二,配置必要信息

第三,使用提供的API操作即可

下面就开始springboot整合MongoDB,操作步骤如下:

步骤①:导入springboot整合MongoDB的starter坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

上述坐标也可以在创建模块的时候通过勾选的形式进行选择,同样归属NoSQL分类中
在这里插入图片描述
步骤②:进行基础配置

spring:
  data:
    mongodb:
      uri: mongodb://localhost/test

操作MongoDB需要的配置与操作redis一样,最基本的信息都是操作哪一台服务器,区别就是连接的服务器IP地址和端口不同,书写格式不同而已。

步骤③:使用springboot整合MongoDB的专用客户端接口MongoTemplate来进行操作

@SpringBootTest
public class MongodbTest {

    @Resource
    private MongoTemplate mongoTemplate;

    @Test
    void contextLoads() {
        Book book = new Book();
        book.setId(2);
        book.setName("springboot mongodb");
        book.setType("mongodb");
        book.setDescription("test mongodb ---- ");
        mongoTemplate.save(book);
    }

    @Test
    void find() {
        List<Book> all = mongoTemplate.findAll(Book.class);
        System.out.println(all);
    }

}

整合工作到这里就做完了,感觉既熟悉也陌生。熟悉的是这个套路,三板斧,就这三招,导坐标做配置用API操作,陌生的是这个技术,里面具体的操作API可能会不熟悉,有关springboot整合MongoDB我们就讲到这里。有兴趣可以继续学习MongoDB的操作,然后再来这里通过编程的形式操作MongoDB。

SpringBoot整合ES

NoSQL解决方案已经讲完了两种技术的整合了,Redis可以使用内存加载数据并实现数据快速访问,MongoDB可以在内存中存储类似对象的数据并实现数据的快速访问,在企业级开发中对于速度的追求是永无止境的。下面要讲的内容也是一款NoSQL解决方案,只不过他的作用不是为了直接加速数据的读写,而是加速数据的查询的,叫做ES技术。

ES(Elasticsearch)是一个分布式全文搜索引擎,重点是全文搜索。

那什么是全文搜索呢?比如用户要买一本书,以Java为关键字进行搜索,不管是书名中还是书的介绍中,甚至是书的作者名字,只要包含java就作为查询结果返回给用户查看,上述过程就使用了全文搜索技术。搜索的条件不再是仅用于对某一个字段进行比对,而是在一条数据中使用搜索条件去比对更多的字段,只要能匹配上就列入查询结果,这就是全文搜索的目的。而ES技术就是一种可以实现上述效果的技术。

要实现全文搜索的效果,不可能使用数据库中like操作去进行比对,这种效率太低了。ES设计了一种全新的思想,来实现全文搜索。具体操作过程如下:

  1. 将被查询的字段的数据全部文本信息进行查分,分成若干个词

    • 例如“中华人民共和国”就会被拆分成三个词,分别是“中华”、“人民”、“共和国”,此过程有专业术语叫做分词。分词的策略不同,分出的效果不一样,不同的分词策略称为分词器。
  2. 将分词得到的结果存储起来,对应每条数据的id

    • 例如id为1的数据中名称这一项的值是“中华人民共和国”,那么分词结束后,就会出现“中华”对应id为1,“人民”对应id为1,“共和国”对应id为1

    • 例如id为2的数据中名称这一项的值是“人民代表大会“,那么分词结束后,就会出现“人民”对应id为2,“代表”对应id为2,“大会”对应id为2

    • 此时就会出现如下对应结果,按照上述形式可以对所有文档进行分词。需要注意分词的过程不是仅对一个字段进行,而是对每一个参与查询的字段都执行,最终结果汇总到一个表格中

分词结果关键字对应id
中华1
人民1,2
共和国1
代表2
大会2
  1. 当进行查询时,如果输入“人民”作为查询条件,可以通过上述表格数据进行比对,得到id值1,2,然后根据id值就可以得到查询的结果数据了。

上述过程中分词结果关键字内容每一个都不相同,作用有点类似于数据库中的索引,是用来加速数据查询的。但是数据库中的索引是对某一个字段进行添加索引,而这里的分词结果关键字不是一个完整的字段值,只是一个字段中的其中的一部分内容。并且索引使用时是根据索引内容查找整条数据,全文搜索中的分词结果关键字查询后得到的并不是整条的数据,而是数据的id,要想获得具体数据还要再次查询,因此这里为这种分词结果关键字起了一个全新的名称,叫做倒排索引

通过上述内容的学习,发现使用ES其实准备工作还是挺多的,必须先建立文档的倒排索引,然后才能继续使用。快速了解一下ES的工作原理,下面直接开始我们的学习,老规矩,先安装,再操作,最后说整合。

安装

windows版安装包下载地址:https://www.elastic.co/cn/downloads/elasticsearch

下载的安装包是解压缩就能使用的zip文件,解压缩完毕后会得到如下文件
在这里插入图片描述

  • bin目录:包含所有的可执行命令
  • config目录:包含ES服务器使用的配置文件
  • jdk目录:此目录中包含了一个完整的jdk工具包,版本17,当ES升级时,使用最新版本的jdk确保不会出现版本支持性不足的问题
  • lib目录:包含ES运行的依赖jar文件
  • logs目录:包含ES运行后产生的所有日志文件
  • modules目录:包含ES软件中所有的功能模块,也是一个一个的jar包。和jar目录不同,jar目录是ES运行期间依赖的jar包,modules是ES软件自己的功能jar包
  • plugins目录:包含ES软件安装的插件,默认为空

启动服务器

elasticsearch.bat

双击elasticsearch.bat文件即可启动ES服务器,默认服务端口9200。通过浏览器访问 http://localhost:9200 看到如下信息视为ES服务器正常启动

{
  "name" : "CZBK-**********",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "j137DSswTPG8U4Yb-0T1Mg",
  "version" : {
    "number" : "7.16.2",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "2b937c44140b6559905130a8650c64dbd0879cfb",
    "build_date" : "2021-12-18T19:42:46.604893745Z",
    "build_snapshot" : false,
    "lucene_version" : "8.10.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

在这里插入图片描述

基本操作

ES中保存有我们要查询的数据,只不过格式和数据库存储数据格式不同而已。在ES中我们要先创建倒排索引,这个索引的功能又点类似于数据库的表,然后将数据添加到倒排索引中,添加的数据称为文档。所以要进行ES的操作要先创建索引,再添加文档,这样才能进行后续的查询操作。

要操作ES可以通过Rest风格的请求来进行,也就是说发送一个请求就可以执行一个操作。比如新建索引,删除索引这些操作都可以使用发送请求的形式来进行。

  • 创建索引,books是索引名称,下同
PUT请求		http://localhost:9200/books

发送请求后,看到如下信息即索引创建成功

{
    "acknowledged": true,
    "shards_acknowledged": true,
    "index": "books"
}

重复创建已经存在的索引会出现错误信息,reason属性中描述错误原因

{
    "error": {
        "root_cause": [
            {
                "type": "resource_already_exists_exception",
                "reason": "index [books/VgC_XMVAQmedaiBNSgO2-w] already exists",
                "index_uuid": "VgC_XMVAQmedaiBNSgO2-w",
                "index": "books"
            }
        ],
        "type": "resource_already_exists_exception",
        "reason": "index [books/VgC_XMVAQmedaiBNSgO2-w] already exists",	# books索引已经存在
        "index_uuid": "VgC_XMVAQmedaiBNSgO2-w",
        "index": "book"
    },
    "status": 400
}
  • 查询索引
GET请求		http://localhost:9200/books

查询索引得到索引相关信息,如下

{
    "book": {
        "aliases": {},
        "mappings": {},
        "settings": {
            "index": {
                "routing": {
                    "allocation": {
                        "include": {
                            "_tier_preference": "data_content"
                        }
                    }
                },
                "number_of_shards": "1",
                "provided_name": "books",
                "creation_date": "1645768584849",
                "number_of_replicas": "1",
                "uuid": "VgC_XMVAQmedaiBNSgO2-w",
                "version": {
                    "created": "7160299"
                }
            }
        }
    }
}

如果查询了不存在的索引,会返回错误信息,例如查询名称为book的索引后信息如下

{
    "error": {
        "root_cause": [
            {
                "type": "index_not_found_exception",
                "reason": "no such index [book]",
                "resource.type": "index_or_alias",
                "resource.id": "book",
                "index_uuid": "_na_",
                "index": "book"
            }
        ],
        "type": "index_not_found_exception",
        "reason": "no such index [book]",		# 没有book索引
        "resource.type": "index_or_alias",
        "resource.id": "book",
        "index_uuid": "_na_",
        "index": "book"
    },
    "status": 404
}
  • 删除索引
DELETE请求	http://localhost:9200/books

删除所有后,给出删除结果

{
    "acknowledged": true
}

如果重复删除,会给出错误信息,同样在reason属性中描述具体的错误原因

{
    "error": {
        "root_cause": [
            {
                "type": "index_not_found_exception",
                "reason": "no such index [books]",
                "resource.type": "index_or_alias",
                "resource.id": "book",
                "index_uuid": "_na_",
                "index": "book"
            }
        ],
        "type": "index_not_found_exception",
        "reason": "no such index [books]",		# 没有books索引
        "resource.type": "index_or_alias",
        "resource.id": "book",
        "index_uuid": "_na_",
        "index": "book"
    },
    "status": 404
}
  • 创建索引并指定分词器

前面创建的索引是未指定分词器的,可以在创建索引时添加请求参数,设置分词器。目前国内较为流行的分词器是IK分词器,使用前先在下对应的分词器,然后使用。IK分词器下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

分词器下载后解压到ES安装目录的plugins目录中即可,安装分词器后需要重新启动ES服务器。使用IK分词器创建索引格式:

PUT请求		http://localhost:9200/books

请求参数如下(注意是json格式的参数)
{
    "mappings":{							#定义mappings属性,替换创建索引时对应的mappings属性		
        "properties":{						#定义索引中包含的属性设置
            "id":{							#设置索引中包含id属性
                "type":"keyword"			#当前属性可以被直接搜索
            },
            "name":{						#设置索引中包含name属性
                "type":"text",              #当前属性是文本信息,参与分词  
                "analyzer":"ik_max_word",   #使用IK分词器进行分词             
                "copy_to":"all"				#分词结果拷贝到all属性中
            },
            "type":{
                "type":"keyword"
            },
            "description":{
                "type":"text",	                
                "analyzer":"ik_max_word",                
                "copy_to":"all"
            },
            "all":{							#定义属性,用来描述多个字段的分词结果集合,当前属性可以参与查询
                "type":"text",	                
                "analyzer":"ik_max_word"
            }
        }
    }
}

创建完毕后返回结果和不使用分词器创建索引的结果是一样的,此时可以通过查看索引信息观察到添加的请求参数mappings已经进入到了索引属性中

{
    "books": {
        "aliases": {},
        "mappings": {						#mappings属性已经被替换
            "properties": {
                "all": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                },
                "description": {
                    "type": "text",
                    "copy_to": [
                        "all"
                    ],
                    "analyzer": "ik_max_word"
                },
                "id": {
                    "type": "keyword"
                },
                "name": {
                    "type": "text",
                    "copy_to": [
                        "all"
                    ],
                    "analyzer": "ik_max_word"
                },
                "type": {
                    "type": "keyword"
                }
            }
        },
        "settings": {
            "index": {
                "routing": {
                    "allocation": {
                        "include": {
                            "_tier_preference": "data_content"
                        }
                    }
                },
                "number_of_shards": "1",
                "provided_name": "books",
                "creation_date": "1645769809521",
                "number_of_replicas": "1",
                "uuid": "DohYKvr_SZO4KRGmbZYmTQ",
                "version": {
                    "created": "7160299"
                }
            }
        }
    }
}
  • 添加文档,有三种方式
POST请求	http://localhost:9200/books/_doc		#使用系统生成id
POST请求	http://localhost:9200/books/_create/1	#使用指定id
POST请求	http://localhost:9200/books/_doc/1		#使用指定id,不存在创建,存在更新(版本递增)

文档通过请求参数传递,数据格式json
{
    "name":"springboot",
    "type":"springboot",
    "description":"springboot"
}  
  • 查询文档
GET请求	http://localhost:9200/books/_doc/1		 #查询单个文档 		
GET请求	http://localhost:9200/books/_search		 #查询全部文档
  • 条件查询
GET请求	http://localhost:9200/books/_search?q=name:springboot	# q=查询属性名:查询属性值
  • 删除文档
DELETE请求	http://localhost:9200/books/_doc/1
  • 修改文档(全量更新)
PUT请求	http://localhost:9200/books/_doc/1

文档通过请求参数传递,数据格式json
{
    "name":"springboot",
    "type":"springboot",
    "description":"springboot"
}
  • 修改文档(部分更新)
POST请求	http://localhost:9200/books/_update/1

文档通过请求参数传递,数据格式json
{			
    "doc":{						#部分更新并不是对原始文档进行更新,而是对原始文档对象中的doc属性中的指定属性更新
        "name":"springboot"		#仅更新提供的属性值,未提供的属性值不参与更新操作
    }
}

整合

使用springboot整合ES该如何进行呢?老规矩,导入坐标,做配置,使用API接口操作。整合Redis如此,整合MongoDB如此,整合ES依然如此。太没有新意了,其实不是没有新意,这就是springboot的强大之处,所有东西都做成相同规则,对开发者来说非常友好。

下面就开始springboot整合ES,操作步骤如下:

步骤①:导入springboot整合ES的starter坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

步骤②:进行基础配置

spring:
  elasticsearch:
    rest:
      uris: http://localhost:9200

配置ES服务器地址,端口9200

步骤③:使用springboot整合ES的专用客户端接口ElasticsearchRestTemplate来进行操作

@SpringBootTest
class Springboot18EsApplicationTests {
    @Autowired
    private ElasticsearchRestTemplate template;
}

上述操作形式是ES早期的操作方式,使用的客户端被称为Low Level Client,这种客户端操作方式性能方面略显不足,于是ES开发了全新的客户端操作方式,称为High Level Client。高级别客户端与ES版本同步更新,但是springboot最初整合ES的时候使用的是低级别客户端,所以企业开发需要更换成高级别的客户端模式。

下面使用高级别客户端方式进行springboot整合ES,操作步骤如下:

步骤①:导入springboot整合ES高级别客户端的坐标,此种形式目前没有对应的starter

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

步骤②:使用编程的形式设置连接的ES服务器,并获取客户端对象

@SpringBootTest
class Springboot18EsApplicationTests {
    private RestHighLevelClient client;
      @Test
      void testCreateClient() throws IOException {
          HttpHost host = HttpHost.create("http://localhost:9200");
          RestClientBuilder builder = RestClient.builder(host);
          client = new RestHighLevelClient(builder);
  
          client.close();
      }
}

配置ES服务器地址与端口9200,记得客户端使用完毕需要手工关闭。由于当前客户端是手工维护的,因此不能通过自动装配的形式加载对象。

步骤③:使用客户端对象操作ES,例如创建索引

@SpringBootTest
class Springboot18EsApplicationTests {
    private RestHighLevelClient client;
      @Test
      void testCreateIndex() throws IOException {
          HttpHost host = HttpHost.create("http://localhost:9200");
          RestClientBuilder builder = RestClient.builder(host);
          client = new RestHighLevelClient(builder);
          
          CreateIndexRequest request = new CreateIndexRequest("books");
          client.indices().create(request, RequestOptions.DEFAULT); 
          
          client.close();
      }
}

高级别客户端操作是通过发送请求的方式完成所有操作的,ES针对各种不同的操作,设定了各式各样的请求对象,上例中创建索引的对象是CreateIndexRequest,其他操作也会有自己专用的Request对象。

当前操作我们发现,无论进行ES何种操作,第一步永远是获取RestHighLevelClient对象,最后一步永远是关闭该对象的连接。在测试中可以使用测试类的特性去帮助开发者一次性的完成上述操作,但是在业务书写时,还需要自行管理。将上述代码格式转换成使用测试类的初始化方法和销毁方法进行客户端对象的维护。

@SpringBootTest
class Springboot18EsApplicationTests {
    @BeforeEach		//在测试类中每个操作运行前运行的方法
    void setUp() {
        HttpHost host = HttpHost.create("http://localhost:9200");
        RestClientBuilder builder = RestClient.builder(host);
        client = new RestHighLevelClient(builder);
    }

    @AfterEach		//在测试类中每个操作运行后运行的方法
    void tearDown() throws IOException {
        client.close();
    }

    private RestHighLevelClient client;

    @Test
    void testCreateIndex() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest("books");
        client.indices().create(request, RequestOptions.DEFAULT);
    }
}

现在的书写简化了很多,也更合理。下面使用上述模式将所有的ES操作执行一遍,测试结果

创建索引(IK分词器)

@Test
void testCreateIndexByIK() throws IOException {
    CreateIndexRequest request = new CreateIndexRequest("books");
    String json = "{\n" +
            "    \"mappings\":{\n" +
            "        \"properties\":{\n" +
            "            \"id\":{\n" +
            "                \"type\":\"keyword\"\n" +
            "            },\n" +
            "            \"name\":{\n" +
            "                \"type\":\"text\",\n" +
            "                \"analyzer\":\"ik_max_word\",\n" +
            "                \"copy_to\":\"all\"\n" +
            "            },\n" +
            "            \"type\":{\n" +
            "                \"type\":\"keyword\"\n" +
            "            },\n" +
            "            \"description\":{\n" +
            "                \"type\":\"text\",\n" +
            "                \"analyzer\":\"ik_max_word\",\n" +
            "                \"copy_to\":\"all\"\n" +
            "            },\n" +
            "            \"all\":{\n" +
            "                \"type\":\"text\",\n" +
            "                \"analyzer\":\"ik_max_word\"\n" +
            "            }\n" +
            "        }\n" +
            "    }\n" +
            "}";
    //设置请求中的参数
    request.source(json, XContentType.JSON);
    client.indices().create(request, RequestOptions.DEFAULT);
}

IK分词器是通过请求参数的形式进行设置的,设置请求参数使用request对象中的source方法进行设置,至于参数是什么,取决于你的操作种类。当请求中需要参数时,均可使用当前形式进行参数设置。

添加文档

@Test
//添加文档
void testCreateDoc() throws IOException {
    Book book = bookDao.selectById(1);
    IndexRequest request = new IndexRequest("books").id(book.getId().toString());
    String json = JSON.toJSONString(book);
    request.source(json,XContentType.JSON);
    client.index(request,RequestOptions.DEFAULT);
}

添加文档使用的请求对象是IndexRequest,与创建索引使用的请求对象不同。

批量添加文档

@Test
//批量添加文档
void testCreateDocAll() throws IOException {
    List<Book> bookList = bookDao.selectList(null);
    BulkRequest bulk = new BulkRequest();
    for (Book book : bookList) {
        IndexRequest request = new IndexRequest("books").id(book.getId().toString());
        String json = JSON.toJSONString(book);
        request.source(json,XContentType.JSON);
        bulk.add(request);
    }
    client.bulk(bulk,RequestOptions.DEFAULT);
}

批量做时,先创建一个BulkRequest的对象,可以将该对象理解为是一个保存request对象的容器,将所有的请求都初始化好后,添加到BulkRequest对象中,再使用BulkRequest对象的bulk方法,一次性执行完毕。

按id查询文档

@Test
//按id查询
void testGet() throws IOException {
    GetRequest request = new GetRequest("books","1");
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    String json = response.getSourceAsString();
    System.out.println(json);
}

根据id查询文档使用的请求对象是GetRequest。

按条件查询文档

@Test
//按条件查询
void testSearch() throws IOException {
    SearchRequest request = new SearchRequest("books");

    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.termQuery("all","spring"));
    request.source(builder);

    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = response.getHits();
    for (SearchHit hit : hits) {
        String source = hit.getSourceAsString();
        //System.out.println(source);
        Book book = JSON.parseObject(source, Book.class);
        System.out.println(book);
    }
}

按条件查询文档使用的请求对象是SearchRequest,查询时调用SearchRequest对象的termQuery方法,需要给出查询属性名,此处支持使用合并字段,也就是前面定义索引属性时添加的all属性。

springboot整合ES的操作到这里就说完了,与前期进行springboot整合redis和mongodb的差别还是蛮大的,主要原始就是我们没有使用springboot整合ES的客户端对象。至于操作,由于ES操作种类过多,所以显得操作略微有点复杂。有关springboot整合ES就先学习到这里吧。

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

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

相关文章

“1+X+N”模式助力企业数字化转型

近期&#xff0c;中电金信顺利完成某股份制银行“基于战略解析与业务架构的全行科技规划项目”交付。针对客户的实际业务需求&#xff0c;中电金信采用“1XN”服务模式&#xff0c;服务客户全面的企业架构转型规划。项目组联合行方协同创新&#xff0c;首次将企架建模方法应用于…

【腾讯云 findops Crane集训营】深入了解 Crane 开源项目之实验操作指南

引言&#xff1a; 最近我参加了由腾讯云联合 CSDN 推出的“腾讯云 Finops Crane 开发者集训营”活动&#xff0c;通过这个活动我对腾讯云的 Finops Crane 开源项目有了更深入的了解。在本篇博客中&#xff0c;我将分享我对该项目的认识和体验&#xff0c;并介绍其中一些关键特性…

C++:使用红黑树封装map和set

目录 一. 如何使用一颗红黑树同时实现map和set 二. 红黑树的节点插入操作 三. 红黑树迭代器的实现 3.1 begin()和end() 3.2 operator和operator-- 3.3 红黑树迭代器实现完整版代码 四. map和set的封装 附录&#xff1a;用红黑树封装map和set完整版代码 1. RBTree.h文件…

表情识别 emotion recognition

facial expression recognition 表情&#xff0c;人脸上的肌肉状态&#xff0c;可以表达人类的情绪。 1970年&#xff0c;Ekman定义了六种基本表情 如何定义&#xff1f; 动作单元(action unit)是定义表情的重要工具。 心理学家和生物学家认为&#xff0c;人的表情可以分解…

【HCIP】三层架构综合实验

目录 需求&#xff1a; 一、拓扑设计 二、配置 ①eth-trunk ②创建vlan & 划分vlan & trunk干道配置 ③STP生成树根节点备份&负责分担 ④SVI及VRRP网关冗余设置 ⑤DHCP ⑥通公网 ⑦验证 三层架构&#xff1a;核心层&#xff0c;汇聚层&#xff0c;接入层 …

QT桌面项目(第一个应用程序 桌面壁纸软件)

文章目录 前言一、壁纸切换程序的布局二、添加资源文件三、代码编写四、主界面代码五、程序的编写思路六、程序效果总结 前言 上节课我们已经做好了APP的按键图标了&#xff0c;这篇文章就让我们来开始制作第一个桌面程序吧。 一、壁纸切换程序的布局 这个是windows上浏览器…

vue3使用指南

vue3使用指南 主要介绍vue3的使用&#xff0c;同时会涉及到vue2&#xff0c;并会讲解其中的一些差异。 安装 CDN引入 如果想快速体验&#xff0c;可以直接通过cdn进行引入。 <div id"app">{{msg}}</div> <script src"https://unpkg.com/vue…

谷歌推出下一代大型语言模型 PaLM 2

谷歌在 2023 年度 I/O 大会上宣布推出了其下一代大型语言模型 PaLM 2&#xff0c;擅长高级推理任务&#xff0c;包括代码和数学、分类和问答、翻译和多语言能力以及自然语言生成。 谷歌声称 PaLM 2 是一种最先进的语言模型&#xff0c;要优于其之前所有的 LLM&#xff0c;包括…

网络拓扑架构规划设计

小型组网架构 1.网络拓扑 终端用户接入到交换机,交换机直连防火墙构成的简单网络,防火墙连接internet,对内网的用户进行安全控制 2.特点 用户接入数量较少:小型网络应用于接入用户数量较少的场景,一般支持几个至几十个用户 网络覆盖范围小:网络覆盖范围一般也是一个…

网络拓扑图制作软件

1.亿图图示(EdrawMax) 最像VISIO的网络拓扑制作工具 亿图图示实际上就是国产的Visio,与Visio非常相似。支持B/S架构,查看拓扑非常方便,模版也比较丰富。缺点与Visio也类似,画简单的网络拓扑没有问题,但针对大型网络拓扑管理而言,既需要能制作拓扑,又需要具有管理分析…

Hystrix详解及实践---SpringCloud组件(四)

Hystrix详解及实践 1.Hystrix简介2.雪崩问题3.服务降级、线程隔离、原理3.1.服务降级实践&#xff08;在feign的基础上实现&#xff09;1 添加Hystrix依赖2.在yml中开启熔断功能3.编写降级逻辑4.重启测试 4.服务熔断(Circuit Breaker)、原理4.1. 熔断原理4.2.动手实践 5.Hystri…

5个模板非常多的免费样机素材分享

样机素材是设计行业的不可缺少的素材之一&#xff0c;设计师可以将自己的设计作品&#xff0c;应用到一个效果图中进行展示&#xff0c;让你的设计作品看起来更加形象逼真。 本文分享5个非常给力的样机素材网站 1.即时设计资源社区 即时设计是一款「专业UI设计工具」&#x…

【edusrc】某校园网登录系统存在的一个简单爆破

前言 红中(hong_zh0) CSDN内容合伙人、2023年新星计划web安全方向导师、 华为MindSpore截至目前最年轻的优秀开发者、IK&N战队队长、 阿里云专家博主、华为网络安全云享专家、腾讯云自媒体分享计划博主 本文主讲思路&#xff0c;可能有点废话。 该漏洞已修复 最开始的思…

华为OD机试真题 Java 实现【字符串重新排序】【2023Q1 100分】

一、题目描述 给定一个字串s&#xff0c;s包含以空格分隔的若干个单词&#xff0c;请对s进行如下处理后输出&#xff1a; 1、单词内部调整 对每个单词字母重新按字典序排序。 2、单词间顺序调整: 统计每个单词出现的次数&#xff0c;并按次数降序排列&#xff1b;次数相同…

存下吧!Spring高频面试题总结

Spring是什么&#xff1f; Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。 Spring的优点 通过控制反转和依赖注入实现松耦合。支持面向切面的编程&#xff0c;并且把应用业务逻辑和系统服务分开。通过切面和模板减少样板式代码。声明式事务的支持。可以从单…

Windows系统下Chromedriver.exe安装及配置

Windows系统下Chromedriver.exe安装及配置 在利用selenium工具进行Web自动化测试时&#xff0c;必须先要安装浏览器驱动&#xff0c;通常比较常用的是谷歌浏览器和火狐浏览器。 一、浏览器驱动下载地址 1.浏览器驱动官网&#xff1a;http://chromedriver.storage.googleapis…

计算环境安全

计算环境安全 操作系统安全安全机制标识与鉴别访问控制权限管理信道保护安全审计内存保护与文件系统保护 安全部署原则操作系统安全配置密码远程暴力破解安全审计 针对系统的攻击信息收集公开信息收集-搜索引擎信息收集与分析的防范 缓冲区溢出缓冲区溢出基础-堆栈、指针、寄存…

Dubbo源码篇03---点点直连如何实现及背后原理

Dubbo源码篇03---从点点直连探究Complier编译的原理 什么是点点直连实际需求如何实现动态编译&#xff1f;如何发起调用?点点直连原理实现点点直连消费端提供端测试 点点直连小结 什么是点点直连 Dubbo正常的请求模型&#xff0c;都是消费端从注册中心拉取服务提供者列表&…

spring 命令执行 (CVE-2022-22947)

漏洞原理 该漏洞产生的原因是由于&#xff0c;当AddResponseHeaderGatewayFilterFactory传入的值进行计算(getValue())的时候&#xff0c;会逐一向上调用对应的方法&#xff0c;直到进入带有SpEL表达式解析器的位置进行最后的解析&#xff0c;从而触发了SpEL表达式注入漏洞。漏…

分组背包问题 java

&#x1f351; 算法题解专栏 &#x1f351; 分组背包问题 输入 3 5 2 1 2 2 4 1 3 4 1 4 5输出 8&#x1f468;‍&#x1f3eb; 参考题解 &#x1f351; 终极简化版 import java.util.Scanner;public class 分组背包极简版 {static int N 110;static int[] f new int[N]…