企業級開發SpringBoost玩轉Elasticsearch

案例

Spring Boot 提供了 spring-data-elasticsearch 模塊,可以方便地集成 Elasticsearch。 下面我們將詳細講解如何在 Spring Boot 中使用 Elasticsearch 8,并提供示例代碼。

1. 添加依賴:

首先,需要在 pom.xml 文件中添加 spring-data-elasticsearch 的依賴。 注意,你需要選擇與你的 Spring Boot 版本和 Elasticsearch 版本兼容的 spring-data-elasticsearch 版本

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

? ? <!-- 其他依賴 -->
</dependencies>

2. 配置 Elasticsearch:

application.propertiesapplication.yml 文件中配置 Elasticsearch 的連接信息。

spring.elasticsearch.uris=http://localhost:9200
# 如果 Elasticsearch 開啟了安全認證,需要配置用戶名和密碼
#spring.elasticsearch.username=elastic
#spring.elasticsearch.password=your_password?

3. 創建實體類:

創建一個實體類,用于映射 Elasticsearch 中的文檔結構。 使用 @Document 注解指定索引名稱,使用 @Id 注解指定文檔 ID 字段。

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;@Document(indexName = "products")  // 指定索引名稱
public class Product {@Id  // 指定文檔 ID 字段private String id;@Field(type = FieldType.Text, name = "name")private String name;@Field(type = FieldType.Double, name = "price")private Double price;// 必須要有默認構造函數public Product() {}public Product(String id, String name, Double price) {this.id = id;this.name = name;this.price = price;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}
}

4. 創建 Repository 接口:

創建一個 Repository 接口,用于操作 Elasticsearch 中的文檔。 繼承 ElasticsearchRepository 接口,并指定實體類和 ID 的類型。

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;@Repository
public interface ProductRepository extends ElasticsearchRepository<Product, String> {// 可以自定義查詢方法,例如根據名稱查詢商品// Spring Data Elasticsearch 會根據方法名自動生成查詢語句Iterable<Product> findByName(String name);
}

5. 創建 Service 類:

創建一個 Service 類,用于調用 Repository 接口,實現業務邏輯。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;@Service
public class ProductService {@Autowiredprivate ProductRepository productRepository;// 創建索引(可選,通常 Elasticsearch 會自動創建)public void createIndex() {// 注意: Spring Data Elasticsearch 提供了自動索引管理的機制,通常不需要手動創建索引// 如果需要自定義索引設置,可以使用 ElasticsearchClient 手動創建// 例如設置 Settings 和 Mappings。}// 添加商品public Product addProduct(Product product) {return productRepository.save(product);}// 根據ID查找商品public Product findProductById(String id) {return productRepository.findById(id).orElse(null);}// 根據名稱查找商品public Iterable<Product> findProductsByName(String name) {return productRepository.findByName(name);}// 更新商品public Product updateProduct(Product product) {return productRepository.save(product); // save 方法在 ID 存在時更新文檔}// 刪除商品public void deleteProductById(String id) {productRepository.deleteById(id);}// 列出所有商品public Iterable<Product> getAllProducts() {return productRepository.findAll();}
}

6. 創建 Controller 類:

創建一個 Controller 類,提供 RESTful API 接口。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;@RestController
@RequestMapping("/products")
public class ProductController {@Autowiredprivate ProductService productService;@PostMappingpublic Product addProduct(@RequestBody Product product) {return productService.addProduct(product);}@GetMapping("/{id}")public Product findProductById(@PathVariable String id) {return productService.findProductById(id);}@GetMapping("/name/{name}")public Iterable<Product> findProductsByName(@PathVariable String name) {return productService.findProductsByName(name);}@PutMappingpublic Product updateProduct(@RequestBody Product product) {return productService.updateProduct(product);}@DeleteMapping("/{id}")public void deleteProductById(@PathVariable String id) {productService.deleteProductById(id);}@GetMappingpublic Iterable<Product> getAllProducts() {return productService.getAllProducts();}
}

