Elasticsearch Java客户端和Spring data elasticsearch

news2024/9/20 14:38:30

文章目录

  • 官网
  • 版本
  • 组件版本说明
  • 实现代码地址
  • es Spring Data Repositories
    • 例子:
    • ElasticsearchRepository分析
  • es Spring Data Repositories 关键字
  • es Spring Data Repositories client 加载
    • rest风格客户端
    • 直接执行dsl例子
    • 响应式客户端-ReactiveElasticsearchClient
      • pom.xml
      • 例子
  • ES 原生方式加载客户端
    • pom.xml
    • 加载原生客户端
    • controller使用
    • 验证结果
  • 测试请求http文件-TestEs.http
  • 外传

官网

https://www.elastic.co/cn/

整合springboot看上一篇文章

版本

一定要对应好版本,Elasticsearch 的不同版本变化是真大,

https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/

在这里插入图片描述

组件版本说明

Springboot: 2.7.10
spring-data-elasticsearch: 4.4.10
spring-boot-starter-data-elasticsearch: 2.7.10
elasticsearch-java: 7.17.9

实现代码地址

https://github.com/OrderDong/microservice-boot
分支:microservice-boot-1.0.6-es

microservice-boot-eleastic模块

在这里插入图片描述

所有pom.xml引用


<!--elastic search 7.17.9 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <!--高版本单独使用elasticsearch client -->
        <dependency>
            <groupId>co.elastic.clients</groupId>
            <artifactId>elasticsearch-java</artifactId>
            <version>7.17.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>
        <dependency>
            <groupId>jakarta.json</groupId>
            <artifactId>jakarta.json-api</artifactId>
            <version>2.0.1</version>
        </dependency>

        <!-- spring-data-elasticsearch 包含此包
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.17.9</version>
        </dependency>-->

        <!-- Reactive Infrastructure -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>io.projectreactor.netty</groupId>
            <artifactId>reactor-netty-http</artifactId>
        </dependency>

es Spring Data Repositories

类似于spring data封装的ORM框架,也可以理解为MVC的M层,当然,完全可以灵活应用,也支持rest层
https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/#repositories

例子:

    //controller
    @PostMapping("/saveVisitLog")
    @ResponseBody
    public String saveVisitLog(@RequestBody VisitLog visitLog){
        VisitLog saveVisitLog = visitLogService.saveVisitLog(visitLog);
        log.info("----saveVisitLog----:{}", JSON.toJSONString(saveVisitLog));
        return JSON.toJSONString(saveVisitLog);
    }

    @GetMapping("/getVisitLogAll")
    @ResponseBody
    public String getVisitLogAll(){
        List<VisitLog> logList = visitLogService.findAll();
        log.info("----getVisitLogAll----:{}", JSON.toJSONString(logList));
        return JSON.toJSONString(logList);
    }


    //service
    @Override
    public VisitLog saveVisitLog(VisitLog visitLog) {
        return visitLogRepository.save(visitLog);
    }

    @Override
    public List<VisitLog> findAll() {
        Iterable<VisitLog> visitLogs = visitLogRepository.findAll();
        List<VisitLog> logs = new ArrayList<>();
        visitLogs.forEach(visitLog -> logs.add(visitLog));
        return logs;
    }

    //dao层
    @Repository
    public interface VisitLogRepository extends ElasticsearchRepository<VisitLog, String> {


    }

ElasticsearchRepository分析

CrudRepository最终继承了这个对象,这个对象被按照规则封装实现了具体的操作

我们可以看下ElasticsearchRepository实现了哪些方法:
在这里插入图片描述


@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
    <S extends T> S save(S entity);

    <S extends T> Iterable<S> saveAll(Iterable<S> entities);

    Optional<T> findById(ID id);

    boolean existsById(ID id);

    Iterable<T> findAll();

    Iterable<T> findAllById(Iterable<ID> ids);

    long count();

    void deleteById(ID id);

    void delete(T entity);

    void deleteAllById(Iterable<? extends ID> ids);

    void deleteAll(Iterable<? extends T> entities);

    void deleteAll();
}


es Spring Data Repositories 关键字

