Springboot整合spring-boot-starter-data-elasticsearch

前言

<font style="color:rgb(36, 41, 47);">spring-boot-starter-data-elasticsearch</font> 是 Spring Boot 提供的一个起始依赖,旨在简化与 Elasticsearch 交互的开发过程。它集成了 Spring Data Elasticsearch,提供了一套完整的 API,用于与 Elasticsearch 进行 CRUD 操作、查询、索引等

相对于es原生依赖的话,进行了一下封装,在使用过程中相对便捷

项目源码

项目源码:https://gitee.com/shen-chuhao/walker_open_java.git

elasticsearch和springboot版本要求

在使用 <font style="color:rgb(36, 41, 47);">spring-boot-starter-data-elasticsearch</font> 时,Spring Boot 版本和 Elasticsearch 版本不一致可能导致以下问题:

  1. 兼容性问题
    • Spring Data Elasticsearch 依赖于特定版本的 Elasticsearch 客户端库。如果版本不兼容,可能会导致运行时异常或方法未找到的错误。
  2. 功能缺失或错误
    • 一些新功能可能在不兼容的版本中不可用,或者可能会存在实现上的差异,导致某些功能无法正常工作。
  3. 配置问题
    • 某些配置选项可能会因版本不一致而有所不同。例如,某些配置参数在新版本中可能被弃用,或者在旧版本中可能不可用。
  4. 序列化和反序列化问题
    • 数据模型的变化可能导致在 Elasticsearch 中存储的数据格式与预期不符,从而引发解析错误。
  5. 性能问题
    • 不兼容的版本可能导致性能下降或不稳定,尤其是在高并发环境下。

相关版本的要求

我的es是7.3.2的,介于6.8.127.6.2之间,所以springboot版本为2.2.x2.3.x即可

所以在使用spring-boot-starter-data-elasticsearch的过程中,还是要保持版本一致

整合步骤

依赖添加

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

yaml配置添加

spring:elasticsearch:rest:uris: localhost:19200# 账号密码配置,如果没有则不需要password: elasticusername: elastic

实体类添加

package com.walker.es.entity;import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.format.annotation.DateTimeFormat;import java.util.Date;@Data//索引
// boolean createIndex() default true;  默认会创建索引
@Document(indexName = "alarm_record", shards = 2, replicas = 2,createIndex = true)
public class AlarmRecordEntity {//    配置使用的id@Idprivate Long id;//    事件
//  配置属性,分词器@Field(type = FieldType.Text, analyzer = "ik_max_word")private String title;//    设备@Field(type = FieldType.Keyword)private String deviceCode;//    时间  需要使用keyword,否则无法实现范围查询 @Field(type = FieldType.Keyword)private String time;//    在es中进行忽略的@Transientprivate String msg;}
  • @Document注解:可以设置索引的名称,分片、副本,是否自动创建索引等
  • @Id:指定文档的id
  • @Field(type = FieldType.Text, analyzer = “ik_max_word”) 属性配置,可以用于配置字段的类型,分词器等等,具体的可以查看后面的相关注解

Repository类

package com.walker.es.repository;import com.walker.es.entity.AlarmRecordEntity;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;// 添加注解
@Repository
// 继承类 ElasticsearchRepository
public interface AlarmRecordRepository extends ElasticsearchRepository<AlarmRecordEntity, Long> {// 你可以在这里添加自定义查询方法
}
  • 继承ElasticsearchRepository类,可以使用ElasticsearchRepository封装好的增删改查等方法

测试类

  • 先注入repository
    @Autowiredprivate AlarmRecordRepository alarmRecordRepository;

新增数据