7. 完整示例與注意事項:

  • 自動索引管理: spring-data-elasticsearch 提供了自動索引管理的機制。 當你的應用程序啟動時,它會自動檢查 Elasticsearch 中是否存在與你的實體類對應的索引。 如果不存在,它會自動創建索引,并根據實體類的注解設置 mappings。 如果需要更細粒度的控制,你可以禁用自動索引管理,并使用 ElasticsearchClient 手動創建索引。

  • ElasticsearchClient 的使用 (高級): spring-data-elasticsearch 默認提供了 ElasticsearchRestTemplate,可以方便地執行 Elasticsearch 操作。 如果你需要更高級的功能,例如手動創建索引、執行復雜的查詢等,可以使用 ElasticsearchClient

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Map;@Service
public class ElasticsearchIndexService {@Autowiredprivate ElasticsearchOperations  elasticsearchOperations;public void createIndex(String indexName, Map<String, Object> mappings) throws IOException {ElasticsearchClient client = elasticsearchOperations.getClient();CreateIndexRequest request = new CreateIndexRequest.Builder().index(indexName).mappings(m -> m.properties(mappings)) //  這里 mappings 是一個 Map<String,Object>.build();CreateIndexResponse response = client.indices().create(request);if (response.acknowledged()) {System.out.println("Index '" + indexName + "' created successfully.");} else {System.out.println("Failed to create index '" + indexName + "'.");}}
}

企業中使用

ElasticsearchClient 是 Elasticsearch Java 客戶端庫中的核心組件,用于與 Elasticsearch 集群進行交互。它提供了一系列方法來執行各種操作,如索引文檔、搜索數據、更新文檔、刪除文檔等。

//根據查詢條件刪除    
@Overridepublic DeleteByQueryResponse delete(@NonNull Class<?> model, @NonNull Query query) {ModelContext context = ModelContext.of(model);DeleteByQueryRequest request = new DeleteByQueryRequest.Builder().index(context.getIndex()).query(query).conflicts(Conflicts.Proceed).build();try {return this.client.deleteByQuery(request);} catch (IOException e) {throw new RuntimeException(e);}}Query query = QueryBuilders.term(t -> t.field("resumeId").value(resume.getId()));
DeleteByQueryResponse response = this.elasticsearchHandler.delete(Vitae.class, query);//使用
DeleteRequest request = new DeleteRequest.Builder().index(context.getIndex()).id(id).build();

前期學習

修改文檔:
全量修改:PUT/索引庫名/_doc/文檔id{json文檔}

增量修改:POST/索引庫名/_update/文檔id{"doc":{字段}}

    @Overridepublic UpdateByQueryResponse update(@NonNull Class<?> model, @NonNull Query query,@NonNull Map<String, ?> parameters) {ModelContext context = ModelContext.of(model);StringBuilder source = new StringBuilder();Map<String, JsonData> params = Maps.newHashMapWithExpectedSize(parameters.size());parameters.forEach((key, value) -> {if (source.length() > 0) {source.append(";");}if (value == null) {source.append("ctx._source.").append(key).append("=null");} else {source.append("ctx._source.").append(key).append("=params.").append(key);params.put(key, JsonData.of(value));}});Script script = new Script.Builder().lang(ScriptLanguage.Painless).source(source.toString()).params(params).build();UpdateByQueryRequest request = new UpdateByQueryRequest.Builder().index(context.getIndex()).script(script).query(query).conflicts(Conflicts.Proceed).build();try {return this.client.updateByQuery(request);} catch (IOException e) {throw new RuntimeException(e);}}//使用
UpdateByQueryResponse response = this.elasticsearchHandler.update(Vitae.class, query, parameters);
    @Overridepublic UpdateByQueryResponse update(@NonNull Class<?> model, @NonNull Query query, @NonNull String field,Object value) {ModelContext context = ModelContext.of(model);String source = "ctx._source." + field + (value == null ? "=null" : ("=params." + field));Map<String, JsonData> params = value == null ? Collections.emptyMap() :ImmutableMap.of(field, JsonData.of(value));Script script = new Script.Builder().lang(ScriptLanguage.Painless).source(source).params(params).build();UpdateByQueryRequest request = new UpdateByQueryRequest.Builder().index(context.getIndex()).script(script).query(query).conflicts(Conflicts.Proceed).build();try {return this.client.updateByQuery(request);} catch (IOException e) {throw new RuntimeException(e);}}//使用
this.elasticsearchHandler.update(Vitae.class, query, "topping", document);
 @Overridepublic <T> UpdateResponse<T> update(@NonNull Class<T> model, @NonNull String id, @NonNull Object document,Long primary, Long sequence) {ModelContext context = ModelContext.of(model);UpdateRequest<T, ?> request = new UpdateRequest.Builder<T, Object>().index(context.getIndex()).id(id).doc(document).ifPrimaryTerm(primary).ifSeqNo(sequence).retryOnConflict(3).build();try {return this.client.update(request, model);} catch (IOException e) {throw new RuntimeException(e);}}//使用
this.elasticsearchHandler.update(Job.class, id, ImmutableMap.of("recruiting", recruiting));

前期學習

springboot操作es的DSL

QueryBuilders 常用方法
全文查詢
  • matchQuery(String field, Object value): 全文匹配