spring data封装的ORM框架,很多接口继承的方法,也可以自定义方法,需要按照封装的规则自定义
https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/#repositories.definition

例子:

    //controller
    //自定义查询
    @GetMapping("/getVisitLogByUserLoginId")
    @ResponseBody
    public String getVisitLogByUserLoginId(Integer userLoginId){
        List<VisitLog> logList = visitLogService.findByUserLoginId(userLoginId);
        log.info("----getVisitLogAll----:{}", JSON.toJSONString(logList));
        return JSON.toJSONString(logList);
    }



    //service impl
        @Override
    public List<VisitLog> findByUserLoginId(Integer userLoginId) {
        return visitLogRepository.findByUserLoginId(userLoginId);
    }


    //
    @Repository
    public interface VisitLogRepository extends ElasticsearchRepository<VisitLog, String> {

        //自定义规则,By--关键字,UserLoginId字段,翻译下,就是查询-find 通过--By  字段--UserLoginId
        //spring data repository会去解析,同样的方式自行查reference文档
        List<VisitLog> findByUserLoginId(Integer userLoginId);
    }


es Spring Data Repositories client 加载

当然,一般使用封装好的也有一定的麻烦事情,也可以自己加载客户端,使用spring data repository 加载,两种方式,但是7.17的版本把这种方式去掉了,
https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/#elasticsearch.clients

rest风格客户端

The Java High Level REST Clientis the default client of Elasticsearch,it is configured likes hown:

package org.lwd.microservice.boot.es.config;

import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;

/**
 * rest风格客户端
 * The Java High Level REST Client is the default client of Elasticsearch, it is configured like shown:
 *
 * @author weidong
 * @version V1.0.0
 * @since 2023/7/27
 */
@Configuration
public class EsRestHighLevelClientConfig extends AbstractElasticsearchConfiguration {

    @Value("${spring.elasticsearch.uris}")
    private String uris;

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {

        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(uris)
                .build();

        return RestClients.create(clientConfiguration).rest();
    }

}

我们看下,那个bean可用(猜测一定被封装好了),AbstractElasticsearchConfiguration

public abstract class AbstractElasticsearchConfiguration extends ElasticsearchConfigurationSupport {

    /**
     * Return the {@link RestHighLevelClient} instance used to connect to the cluster. <br />
     *
     * @return never {@literal null}.
     */
    @Bean
    public abstract RestHighLevelClient elasticsearchClient();

    /**
     * Creates {@link ElasticsearchOperations}.
     *
     * @return never {@literal null}.
     */
    @Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
    public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter,
            RestHighLevelClient elasticsearchClient) {

        ElasticsearchRestTemplate template = new ElasticsearchRestTemplate(elasticsearchClient, elasticsearchConverter);
        template.setRefreshPolicy(refreshPolicy());

        return template;
    }
}

不知道各位发现没:@Bean(name = { “elasticsearchOperations”, “elasticsearchTemplate” })
用这个bean去操作

直接执行dsl例子

    //rest模版操作
    @Autowired
    ElasticsearchOperations elasticsearchOperations;


        //rest客户端模版
    @GetMapping("/getHighTempt")
    @ResponseBody
    public String getHighTempt(){
        Query query = new StringQuery("{ \"match\": { \"userLoginId\": 1 } } ");
        query.setPageable(PageRequest.of(0, 10));
        SearchHits<VisitLog>  searchHits = elasticsearchOperations.search(query,VisitLog.class);
        return JSON.toJSONString(searchHits);
    }


响应式客户端-ReactiveElasticsearchClient

  • The ReactiveElasticsearchClient is a non official driver based on WebClient.
  • It uses the request/response objects provided by the Elasticsearch core project.
  • Calls are directly operated on the reactive stack, not wrapping async (thread pool bound) responses into reactive types.
    如果不知道什么是响应式,自行百度

pom.xml


<!-- Reactive Infrastructure -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>io.projectreactor.netty</groupId>
            <artifactId>reactor-netty-http</artifactId>
        </dependency>

例子