    // 创建新警报记录@PostMappingpublic ResponseEntity<AlarmRecordEntity> createAlarmRecord(@RequestBody AlarmRecordEntity alarmRecord) {
//      自动生成雪花idalarmRecord.setId(IdUtil.getSnowflakeNextId());AlarmRecordEntity savedRecord = alarmRecordRepository.save(alarmRecord);return ResponseEntity.ok(savedRecord);}

请求参数:

{"title": "打架告警","deviceCode": "A001","time": "2024-11-10 10:10:00","msg": "消息描述"
}

执行后,如果第一次插入数据,则会自动生成索引。

副本、分片

字段映射情况

查询插入的数据

修改数据

@Autowiredprivate DocumentOperations documentOperations;@Autowiredprivate ElasticsearchConverter elasticsearchConverter;// 更新警报记录@PutMapping("/{id}")public ResponseEntity<AlarmRecordEntity> updateAlarmRecord(@PathVariable Long id, @RequestBody AlarmRecordEntity alarmRecord) {//使用ElasticsearchConverter 将对象转成Document对象Document document = elasticsearchConverter.mapObject(alarmRecord);// 修改方法UpdateQuery updateQuery = UpdateQuery.builder(String.valueOf(id)).withDocument(document).build();UpdateResponse updateResponse = documentOperations.update(updateQuery, IndexCoordinates.of("alarm_record"));log.info("修改数据结果:{}", JSONUtil.toJsonStr(updateResponse));return ResponseEntity.ok(alarmRecord);}
  • Repository中是没有修改数据的方法的
  • 所有得使用操作类DocumentOperations、或者ElasticsearchOperations

实践结果:

修改结果如下:

删除

    // 删除警报记录@DeleteMapping("/{id}")public ResponseEntity<Void> deleteAlarmRecord(@PathVariable Long id) {if (!alarmRecordRepository.existsById(id)) {return ResponseEntity.notFound().build();}alarmRecordRepository.deleteById(id);return ResponseEntity.noContent().build();}
  • 使用repository的deleteById

  • 批量删除

使用repository进行基础查询

    // 获取所有警报记录@GetMapping("/findByDeviceCode")public List<AlarmRecordEntity> findByDeviceCode(String deviceCode) {return  alarmRecordRepository.findAlarmRecordEntitiesByDeviceCodeEquals(deviceCode);}
  • 继承ElasticsearchRepository类后,可以使用findXXByXX,进行查询,类似于jpa
  • 例如下面的方法
package com.walker.es.repository;import com.walker.es.entity.AlarmRecordEntity;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;import java.util.List;@Repository
public interface AlarmRecordRepository extends ElasticsearchRepository<AlarmRecordEntity, Long> {// 根据deviceCode=xx进行查询,不需要去重写方法等,相对简便List<AlarmRecordEntity> findAlarmRecordEntitiesByDeviceCodeEquals(String deviceCode);}
  • 具体的关键词使用,可以查看附录1repository关键词

分页查询、条件搜索

这个是实际业务场景中用的比较多的了

但是_ElasticsearchRepository 无法实现复杂的查询,所以还是得使用ElasticsearchTemplate 或者_<font style="color:rgb(36, 41, 47);">ElasticsearchOperations</font> 进行处理

spring-data-elasticsearch的操作类主要有以下几种:

<font style="color:rgb(36, 41, 47);">IndexOperations</font> 定义了在索引级别执行的操作,比如创建或删除索引。

<font style="color:rgb(36, 41, 47);">DocumentOperations</font> 定义了基于实体 ID 存储、更新和检索实体的操作。

<font style="color:rgb(36, 41, 47);">SearchOperations</font> 定义了使用查询搜索多个实体的操作。

<font style="color:rgb(36, 41, 47);">ElasticsearchOperations</font> 结合了 <font style="color:rgb(36, 41, 47);">DocumentOperations</font><font style="color:rgb(36, 41, 47);">SearchOperations</font> 接口的功能。

__

__

__

  • 请求体
@Data
public class AlarmSearchDTO {
//    注意,页码需要从0开始,否则会跳过private Integer pageIndex=0;private Integer pageSize=10;private String title;private String deviceCode;private String startTime;private String endTime;
}

__