  • multiMatchQuery(Object value, String... fields): 多字段匹配

  • matchPhraseQuery(String field, Object value): 短語匹配

  • matchPhrasePrefixQuery(String field, Object value): 短語前綴匹配

詞項查詢
  • termQuery(String field, Object value): 精確詞項匹配

  • termsQuery(String field, String... values): 多詞項精確匹配

  • rangeQuery(String field): 范圍查詢(如數值、日期)

  • existsQuery(String field): 檢查字段是否存在

  • prefixQuery(String field, String value): 前綴匹配

  • wildcardQuery(String field, String value): 通配符匹配(如*?

  • regexpQuery(String field, String value): 正則表達式匹配

  • fuzzyQuery(String field, String value): 模糊匹配(容錯匹配)

復合查詢
  • boolQuery(): 布爾查詢(組合多個子查詢)

  • disMaxQuery(): 取多個查詢中的最佳匹配

  • constantScoreQuery(QueryBuilder query): 固定評分查詢

  • nestedQuery(String path, QueryBuilder query, ScoreMode scoreMode): 嵌套對象查詢

  • functionScoreQuery(QueryBuilder query, FunctionScoreBuilder... functions): 自定義評分函數

地理位置查詢

  • geoDistanceQuery(String field): 地理距離范圍查詢

  • geoBoundingBoxQuery(String field): 地理邊界框查詢

其他查詢
  • scriptQuery(Script script): 腳本查詢

  • idsQuery().addIds(String... ids): 根據ID查詢


綜合示例一

假設有一個products索引,包含以下字段:

  • name(文本)

  • price(整數)

  • status(關鍵字)

  • tags(關鍵字數組)

  • location(地理坐標)

  • metadata(嵌套類型,包含keyvalue

import org.elasticsearch.index.query.*;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.action.search.SearchRequest;public class QueryExample {public static void main(String[] args) {// 1. 布爾查詢(組合多個子查詢)BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 2. 全文匹配:搜索name中包含"phone"boolQuery.must(QueryBuilders.matchQuery("name", "phone"));// 3. 多字段匹配:在name和description中搜索"smart"boolQuery.must(QueryBuilders.multiMatchQuery("smart", "name", "description"));// 4. 短語匹配:description中精確匹配"high quality"boolQuery.must(QueryBuilders.matchPhraseQuery("description", "high quality"));// 5. 精確詞項匹配:status為"active"boolQuery.must(QueryBuilders.termQuery("status", "active"));// 6. 多詞項匹配:tags包含"electronics"或"gadgets"boolQuery.must(QueryBuilders.termsQuery("tags", "electronics", "gadgets"));// 7. 范圍查詢:price在100到500之間boolQuery.must(QueryBuilders.rangeQuery("price").gte(100).lte(500));// 8. 存在性檢查:stock字段必須存在boolQuery.filter(QueryBuilders.existsQuery("stock"));// 9. 前綴匹配:description以"latest"開頭boolQuery.should(QueryBuilders.prefixQuery("description", "latest"));// 10. 通配符匹配:tags字段匹配"tec*"(如"tech")boolQuery.should(QueryBuilders.wildcardQuery("tags", "tec*"));// 11. 正則表達式匹配:name匹配正則"pho.*e"boolQuery.should(QueryBuilders.regexpQuery("name", "pho.*e"));// 12. 模糊查詢:name容錯匹配"fone"boolQuery.should(QueryBuilders.fuzzyQuery("name", "fone"));// 13. 地理距離查詢:location距離(37.7749, -122.4194)10公里內boolQuery.filter(QueryBuilders.geoDistanceQuery("location").point(37.7749, -122.4194).distance("10km"));// 14. 嵌套查詢:metadata.key為"color"且metadata.value為"black"boolQuery.must(QueryBuilders.nestedQuery("metadata",QueryBuilders.boolQuery().must(QueryBuilders.termQuery("metadata.key", "color")).must(QueryBuilders.matchQuery("metadata.value", "black")),ScoreMode.Total));// 15. 腳本查詢:price大于200Script script = new Script("doc['price'].value > 200");boolQuery.filter(QueryBuilders.scriptQuery(script));// 構建搜索請求SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.query(boolQuery);SearchRequest searchRequest = new SearchRequest("products");searchRequest.source(sourceBuilder);// 執行搜索(需Elasticsearch客戶端)// SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);}
}
綜合案例二?
 @Overridepublic List<Job> listSearchJobs(@NonNull TextSearch search) {List<Query> pairs = Lists.newLinkedList();if (search.getRegion() != null) {pairs.add(this.jobRegionQuery("regionId", search.getRegion()));}if (StringUtils.notEmpty(search.getKeyword())) {pairs.add(QueryBuilders.match(b -> b.field("description").query(search.getKeyword())));}if (search.getType() != null) {// 指定職位類型pairs.add(QueryBuilders.term(t -> t.field("type").value(search.getType().name())));}if (ObjectUtils.notEmpty(search.getDriveLicenses())) {List<FieldValue> values = search.getDriveLicenses().stream().map(driveLicense -> FieldValue.of(driveLicense.name())).collect(Collectors.toList());pairs.add(QueryBuilders.terms(t -> t.field("driveLicense").terms(v -> v.value(values))));}if (ObjectUtils.isEmpty(pairs)) {return Collections.emptyList();}pairs.add(QueryBuilders.term(t -> t.field("status").value(ContentStatus.ONLINE.name())));Query query = QueryBuilders.bool(b -> b.must(pairs));SearchResponse<Job> response = this.elasticsearchHandler.search(Job.class, query,b -> b.sort(s -> s.field(f -> f.field("refreshTime").order(SortOrder.Desc))).sort(s -> s.field(f -> f.field("_score").order(SortOrder.Desc))).from(search.getPaging().getIndex()).size(search.getPaging().getSize()));return ElasticsearchUtils.sources(response);}

根據id查詢:

    @Overridepublic <T> MgetResponse<T> get(@NonNull Class<T> model, @NonNull List<String> ids) {ModelContext context = ModelContext.of(model);MgetRequest request = new MgetRequest.Builder().index(context.getIndex()).ids(ids).build();try {return this.client.mget(request, model);} catch (IOException e) {throw new RuntimeException(e);}}//使用
MgetResponse<Vitae> response = this.elasticsearchHandler.get(Vitae.class, vitaeIds);
Set<Long> exists = response.docs().stream().map(doc -> doc.result().source()).filter(Objects::nonNull).map(Vitae::getId).collect(Collectors.toSet());

?滾動:

    @Overridepublic <T> ScrollResponse<T> scroll(@NonNull Class<T> model, @NonNull String id, @NonNull String time) {ScrollRequest request = new ScrollRequest.Builder().scrollId(id).scroll(s -> s.time(time)).build();try {return this.client.scroll(request, model);} catch (IOException e) {throw new RuntimeException(e);}}//使用
scrollResponse = elasticsearchHandler.scroll(Job.class, scrollId, keyLive + "m");
ElasticsearchUtils.sources(scrollResponse)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/76536.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/76536.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/76536.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

磐石云智能語音客服系統——技術革新引領服務新體驗

在人工智能技術飛速發展的今天&#xff0c;企業對于智能化客戶服務的需求日益增長。磐石云智能語音客服系統憑借其前沿技術架構與深度場景適配能力&#xff0c;正在重新定義人機交互的邊界。本文將深入解析該系統如何通過技術創新實現服務效率與體驗的雙重突破。 一、意圖識別…

OpenGL學習筆記(assimp封裝、深度測試、模板測試)

目錄 模型加載Assimp網格模型及導入 深度測試深度值精度深度緩沖的可視化深度沖突 模板測試物體輪廓 GitHub主頁&#xff1a;https://github.com/sdpyy1 OpenGL學習倉庫:https://github.com/sdpyy1/CppLearn/tree/main/OpenGLtree/main/OpenGL):https://github.com/sdpyy1/CppL…

通過AWS EKS 生成并部署容器化應用

今天給大家分享一個實戰例子&#xff0c;如何在EKS上創建容器化應用并通過ALB來發布。先介紹一下幾個基本概念&#xff1a; IAM, OpenID Connect (OIDC) 2014 年&#xff0c;AWS Identity and Access Management 增加了使用 OpenID Connect (OIDC) 的聯合身份支持。此功能允許…

入侵檢測snort功能概述

1. 數據包嗅探與日志記錄 網絡流量監控&#xff1a;實時捕獲和分析網絡數據包&#xff08;支持以太網、無線等&#xff09;。 日志記錄&#xff1a;將數據包以二進制格式&#xff08;pcap&#xff09;或文本格式存儲&#xff0c;供后續分析。 2. 協議分析與解碼 深度協議解析…

【Easylive】定時任務-每日數據統計和臨時文件清理

【Easylive】項目常見問題解答&#xff08;自用&持續更新中…&#xff09; 匯總版 這個定時任務系統主要包含兩個核心功能&#xff1a;每日數據統計和臨時文件清理。下面我將詳細解析這兩個定時任務的實現邏輯和技術要點&#xff1a; Component Slf4j public class SysTas…

藍橋杯 15g

班級活動 問題描述 小明的老師準備組織一次班級活動。班上一共有 nn 名 (nn 為偶數) 同學&#xff0c;老師想把所有的同學進行分組&#xff0c;每兩名同學一組。為了公平&#xff0c;老師給每名同學隨機分配了一個 nn 以內的正整數作為 idid&#xff0c;第 ii 名同學的 idid 為…

如何使用AI輔助開發R語言

R語言是一種用于統計計算和圖形生成的編程語言和軟件環境&#xff0c;很多學術研究和數據分析的科學家和統計學家更青睞于它。但對與沒有編程基礎的初學者而言&#xff0c;R語言也是有一定使用難度的。不過現在有了通義靈碼輔助編寫R語言代碼&#xff0c;我們完全可以用自然語言…

CISCO組建RIP V2路由網絡

1.實驗準備&#xff1a; 2.具體配置&#xff1a; 2.1根據分配好的IP地址配置靜態IP&#xff1a; 2.1.1PC配置&#xff1a; PC0&#xff1a; PC1&#xff1a; PC2&#xff1a; 2.1.2路由器配置&#xff1a; R0&#xff1a; Router>en Router#conf t Enter configuration…

React + TipTap 富文本編輯器 實現消息列表展示,類似Slack,Deepseek等對話框功能

經過幾天折騰再折騰&#xff0c;弄出來了&#xff0c;弄出來了&#xff01;&#xff01;&#xff01; 消息展示 在位編輯功能。 兩個tiptap實例1個用來展示 消息列表&#xff0c;一個用來在位編輯消息。 tiptap靈活富文本編輯器&#xff0c;拓展性太好了!!! !!! 關鍵點&#x…

Ubuntu搭建Pytorch環境

Ubuntu搭建Pytorch環境 例如&#xff1a;第一章 Python 機器學習入門之pandas的使用 提示&#xff1a;寫完文章后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 Ubuntu搭建Pytorch環境前言一、Anaconda二、Cuda1.安裝流程2、環境變量&#…

Sping Cloud配置和注冊中心

1.Nacos實現原理了解嗎&#xff1f; Nacos是注冊中心&#xff0c;主要是幫助我們管理服務列表。Nacos的實現原理大概可以從下面三個方面來講&#xff1a; 服務注冊與發現&#xff1a;當一個服務實例啟動時&#xff0c;它會向Nacos Server發送注冊請求&#xff0c;將自己的信息…

C++筆記之父類引用是否可以訪問到子類特有的屬性?

C++筆記之父類引用是否可以訪問到子類特有的屬性? code review! 參考筆記 1.C++筆記之在基類和派生類之間進行類型轉換的所有方法 文章目錄 C++筆記之父類引用是否可以訪問到子類特有的屬性?1.主要原因2.示例代碼3.說明4.如何訪問子類特有的屬性5.注意事項6.總結在 C++ 中,…

JavaScript逆向工程:如何判斷對稱加密與非對稱加密

在現代Web應用安全分析中&#xff0c;加密算法的識別是JavaScript逆向工程的關鍵環節。本文將詳細介紹如何在逆向工程中判斷JavaScript代碼使用的是對稱加密還是非對稱加密。 一、加密算法基礎概念 1. 對稱加密 (Symmetric Encryption) 特點&#xff1a;加密和解密使用相同的…

物理備份工具 BRM vs gs_probackup

什么是BRM 上一篇文章講了openGauss的物理備份工具gs_probackup&#xff0c;今天來說說BRM備份工具。 BRM備份恢復工具全稱為&#xff1a;Backup and Recovery Manager&#xff0c;是MogDB基于opengauss的備份工具 gs_probackup 做了一些封裝和優化,面向MogDB數據庫實現備份和…

問問lua怎么寫DeepSeek,,,,,

很坦白說&#xff0c;這十年&#xff0c;我幾乎沒辦法從互聯網找到這個這樣的代碼&#xff0c;互聯網引擎找不到&#xff0c;我也沒有很大的“追求”要傳承&#xff0c;或者要宣傳什么&#xff1b;直到DeepSeek的出現 兄弟&#xff0c;Deepseek現在已經比你更了解你樓下的超市…

react+Tesseract.js實現前端拍照獲取/選擇文件等文字識別OCR

需求背景 在開發過程中可能會存在用戶上傳一張圖片后下方需要自己識別出來文字數字等信息&#xff0c;有的時候會通過后端來識別后返回&#xff0c;但是也會存在純前端去識別的情況&#xff0c;這個時候就需要使用到Tesseract.js這個庫了 附Tesseract.js官方&#xff08;htt…

藍橋杯考前復盤

明天就是考試了&#xff0c;適當的停下刷題的步伐。 靜靜回望、思考、總結一下&#xff0c;我走過的步伐。 考試不是結束&#xff0c;他只是檢測這一段時間學習成果的工具。 該繼續走的路&#xff0c;還是要繼續走的。 只是最近&#xff0c;我偶爾會感到迷惘&#xff0c;看…

前端-Vue3

1. Vue3簡介 2020年9月18日&#xff0c;Vue.js發布版3.0版本&#xff0c;代號&#xff1a;One Piece&#xff08;n 經歷了&#xff1a;4800次提交、40個RFC、600次PR、300貢獻者 官方發版地址&#xff1a;Release v3.0.0 One Piece vuejs/core 截止2023年10月&#xff0c;最…

[ctfshow web入門] web39

信息收集 題目發生了微妙的變化&#xff0c;只過濾flag&#xff0c;include后固定跟上了.php。且沒有了echo $flag;&#xff0c;雖說本來就沒什么用 if(isset($_GET[c])){$c $_GET[c];if(!preg_match("/flag/i", $c)){include($c.".php");} }else{…

【動手學深度學習】LeNet:卷積神經網絡的開山之作

【動手學深度學習】LeNet&#xff1a;卷積神經網絡的開山之作 1&#xff0c;LeNet卷積神經網絡簡介2&#xff0c;Fashion-MNIST圖像分類數據集3&#xff0c;LeNet總體架構4&#xff0c;LeNet代碼實現4.1&#xff0c;定義LeNet模型4.2&#xff0c;定義模型評估函數4.3&#xff0…