package org.lwd.microservice.boot.es.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
import org.springframework.data.elasticsearch.client.reactive.ReactiveRestClients;
import org.springframework.data.elasticsearch.config.AbstractReactiveElasticsearchConfiguration;

/**
 * 响应式客户端
 * The ReactiveElasticsearchClient is a non official driver based on WebClient.
 * It uses the request/response objects provided by the Elasticsearch core project.
 * Calls are directly operated on the reactive stack, not wrapping async (thread pool bound) responses into reactive types.
 *
 * @author weidong
 * @version V1.0.0
 * @since 2023/7/28
 */
@Configuration
public class EsReactiveRestClientConfig extends AbstractReactiveElasticsearchConfiguration {

    @Value("${spring.elasticsearch.uris}")
    private String uris;

    @Bean
    @Override
    public ReactiveElasticsearchClient reactiveElasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(uris) //
                .build();
        return ReactiveRestClients.create(clientConfiguration);
    }
}



    //响应式模版操作
    @Autowired
    ReactiveElasticsearchOperations reactiveElasticsearchOperations;


    //响应式客户端
    @GetMapping("/getReactiveTemp")
    @ResponseBody
    public String getReactiveTemp(){
        Query query = new StringQuery("{ \"match\": { \"userLoginId\": 1 } } ");
        query.setPageable(PageRequest.of(0, 10));
        Flux<SearchHit<VisitLog>> result = reactiveElasticsearchOperations.search(query,VisitLog.class);
        return JSON.toJSONString(result);
    }

ES 原生方式加载客户端

从 ElasticSearch7.17 这个版本开始,原先的 Java 高级客户端
Java High Level REST Client 废弃了,不支持了。老实说,ElasticSearch 算是我用过的所有 Java 工具中,更新最为激进的一个了,在 Es7 中废弃了 TransportClient,7.17 又废弃了 TransportClient,那么现在用啥呢?现在的客户端叫做 Elasticsearch Java API Client。

Elasticsearch Java API Client 具有如下特性:

为所有 Elasticsearch APIs 提供强类型的请求和响应。
所有 API 都有阻塞和异步版本。
使用构建器模式,在创建复杂的嵌套结构时,可以编写简洁而可读的代码。
通过使用对象映射器(如 Jackson 或任何实现了 JSON-B 的解析器),实现应用程序类的无缝集成。
将协议处理委托给一个 http 客户端,如 Java Low Level REST Client,它负责所有传输级的问题。HTTP 连接池、重试、节点发现等等由它去完成。
关于第三点,松哥吐槽一句,确实简洁,但是可读性一般般吧。

另外还有两点需要注意:

Elasticsearch Java 客户端是向前兼容的,即该客户端支持与 Elasticsearch 的更大或相等的次要版本进行通信。
Elasticsearch Java 客户端只向后兼容默认的发行版本,并且没有做出保证。

pom.xml

<!--高版本单独使用elasticsearch client -->
        <dependency>
            <groupId>co.elastic.clients</groupId>
            <artifactId>elasticsearch-java</artifactId>
            <version>7.17.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>
        <dependency>
            <groupId>jakarta.json</groupId>
            <artifactId>jakarta.json-api</artifactId>
            <version>2.0.1</version>
        </dependency>

加载原生客户端

注意下,一定要用原生elasticsearch-java jar中的类

package org.lwd.microservice.boot.es.config;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 使用elasticsearch client 7.17.9
 *
 * @author weidong
 * @version V1.0.0
 * @since 2023/7/31
 */
@Configuration
public class EsRestClientConfig {
    @Value("${spring.elasticsearch.uris}")
    private String uris;

    @Bean
    public ElasticsearchClient initSyncRestClient() {
        RestClient restClient = RestClient.builder(HttpHost.create(uris)).build();
        ElasticsearchTransport transport = new RestClientTransport(
                restClient, new JacksonJsonpMapper());
        ElasticsearchClient client = new ElasticsearchClient(transport);

        return client;
    }
}