  • controllerfangfa
 @PostMapping("/page")public PageVo<AlarmRecordEntity> getAlarmRecords(@RequestBody AlarmSearchDTO dto) {// 分页类  将页码和页数参数填入Pageable pageable = PageRequest.of(dto.getPageIndex(),dto.getPageSize());// 构建查询 在spring-data-elastic中有三种查询方式,具体可以查看后面的查询方式NativeSearchQueryBuilder  query = new NativeSearchQueryBuilder().withPageable(pageable);//        如果设备编码非空if(StrUtil.isNotEmpty(dto.getDeviceCode())){
//            精确查询 termQueryquery.withQuery(QueryBuilders.termQuery("deviceCode",dto.getDeviceCode() ));}if(StrUtil.isNotEmpty(dto.getTitle())){
//            模糊查询 fuzzyQuery   如果是要根据分词拆分查询的话,得使用matchQueryquery.withQuery(QueryBuilders.fuzzyQuery("title",dto.getTitle() ));}//        范围查询if (StrUtil.isNotEmpty(dto.getStartTime())) {
//            range范围查询需要keyword才能生效,如果使用text则会不生效query.withQuery(QueryBuilders.rangeQuery("time").gte(dto.getStartTime()).lte(dto.getEndTime()));}NativeSearchQuery searchQuery = query.build();//        排序:根据id倒叙searchQuery.addSort(Sort.sort(AlarmRecordEntity.class).by(AlarmRecordEntity::getId).descending());// 执行查询SearchHits<AlarmRecordEntity> search = elasticsearchTemplate.search(searchQuery, AlarmRecordEntity.class);PageVo<AlarmRecordEntity> pageVo = new PageVo<>();if(search!=null){//设置总数pageVo.setTotal(search.getTotalHits());// 返回的行数List<SearchHit<AlarmRecordEntity>> searchHits = search.getSearchHits();if(CollUtil.isNotEmpty(searchHits)){ArrayList<AlarmRecordEntity> rows = new ArrayList<>();for (SearchHit<AlarmRecordEntity> searchHit : searchHits) {AlarmRecordEntity content = searchHit.getContent();rows.add(content);}pageVo.setList(rows);}}return pageVo;}
Query查询方式主要有以下几种

1. CriteriaQuery

定义<font style="color:rgb(36, 41, 47);">CriteriaQuery</font> 是一个用于构建类型安全查询的方式。它允许通过构建查询条件来进行灵活的查询。

使用案例

 CodeCriteriaQuery criteriaQuery = new CriteriaQuery();
criteriaQuery.addCriteria(Criteria.where("fieldName").is("value"));List<MyEntity> results = elasticsearchOperations.queryForList(criteriaQuery, MyEntity.class);

2. StringQuery

定义<font style="color:rgb(36, 41, 47);">StringQuery</font> 是一种基于字符串的查询方式,允许直接使用 Elasticsearch 的查询 DSL(Domain Specific Language)。

使用案例

CodeStringQuery stringQuery = new StringQuery("{\"match\":{\"fieldName\":\"value\"}}");List<MyEntity> results = elasticsearchOperations.queryForList(stringQuery, MyEntity.class);

3. NativeQuery

定义<font style="color:rgb(36, 41, 47);">NativeQuery</font> 允许执行原生的 Elasticsearch 查询,通常用于需要更复杂或特定的查询场景。

使用案例

CodeNativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
searchQueryBuilder.withQuery(QueryBuilders.matchQuery("fieldName", "value"));NativeSearchQuery searchQuery = searchQueryBuilder.build();
List<MyEntity> results = elasticsearchOperations.queryForList(searchQuery, MyEntity.class);

总结

  • <font style="color:rgb(36, 41, 47);">CriteriaQuery</font> 适用于类型安全且灵活的查询构建。
  • <font style="color:rgb(36, 41, 47);">StringQuery</font> 提供直接使用查询 DSL 的能力。
  • <font style="color:rgb(36, 41, 47);">NativeQuery</font> 适合复杂的查询需求,允许使用原生的 Elasticsearch 查询。

可以发现,在查询条件中,还是需要手动写出属性的名称,使用起来相对会麻烦一些。

具体的查询方式,可以自己去查找一下,例如范围查询,模糊查询,分词查询等等。

总结

  • spring-data-elasticsearch的查询,相当于原生的es依赖而言,多了一些注解封装、repository类等,但是对于复杂查询还是没有办法很简便,因此便有了第三方的依赖Easy-es的诞生,类似于Mybatis-plus的方式,对于新手对es的使用比较友好,后面会进行讲解

最后:我是Walker,一个热爱分享的程序员,希望我的输出能够帮助到你

附录

repository关键词

KeywordSampleElasticsearch Query String
AndfindByNameAndPrice{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}
OrfindByNameOrPrice{ "query" : { "bool" : { "should" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}
IsfindByName{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}
NotfindByNameNot{ "query" : { "bool" : { "must_not" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}
BetweenfindByPriceBetween{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}
LessThanfindByPriceLessThan{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : false } } } ] } }}
LessThanEqualfindByPriceLessThanEqual{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}
GreaterThanfindByPriceGreaterThan{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : false, "include_upper" : true } } } ] } }}
GreaterThanEqualfindByPriceGreaterThanEqual{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}
BeforefindByPriceBefore{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}
AfterfindByPriceAfter{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}
LikefindByNameLike{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
StartingWithfindByNameStartingWith{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
EndingWithfindByNameEndingWith{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
Contains/ContainingfindByNameContaining{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
In (when annotated as FieldType.Keyword)findByNameIn(Collection<String>names){ "query" : { "bool" : { "must" : [ {"bool" : {"must" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}
InfindByNameIn(Collection<String>names){ "query": {"bool": {"must": [{"query_string":{"query": "\"?\" \"?\"", "fields": ["name"]}}]}}}
NotIn (when annotated as FieldType.Keyword)findByNameNotIn(Collection<String>names){ "query" : { "bool" : { "must" : [ {"bool" : {"must_not" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}
NotInfindByNameNotIn(Collection<String>names){"query": {"bool": {"must": [{"query_string": {"query": "NOT(\"?\" \"?\")", "fields": ["name"]}}]}}}
TruefindByAvailableTrue{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }}
FalsefindByAvailableFalse{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "false", "fields" : [ "available" ] } } ] } }}
OrderByfindByAvailableTrueOrderByNameDesc{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }, "sort":[{"name":{"order":"desc"}}] }
ExistsfindByNameExists{"query":{"bool":{"must":[{"exists":{"field":"name"}}]}}}
IsNullfindByNameIsNull{"query":{"bool":{"must_not":[{"exists":{"field":"name"}}]}}}
IsNotNullfindByNameIsNotNull{"query":{"bool":{"must":[{"exists":{"field":"name"}}]}}}
IsEmptyfindByNameIsEmpty{"query":{"bool":{"must":[{"bool":{"must":[{"exists":{"field":"name"}}],"must_not":[{"wildcard":{"name":{"wildcard":"*"}}}]}}]}}}
IsNotEmptyfindByNameIsNotEmpty{"query":{"bool":{"must":[{"wildcard":{"name":{"wildcard":"*"}}}]}}}

相关注解

@Document:应用于类级别,指示该类可以映射到数据库。最重要的属性包括(检查 API 文档以获取完整属性列表):

  • indexName:存储此实体的索引名称。可以包含像 <font style="color:rgb(36, 41, 47);">"log-#{T(java.time.LocalDate).now().toString()}"</font> 这样的 SpEL 模板表达式。
  • createIndex:标记是否在仓库引导时创建索引。默认值为 true。请参阅与相应映射的自动创建索引相关内容。

@Id:应用于字段级别,用于标记用于身份目的的字段。

@Transient、@ReadOnlyProperty、@WriteOnlyProperty:请参见以下部分“控制哪些属性被写入和从 Elasticsearch 读取”的详细信息。

@PersistenceConstructor:标记在从数据库实例化对象时使用的构造函数——即使是包保护的构造函数。构造函数参数通过名称映射到检索到的文档中的键值。

@Field:应用于字段级别,定义字段的属性,大多数属性映射到相应的 Elasticsearch 映射定义(以下列表并不完整,请检查注解 Javadoc 以获取完整参考):

  • name:字段在 Elasticsearch 文档中的表示名称,如果未设置,则使用 Java 字段名称。
  • type:字段类型,可以是 Text、Keyword、Long、Integer、Short、Byte、Double、Float、Half_Float、Scaled_Float、Date、Date_Nanos、Boolean、Binary、Integer_Range、Float_Range、Long_Range、Double_Range、Date_Range、Ip_Range、Object、Nested、Ip、TokenCount、Percolator、Flattened、Search_As_You_Type 之一。请参阅 Elasticsearch 映射类型。如果未指定字段类型,则默认为 FieldType.Auto。这意味着不会为该属性写入映射条目,并且 Elasticsearch 会在首次存储该属性的数据时动态添加映射条目(请检查 Elasticsearch 文档中的动态映射规则)。
  • format:一个或多个内置日期格式,请参见下一节日期格式映射。
  • pattern:一个或多个自定义日期格式,请参见下一节日期格式映射。
  • store:标记原始字段值是否应存储在 Elasticsearch 中,默认值为 false。
  • analyzersearchAnalyzernormalizer:用于指定自定义分析器和规范化器。

@GeoPoint:标记字段为 geo_point 数据类型。如果字段是 GeoPoint 类的实例,则可以省略此注解。

@ValueConverter:定义一个类,用于转换给定属性。与注册的 Spring 转换器不同,这仅转换注解的属性,而不是给定类型的所有属性。

@Transient:该注解表示该属性不会包含在映射中。其值不会发送到 Elasticsearch,并且在从 Elasticsearch 检索文档时,该属性不会在实体中被填充。

@ReadOnlyProperty:此注解标记一个属性,该属性不会写入 Elasticsearch,但在数据检索时,将根据 Elasticsearch 文档中的值填充该属性。适用于索引映射中定义的运行时字段。

@WriteOnlyProperty:该注解指示一个属性会存储在 Elasticsearch 中,但在读取文档时不会被填充。通常用于需要索引到 Elasticsearch 但在其他地方不需要使用的合成字段。

参考

官方文档

https://docs.spring.io/spring-data/elasticsearch/docs/

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql-Innodb锁相关内容

1、InnoDB存储引擎包含的锁类型 共享锁&#xff08;S锁&#xff09;和排他锁&#xff08;X锁&#xff09;意向锁记录锁间隙锁Next-key锁插入意向锁Auto-INC 锁空间索引的谓词锁 2、共享锁&#xff08;S锁&#xff09;和排他锁&#xff08;X锁&#xff09;-- 锁定数据行 共享…

使用Git进行团队协作开发

使用Git进行团队协作开发 Git简介 安装Git 在Windows上安装Git 在macOS上安装Git 在Linux上安装Git 设置Git用户信息 创建Git仓库 基本Git命令 添加文件 提交更改 查看状态 克隆仓库 推送更改 获取更改 分支管理 创建分支 切换分支 合并分支 删除分支 解决合并冲突 检查冲突…

docker安装、设置非sudo执行、卸载

安装 sudo snap install docker 设置docker非sudo执行 sudo groupadd docker sudo usermod -aG docker $USER newgrp docker sudo chown root:docker /var/run/docker.sock 卸载docker 1.删除docker及安装时自动安装的所有包 apt-get autoremove docker docker-ce docker-…

数据结构_二叉树

二叉树的性质 满二叉树 完全二叉树 完全二叉树的特点 二叉树的存储结构 顺序存储 链式存储 二叉链表 三叉链表 二叉树遍历算法 先序遍历 先序遍历&#xff1a;ABDC 中序遍历 后序遍历 层次遍历

Win11安装基于WSL2的Ubuntu

1. 概述 趁着还没有完全忘记&#xff0c;详细记录一下在Win11下安装基于WSL2的Ubuntu的详细过程。不得不说WSL2现在被微软开发的比较强大了&#xff0c;还是很值得安装和使用的&#xff0c;笔者就通过WSL2安装的Ubuntu成功搭建了ROS环境。 2. 详论 2.1 子系统安装 在Win11搜…

Unity编辑器 连接不到SteamVR问题记录

问题表现&#xff1a;之前正常的工程&#xff0c;某天打开后运行&#xff0c;在SteamVR未打开时&#xff0c;Unity工程运行后无法调用起来Steam VR&#xff0c;无任何反应&#xff0c;但用其他软件则可以调用起来SteamVR&#xff0c;并且运行正常&#xff0c;在重装了XR的一些插…

nfs作业

nfs作业 服务机&#xff1a; 编写配置文件&#xff1a; [rootlocalhost ~]# vim /etc/exports 配置文件内容&#xff1a; /nfs/shared *(ro,sync) /nfs/upload 192.168.36.0/24(rw,anonuid210,anongid210,sync) /home/tom 192.168.36.132(rw) 创建目录&#xff0c;文件&am…

qt QMainWindow详解

一、概述 QMainWindow继承自QWidget&#xff0c;并提供了一个预定义的布局&#xff0c;将窗口分成了菜单栏、工具栏、状态栏和中央部件区域。这些区域共同构成了一个功能丰富的主窗口&#xff0c;使得应用程序的开发更加简单和高效。 二、QMainWindow的常用组件及功能 菜单栏&…

Leetcode11:盛水最多的容器

原题地址&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳…

【每日一题】LeetCode - 判断回文数

今天我们来看一道经典的回文数题目&#xff0c;给定一个整数 x &#xff0c;判断它是否是回文整数。如果 x 是一个回文数&#xff0c;则返回 true&#xff0c;否则返回 false。 回文数 是指从左往右读和从右往左读都相同的整数。例如&#xff0c;121 是回文&#xff0c;而 123 …

Maven 项目管理工具

目录 Maven简介 Maven快速上手 Maven详细介绍 Maven工作机制 Maven安装及配置 使用IDEA创建Maven Web工程 Maven简介 Maven是 Apache 开源组织奉献的一个开源项目&#xff0c;可以翻译为“专家”或“内行”。 Maven 的本质是一个项目管理工具&#xff0c;将项目开发和管…

Tangible Software Solutions 出品最准确可靠的源代码转换器

Tangible Software Solutions 出品最准确可靠的源代码转换器 简介1、Instant C#(VB.NET to C#)2、Instant VB(C# to VB.NET)3、C to C# Converter4、C to Java Converter5、C to Python Converter6、Java to C# Converter7、Java to C Converter8、Java to Python Converter9、…

首届The VRAnimation Award 震撼启幕!VsoCloud独家赞助此次大赛!

CG行业的精英与爱好者们&#xff0c;你们的舞台已经搭好&#xff01;备受瞩目的首届The VR & Animation Award现已正式拉开帷幕&#xff0c;诚邀各位共襄盛举&#xff01;丰厚大奖、作品曝光、行业资源分享……多重惊喜等你来解锁&#xff01; 此次大赛由Rival Technologie…

生产工单系统如何帮助企业控制成本?

我们都知道&#xff0c;在现在竞争日益激烈的市场环境中&#xff0c;企业对于成本控制的需求达到了前所未有的高度。每一分成本的优化&#xff0c;都直接关系到企业的盈利能力和市场竞争力。成本贯穿于生产、销售、管理等各个环节。其中&#xff0c;生产环节的成本控制更是关键…

【瑞吉外卖】-day01

目录 前言 第一天项目启动 获取资料 创建项目 ​编辑 连接本地数据库 连接数据库 修改用户名和密码 ​编辑创建表 创建启动类来进行测试 导入前端页面 创建项目所需目录 检查登录功能 登录界面 登录成功 登录失败 代码 退出功能 易错点 前言 尝试一下企业级项…

2024.10.25 软考学习笔记(知识点)

刷题网站&#xff1a; 软考中级软件设计师在线试题、软考解析及答案-51CTO题库-软考在线做题备考工具

map 和 set 的使用

文章目录 一.序列式容器和关联式容器二. set 系列的使用1. set 和 multiset 参考文档2. set 类介绍3. set 的构造和迭代器4. set 的增删查5. insert 和迭代器遍历使用样例6. find 和 erase 使用样例7. multiset 和 set 的差异 三. map 系列的使用1. map 和 multimap参考文档2. …

【Spring】Spring Boot 日志(8)

本系列共涉及4个框架&#xff1a;Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点&#xff0c;根据序号学习即可。 1、日志概述 1.1学习日志的必要性 在第一次学习编程语言的时候&#xff0c;我们就在使用printf或者System.out.println等打印语句打印日志了…

Python超轻量对话框:easyGUI

文章目录 简介box回调函数 简介 EasyGUI是一个非常简单的GUI模块&#xff0c;提供了许多对话框&#xff0c;所有交互操作都通过简单的函数调用实现。支持pip安装&#xff0c;十分便捷 pip install easygui通过一行代码&#xff0c;即可实现下面的对话框 其对应的代码为 impo…

ArrayList和Array、LinkedList、Vector 间的区别

一、ArrayList 和 Array 的区别 ArrayList 内部基于动态数组实现&#xff0c;比 Array&#xff08;静态数组&#xff09; 使用起来更加灵活&#xff1a; ArrayList 会根据实际存储的元素动态地扩容或缩容&#xff0c;而 Array 被创建之后就不能改变它的长度了。ArrayList 允许…