SpringBoot整合Elasticsearch實現(xiàn)索引和文檔的操作方法
Elasticsearch 是一個分布式、可擴展、近實時的高性能搜索與數(shù)據(jù)分析引擎。Elasticsearch 基于 Apache Lucene 構(gòu)建,采用 Java 編寫,并使用 Lucene 構(gòu)建索引、提供搜索功能。Elasticsearch 的目標是讓全文搜索功能的落地變得簡單。
本文是SpringBoot整合Elasticsearch與綜合實例的第一篇,主要實現(xiàn)SpringBoot整合Elasticsearch實現(xiàn)索引和文檔的相關(guān)操作。
1、SpringBoot整合Elasticsearch的步驟
(1)創(chuàng)建SpringBoot項目,項目結(jié)構(gòu)如下圖:

(2)使用Maven添加依賴文件
在pom.xml配置信息文件中,添加 Elasticsearch服務(wù)、Elasticsearch高級客戶端的依賴:
<!-- Elasticsearch服務(wù) -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.11.1</version>
</dependency>
<!-- Elasticsearch高級客戶端 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.11.1</version>
</dependency>
(3)Elasticsearch的配置
在 application.yml 配置文件中配置 Elasticsearch 信息:
# Elasticsearch配置 elasticsearch: hostname: 127.0.0.1 port: 9200 scheme: http
(4)Elasticsearch配置類(config層)
創(chuàng)建 com.pjb.config 包,并創(chuàng)建 ElasticsearchConfig 類(Elasticsearch配置類),并使用 @Configuration 注解,標注該類為配置類。
package com.pjb.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Elasticsearch配置類
* @author pan_junbiao
**/
@Configuration
public class ElasticsearchConfig
{
@Value("${elasticsearch.hostname}")
private String hostname;
@Value("${elasticsearch.port}")
private int port;
@Value("${elasticsearch.scheme}")
private String scheme;
/**
* 初始化:高級客戶端
* @return
*/
@Bean
public RestHighLevelClient restHighLevelClient()
{
RestHighLevelClient restHighLevelClient = null;
try
{
RestClientBuilder builder = RestClient.builder(new HttpHost(hostname, port, scheme));
restHighLevelClient = new RestHighLevelClient(builder);
return restHighLevelClient;
}
catch (Exception ex)
{
System.out.println("初始化Elasticsearch高級客戶端失敗");
ex.printStackTrace();
}
return restHighLevelClient;
}
}
2、索引的操作
在 Elasticsearch 中開始為數(shù)據(jù)建立索引之前要做的第一步操作是創(chuàng)建——我們的數(shù)據(jù)主要容器。這里的索引類似于 SQL 中的數(shù)據(jù)庫概念。它是類型(相當于 SQL 中的表)和文檔(相當于 SQL 中的記錄)的容器。
存儲數(shù)據(jù)的行為叫作索引。在 Elasticsearch 中,文檔會歸屬于一種類型,這些類型會存在于索引中。
Elasticsearch 集群和數(shù)據(jù)庫中核心概念的對應(yīng)關(guān)系如下:
| Elasticsearch 集群 | 關(guān)系型數(shù)據(jù)庫 |
|---|---|
| 索引 | 數(shù)據(jù)庫 |
| 類型 | 表 |
| 文檔 | 行數(shù)據(jù) |
| 字段 | 列數(shù)據(jù) |
定義一個博客信息(blog_info)的數(shù)據(jù)表結(jié)構(gòu):
| 字段 | 類型 | 說明 |
|---|---|---|
| blogId | long | 博客ID |
| blogName | text | 博客名稱 |
| blogUrl | keyword | 博客地址 |
| blogPoints | double | 博客積分 |
| createDate | date | 創(chuàng)建時間 |
| blogDescribe | text | 博客描述 |
字段類型必須映射到 Elasticsearch 的基本類型之一,并且需要添加有關(guān)如何索引字段的選項。
推薦本博客文章1:《Elasticsearch映射類型》
推薦本博客文章2:《Elasticsearch基本操作》
Elasticsearch教程:《Elasticsearch教程》
創(chuàng)建 com.pjb.entity 包,并創(chuàng)建BlogInfo類(博客信息實體類)。
package com.pjb.entity;
import java.util.Date;
/**
* 博客信息實體類
* @author pan_junbiao
**/
public class BlogInfo
{
private int blogId; //博客ID
private String blogName; //博客名稱
private String blogUrl; //博客地址
private double blogPoints; //博客積分
private Date createDate; //創(chuàng)建時間
private String blogDescribe; //博客描述
//構(gòu)建方法1
public BlogInfo()
{
}
//構(gòu)建方法2
public BlogInfo(int blogId, String blogName, String blogUrl, double blogPoints, Date createDate, String blogDescribe)
{
this.blogId = blogId;
this.blogName = blogName;
this.blogUrl = blogUrl;
this.blogPoints = blogPoints;
this.createDate = createDate;
this.blogDescribe = blogDescribe;
}
public int getBlogId()
{
return blogId;
}
public void setBlogId(int blogId)
{
this.blogId = blogId;
}
public String getBlogName()
{
return blogName;
}
public void setBlogName(String blogName)
{
this.blogName = blogName;
}
public String getBlogUrl()
{
return blogUrl;
}
public void setBlogUrl(String blogUrl)
{
this.blogUrl = blogUrl;
}
public double getBlogPoints()
{
return blogPoints;
}
public void setBlogPoints(double blogPoints)
{
this.blogPoints = blogPoints;
}
public Date getCreateDate()
{
return createDate;
}
public void setCreateDate(Date createDate)
{
this.createDate = createDate;
}
public String getBlogDescribe()
{
return blogDescribe;
}
public void setBlogDescribe(String blogDescribe)
{
this.blogDescribe = blogDescribe;
}
}
2.1 索引存在驗證
(1)編寫索引存在驗證方法:
/**
* Elasticsearch高級客戶端
*/
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 索引存在驗證
* @param indexName 索引名稱
*/
@Override
public boolean existsIndex(String indexName)
{
boolean exists = false;
//參數(shù)驗證
if(indexName==null || indexName.length()<=0)
{
return false;
}
try
{
//構(gòu)建索引存在驗證請求
GetIndexRequest request = new GetIndexRequest(indexName);
//執(zhí)行請求
exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
}
catch (Exception ex)
{
ex.printStackTrace();
}
return exists;
}
2.2 創(chuàng)建索引
(1)編寫創(chuàng)建索引方法:
/**
* Elasticsearch高級客戶端
*/
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 創(chuàng)建索引
* @param indexName 索引名稱
*/
@Override
public boolean createIndex(String indexName)
{
boolean result = false;
//參數(shù)驗證
if(indexName==null || indexName.length()<=0)
{
return false;
}
try
{
//1.創(chuàng)建索引的請求
CreateIndexRequest request = new CreateIndexRequest(indexName);
//構(gòu)建索引結(jié)構(gòu)
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.startObject("properties");
{
//創(chuàng)建博客ID文檔字段
builder.startObject("blogId");
{
builder.field("type", "long");
}
builder.endObject();
//創(chuàng)建博客名稱文檔字段
builder.startObject("blogName");
{
builder.field("type", "text");
}
builder.endObject();
//創(chuàng)建博客地址文檔字段
builder.startObject("blogUrl");
{
builder.field("type", "keyword");
}
builder.endObject();
//創(chuàng)建博客積分字段
builder.startObject("blogPoints");
{
builder.field("type", "double");
}
builder.endObject();
//創(chuàng)建創(chuàng)建時間字段
builder.startObject("createDate");
{
builder.field("type", "date");
}
builder.endObject();
//創(chuàng)建博客描述字段
builder.startObject("blogDescribe");
{
builder.field("type", "text")
//插入時分詞
.field("analyzer", "ik_smart")
//搜索時分詞
.field("search_analyzer", "ik_max_word");
}
builder.endObject();
}
builder.endObject();
}
builder.endObject();
request.mapping(builder);
//2客戶端執(zhí)行請求,請求后獲得響應(yīng)
CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
result = true;
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
(2)編寫測試方法:
package com.pjb;
import com.pjb.entity.BlogInfo;
import com.pjb.service.impl.BlogService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 博客服務(wù)測試類
* @author pan_junbiao
**/
@SpringBootTest
public class BlogServiceTest
{
@BeforeEach
private void setUp()
{
}
@AfterEach
private void tearDown()
{
}
/**
* 博客業(yè)務(wù)邏輯類
*/
@Autowired
private BlogService blogService;
/**
* 索引名稱
* 注意:索引名稱必須小寫
*/
private String _indexName = "blog_info";
/**
* 測試:創(chuàng)建索引
* @author pan_junbiao
*/
@Test
public void createIndex()
{
//判斷索引是否存在
boolean exists = blogService.existsIndex(_indexName);
if(exists)
{
System.out.println("索引已經(jīng)存在");
return;
}
//創(chuàng)建索引
boolean result = blogService.createIndex(_indexName);
if(result)
{
System.out.println("索引創(chuàng)建成功");
}
else
{
System.out.println("索引創(chuàng)建失敗");
}
}
}
(4)使用 ElasticSearch-head 插件查看執(zhí)行結(jié)果:

2.3 刪除索引
(1)編寫刪除索引方法:
/**
* 刪除索引
* @param indexName 索引名稱
*/
@Override
public boolean deleteIndex(String indexName)
{
boolean result = false;
//參數(shù)驗證
if(indexName==null || indexName.length()<=0)
{
return false;
}
//注意:刪除索引前,必須先判斷索引是否存在,否則會報異常
if(!existsIndex(indexName))
{
//該索引不存在
return false;
}
try
{
//創(chuàng)建刪除索引請求
DeleteIndexRequest request = new DeleteIndexRequest(indexName);
//執(zhí)行請求返回響應(yīng)結(jié)果
AcknowledgedResponse deleteIndexResponse = restHighLevelClient.indices().delete(request,RequestOptions.DEFAULT);
//解析響應(yīng)結(jié)果
result = deleteIndexResponse.isAcknowledged();
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
(2)編寫測試方法:
/**
* 測試:刪除索引
* @author pan_junbiao
*/
@Test
public void deleteIndex()
{
//刪除索引
boolean result = blogService.deleteIndex(_indexName);
if(result)
{
System.out.println("刪除索引成功");
}
else
{
System.out.println("刪除索引失敗");
}
//判斷索引是否存在
boolean exists = blogService.existsIndex(_indexName);
if(exists)
{
System.out.println("索引存在");
}
else
{
System.out.println("索引不存在");
}
}
(3)通過控制器查看執(zhí)行結(jié)果:

3、文檔的操作
創(chuàng)建文檔表示將一個或多個文檔存儲在索引中,這與在關(guān)系型數(shù)據(jù)庫中插入記錄的概念是類似的。
在 Elasticsearch 的核心引擎 Lucene 中,插入或更新文檔的成本是相同的:在 Lucene 和 Elasticsearch 中,更新意味著替換。
3.1 新增文檔
(1)編寫新增文檔方法:
/**
* 新增文檔
* @param indexName 索引名稱
* @param documentId 文檔ID
* @param blogInfo 博客實體類
*/
@Override
public boolean addDocument(String indexName, String documentId, BlogInfo blogInfo)
{
boolean result = false;
try
{
//將博客信息實體類轉(zhuǎn)換為Map格式
Map<String, Object> blogMap = toBlogMap(blogInfo);
//1、構(gòu)建新增文檔請求
IndexRequest request = new IndexRequest(indexName).id(documentId).source(blogMap);
//2、執(zhí)行請求,返回響應(yīng)結(jié)果
IndexResponse response = restHighLevelClient.index(request,RequestOptions.DEFAULT);
result = true;
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
/**
* 將博客信息實體類轉(zhuǎn)換為Map格式
*/
private Map<String,Object> toBlogMap(BlogInfo blogInfo)
{
Map<String, Object> blogMap = new HashMap<>();
blogMap.put("blogId", blogInfo.getBlogId());
blogMap.put("blogName", blogInfo.getBlogName());
blogMap.put("blogUrl", blogInfo.getBlogUrl());
blogMap.put("blogPoints", blogInfo.getBlogPoints());
blogMap.put("createDate", blogInfo.getCreateDate());
blogMap.put("blogDescribe", blogInfo.getBlogDescribe());
return blogMap;
}
(2)編寫測試方法:
/**
* 測試:新增文檔
* @author pan_junbiao
*/
@Test
public void addDocument()
{
//創(chuàng)建博客實體類
BlogInfo blogInfo = new BlogInfo();
blogInfo.setBlogId(1);
blogInfo.setBlogName("pan_junbiao的博客");
blogInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao");
blogInfo.setBlogPoints(120.68);
blogInfo.setCreateDate(new Date());
blogInfo.setBlogDescribe("您好,歡迎訪問 pan_junbiao的博客");
//文檔ID(根據(jù)業(yè)務(wù),我們以博客ID作為文檔ID)
String documentId = String.valueOf(blogInfo.getBlogId());
//新增文檔
boolean result = blogService.addDocument(_indexName, documentId, blogInfo);
if(result)
{
System.out.println("新增文檔成功");
}
else
{
System.out.println("新增文檔失敗");
}
}
(3)使用Kibana工具查看執(zhí)行結(jié)果:
Elasticsearch查詢命令:GET /blog_info/_doc/1

3.2 批量新增文檔
(1)編寫批量新增文檔方法:
/**
* 批量新增文檔
* @param indexName 索引名稱
* @param blogList 博客列表
*/
@Override
public boolean addBulkDocument(String indexName, List<BlogInfo> blogList)
{
boolean result = false;
try
{
//1、構(gòu)建批量請求
BulkRequest request = new BulkRequest();
//遍歷博客列表,添加批量請求
for(BlogInfo blogInfo : blogList)
{
//將博客信息實體類轉(zhuǎn)換為Map格式
Map<String, Object> blogMap = toBlogMap(blogInfo);
//文檔ID(根據(jù)業(yè)務(wù),我們以博客ID作為文檔ID)
String documentId = String.valueOf(blogInfo.getBlogId());
//加入請求
request.add(new IndexRequest(indexName).id(documentId).source(blogMap));
}
//執(zhí)行批量請求
BulkResponse bulkItemResponses = restHighLevelClient.bulk(request,RequestOptions.DEFAULT);
result = true;
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
(2)編寫測試方法:
/**
* 測試:批量新增文檔
* @author pan_junbiao
*/
@Test
public void addBulkDocument()
{
//創(chuàng)建博客實體列表
List<BlogInfo> blogInfoList = new ArrayList<>();
blogInfoList.add(new BlogInfo(1,"pan_junbiao的博客","https://blog.csdn.net/pan_junbiao",120.68,new Date(),"您好,歡迎訪問 pan_junbiao的博客"));
blogInfoList.add(new BlogInfo(2,"pan_junbiao的博客","https://blog.csdn.net/pan_junbiao",85.12,new Date(),"您好,歡迎訪問 pan_junbiao的博客"));
blogInfoList.add(new BlogInfo(3,"pan_junbiao的博客","https://blog.csdn.net/pan_junbiao",94.37,new Date(),"您好,歡迎訪問 pan_junbiao的博客"));
blogInfoList.add(new BlogInfo(4,"pan_junbiao的博客","https://blog.csdn.net/pan_junbiao",365.19,new Date(),"您好,歡迎訪問 pan_junbiao的博客"));
blogInfoList.add(new BlogInfo(5,"pan_junbiao的博客","https://blog.csdn.net/pan_junbiao",287.33,new Date(),"您好,歡迎訪問 pan_junbiao的博客"));
//批量新增文檔
boolean result = blogService.addBulkDocument(_indexName, blogInfoList);
if(result)
{
System.out.println("批量新增文檔成功");
}
else
{
System.out.println("批量新增文檔失敗");
}
}
(3)使用 ElasticSearch-head 插件查看執(zhí)行結(jié)果:

3.3 修改文檔
(1)編寫修改文檔方法:
/**
* 修改文檔
* @param indexName 索引名稱
* @param documentId 文檔ID
* @param blogInfo 博客實體類
*/
@Override
public boolean updateDocument(String indexName, String documentId, BlogInfo blogInfo)
{
boolean result = false;
try
{
//將博客信息實體類轉(zhuǎn)換為Map格式
Map<String, Object> blogMap = toBlogMap(blogInfo);
//1、構(gòu)建更新文檔請求
UpdateRequest request = new UpdateRequest(indexName,documentId).doc(blogMap);
//2、執(zhí)行請求,返回響應(yīng)結(jié)果
UpdateResponse response = restHighLevelClient.update(request,RequestOptions.DEFAULT);
result = true;
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
(2)編寫測試方法:
/**
* 測試:修改文檔
* @author pan_junbiao
*/
@Test
public void updateDocument()
{
//創(chuàng)建博客實體類
BlogInfo blogInfo = new BlogInfo();
blogInfo.setBlogId(2);
blogInfo.setBlogName("pan_junbiao的博客_002");
blogInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao");
blogInfo.setBlogPoints(120.68);
blogInfo.setCreateDate(new Date());
blogInfo.setBlogDescribe("您好,歡迎訪問 pan_junbiao的博客_002");
//文檔ID(根據(jù)業(yè)務(wù),我們以博客ID作為文檔ID)
String documentId = String.valueOf(blogInfo.getBlogId());
//新增文檔
boolean result = blogService.updateDocument(_indexName, documentId, blogInfo);
if(result)
{
System.out.println("修改文檔成功");
}
else
{
System.out.println("修改文檔失敗");
}
}
(3)使用Kibana工具查看執(zhí)行結(jié)果:
Elasticsearch查詢命令:GET /blog_info/_doc/2

3.4 刪除文檔
(1)編寫刪除文檔方法:
/**
* 刪除文檔
* @param indexName 索引名稱
* @param documentId 文檔ID
*/
@Override
public boolean deleteDocument(String indexName, String documentId)
{
boolean result = false;
try
{
//1、構(gòu)建刪除文檔請求
DeleteRequest request = new DeleteRequest(indexName,documentId);
//2、執(zhí)行刪除請求,返回響應(yīng)結(jié)果
DeleteResponse deleteResponse = restHighLevelClient.delete(request,RequestOptions.DEFAULT);
result = true;
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
(2)編寫測試方法:
/**
* 測試:刪除文檔
* @author pan_junbiao
*/
@Test
public void deleteDocument()
{
//刪除文檔ID為3的文檔信息
String documentId = "3";
boolean result = blogService.deleteDocument(_indexName, documentId);
if(result)
{
System.out.println("修改文檔成功");
}
else
{
System.out.println("修改文檔失敗");
}
}
(3)使用Kibana工具查看執(zhí)行結(jié)果:
Elasticsearch查詢命令:GET /blog_info/_doc/3

3.5 判斷文檔是否存在
(1)編寫判斷文檔是否存在方法:
/**
* 判斷文檔是否存在
* @param indexName 索引名稱
* @param documentId 文檔ID
*/
@Override
public boolean existsDocument(String indexName, String documentId)
{
boolean result = false;
try
{
//1、構(gòu)建請求
GetRequest getRequest = new GetRequest(indexName, documentId);
//禁用提取源
getRequest.fetchSourceContext(new FetchSourceContext(false));
//禁用提取存儲字段
getRequest.storedFields("_none_");
//2、執(zhí)行請求,返回結(jié)果
result = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
(2)編寫測試方法:
/**
* 測試:判斷文檔是否存在
* @author pan_junbiao
*/
@Test
public void existsDocument()
{
//判斷文檔ID為3的文檔是否存在
String documentId = "3";
boolean result = blogService.existsDocument(_indexName, documentId);
if(result)
{
System.out.println("文檔存在");
}
else
{
System.out.println("文檔不存在");
}
}
(3)通過控制器查看執(zhí)行結(jié)果:

3.6 獲取文檔
(1)編寫獲取文檔方法:
/**
* 獲取文檔
* @param indexName 索引名稱
* @param documentId 文檔ID
* @param beanType 返回結(jié)果的類型
*/
@Override
public <T> T getDocumentToBean(String indexName, String documentId, Class<T> beanType)
{
T result = null;
try
{
//1、構(gòu)建請求
GetRequest getRequest = new GetRequest(indexName, documentId);
//2、執(zhí)行請求,返回響應(yīng)結(jié)果
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
//3、解析響應(yīng)結(jié)果
if (getResponse != null)
{
//獲取JSON結(jié)果
String jsonString = getResponse.getSourceAsString();
//使用Jackson工具,將JSON轉(zhuǎn)換為實體類
ObjectMapper mapper = new ObjectMapper();
result = mapper.readValue(jsonString, beanType);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
(2)編寫測試方法:
/**
* 測試:獲取文檔
* @author pan_junbiao
*/
@Test
public void getDocumentToBean() throws Exception
{
//判斷文檔ID為1的文檔信息
String documentId = "1";
BlogInfo blogInfo = blogService.getDocumentToBean(_indexName, documentId,BlogInfo.class);
//打印信息
if(blogInfo!=null)
{
System.out.println("博客ID:" + blogInfo.getBlogId());
System.out.println("博客名稱:" + blogInfo.getBlogName());
System.out.println("博客地址:" + blogInfo.getBlogUrl());
System.out.println("博客積分:" + blogInfo.getBlogPoints());
System.out.println("創(chuàng)建時間:" + blogInfo.getCreateDate());
System.out.println("博客描述:" + blogInfo.getBlogDescribe());
}
}
(3)通過控制器查看執(zhí)行結(jié)果:

到此這篇關(guān)于SpringBoot整合Elasticsearch的詳細步驟(索引、文檔)的文章就介紹到這了,更多相關(guān)SpringBoot整合Elasticsearch內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SSM如何實現(xiàn)在Controller中添加事務(wù)管理
這篇文章主要介紹了SSM如何實現(xiàn)在Controller中添加事務(wù)管理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
Java實現(xiàn)短信驗證碼服務(wù)的完整代碼示例
這篇文章主要介紹了Java實現(xiàn)短信驗證碼服務(wù)的完整代碼示例,文中使用阿里云的短信服務(wù)進行應(yīng)用開發(fā)的流程,包括將屬性寫入application.yml配置文件,定義類并指定配置文件,注入實體類對象等等,需要的朋友可以參考下2024-09-09
java如何讀取properties文件將參數(shù)值配置到靜態(tài)變量
這篇文章主要介紹了java如何讀取properties文件將參數(shù)值配置到靜態(tài)變量問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
Java filter中的chain.doFilter使用詳解
這篇文章主要介紹了Java filter中的chain.doFilter使用詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
布隆過濾器(Bloom Filter)的Java實現(xiàn)方法
下面小編就為大家?guī)硪黄悸∵^濾器(Bloom Filter)的Java實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12