controller使用


    @Autowired
    ElasticsearchClient elasticsearchClient;
    //elasticsearch client 7.17.9
    @GetMapping("/getRestTemp")
    @ResponseBody
    public String getRestTemp(){
        StringReader sr = new StringReader(
                "{\n" +
                        "  \"query\": { \"match\": {\n" +
                        "    \"userLoginId\": \"1\"\n" +
                        "  }}" +
                        "}"
        );
        //查询所有
       /* StringReader sr = new StringReader(
               "{\n" +
                       "  \"query\": {\n" +
                       "    \"match_all\" : {}\n" +
                       "  }\n" +
                       "}\n"
        );*/
        SearchRequest request = new SearchRequest.Builder().index(Arrays.asList(new String[]{"visit_log"}))
                .withJson(sr)
                .build();
        try {
            SearchResponse<VisitLog>  search = elasticsearchClient.search(request,VisitLog.class);
            System.out.println("search.toString() = " + search.toString());
            long took = search.took();
            System.out.println("took = " + took);
            boolean b = search.timedOut();
            System.out.println("b = " + b);
            ShardStatistics shards = search.shards();
            System.out.println("shards = " + shards);
            HitsMetadata<VisitLog> hits = search.hits();
            TotalHits total = hits.total();
            System.out.println("total = " + total);
            Double maxScore = hits.maxScore();
            System.out.println("maxScore = " + maxScore);
            List<Hit<VisitLog>> list = hits.hits();
            for (Hit<VisitLog> visitLogHit : list) {
                System.out.println("visitLogHit.source() = " + JSON.toJSONString(visitLogHit.source()));
                System.out.println("visitLogHit.score() = " + visitLogHit.score());
                System.out.println("visitLogHit.index() = " + visitLogHit.index());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


可以看到,直接把查询的 JSON 参数传进来也是可以的。这样我们就可以先在 Kibana 中写好脚本,然后直接将脚本拷贝到 Java 代码中来执行就行了。

验证结果

request [POST http://10.255.20.231:9200/visit_log/_search?typed_keys=true] returned 1 warnings: [299 Elasticsearch-7.17.9-ef48222227ee6b9e70e502f0f0daa52435ee634d "Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security."]
search.toString() = SearchResponse: {"took":0,"timed_out":false,"_shards":{"failed":0.0,"successful":1.0,"total":1.0,"skipped":0.0},"hits":{"total":{"relation":"eq","value":1},"hits":[{"_index":"visit_log","_id":"2","_score":0.9808291,"_type":"_doc","_source":"org.lwd.microservice.boot.es.entity.VisitLog@1bbbdce9"}],"max_score":0.9808291}}
took = 0
b = false
shards = ShardStatistics: {"failed":0.0,"successful":1.0,"total":1.0,"skipped":0.0}
total = TotalHits: {"relation":"eq","value":1}
maxScore = 0.9808291
visitLogHit.source() = {"_class":"org.lwd.microservice.boot.es.entity.VisitLog","createTime":"2023-07-27 16:34:36","id":2,"initialRequest":"http://localhost:8023","msgContent":"test es add2","serverHostName":"weidong","serverIpAddress":"127.0.0.1","tableName":"VisitLog","userLoginId":"1"}
visitLogHit.score() = 0.9808291
visitLogHit.index() = visit_log

测试请求http文件-TestEs.http


## 新增日志
POST http://localhost:8023/es/saveVisitLog
Content-Type: application/json

{
  "id": 3,
  "tableName": "VisitLog",
  "userLoginId": 3,
  "serverIpAddress": "127.0.0.1",
  "serverHostName": "weidong",
  "initialRequest": "http://localhost:8023",
  "msgContent": "test es add3",
  "createTime": "2023-07-27 16:34:36"
}


### 获取所有数据-不分页

GET http://localhost:8023/es/getVisitLogAll

### 获取所有数据-自定义查询规则

GET http://localhost:8023/es/getVisitLogByUserLoginId?userLoginId=1

### 获取所有数据-high rest

GET http://localhost:8023/es/getHighTempt

### 获取所有数据-reactive rest

GET http://localhost:8023/es/getReactiveTemp

### 获取所有数据-elasticsearch client 7.17.9

GET http://localhost:8023/es/getRestTemp


外传

😜 原创不易,如若本文能够帮助到您的同学
🎉 支持我:关注我+点赞👍+收藏⭐️
📝 留言:探讨问题,看到立马回复
💬 格言:己所不欲勿施于人 扬帆起航、游历人生、永不言弃!🔥

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

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

相关文章

SSD市场上演大洗牌,61TB豪华「别墅」横空出世

最近几年 SSD 售价是肉眼可见的下降&#xff0c;相信大伙儿没少跟着喝汤吃肉吧。 有人将这些变化归结于全球市场过饱和&#xff0c;需求下滑。 也有人认为国产 NAND 闪存崛起是压垮 SSD 高昂售价的最后一根稻草。 在小忆看来&#xff0c;不论是需求矛盾还是国产崛起不过是其中…

Maven右侧依赖Dependencies消失

项目右侧的Maven依赖Dependencies突然消失&#xff0c;项目中的注解都出现报错&#xff0c;出现这种情况应该是因为IDEA版本早于maven版本&#xff0c;重新检查项目中的Maven路径&#xff0c;选择File->Settings->搜索Maven&#xff0c;检查Maven home directory&#xf…

爆肝整理,接口自动化测试-数据驱动框架封装(实战)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口自动化框架—…

没有软件测试经验,怎样面试测试工作?

纸上得来终觉浅&#xff0c;所有的面试经验都是要自己去体验&#xff0c;他人说来的都是他人的经验。 同样&#xff0c;每个公司&#xff0c;面对的面试官都会有不同的问题&#xff0c;当然这些问题可能会大同小异&#xff0c;但是也需要自己总结得出&#xff0c;这样的经验不…

1221. 四平方和(超详细!!)

输入样例&#xff1a; 5输出样例&#xff1a; 0 0 1 2 本题思路&#xff1a;以空间换时间 由于暴力解法我们至少要枚举三个数&#xff0c;然后计算出第四个数 呢么需要进行三重循环,时间复杂度大概为O(n3),则会超时 所以我们要进行优化来降低时间复杂度 我们的思路是&#xf…

怎么学习C语言,才能快速掌握?

有多年软件行业经验&#xff0c;期间参与过多个C语言项目。要掌握一门编程语言&#xff0c;仅仅投入时间学习是不够的&#xff0c;关键在于实际项目经验。在没有真正实战经验之前&#xff0c;不宜轻易声称掌握某种编程语言&#xff0c;因为编程是积累性的工作&#xff0c;理论知…

需求太多处理不过来?MoSCoW模型帮你

一、MoSCoW模型是什么 MoSCoW模型 是在项目管理、软件开发中使用的一种排序优先级的方法&#xff0c;以便开发人员、产品经理、客户对每个需求交付的重要性达成共识。 MoSCoW是一个首字母缩略词&#xff0c;代表&#xff1a; M&#xff08;Must have&#xff09;&#xff1a…

IDEA开启并配置services窗口

前言&#xff1a; 一般一个spring cloud项目中大大小小存在几个十几个module编写具体的微服务项目。此时&#xff0c;如果要调试测需要依次启动各个项目比较麻烦。 方法一&#xff1a; 默认第一次打开项目的时候&#xff0c;idea会提示是否增加这个选项卡&#xff0c;如果你没…

NIDEC COMPONENTS尼得科科宝滑动型DIP开关各系列介绍

今天AMEYA360对尼得科科宝电子滑动型DIP开关各系列参数进行详细介绍&#xff0c;方便大家选择适合自己的型号。 系列一、滑动型DIP开关 CVS 针脚数&#xff1a;1, 2, 3, 4, 8 安装类型&#xff1a;表面贴装&#xff0c;通孔 可水洗&#xff1a;无 端子类型&#xff1a;PC引脚(只…

Closure Table-树形多级关系数据库设计(MySql)

一般树形多级关系数据库设计&#xff0c;比较普遍的就是四种方法&#xff1a;&#xff08;具体见 SQL Anti-patterns这本书&#xff09; Adjacency List&#xff1a;每一条记录存parent_id Path Enumerations&#xff1a;每一条记录存整个tree path经过的node枚举&#xff08…

Java互斥锁简单实例

Java互斥锁简单实例 本文实例讲述了java互斥锁。分享给大家供大家参考。具体分析如下&#xff1a; 互斥锁&#xff0c;常常用于多个线程访问独占式资源&#xff0c;比如多个线程同时写一个文件&#xff0c;虽然互斥访问方式不够高效&#xff0c;但是对于一些应用场景却很有意义…

STM32 LoRa(学习二)

LoRa关键参数说明 LoRa数据包由三个部分组成&#xff1a;前导码、可选报头、数据有效负载。 前导码&#xff1a;用于保持接收机与输入的数据流同步。默认情况下&#xff0c;数据包含有12个符号长度的前导码。前导码是一个可以通过编程来设置的变量&#xff0c;所以前导码的长度…

我总结的接地概念,为什么水泥大地是导体,为什么要接地,TT和TN供电系统等

我总结的接地概念&#xff0c;为什么水泥大地是导体&#xff0c;为什么要接地&#xff0c;TT和TN供电系统等 wxleasyland 个人参考网上资料理解的相关接地的问题&#xff0c;可能会有不对的地方&#xff0c;仅供参考。 主要参考了大神的&#xff1a;《浅谈接地》https://zhuan…

软件测试员怎么提升自己的职业竞争力?

目录 管理方向 技术方向 初级测试人员 中级测试人员 高级测试人员 首先分析下软件测试岗位的发展方向&#xff1a;软件测试岗位可以向两个方向发展&#xff0c;一个管理方向&#xff0c;一个技术方向。现在很多做测试的人感到很迷茫&#xff0c;自己整天做着重复的事情&am…

关于远程直接内存访问技术 RDMA 的高性能架构设计介绍 | 龙蜥技术

编者按&#xff1a;传统以太网方案存在系统调用消耗大量时间、增加数据传输延时、对 CPU 造成很重的负担三个缺点&#xff0c;而 RDMA 技术可以解决以上三个缺点。那 RDMA 究竟是什么&#xff1f;它的方案的设计思路是什么&#xff1f;今天&#xff0c;浪潮信息驱动工程师刘伟带…

从零开始学python(十三)爬虫工程师自动化和抓包

前言 回顾之前讲述了python语法编程 必修入门基础和网络编程&#xff0c;多线程/多进程/协程等方面的内容&#xff0c;后续讲到了数据库编程篇MySQL&#xff0c;Redis&#xff0c;MongoDB篇&#xff0c;和机器学习&#xff0c;全栈开发&#xff0c;数据分析&#xff0c;爬虫数…

三十三章 uboot使用(universal boot loader)

Linux 系统要启动就必须需要一个 bootloader 程序&#xff0c;也就说芯片上电以后先运行一段bootloader 程序。这段bootloader程序会先初始化DDR等外设&#xff0c;然后将Linux内核从flash(NAND&#xff0c;NORFLASH&#xff0c;SD&#xff0c; MMC 等)拷贝到 DDR 中&#xff0…

Mybatis-plus的批量插入真的不能用吗?

目录 &#x1f9e8;一、前言 &#x1f9e8;二、走进源码 1.进入 saveBatch 看下 2.往里ServiceImpl#saveBatch走 3.SqlHelper#executeBatch(Class, Log, Collection, int, BiConsumer),e> 4.SqlHelper#executeBatch(Class entityClass, Log log, Consumer consumer) …

Kata Containers

Kata Containers&#xff08;简称 Kata 或 Kata Containers&#xff09;是一个开源的容器运行时项目&#xff0c;它提供了一种轻量级的虚拟化解决方案&#xff0c;用于在容器内运行应用程序。Kata Containers 结合了虚拟机&#xff08;VM&#xff09;和容器的优势&#xff0c;旨…

无涯教程-jQuery - innerHeight( )方法函数

innerHeight()方法获取第一个匹配元素的内部高度(不包括边框&#xff0c;包括填充)。 innerHeight( ) - 语法 selector.innerHeight( ) innerHeight( ) - 示例 以下是一个简单的示例&#xff0c;简单说明了此方法的用法- <html><head><title>The jQuery…